From 7ef53ce6cf544cb9f3fa2477e2326480b0265da9 Mon Sep 17 00:00:00 2001 From: taynpg Date: Fri, 27 Feb 2026 12:31:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9F=BA=E6=9C=AC=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .clang-format | 17 ++ .gitignore | 45 ++++ .vscode/settings.json | 173 +++++++++++++ CMakeLists.txt | 27 ++ main.cpp | 26 ++ res/ico.ico | Bin 0 -> 67646 bytes res/ico.rc | 1 + res/manifest.rc | 1 + res/manifest.xml | 42 ++++ src/mainframe.cpp | 573 ++++++++++++++++++++++++++++++++++++++++++ src/mainframe.h | 62 +++++ 11 files changed, 967 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 .vscode/settings.json create mode 100644 CMakeLists.txt create mode 100644 main.cpp create mode 100644 res/ico.ico create mode 100644 res/ico.rc create mode 100644 res/manifest.rc create mode 100644 res/manifest.xml create mode 100644 src/mainframe.cpp create mode 100644 src/mainframe.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..36e4997 --- /dev/null +++ b/.clang-format @@ -0,0 +1,17 @@ +BasedOnStyle: LLVM +IndentWidth: 4 +PointerAlignment: Left +AccessModifierOffset: -4 +BreakBeforeBraces: Custom +BraceWrapping: + AfterFunction: true + AfterClass: true +Cpp11BracedListStyle: true +ReflowComments: true +SpacesBeforeTrailingComments: 3 +TabWidth: 4 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ColumnLimit: 130 +AllowShortBlocksOnASingleLine: Never +AllowShortFunctionsOnASingleLine: None +AllowShortEnumsOnASingleLine: false diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03b6eee --- /dev/null +++ b/.gitignore @@ -0,0 +1,45 @@ +# Prerequisites +*.d +.idea +cmake-build-* + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +!lebo_motor.lib +!lebo_motor.dll +!liblebo_motor.so + +# Executables +*.exe +*.out +*.app +build +*.user +compile_commands.json +.vs +out +.cache +CMakeLists.txt.* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..015d958 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,173 @@ +{ + "files.autoSave": "onFocusChange", + "editor.fontSize": 14, + "cmake.configureOnOpen": true, + "editor.fontFamily": "'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light'", + "cmake.debugConfig": { + "type": "lldb", + "console": "externalTerminal", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ], + "args": [] + }, + "cmake.configureSettings": { + "CMAKE_PREFIX_PATH": "C:/local", + }, + "cmake.configureArgs": [ + "-Wno-dev" + ], + "cmake.options.statusBarVisibility": "visible", + "cmake.generator": "Ninja", + "C_Cpp.default.compileCommands": "${workspaceRoot}/build/compile_commands.json", + "C_Cpp.default.cppStandard": "c++17", + "C_Cpp.default.configurationProvider": "ms-vscode.cmake-tools", + "editor.inlayHints.enabled": "off", + "editor.unicodeHighlight.allowedLocales": { + "ja": true, + "zh-hant": true, + "zh-hans": true + }, + "files.associations": { + "string": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "charconv": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "compare": "cpp", + "concepts": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "forward_list": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "source_location": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "format": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "numbers": "cpp", + "ostream": "cpp", + "queue": "cpp", + "ranges": "cpp", + "semaphore": "cpp", + "shared_mutex": "cpp", + "span": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "stop_token": "cpp", + "streambuf": "cpp", + "text_encoding": "cpp", + "thread": "cpp", + "cfenv": "cpp", + "cinttypes": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "ios": "cpp", + "locale": "cpp", + "xfacet": "cpp", + "xhash": "cpp", + "xiosbase": "cpp", + "xlocale": "cpp", + "xlocbuf": "cpp", + "xlocinfo": "cpp", + "xlocmes": "cpp", + "xlocmon": "cpp", + "xlocnum": "cpp", + "xloctime": "cpp", + "xmemory": "cpp", + "xstring": "cpp", + "xtr1common": "cpp", + "xutility": "cpp", + "coroutine": "cpp", + "csignal": "cpp", + "future": "cpp", + "stdfloat": "cpp", + "regex": "cpp", + "stack": "cpp", + "valarray": "cpp", + "filesystem": "cpp", + "qmainwindow": "cpp", + "qlabel": "cpp", + "*.in": "cpp", + "fstream": "cpp", + "xmemory0": "cpp", + "xstddef": "cpp", + "xtree": "cpp", + "qxmlstreamwriter": "cpp", + "qgraphicsdropshadoweffect": "cpp", + "qpushbutton": "cpp", + "qpainter": "cpp", + "qdialog": "cpp", + "quuid": "cpp", + "complex": "cpp", + "expected": "cpp", + "qmessagebox": "cpp" + }, + "editor.tokenColorCustomizations": { + "textMateRules": [ + { + "scope": "googletest.failed", + "settings": { + "foreground": "#f00" + } + }, + { + "scope": "googletest.passed", + "settings": { + "foreground": "#0f0" + } + }, + { + "scope": "googletest.run", + "settings": { + "foreground": "#0f0" + } + } + ] + } +} \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..00e3c85 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.16) + +project(cmakeCreate LANGUAGES CXX) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +if (MSVC) + add_compile_options(/utf-8) +endif() + +set(CMAKE_DEBUG_POSTFIX "d") +set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib/${CMAKE_BUILD_TYPE}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin/${CMAKE_BUILD_TYPE}/) + +find_package(wxWidgets CONFIG REQUIRED) + +set(SOURCES +src/mainframe.h +src/mainframe.cpp +res/ico.rc +res/manifest.rc +) + +include_directories(src) +add_executable(cmakeCreate main.cpp ${SOURCES}) +target_link_libraries(cmakeCreate PRIVATE wx::core wx::base wx::stc) +set_target_properties(cmakeCreate PROPERTIES WIN32_EXECUTABLE TRUE) \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..fcd25ef --- /dev/null +++ b/main.cpp @@ -0,0 +1,26 @@ +#include "mainframe.h" + +class CWxNewProject : public wxApp +{ +public: + virtual bool OnInit() + { + wxString title = wxString::Format(wxT("创建cmake工程 v1.0.0")); + auto* f = new MainFrame(title); + f->Show(true); + f->SetIcon(wxICON(IDI_ICON1)); + +#ifdef __WXMSW__ + SetProcessDPIAware(); +#endif + + return true; + } + virtual int OnExit() + { + return wxApp::OnExit(); + } +}; + +IMPLEMENT_APP(CWxNewProject); +DECLARE_APP(CWxNewProject); \ No newline at end of file diff --git a/res/ico.ico b/res/ico.ico new file mode 100644 index 0000000000000000000000000000000000000000..65de4f2f7aaf58575b2602aaecd465520c262bf9 GIT binary patch literal 67646 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 + + + + Your Application Description + + + + + + + + + + + + true + PerMonitorV2 + + + + + + \ No newline at end of file diff --git a/src/mainframe.cpp b/src/mainframe.cpp new file mode 100644 index 0000000..2a239d0 --- /dev/null +++ b/src/mainframe.cpp @@ -0,0 +1,573 @@ +#include "mainframe.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +MainFrame::MainFrame(const wxString& title) : wxFrame(nullptr, wxID_ANY, title) +{ + SetSize(wxSize(1100, 600)); + InitControl(); + InitCMakeSyntaxHighlighting(); + configDir_ = GetConfigDir(); + ShowConfig(); + ShowExist(); + LoadConfig(); +} + +void MainFrame::InitControl() +{ + addID_ = wxNewId(); + delID_ = wxNewId(); + + wxPanel* mainPanel = new wxPanel(this, wxID_ANY); + listBox_ = new wxListBox(mainPanel, wxID_ANY, wxDefaultPosition, wxSize(200, -1)); + listBox_->Bind(wxEVT_COMMAND_LISTBOX_SELECTED, &MainFrame::OnListBoxSelected, this); + listBox_->Bind(wxEVT_CONTEXT_MENU, &MainFrame::OnRightClick, this); + + textCtrl_ = new wxStyledTextCtrl(mainPanel, wxID_ANY); + btnNewer_ = new wxButton(mainPanel, wxID_ANY, wxT("新建工程")); + btnExit_ = new wxButton(mainPanel, wxID_ANY, wxT("退出")); + btnRefresh_ = new wxButton(mainPanel, wxID_ANY, wxT("刷新列表")); + btnRefresh_->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MainFrame::ShowConfig, this); + btnSelectPath_ = new wxButton(mainPanel, wxID_ANY, wxT("选择路径")); + + // + btnSave_ = new wxButton(mainPanel, wxID_ANY, wxT("保存"), wxDefaultPosition, wxSize(150, -1)); + + textPath_ = new wxTextCtrl(mainPanel, wxID_ANY); + auto* labelProjectName = new wxStaticText(mainPanel, wxID_ANY, wxT("项目名称:")); + projectName_ = new wxTextCtrl(mainPanel, wxID_ANY); + + // + btnExit_->SetMinSize(wxSize(150, -1)); + btnNewer_->SetMinSize(wxSize(150, -1)); + + // + btnOpenPrjDir_ = new wxButton(mainPanel, wxID_ANY, wxT("打开项目目录")); + auto* staticSelectPath = new wxStaticText(mainPanel, wxID_ANY, wxT("工程目录:")); + wxBoxSizer* selectSizer = new wxBoxSizer(wxHORIZONTAL); + selectSizer->Add(staticSelectPath, 0, wxALL | wxCENTER, 2); + selectSizer->Add(textPath_, 1, wxALL | wxEXPAND, 2); + selectSizer->Add(btnSelectPath_, 0, wxALL | wxCENTER, 2); + selectSizer->Add(btnOpenPrjDir_, 0, wxALL | wxCENTER, 2); + + // + curFileTitle_ = new wxStaticText(mainPanel, wxID_ANY, wxT("无当前文件")); + auto* centerSizer = new wxBoxSizer(wxVERTICAL); + centerSizer->Add(curFileTitle_, 0, wxALL | wxLEFT, 2); + centerSizer->Add(textCtrl_, 1, wxALL | wxEXPAND, 2); + centerSizer->Add(selectSizer, 0, wxALL | wxEXPAND, 2); + + // + btnOpenResDir_ = new wxButton(mainPanel, wxID_ANY, wxT("打开模板目录")); + auto* controlSizer = new wxBoxSizer(wxVERTICAL); + controlSizer->Add(btnRefresh_, 0, wxALL | wxEXPAND, 2); + controlSizer->Add(btnSave_, 0, wxALL | wxEXPAND, 2); + controlSizer->Add(btnOpenResDir_, 0, wxALL | wxEXPAND, 2); + controlSizer->AddStretchSpacer(1); + controlSizer->Add(labelProjectName, 0, wxALL | wxLEFT, 2); + controlSizer->Add(projectName_, 0, wxALL | wxEXPAND, 2); + controlSizer->Add(btnNewer_, 0, wxALL | wxCENTER, 2); + controlSizer->Add(btnExit_, 0, wxALL | wxCENTER, 2); + + // + auto* topSizer = new wxBoxSizer(wxHORIZONTAL); + topSizer->Add(listBox_, 0, wxALL | wxEXPAND, 2); + topSizer->Add(centerSizer, 3, wxALL | wxEXPAND, 2); + topSizer->Add(controlSizer, 0, wxALL | wxEXPAND, 2); + + SetMinSize(wxSize(800, 500)); + mainPanel->SetSizer(topSizer); + + btnExit_->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MainFrame::OnExitClick, this); + btnNewer_->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MainFrame::OnNewerClick, this); + btnSelectPath_->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MainFrame::OnSelectPathClick, this); + btnSave_->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MainFrame::SaveCurrent, this); + btnOpenResDir_->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MainFrame::OpenResDir, this); + btnOpenPrjDir_->Bind(wxEVT_COMMAND_BUTTON_CLICKED, &MainFrame::OpenPrjDir, this); + Bind(wxEVT_MENU, &MainFrame::DelMenu, this, delID_); + Bind(wxEVT_MENU, &MainFrame::AddMenu, this, addID_); +} + +void MainFrame::OnNewerClick(wxCommandEvent& event) +{ + wxString targetPath = textPath_->GetValue().Trim(); + if (targetPath.IsEmpty()) { + wxMessageBox(wxT("目标路径不能为空"), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + if (!wxDirExists(targetPath)) { + wxMessageBox(wxString::Format(wxT("目标路径不存在:\n%s"), targetPath), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + wxString projectName = projectName_->GetValue().Trim(); + if (projectName.IsEmpty()) { + wxMessageBox(wxT("项目名称不能为空"), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + wxString destDir = wxFileName::DirName(targetPath).GetFullPath(); + destDir += wxFileName::GetPathSeparator() + projectName; + destDir = Normalize(destDir); + + if (wxDirExists(destDir)) { + wxMessageBox(wxString::Format(wxT("目标目录已存在:\n%s"), destDir), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + wxString sourceDir = configDir_ + wxFileName::GetPathSeparator() + curFileTitle_->GetLabelText(); + sourceDir = Normalize(sourceDir); + if (!wxDirExists(sourceDir)) { + wxMessageBox(wxString::Format(wxT("源目录不存在:\n%s"), sourceDir), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + if (!wxFileName::Mkdir(destDir, 0755, wxPATH_MKDIR_FULL)) { + wxMessageBox(wxString::Format(wxT("无法创建目录:\n%s"), destDir), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + wxDir dir(sourceDir); + wxString filename; + bool success = true; + wxString errorFile; + + if (dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES | wxDIR_DIRS)) { + do { + wxString sourceItem = sourceDir + wxFileName::GetPathSeparator() + filename; + wxString destItem = destDir + wxFileName::GetPathSeparator() + filename; + sourceItem = Normalize(sourceItem); + destItem = Normalize(destItem); + + if (wxDirExists(sourceItem)) { + if (!wxFileName::Mkdir(destItem, 0755, wxPATH_MKDIR_FULL)) { + success = false; + errorFile = filename; + break; + } + + if (!CopyDirectory(sourceItem, destItem, projectName)) { + success = false; + errorFile = filename; + break; + } + } else { + if (!wxCopyFile(sourceItem, destItem)) { + success = false; + errorFile = filename; + break; + } + if (filename == wxT("CMakeLists.txt")) { + ProcessCMakeListsFile(destItem, projectName); + } + } + } while (success && dir.GetNext(&filename)); + } + if (success) { + wxMessageBox(wxString::Format(wxT("成功创建项目:\n%s\n并复制所有文件"), destDir), wxT("完成"), wxOK | wxICON_INFORMATION, + this); + } else { + wxMessageBox(wxString::Format(wxT("复制文件失败:\n%s"), errorFile), wxT("错误"), wxOK | wxICON_ERROR, this); + wxFileName::Rmdir(destDir, wxPATH_RMDIR_RECURSIVE); + } + SaveConfig(); +} + +void MainFrame::OnExitClick(wxCommandEvent& event) +{ + Close(true); +} + +void MainFrame::OnSelectPathClick(wxCommandEvent& event) +{ + wxDirDialog dirDialog(this, wxT("选择工程创建所在目录"), textPath_->GetValue(), wxDD_DEFAULT_STYLE | wxDD_DIR_MUST_EXIST); + if (dirDialog.ShowModal() == wxID_OK) { + wxString selectedPath = dirDialog.GetPath(); + textPath_->SetValue(selectedPath); + } +} + +wxString MainFrame::GetConfigDir() +{ + wxString exePath = wxStandardPaths::Get().GetExecutablePath(); + wxFileName exeFile(exePath); + wxString parentDir = exeFile.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR); + wxString configDir = parentDir + wxFileName::GetPathSeparator() + wxT("res"); + wxFileName configDirFile(configDir); + configDirFile.Normalize(wxPATH_NORM_ALL); + if (!configDirFile.DirExists()) { + if (!wxFileName::Mkdir(configDirFile.GetFullPath(), 0755, wxPATH_MKDIR_FULL)) { + wxLogError(wxT("无法创建配置目录: %s"), configDirFile.GetFullPath()); + return wxEmptyString; + } + wxLogMessage(wxT("已创建配置目录: %s"), configDirFile.GetFullPath()); + } + return configDirFile.GetFullPath(); +} + +void MainFrame::ShowConfig() +{ + listBox_->Clear(); + if (configDir_.empty()) { + wxMessageBox(wxT("配置目录路径为空")); + return; + } + if (!wxDirExists(configDir_)) { + if (!wxFileName::Mkdir(configDir_, 0755, wxPATH_MKDIR_FULL)) { + wxMessageBox(wxString::Format(wxT("无法创建配置目录: %s"), configDir_)); + return; + } + wxMessageBox(wxString::Format(wxT("已创建配置目录: %s"), configDir_)); + } + + wxDir dir(configDir_); + if (!dir.IsOpened()) { + wxMessageBox(wxString::Format(wxT("无法打开配置目录: %s"), configDir_)); + return; + } + + wxString dirName; + bool cont = dir.GetFirst(&dirName, wxEmptyString, wxDIR_DIRS); + while (cont) { + wxString fullPath = configDir_ + wxFileName::GetPathSeparator() + dirName; + if (wxDirExists(fullPath)) { + listBox_->Append(dirName); + int lastIndex = listBox_->GetCount() - 1; + listBox_->SetClientData(lastIndex, new wxString(fullPath)); + } + cont = dir.GetNext(&dirName); + } +} + +void MainFrame::ShowConfig(wxCommandEvent& event) +{ + ShowConfig(); +} + +void MainFrame::OnListBoxSelected(wxCommandEvent& event) +{ + wxString cmakeContent; + int selection = listBox_->GetSelection(); + if (selection == wxNOT_FOUND) { + return; + } + + wxString selectedText = listBox_->GetString(selection); + wxString fullPath = configDir_ + wxFileName::GetPathSeparator() + selectedText; + + if (!wxDirExists(fullPath)) { + wxMessageBox(wxString::Format(wxT("目录不存在: %s"), fullPath), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + curFileTitle_->SetLabel(selectedText); + currentFilePath_ = fullPath + wxFileName::GetPathSeparator() + wxT("CMakeLists.txt"); + if (!wxFileExists(currentFilePath_)) { + textCtrl_->SetValue(cmakeContent); + return; + } + + wxFile cmakeFile(currentFilePath_); + if (!cmakeFile.IsOpened()) { + wxMessageBox(wxT("无法打开CMakeLists.txt文件"), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + cmakeFile.ReadAll(&cmakeContent); + cmakeFile.Close(); + textCtrl_->SetValue(cmakeContent); +} + +void MainFrame::InitCMakeSyntaxHighlighting() +{ + textCtrl_->SetLexer(wxSTC_LEX_CMAKE); + + // 基础样式配置 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_DEFAULT, *wxBLACK); + textCtrl_->StyleSetForeground(wxSTC_CMAKE_COMMENT, wxColour(0, 128, 0)); // 绿色注释 + + // 字符串类型 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_STRINGDQ, wxColour(163, 21, 21)); // 红色双引号字符串 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_STRINGLQ, wxColour(163, 21, 21)); // 红色左单引号 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_STRINGRQ, wxColour(163, 21, 21)); // 红色右单引号 + + // 命令和参数 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_COMMANDS, wxColour(0, 0, 255)); // 蓝色命令 + textCtrl_->StyleSetBold(wxSTC_CMAKE_COMMANDS, true); + textCtrl_->StyleSetForeground(wxSTC_CMAKE_PARAMETERS, wxColour(255, 105, 0)); // 橙色参数 + + // 变量和数字 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_VARIABLE, wxColour(128, 0, 128)); // 紫色变量 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_STRINGVAR, wxColour(128, 0, 128)); // 紫色字符串变量 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_NUMBER, wxColour(0, 100, 0)); // 深绿色数字 + + // 控制结构 + textCtrl_->StyleSetForeground(wxSTC_CMAKE_WHILEDEF, wxColour(0, 0, 139)); // 深蓝色while + textCtrl_->StyleSetForeground(wxSTC_CMAKE_FOREACHDEF, wxColour(0, 0, 139)); // 深蓝色foreach + textCtrl_->StyleSetForeground(wxSTC_CMAKE_IFDEFINEDEF, wxColour(0, 0, 139)); // 深蓝色if + textCtrl_->StyleSetForeground(wxSTC_CMAKE_MACRODEF, wxColour(139, 0, 139)); // 深紫色宏 + + const char* cmakeCommands = "add_executable add_library target_link_libraries " + "find_package if else endif foreach endfunction project cmake_minimum_required" + "while endwhile macro endmacro function set add_compile_options"; + + textCtrl_->SetKeyWords(0, cmakeCommands); + textCtrl_->StyleSetBackground(wxSTC_CMAKE_DEFAULT, wxColour(255, 255, 255)); +} + +void MainFrame::SaveCurrent(wxCommandEvent& event) +{ + if (currentFilePath_.empty()) { + wxMessageBox(wxT("当前无配置选择"), wxT("提示"), wxOK | wxICON_ERROR, this); + return; + } + wxFile cmakeFile(currentFilePath_, wxFile::write); + if (!cmakeFile.IsOpened()) { + wxMessageBox(wxT("无法打开CMakeLists.txt文件"), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + wxString content = textCtrl_->GetValue(); + if (!cmakeFile.Write(content)) { + wxMessageBox(wxString::Format(wxT("写入文件失败: %s"), currentFilePath_), wxT("错误"), wxOK | wxICON_ERROR, this); + cmakeFile.Close(); + return; + } + cmakeFile.Close(); + wxMessageBox(wxT("已保存")); +} + +void MainFrame::OnRightClick(wxCommandEvent& event) +{ + wxMenu menu; + bool hasSelection = (listBox_->GetSelection() != wxNOT_FOUND); + menu.Append(addID_, wxT("添加")); + menu.AppendSeparator(); + menu.Append(delID_, wxT("删除"))->Enable(hasSelection); + listBox_->PopupMenu(&menu); +} + +void MainFrame::AddMenu(wxCommandEvent& event) +{ + wxTextEntryDialog dialog(this, wxT("请输入新条目名称:"), wxT("添加新条目"), wxEmptyString, wxOK | wxCANCEL | wxCENTRE); + if (dialog.ShowModal() != wxID_OK) { + return; + } + wxString newItem = dialog.GetValue().Trim(); + if (newItem.IsEmpty()) { + wxMessageBox(wxT("条目名称不能为空"), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + wxString newDir = configDir_ + wxFileName::GetPathSeparator() + newItem; + + if (!wxFileName::Mkdir(newDir, 0755, wxPATH_MKDIR_FULL)) { + wxMessageBox(wxT("无法创建目录: ") + newDir, wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + listBox_->Append(newItem); + listBox_->SetSelection(listBox_->GetCount() - 1); + curFileTitle_->SetLabel(newItem); + currentFilePath_ = newDir + wxFileName::GetPathSeparator() + wxT("CMakeLists.txt"); + textCtrl_->SetValue(wxEmptyString); +} + +void MainFrame::DelMenu(wxCommandEvent& event) +{ + int selection = listBox_->GetSelection(); + if (selection == wxNOT_FOUND) { + return; + } + wxString selectedItem = listBox_->GetString(selection); + wxString targetDir = Normalize(configDir_ + wxFileName::GetPathSeparator() + selectedItem); + wxString msg = wxString::Format(wxT("确定要删除目录:\n%s\n及其所有内容吗?"), targetDir); + + wxMessageDialog dlg(this, msg, wxT("确认删除"), wxYES_NO | wxNO_DEFAULT | wxICON_WARNING); + + if (dlg.ShowModal() != wxID_YES) { + return; + } + + if (wxDirExists(targetDir)) { + wxFileName::Rmdir(targetDir, wxPATH_RMDIR_RECURSIVE); + listBox_->Delete(selection); + ShowExist(); + } else { + wxMessageBox(wxString::Format(wxT("目录 %s 不存在"), targetDir), wxT("错误"), wxOK | wxICON_ERROR, this); + } +} + +void MainFrame::ShowExist() +{ + if (!listBox_ || listBox_->IsEmpty()) { + return; + } + wxString firstItem = listBox_->GetString(0); + listBox_->SetSelection(0); + + wxString selectedText = firstItem; + wxString fullPath = Normalize(configDir_ + wxFileName::GetPathSeparator() + selectedText); + + if (!wxDirExists(fullPath)) { + wxMessageBox(wxString::Format(wxT("目录不存在: %s"), fullPath), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + wxString cmakeContent; + curFileTitle_->SetLabel(selectedText); + currentFilePath_ = Normalize(fullPath + wxFileName::GetPathSeparator() + wxT("CMakeLists.txt")); + + if (!wxFileExists(currentFilePath_)) { + textCtrl_->SetValue(cmakeContent); + return; + } + + wxFile cmakeFile(currentFilePath_); + if (!cmakeFile.IsOpened()) { + wxMessageBox(wxT("无法打开CMakeLists.txt文件"), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + cmakeFile.ReadAll(&cmakeContent); + cmakeFile.Close(); + textCtrl_->SetValue(cmakeContent); +} + +void MainFrame::OpenDir(const wxString& path) +{ + if (!wxDirExists(path)) { + wxMessageBox(wxString::Format(wxT("目录不存在:\n%s"), path), wxT("错误"), wxOK | wxICON_ERROR, this); + return; + } + + bool success = wxLaunchDefaultApplication(path); + + if (!success) { +#ifdef __WXMSW__ + wxString cmd = wxT("explorer \"") + path + wxT("\""); +#elif defined(__WXMAC__) + wxString cmd = wxT("open \"") + path + wxT("\""); +#else // Linux/Unix + wxString cmd = wxT("xdg-open \"") + path + wxT("\""); +#endif + success = wxExecute(cmd) != 0; + } + if (!success) { + wxMessageBox(wxString::Format(wxT("无法打开目录:\n%s"), path), wxT("错误"), wxOK | wxICON_ERROR, this); + } +} + +void MainFrame::OpenResDir(wxCommandEvent& event) +{ + OpenDir(configDir_); +} + +void MainFrame::OpenPrjDir(wxCommandEvent& event) +{ + OpenDir(textPath_->GetValue()); +} + +wxString MainFrame::Normalize(const wxString& path) +{ + wxFileName configDirFile(path); + configDirFile.Normalize(wxPATH_NORM_ALL); + return configDirFile.GetFullPath(); +} + +void MainFrame::SaveConfig() +{ + if (!wxFileName::DirExists(configDir_)) { + if (!wxFileName::Mkdir(configDir_, 0755, wxPATH_MKDIR_FULL)) { + wxLogError(wxT("无法创建配置目录: %s"), configDir_); + return; + } + } + wxString configFile = configDir_ + wxFileName::GetPathSeparator() + wxT("newproject.ini"); + wxFileConfig config(wxEmptyString, wxEmptyString, configFile, wxEmptyString, wxCONFIG_USE_LOCAL_FILE); + config.Write(wxT("/Paths/TextPath"), textPath_->GetValue()); + config.Write(wxT("/Paths/ProjectName"), projectName_->GetValue()); + config.Flush(); +} + +void MainFrame::LoadConfig() +{ + wxString configFile = configDir_ + wxFileName::GetPathSeparator() + wxT("newproject.ini"); + if (!wxFileName::FileExists(configFile)) { + return; + } + wxFileConfig config(wxEmptyString, wxEmptyString, configFile, wxEmptyString, wxCONFIG_USE_LOCAL_FILE); + wxString textPath, projectName; + if (config.Read(wxT("/Paths/TextPath"), &textPath)) { + textPath_->SetValue(textPath); + } + if (config.Read(wxT("/Paths/ProjectName"), &projectName)) { + projectName_->SetValue(projectName); + } +} + +bool MainFrame::CopyDirectory(const wxString& source, const wxString& dest, const wxString& projectName) +{ + wxDir dir(source); + wxString filename; + bool success = true; + + if (dir.GetFirst(&filename, wxEmptyString, wxDIR_FILES | wxDIR_DIRS)) { + do { + wxString sourceItem = source + wxFileName::GetPathSeparator() + filename; + wxString destItem = dest + wxFileName::GetPathSeparator() + filename; + sourceItem = Normalize(sourceItem); + destItem = Normalize(destItem); + + if (wxDirExists(sourceItem)) { + if (!wxFileName::Mkdir(destItem, 0755, wxPATH_MKDIR_FULL)) { + success = false; + break; + } + + if (!CopyDirectory(sourceItem, destItem, projectName)) { + success = false; + break; + } + } else { + if (!wxCopyFile(sourceItem, destItem)) { + success = false; + break; + } + + if (filename == wxT("CMakeLists.txt")) { + ProcessCMakeListsFile(destItem, projectName); + } + } + } while (success && dir.GetNext(&filename)); + } + + return success; +} + +void MainFrame::ProcessCMakeListsFile(const wxString& filePath, const wxString& projectName) +{ + wxFile file(filePath, wxFile::read); + if (file.IsOpened()) { + wxString content; + file.ReadAll(&content); + file.Close(); + + content.Replace(wxT("PJNAME"), projectName); + + wxFile dest(filePath, wxFile::write); + if (dest.IsOpened()) { + dest.Write(content); + dest.Close(); + } else { + wxMessageBox(wxString::Format(wxT("无法打开文件进行修改: %s"), filePath)); + } + } else { + wxMessageBox(wxString::Format(wxT("无法读取源文件: %s"), filePath)); + } +} \ No newline at end of file diff --git a/src/mainframe.h b/src/mainframe.h new file mode 100644 index 0000000..5599113 --- /dev/null +++ b/src/mainframe.h @@ -0,0 +1,62 @@ +#ifndef MAINFRAME_H +#define MAINFRAME_H + +#include +#include +#include +#include +#include + +class MainFrame : public wxFrame +{ +public: + explicit MainFrame(const wxString& title); + +private: + void InitControl(); + +private: + void OnNewerClick(wxCommandEvent& event); + void OnExitClick(wxCommandEvent& event); + void OnSelectPathClick(wxCommandEvent& event); + wxString GetConfigDir(); + void ShowConfig(wxCommandEvent& event); + void ShowConfig(); + void OnListBoxSelected(wxCommandEvent& event); + void InitCMakeSyntaxHighlighting(); + void SaveCurrent(wxCommandEvent& event); + void OnRightClick(wxCommandEvent& event); + void AddMenu(wxCommandEvent& event); + void DelMenu(wxCommandEvent& event); + void ShowExist(); + void OpenResDir(wxCommandEvent& event); + void OpenPrjDir(wxCommandEvent& event); + wxString Normalize(const wxString& path); + void SaveConfig(); + void LoadConfig(); + bool CopyDirectory(const wxString& source, const wxString& dest, const wxString& projectName); + void ProcessCMakeListsFile(const wxString& filePath, const wxString& projectName); + void OpenDir(const wxString& path); + +private: + wxListBox* listBox_; + wxStyledTextCtrl* textCtrl_; + wxButton* btnNewer_; + wxButton* btnExit_; + wxButton* btnSelectPath_; + wxTextCtrl* textPath_; + wxString configDir_; + wxTextCtrl* projectName_; + wxButton* btnRefresh_; + wxButton* btnSave_; + wxString currentFilePath_; + wxStaticText* curFileTitle_; + wxButton* btnOpenResDir_; + wxButton* btnOpenPrjDir_; + +private: + wxWindowID addID_; + wxWindowID delID_; +}; + +#endif // MAINFRAME_H \ No newline at end of file