diff --git a/README.md b/README.md index 09b0e05..31c24aa 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,9 @@ ## WingTool -  `WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪、选词等相关借口。通过开发强大的对应的插件,就可以大大提高生产力。 +  `WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪等基本接口。通过开发强大的对应的插件,就可以大大提高生产力。 -  该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Ctrl`键可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。 +  该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Super`键(在`Windows`系统中称之为`Win`键)可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。 ### 协议 diff --git a/TestPlugin/testplugin.cpp b/TestPlugin/testplugin.cpp index f64bfff..d45e795 100644 --- a/TestPlugin/testplugin.cpp +++ b/TestPlugin/testplugin.cpp @@ -16,13 +16,17 @@ TestPlugin::TestPlugin(QObject *parent) { tbinfo->setFixedSize(dialog->size()); tbinfo->setUndoRedoEnabled(false); services = new TestService(tbinfo, dialog); + + testmenu = new QAction; + testmenu->setIcon(QIcon(":/TestPlugin/logo.svg")); + testmenu->setText("TestMenu"); } int TestPlugin::sdkVersion() { return SDKVERSION; } QString TestPlugin::signature() { return WINGSUMMER; } -TestPlugin::~TestPlugin() {} +TestPlugin::~TestPlugin() { testmenu->deleteLater(); } bool TestPlugin::init(QList loadedplugin) { Q_UNUSED(loadedplugin); @@ -63,6 +67,8 @@ const QMetaObject *TestPlugin::serviceMeta() { return services->metaObject(); } HookIndex TestPlugin::getHookSubscribe() { return HookIndex::None; } +QObject *TestPlugin::trayRegisteredMenu() { return testmenu; } + QVariant TestPlugin::pluginServicePipe(int serviceID, QList params) { switch (serviceID) { case HostService: diff --git a/TestPlugin/testplugin.h b/TestPlugin/testplugin.h index e3ed7ae..b8b7de9 100644 --- a/TestPlugin/testplugin.h +++ b/TestPlugin/testplugin.h @@ -62,6 +62,8 @@ public: const QPointer serviceHandler() override; HookIndex getHookSubscribe() override; + QObject *trayRegisteredMenu() override; + public slots: QVariant pluginServicePipe(int serviceID, QList params) override; virtual void onSetting() override; @@ -73,6 +75,8 @@ private: TestService *services; QTranslator translator; + + QAction *testmenu; }; #endif // GENERICPLUGIN_H diff --git a/WingTool.pro b/WingTool.pro index 40b46ba..371270f 100644 --- a/WingTool.pro +++ b/WingTool.pro @@ -8,6 +8,8 @@ TEMPLATE = app QT += x11extras LIBS += -lX11 -lXext -lXtst +CONFIG += exception + SOURCES += \ main.cpp \ class/eventmonitor.cpp \ diff --git a/class/appmanager.cpp b/class/appmanager.cpp index 5cfbd6b..34989ea 100644 --- a/class/appmanager.cpp +++ b/class/appmanager.cpp @@ -8,7 +8,7 @@ AppManager *AppManager::m_instance = nullptr; AppManager::AppManager(QObject *parent) : QObject(parent) { // 初始化全局鼠标监控 -#define CONNECT(sig) connect(&monitor, SIGNAL(sig), SLOT(sig)); +#define CONNECT(sig) connect(&monitor, SIGNAL(sig), this, SLOT(sig)); CONNECT(clicked); CONNECT(doubleClicked); CONNECT(mouseWheel); @@ -99,12 +99,10 @@ void AppManager::clearHotkey() { hotkeys.clear(); } -Qt::KeyboardModifier AppManager::getKeyModifier() const { - return monitor.getKeyModifier(); +Qt::KeyboardModifiers AppManager::getKeyModifiers() const { + return monitor.getKeyModifiers(); } -void AppManager::setToolIcons(QVector icons) { toolwin.setIcons(icons); } - -void AppManager::setToolIcon(int index, QIcon icon) { - toolwin.setIcon(index, icon); +void AppManager::setToolIcon(int index, QIcon icon, QString tip) { + toolwin.setIcon(index, icon, tip); } diff --git a/class/appmanager.h b/class/appmanager.h index 4342c8d..01c477b 100644 --- a/class/appmanager.h +++ b/class/appmanager.h @@ -25,7 +25,7 @@ public: bool editHotkey(Hotkey *hotkey, QKeySequence &keyseq); void clearHotkey(); - Qt::KeyboardModifier getKeyModifier() const; + Qt::KeyboardModifiers getKeyModifiers() const; signals: void buttonPress(Qt::MouseButton btn, int x, int y); @@ -45,8 +45,7 @@ signals: void toolSelTriggered(int index); public slots: - void setToolIcons(QVector icons); - void setToolIcon(int index, QIcon icon); + void setToolIcon(int index, QIcon icon, QString tip); private: EventMonitor monitor; diff --git a/class/eventmonitor.cpp b/class/eventmonitor.cpp index 2f090f3..140d1ac 100644 --- a/class/eventmonitor.cpp +++ b/class/eventmonitor.cpp @@ -65,8 +65,8 @@ void EventMonitor::run() { isClicked = false; } -Qt::KeyboardModifier EventMonitor::getKeyModifier() const { - return keyModifier; +Qt::KeyboardModifiers EventMonitor::getKeyModifiers() const { + return keyModifiers; } void EventMonitor::callback(XPointer ptr, XRecordInterceptData *data) { @@ -160,26 +160,45 @@ void EventMonitor::handleRecordEvent(XRecordInterceptData *data) { switch (code) { case 50: case 62: - keyModifier = Qt::ShiftModifier; + keyModifiers.setFlag(Qt::ShiftModifier); break; case 37: case 105: - keyModifier = Qt::ControlModifier; + keyModifiers.setFlag(Qt::ControlModifier); break; case 64: case 108: - keyModifier = Qt::AltModifier; + keyModifiers.setFlag(Qt::AltModifier); break; case 133: - keyModifier = Qt::MetaModifier; + keyModifiers.setFlag(Qt::MetaModifier); + break; + default: + break; + } + } break; + case KeyRelease: { + auto code = data->data[1]; + switch (code) { + case 50: + case 62: + keyModifiers.setFlag(Qt::ShiftModifier, false); + break; + case 37: + case 105: + keyModifiers.setFlag(Qt::ControlModifier, false); + break; + case 64: + case 108: + keyModifiers.setFlag(Qt::AltModifier, false); + break; + case 133: + keyModifiers.setFlag(Qt::MetaModifier, false); break; default: break; } } break; - case KeyRelease: - keyModifier = Qt::NoModifier; - break; default: break; } diff --git a/class/eventmonitor.h b/class/eventmonitor.h index 5a5b0eb..040a76d 100644 --- a/class/eventmonitor.h +++ b/class/eventmonitor.h @@ -46,7 +46,7 @@ public: EventMonitor(QObject *parent = nullptr); ~EventMonitor() override; - Qt::KeyboardModifier getKeyModifier() const; + Qt::KeyboardModifiers getKeyModifiers() const; signals: void buttonPress(Qt::MouseButton btn, int x, int y); // 当鼠标按键被按下时 @@ -70,7 +70,7 @@ private: std::chrono::system_clock::time_point clickbefore; - Qt::KeyboardModifier keyModifier; + Qt::KeyboardModifiers keyModifiers; }; #endif diff --git a/class/settingmanager.cpp b/class/settingmanager.cpp index f79cee3..d4cb640 100644 --- a/class/settingmanager.cpp +++ b/class/settingmanager.cpp @@ -31,6 +31,16 @@ SettingManager *SettingManager::instance() { return m_instance; } bool SettingManager::loadSettings(QString filename) { +#define FAILRETURN \ + { \ + f.close(); \ + return false; \ + } + +#define VAILDSTR(str) \ + if (!Utilities::isVaildString(arr, str)) \ + FAILRETURN; + #define CORRECTINFO(info) \ if (info.isPlugin) { \ info.pluginIndex = plgsys->pluginIndexByProvider(info.provider); \ @@ -49,7 +59,7 @@ bool SettingManager::loadSettings(QString filename) { if (memcmp(header, buffer, 8)) { // 如果文件头不对劲,就视为非法配置 loadedGeneral(); - return false; + FAILRETURN; } // 读取配置文件 @@ -57,9 +67,8 @@ bool SettingManager::loadSettings(QString filename) { stream.readRawData(&ver, 1); if (ver != CONFIGVER) { - f.close(); - loadedGeneral(); - return false; + emit loadedGeneral(); + FAILRETURN; } if (filename.length()) @@ -72,8 +81,33 @@ bool SettingManager::loadSettings(QString filename) { auto plgsys = PluginSystem::instance(); // General - stream >> m_toolwin >> m_wintool >> m_toolGridSize >> m_toolBox >> - m_toolwinMod >> m_toolMouse; + stream >> m_toolwin >> m_wintool >> m_toolGridSize >> m_runWin >> + m_toolBox >> m_toolwinMod >> m_toolMouse; + + // check + if (m_toolGridSize < 30 || m_toolGridSize > 60) + FAILRETURN; + if (m_toolBox.isEmpty()) + FAILRETURN; + switch (m_toolwinMod) { + case Qt::AltModifier: + case Qt::ControlModifier: + case Qt::MetaModifier: + case Qt::ShiftModifier: + break; + default: + FAILRETURN; + } + switch (m_toolMouse) { + case Qt::LeftButton: + case Qt::MiddleButton: + case Qt::RightButton: + case Qt::XButton1: + case Qt::XButton2: + break; + default: + FAILRETURN; + } // 读取结束,提示可以加载基础配置内容了 emit loadedGeneral(); @@ -83,22 +117,32 @@ bool SettingManager::loadSettings(QString filename) { // 读取 Hotkey 的相关信息 int len; stream >> len; // 先读取一下有几个 + if (len < 0) + return false; for (auto i = 0; i < len; i++) { ToolStructInfo buf; stream >> buf.enabled >> buf.isPlugin >> buf.seq; + if (buf.seq.isEmpty()) + FAILRETURN; if (buf.isPlugin) { stream >> buf.serviceID; + if (buf.serviceID < 0) + FAILRETURN; QByteArray arr; stream >> arr; - buf.provider = QString::fromUtf8(arr); + VAILDSTR(buf.provider); stream >> arr; - buf.params = QString::fromUtf8(arr); + VAILDSTR(buf.params); + stream >> arr; + VAILDSTR(buf.fakename); bool isStored; stream >> isStored; if (isStored) { int index; stream >> index; + if (index < 0 || index >= hashes.count()) + FAILRETURN; arr = hashes[index]; } else { stream >> arr; @@ -122,9 +166,11 @@ bool SettingManager::loadSettings(QString filename) { // 如果是打开文件就没这么多事情了 QByteArray arr; stream >> arr; - buf.process = QString::fromUtf8(arr); + VAILDSTR(buf.process); stream >> arr; - buf.params = QString::fromUtf8(arr); + VAILDSTR(buf.params); + stream >> arr; + VAILDSTR(buf.fakename); emit addHotKeyInfo(buf); } } @@ -142,17 +188,28 @@ bool SettingManager::loadSettings(QString filename) { stream >> buf.isPlugin; if (buf.isPlugin) { stream >> buf.serviceID; + if (buf.serviceID < 0) + FAILRETURN; QByteArray arr; stream >> arr; - buf.provider = QString::fromUtf8(arr); + VAILDSTR(buf.iconpath); + buf.icon = Utilities::trimIconFromFile(buf.iconpath); + if (buf.icon.isNull()) + buf.iconpath.clear(); stream >> arr; - buf.params = QString::fromUtf8(arr); + VAILDSTR(buf.provider); + stream >> arr; + VAILDSTR(buf.params); + stream >> arr; + VAILDSTR(buf.fakename); bool isStored; stream >> isStored; if (isStored) { int index; stream >> index; + if (index < 0 || index >= hashes.count()) + FAILRETURN; arr = hashes[index]; } else { stream >> arr; @@ -175,9 +232,16 @@ bool SettingManager::loadSettings(QString filename) { } else { // 如果是打开文件就没这么多事情了 QByteArray arr; stream >> arr; - buf.process = QString::fromUtf8(arr); + VAILDSTR(buf.process); stream >> arr; - buf.params = QString::fromUtf8(arr); + VAILDSTR(buf.params); + stream >> arr; + VAILDSTR(buf.fakename); + stream >> arr; + VAILDSTR(buf.iconpath); + buf.icon = Utilities::trimIconFromFile(buf.iconpath); + if (buf.icon.isNull()) + buf.iconpath.clear(); emit setToolWinInfo(i, buf); } } @@ -188,7 +252,7 @@ bool SettingManager::loadSettings(QString filename) { stream >> len; // 先读一下有几个 for (auto i = 0; i < len; i++) { ToolStructInfo buf; - + buf.enabled = true; // 修复信息 // 对于 WinTool 来说, enabled 就没用了 // 只存储相关基础信息就可以了 stream >> buf.isPlugin; @@ -196,15 +260,22 @@ bool SettingManager::loadSettings(QString filename) { stream >> buf.serviceID; QByteArray arr; stream >> arr; - buf.provider = QString::fromUtf8(arr); + VAILDSTR(buf.iconpath); + buf.icon = Utilities::trimIconFromFile(buf.iconpath); stream >> arr; - buf.params = QString::fromUtf8(arr); + VAILDSTR(buf.provider); + stream >> arr; + VAILDSTR(buf.params); + stream >> arr; + VAILDSTR(buf.fakename); bool isStored; stream >> isStored; if (isStored) { int index; stream >> index; + if (index < 0 || index >= hashes.count()) + return false; arr = hashes[index]; } else { stream >> arr; @@ -228,9 +299,16 @@ bool SettingManager::loadSettings(QString filename) { } else { QByteArray arr; stream >> arr; - buf.process = QString::fromUtf8(arr); + VAILDSTR(buf.process); stream >> arr; - buf.params = QString::fromUtf8(arr); + VAILDSTR(buf.params); + stream >> arr; + VAILDSTR(buf.fakename); + stream >> arr; + VAILDSTR(buf.iconpath); + buf.icon = Utilities::trimIconFromFile(buf.iconpath); + if (buf.icon.isNull()) + buf.iconpath.clear(); emit addWinToolInfo(buf); } } @@ -260,7 +338,7 @@ bool SettingManager::exportSettings(QString filename) { static char header[] = {'W', 'I', 'N', 'G', 'T', 'O', 'O', 'L', CONFIGVER}; stream.writeRawData(header, sizeof(header)); // General - stream << m_toolwin << m_wintool << m_toolGridSize << m_toolBox + stream << m_toolwin << m_wintool << m_toolGridSize << m_runWin << m_toolBox << m_toolwinMod << m_toolMouse; // 有些配置直接保存到 CenterWindow 里面了,为了减少内存占用 emit sigSaveConfig(stream); @@ -277,7 +355,7 @@ void SettingManager::resetSettings() { m_wintool = true; m_toolGridSize = TOOLGRIDSIZE; - m_toolBox = QKeySequence(Qt::KeyboardModifier::ShiftModifier | Qt::Key_Space); + m_toolBox = QKeySequence(Qt::KeyboardModifier::MetaModifier | Qt::Key_Space); m_runWin = QKeySequence(Qt::KeyboardModifier::MetaModifier | Qt::Key_R); m_toolwinMod = Qt::KeyboardModifier::ControlModifier; m_toolMouse = Qt::MouseButton::MidButton; @@ -292,6 +370,26 @@ void SettingManager::resetSettings() { emit sigRunWinHotkeyChanged(m_runWin); } +QString SettingManager::backupOrignSetting() { + auto config = + QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + + "/wingTool_" + QUuid::createUuid().toString() + ".bak"; + QFile::copy(configfile, config); + return config; +} + +void SettingManager::saveFileDialogCurrent(QString path) { + QSettings settings(QApplication::organizationName(), + QApplication::applicationName()); + settings.setValue("curpath", path); +} + +QString SettingManager::loadFileDialogCurrent() { + QSettings settings(QApplication::organizationName(), + QApplication::applicationName()); + return settings.value("curpath").toString(); +} + void SettingManager::setModified() { ismod = true; } int SettingManager::toolGridSize() const { return m_toolGridSize; } diff --git a/class/settingmanager.h b/class/settingmanager.h index d2ab76c..303b0a5 100644 --- a/class/settingmanager.h +++ b/class/settingmanager.h @@ -21,6 +21,10 @@ public: bool saveSettings(); bool exportSettings(QString filename); void resetSettings(); + QString backupOrignSetting(); + + void saveFileDialogCurrent(QString path); + QString loadFileDialogCurrent(); public: void setModified(); diff --git a/dialog/centerwindow.cpp b/dialog/centerwindow.cpp index 91d8f56..f2c4f36 100644 --- a/dialog/centerwindow.cpp +++ b/dialog/centerwindow.cpp @@ -176,6 +176,7 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { {tr("Enable"), tr("HotKey"), tr("Exec"), tr("Params")}); tbhotkeys->setCornerButtonEnabled(true); tbhotkeys->horizontalHeader()->setStretchLastSection(true); + tbhotkeys->setFocusPolicy(Qt::StrongFocus); auto *menu = new DMenu(tbhotkeys); QAction *a; @@ -258,6 +259,7 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { tbtoolinfo->setText(tr("[Plugin]")); tbtoolinfo->append(QObject::tr("PluginName:") + plg->pluginName()); + tbtoolinfo->append(tr("FakeName:") + info.fakename); tbtoolinfo->append(tr("Service:") + plgsys->pluginServicetrNames( plg)[info.serviceID]); tbtoolinfo->append(tr("Params:") + info.params); @@ -279,6 +281,7 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { } else { if (info.enabled) { tbtoolinfo->setText(tr("[File]")); + tbtoolinfo->append(tr("FakeName:") + info.fakename); tbtoolinfo->append(tr("FileName:") + info.process); tbtoolinfo->append(tr("Params:") + info.params); } else { @@ -334,8 +337,8 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { lbls[sellbl]->setIcon(icon2); lbls[res]->setIcon(icon1); - manager->setToolIcon(sellbl, icon2); - manager->setToolIcon(res, icon1); + manager->setToolIcon(sellbl, icon2, toolinfos[sellbl].fakename); + manager->setToolIcon(res, icon1, toolinfos[res].fakename); lbls[res]->setChecked(true); } }); @@ -345,10 +348,10 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { b->setIconSize(QSize(20, 20)); b->setToolTip(tr("Delete")); connect(b, &DButtonBoxButton::clicked, this, [=] { - toolinfos[sellbl].enabled = false; + toolinfos[sellbl] = ToolStructInfo(); auto ilbl = lbls[sellbl]; ilbl->setIcon(QIcon()); - manager->setToolIcon(sellbl, QIcon()); + manager->setToolIcon(sellbl, QIcon(), ""); emit ilbl->toggled(true); }); blist.append(b); @@ -589,13 +592,14 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { l = new DLabel(this); l->setPixmap(QPixmap(":/sponsor.png")); - l->setScaledContents(true); - slayout->addWidget(l); + slayout->addWidget(l, 0, Qt::AlignCenter); tabs->addTab(w, tr("Sponsor")); } void CenterWindow::show(CenterWindow::TabPage index) { - tabs->setCurrentIndex(int(index)); + auto i = int(index); + if (i >= 0) + tabs->setCurrentIndex(i); DMainWindow::show(); } @@ -612,22 +616,34 @@ bool CenterWindow::runTask(ToolStructInfo record) { return true; } - QMimeDatabase db; - QFileInfo info(record.process); auto absp = info.absoluteFilePath(); - - auto mt = db.mimeTypeForFile(absp); - auto n = mt.name(); - if (n == "application/x-executable") { + if (info.isExecutable()) { if (!pstart.startDetached(absp, Utilities::parseCmdParams(record.params))) { DMessageBox::critical(this, tr("runErr"), pstart.errorString()); return false; } } else { - if (!QDesktopServices::openUrl(QUrl("file://" + absp))) { - DMessageBox::critical(this, tr("err"), tr("openErr")); - return false; + if (record.params.count()) { + auto params = Utilities::parseCmdParams(record.params); + params.prepend("-c"); + QString inter; + if (QFile::exists("/usr/bin/bash")) { + inter = "/usr/bin/bash"; + } else { + if (QFile::exists("/bin/sh")) { + inter = "/bin/sh"; + } + } + if (inter.isEmpty() || !pstart.startDetached(inter, params)) { + DMessageBox::critical(this, tr("runErr"), pstart.errorString()); + return false; + } + } else { + if (!QDesktopServices::openUrl(QUrl("file://" + absp))) { + DMessageBox::critical(this, tr("err"), tr("openErr")); + return false; + } } } return true; @@ -645,8 +661,10 @@ void CenterWindow::editTask(int index) { wt->setCheckState(res.enabled ? Qt::Checked : Qt::Unchecked); tbhotkeys->setItem(index, 0, wt); tbhotkeys->setItem(index, 1, new QTableWidgetItem(res.seq.toString())); - wt = new QTableWidgetItem(QString(res.process)); - wt->setToolTip(res.process); + auto plg = plgsys->plugin(res.pluginIndex); + auto &srvs = plgsys->pluginServicetrNames(plg); + wt = new QTableWidgetItem(Utilities::getProgramName(srvs, res)); + wt->setToolTip(Utilities::getToolTipContent(srvs, res)); tbhotkeys->setItem(index, 2, wt); wt = new QTableWidgetItem(res.params); wt->setToolTip(res.params); @@ -714,8 +732,10 @@ void CenterWindow::on_addHotkey() { wt->setCheckState(res.enabled ? Qt::Checked : Qt::Unchecked); tbhotkeys->setItem(index, 0, wt); tbhotkeys->setItem(index, 1, new QTableWidgetItem(res.seq.toString())); - wt = new QTableWidgetItem(res.process); - wt->setToolTip(res.process); + auto plg = plgsys->plugin(res.pluginIndex); + auto &srvs = plgsys->pluginServicetrNames(plg); + wt = new QTableWidgetItem(Utilities::getProgramName(srvs, res)); + wt->setToolTip(Utilities::getToolTipContent(srvs, res)); tbhotkeys->setItem(index, 2, wt); wt = new QTableWidgetItem(res.params); wt->setToolTip(res.params); @@ -747,8 +767,9 @@ void CenterWindow::on_editWinTool() { auto item = lstoolwin->item(index); auto plg = plgsys->plugin(res.pluginIndex); item->setIcon(Utilities::trimIconFromInfo(plg, res)); - // item->setText(Utilities::getProgramName(plg, res)); - item->setToolTip(res.process); + auto &srvs = plgsys->pluginServicetrNames(plg); + item->setText(Utilities::getProgramName(srvs, res)); + item->setToolTip(Utilities::getToolTipContent(srvs, res)); sm->setModified(); } } @@ -792,12 +813,12 @@ void CenterWindow::on_addWinTool() { if (index < 0) { wintoolinfos.append(res); auto plg = plgsys->plugin(res.pluginIndex); - auto &srvs = plgsys->pluginServiceNames(plg); + auto &srvs = plgsys->pluginServicetrNames(plg); auto item = new QListWidgetItem(Utilities::trimIconFromInfo(plg, res), Utilities::getProgramName(srvs, res)); item->setToolTip(Utilities::getToolTipContent(srvs, res)); lstoolwin->addItem(item); - wintool.addItem(res, srvs[res.serviceID]); + wintool.addItem(res, res.isPlugin ? srvs[res.serviceID] : QString()); } else { wintoolinfos.insert(index + 1, res); auto plg = plgsys->plugin(res.pluginIndex); @@ -806,7 +827,8 @@ void CenterWindow::on_addWinTool() { Utilities::getProgramName(srvs, res)); item->setToolTip(Utilities::getToolTipContent(srvs, res)); lstoolwin->insertItem(index + 1, item); - wintool.addItem(res, srvs[res.serviceID], index + 1); + wintool.addItem(res, res.isPlugin ? srvs[res.serviceID] : QString(), + index + 1); } sm->setModified(); } @@ -908,7 +930,14 @@ void CenterWindow::on_importSettings() { } } -void CenterWindow::on_resetSettings() { sm->resetSettings(); } +void CenterWindow::on_resetSettings() { + if (DMessageBox::question(this, tr("Warn"), tr("ResetSettings")) == + DMessageBox::No) + return; + + sm->resetSettings(); + sm->saveSettings(); +} void CenterWindow::on_runplg() { RunDialog d; @@ -925,8 +954,10 @@ void CenterWindow::addHotKeyInfo(ToolStructInfo &info) { wt->setCheckState(info.enabled ? Qt::Checked : Qt::Unchecked); tbhotkeys->setItem(index, 0, wt); tbhotkeys->setItem(index, 1, new QTableWidgetItem(info.seq.toString())); - wt = new QTableWidgetItem(info.process); - wt->setToolTip(info.process); + auto plg = plgsys->plugin(info.pluginIndex); + auto &srvs = plgsys->pluginServicetrNames(plg); + wt = new QTableWidgetItem(Utilities::getProgramName(srvs, info)); + wt->setToolTip(Utilities::getToolTipContent(srvs, info)); tbhotkeys->setItem(index, 2, wt); wt = new QTableWidgetItem(info.params); wt->setToolTip(info.params); @@ -947,7 +978,7 @@ void CenterWindow::setToolWinInfo(int index, ToolStructInfo &info) { Utilities::trimIconFromInfo(plgsys->plugin(info.pluginIndex), info); auto ilbl = lbls[index]; ilbl->setIcon(icon); - manager->setToolIcon(index, icon); + manager->setToolIcon(index, icon, info.fakename); } void CenterWindow::setToolFinished() { lbls[0]->setChecked(true); } @@ -955,12 +986,12 @@ void CenterWindow::setToolFinished() { lbls[0]->setChecked(true); } void CenterWindow::addWinToolInfo(ToolStructInfo &info) { wintoolinfos.append(info); auto plg = plgsys->plugin(info.pluginIndex); - auto &srvs = plgsys->pluginServiceNames(plg); + auto &srvs = plgsys->pluginServicetrNames(plg); auto item = new QListWidgetItem(Utilities::trimIconFromInfo(plg, info), Utilities::getProgramName(srvs, info)); item->setToolTip(Utilities::getToolTipContent(srvs, info)); lstoolwin->addItem(item); - wintool.addItem(info, srvs[info.serviceID]); + wintool.addItem(info, info.isPlugin ? srvs[info.serviceID] : QString()); } void CenterWindow::initGeneralSettings() { @@ -1001,6 +1032,7 @@ void CenterWindow::initGeneralSettings() { connect(hkwintool, &Hotkey::activated, this, [&] { Dtk::Widget::moveToCenter(&wintool); wintool.show(); + wintool.activateWindow(); wintool.raise(); }); @@ -1151,7 +1183,8 @@ void CenterWindow::getConfig(QDataStream &f) { for (auto &p : scinfos) { f << p.enabled << p.isPlugin << p.seq; if (p.isPlugin) { - f << p.serviceID << p.provider.toUtf8() << p.params.toUtf8(); + f << p.serviceID << p.provider.toUtf8() << p.params.toUtf8() + << p.fakename.toUtf8(); auto i = plgindices.indexOf(p.pluginIndex); if (i >= 0) { f << true << i; @@ -1159,8 +1192,8 @@ void CenterWindow::getConfig(QDataStream &f) { f << false << plgsys->pluginHash(p.pluginIndex); } } else { - f << p.process.toUtf8() - << p.params.toUtf8(); // 如果是打开文件就没这么多事情了 + f << p.process.toUtf8() << p.params.toUtf8() + << p.fakename.toUtf8(); // 如果是打开文件就没这么多事情了 } } @@ -1174,7 +1207,8 @@ void CenterWindow::getConfig(QDataStream &f) { if (p.enabled) { f << p.isPlugin; if (p.isPlugin) { - f << p.serviceID << p.provider.toUtf8() << p.params.toUtf8(); + f << p.serviceID << p.iconpath.toUtf8() << p.provider.toUtf8() + << p.params.toUtf8() << p.fakename.toUtf8(); auto i = plgindices.indexOf(p.pluginIndex); if (i >= 0) { f << true << i; @@ -1182,8 +1216,8 @@ void CenterWindow::getConfig(QDataStream &f) { f << false << plgsys->pluginHash(p.pluginIndex); } } else { - f << p.process.toUtf8() - << p.params.toUtf8(); // 如果是打开文件就没这么多事情了 + f << p.process.toUtf8() << p.params.toUtf8() << p.fakename.toUtf8() + << p.iconpath.toUtf8(); // 如果是打开文件就没这么多事情了 } } } @@ -1195,7 +1229,8 @@ void CenterWindow::getConfig(QDataStream &f) { // 只存储相关基础信息就可以了 f << p.isPlugin; if (p.isPlugin) { - f << p.serviceID << p.provider.toUtf8() << p.params.toUtf8(); + f << p.serviceID << p.iconpath.toUtf8() << p.provider.toUtf8() + << p.params.toUtf8() << p.fakename.toUtf8(); auto i = plgindices.indexOf(p.pluginIndex); if (i >= 0) { f << true << i; @@ -1203,8 +1238,8 @@ void CenterWindow::getConfig(QDataStream &f) { f << false << plgsys->pluginHash(p.pluginIndex); } } else { - f << p.process.toUtf8() - << p.params.toUtf8(); // 如果是打开文件就没这么多事情了 + f << p.process.toUtf8() << p.params.toUtf8() << p.fakename.toUtf8() + << p.iconpath.toUtf8(); // 如果是打开文件就没这么多事情了 } } @@ -1218,7 +1253,7 @@ void CenterWindow::resetConfig() { QIcon icon; auto ilbl = lbls[i]; ilbl->setIcon(icon); - manager->setToolIcon(i, icon); + manager->setToolIcon(i, icon, toolinfo.fakename); } lstoolwin->clear(); wintoolinfos.clear(); diff --git a/dialog/centerwindow.h b/dialog/centerwindow.h index 249cae8..ae045bb 100644 --- a/dialog/centerwindow.h +++ b/dialog/centerwindow.h @@ -26,6 +26,7 @@ class CenterWindow : public DMainWindow { Q_OBJECT public: enum class TabPage { + None = -1, General, Hotkeys, ToolBox, @@ -39,7 +40,7 @@ public: public: CenterWindow(DMainWindow *parent = nullptr); - void show(TabPage index); + void show(TabPage index = TabPage::None); private: bool runTask(ToolStructInfo record); diff --git a/dialog/rundialog.cpp.NXeHZl b/dialog/rundialog.cpp.NXeHZl deleted file mode 100644 index 3cdcdaf..0000000 --- a/dialog/rundialog.cpp.NXeHZl +++ /dev/null @@ -1,68 +0,0 @@ -#include "rundialog.h" -#include -#include -#include - -RunDialog::RunDialog(DDialog *parent) - : DDialog(parent), plgsys(PluginSystem::instance()) { - - auto screen = QGuiApplication::primaryScreen(); - screen-> - - setWindowTitle(tr("RunPlugin")); - addContent(new DLabel(tr("Plugin"), this)); - addSpacing(5); - ps = new PluginSelector(this); - connect(ps, &PluginSelector::finished, this, [=] { - auto plg = ps->getSelectedPlg(); - cbService->clear(); - Utilities::addPluginServiceNames(cbService, plg); - cbService->setVisible(true); - }); - addContent(ps); - addSpacing(10); - - addContent(new DLabel(tr("Service"), this)); - addSpacing(5); - - cbService = new DComboBox(this); - - Utilities::addPluginServiceNames(cbService, ps->getSelectedPlg()); - cbService->setCurrentIndex(0); - addContent(cbService); - - addSpacing(10); - - addContent(new DLabel(tr("Param"), this)); - addSpacing(5); - dledit = new DLineEdit(this); - addContent(dledit); - - addSpacing(20); - auto dbbox = new DDialogButtonBox( - DDialogButtonBox::Ok | DDialogButtonBox::Cancel, this); - connect(dbbox, &DDialogButtonBox::accepted, this, &RunDialog::on_accept); - connect(dbbox, &DDialogButtonBox::rejected, this, &RunDialog::on_reject); - auto key = QKeySequence(Qt::Key_Return); - auto s = new QShortcut(key, this); - connect(s, &QShortcut::activated, this, &RunDialog::on_accept); - addContent(dbbox); -} - -void RunDialog::on_accept() { - auto plg = ps->getSelectedPlg(); - QList params; - for (auto &item : Utilities::parseCmdParams(dledit->text())) { - params.append(item); - } - auto res = - plgsys->pluginCall(plg->provider(), cbService->currentIndex(), params); - done(res); -} - -void RunDialog::on_reject() { done(0); } - -void RunDialog::closeEvent(QCloseEvent *event) { - Q_UNUSED(event); - done(0); -} diff --git a/dialog/shortcuteditdialog.cpp b/dialog/shortcuteditdialog.cpp index 257053c..0fdfd8d 100644 --- a/dialog/shortcuteditdialog.cpp +++ b/dialog/shortcuteditdialog.cpp @@ -6,13 +6,15 @@ ShortCutEditDialog::ShortCutEditDialog(ToolStructInfo res, DMainWindow *parent) : DDialog(parent), manager(AppManager::instance()), - plgsys(PluginSystem::instance()) { + plgsys(PluginSystem::instance()), sm(SettingManager::instance()) { // 处于编辑状态直接堵塞所有相应(屏蔽鼠标追踪和热键触发以防干扰) manager->blockSignals(true); setWindowTitle(tr("HotkeyEdit")); + lastusedpath = sm->loadFileDialogCurrent(); + cb = new DCheckBox(tr("Enabled"), this); if (res.seq.isEmpty()) { cb->setChecked(true); @@ -55,9 +57,15 @@ ShortCutEditDialog::ShortCutEditDialog(ToolStructInfo res, DMainWindow *parent) addContent(lblp); addSpacing(5); fcedit = new DFileChooserEdit(this); + fcedit->setDirectoryUrl(QUrl(lastusedpath)); fcedit->initDialog(); fcedit->setText(res.process); fcedit->setVisible(!res.isPlugin); + connect(fcedit, &DFileChooserEdit::fileChoosed, this, + [=](const QString &fileName) { + lastusedpath = QFileInfo(fileName).absoluteDir().absolutePath(); + fcedit->setDirectoryUrl(QUrl(lastusedpath)); + }); addContent(fcedit); cbService = new DComboBox(this); @@ -75,7 +83,12 @@ ShortCutEditDialog::ShortCutEditDialog(ToolStructInfo res, DMainWindow *parent) dledit = new DLineEdit(this); dledit->setText(res.params); addContent(dledit); - + addSpacing(10); + addContent(new DLabel(tr("FakeName"), this)); + addSpacing(5); + dlfkname = new DLineEdit(this); + dlfkname->setText(res.fakename); + addContent(dlfkname); addSpacing(20); auto dbbox = new DDialogButtonBox( DDialogButtonBox::Ok | DDialogButtonBox::Cancel, this); @@ -110,7 +123,7 @@ void ShortCutEditDialog::on_accept() { res.provider = plgsys->pluginProvider(sel); res.pluginIndex = ps->getSelectedIndex(); } else { - res.process = fcedit->text(); + res.process = fcedit->text().trimmed(); if (res.process.isEmpty()) { DMessageManager::instance()->sendMessage(this, ProgramIcon, tr("NoProcessSet")); @@ -118,7 +131,8 @@ void ShortCutEditDialog::on_accept() { } } - res.params = dledit->text(); + res.fakename = dlfkname->text().trimmed(); + res.params = dledit->text().trimmed(); manager->blockSignals(false); // 恢复能力 done(1); @@ -131,6 +145,7 @@ void ShortCutEditDialog::on_reject() { void ShortCutEditDialog::closeEvent(QCloseEvent *event) { Q_UNUSED(event); + sm->saveFileDialogCurrent(lastusedpath); manager->blockSignals(false); // 恢复能力 done(0); } diff --git a/dialog/shortcuteditdialog.h b/dialog/shortcuteditdialog.h index 9d36159..43a4834 100644 --- a/dialog/shortcuteditdialog.h +++ b/dialog/shortcuteditdialog.h @@ -4,6 +4,7 @@ #include "utilities.h" #include "class/appmanager.h" +#include "class/settingmanager.h" #include "control/pluginselector.h" #include "plugin/pluginsystem.h" #include @@ -34,6 +35,8 @@ protected: private: AppManager *manager; PluginSystem *plgsys; + SettingManager *sm; + ToolStructInfo res; PluginSelector *ps; @@ -41,9 +44,12 @@ private: DFileChooserEdit *fcedit; DLineEdit *dledit; DKeySequenceEdit *ksedit; + DLineEdit *dlfkname; DLabel *lblp; DComboBox *cbService; + + QString lastusedpath; }; #endif // SHORTCUTEDITDIALOG_H diff --git a/dialog/toolboxwindow.cpp b/dialog/toolboxwindow.cpp index 20a8a21..9b6bb92 100644 --- a/dialog/toolboxwindow.cpp +++ b/dialog/toolboxwindow.cpp @@ -7,6 +7,8 @@ #include #include +DWIDGET_USE_NAMESPACE + ToolBoxWindow::ToolBoxWindow(DMainWindow *parent) : DDialog(parent) { setWindowTitle(tr("PleaseChoose")); setWindowFlag(Qt::Tool); @@ -22,8 +24,9 @@ ToolBoxWindow::ToolBoxWindow(DMainWindow *parent) : DDialog(parent) { : pe.base().color().lighter(125)); lstool->setPalette(pe); lstool->setAlternatingRowColors(true); - itemheight = lstool->fontMetrics().lineSpacing() * 4; + itemheight = lstool->fontMetrics().lineSpacing() * 5; lstool->setMinimumHeight(itemheight * 5); + lstool->setFocusPolicy(Qt::StrongFocus); addContent(lstool); connect(DGuiApplicationHelper::instance(), @@ -45,18 +48,19 @@ void ToolBoxWindow::addItem(ToolStructInfo &info, QString service, int index) { auto plg = plgsys->plugin(info.pluginIndex); auto icon = Utilities::trimIconFromInfo(plg, info); QString content = - tr("Process:") + + tr("FakeName:") + info.fakename + '\n' + tr("Process:") + (info.isPlugin ? info.process : QFileInfo(info.process).fileName()) + '\n'; if (info.isPlugin) - content += (tr("Service:") + service); + content += (tr("Service:") + service + '\n'); if (info.params.length()) - content += ('\n' + tr("Params:") + info.params); + content += (tr("Params:") + info.params); auto pitem = new QListWidgetItem(icon, content); pitem->setTextAlignment(Qt::AlignCenter); pitem->setSizeHint(QSize(0, itemheight)); + pitem->setToolTip(content); if (index < 0) lstool->addItem(pitem); diff --git a/dialog/tooleditdialog.cpp b/dialog/tooleditdialog.cpp index c498d62..083713b 100644 --- a/dialog/tooleditdialog.cpp +++ b/dialog/tooleditdialog.cpp @@ -1,17 +1,21 @@ #include "tooleditdialog.h" #include #include +#include #include ToolEditDialog::ToolEditDialog(ToolStructInfo res, DMainWindow *parent) : DDialog(parent), manager(AppManager::instance()), - plgsys(PluginSystem::instance()) { + plgsys(PluginSystem::instance()), sm(SettingManager::instance()) { // 处于编辑状态直接堵塞所有相应(屏蔽鼠标追踪和热键触发以防干扰) manager->blockSignals(true); + this->res = res; setWindowTitle(tr("ToolWinEdit")); + lastusedpath = sm->loadFileDialogCurrent(); + res.enabled = true; addContent(new DLabel(tr("Plugin"), this)); addSpacing(5); @@ -29,18 +33,78 @@ ToolEditDialog::ToolEditDialog(ToolStructInfo res, DMainWindow *parent) fcedit->setVisible(true); cbService->setVisible(false); } + this->refreshIcon(); }); ps->setSelectedIndex(res.pluginIndex); addContent(ps); addSpacing(10); + iconpre = new DIconButton(this); // 提前创建好 + + addContent(new DLabel(tr("Icon"), this)); + addSpacing(5); + fcicon = new DFileChooserEdit(this); + fcicon->initDialog(); + fcicon->setNameFilters({tr("Image Format (*.png *.svg *.jpg *.jpeg)")}); + fcicon->setDirectoryUrl(QUrl(lastusedpath)); + connect(fcicon, &DFileChooserEdit::textChanged, this, [=] { + auto name = fcicon->text().trimmed(); + this->res.iconpath = name; + if (name.isEmpty()) { + sicon = QIcon(); + this->refreshIcon(); + return; + } + if (QIcon::hasThemeIcon(name)) { + sicon = QIcon::fromTheme(name); + } else { + if (QFile::exists(name)) { + QPixmap img; + if (img.load(name)) { + auto icon = QIcon((img.width() > 64 || img.height() > 64) + ? img.scaled(64, 64, Qt::KeepAspectRatio) + : img); + sicon = icon; + } else { + sicon = QIcon(); + DMessageManager::instance()->sendMessage(this, ProgramIcon, + tr("InvalidIcon")); + } + } + } + this->refreshIcon(); + }); + connect(fcicon, &DFileChooserEdit::fileChoosed, this, + [=](const QString &fileName) { + lastusedpath = QFileInfo(fileName).absoluteDir().absolutePath(); + fcicon->setDirectoryUrl(QUrl(lastusedpath)); + fcedit->setDirectoryUrl(QUrl(lastusedpath)); + emit fcicon->editingFinished(); + }); + fcicon->setText(res.iconpath); + addContent(fcicon); + addSpacing(10); + lblp = new DLabel(res.isPlugin ? tr("Service") : tr("FilePath"), this); addContent(lblp); addSpacing(5); fcedit = new DFileChooserEdit(this); fcedit->initDialog(); - fcedit->setText(res.process); fcedit->setVisible(!res.isPlugin); + fcedit->setDirectoryUrl(QUrl(lastusedpath)); + connect(fcedit, &DFileChooserEdit::textChanged, this, [=] { + this->res.process = fcedit->text(); + ficon = Utilities::trimIconFromFile(this->res.process); + this->refreshIcon(); + }); + connect(fcedit, &DFileChooserEdit::fileChoosed, this, + [=](const QString &fileName) { + lastusedpath = QFileInfo(fileName).absoluteDir().absolutePath(); + fcicon->setDirectoryUrl(QUrl(lastusedpath)); + fcedit->setDirectoryUrl(QUrl(lastusedpath)); + emit fcedit->editingFinished(); + }); + fcedit->setText(res.process); addContent(fcedit); cbService = new DComboBox(this); @@ -58,8 +122,21 @@ ToolEditDialog::ToolEditDialog(ToolStructInfo res, DMainWindow *parent) dledit = new DLineEdit(this); dledit->setText(res.params); addContent(dledit); - + addSpacing(10); + addContent(new DLabel(tr("FakeName"), this)); + addSpacing(5); + dlfkname = new DLineEdit(this); + dlfkname->setText(res.fakename); + addContent(dlfkname); addSpacing(20); + + auto w = new QWidget(this); + auto hlayout = new QHBoxLayout(w); + iconpre->setToolTip(tr("IconPreview")); + iconpre->setIcon(res.icon); + iconpre->setIconSize(QSize(25, 25)); + connect(iconpre, &DIconButton::clicked, this, &ToolEditDialog::refreshIcon); + hlayout->addWidget(iconpre, 0, Qt::AlignLeft); auto dbbox = new DDialogButtonBox( DDialogButtonBox::Ok | DDialogButtonBox::Cancel, this); connect(dbbox, &DDialogButtonBox::accepted, this, &ToolEditDialog::on_accept); @@ -67,12 +144,22 @@ ToolEditDialog::ToolEditDialog(ToolStructInfo res, DMainWindow *parent) auto key = QKeySequence(Qt::Key_Return); auto s = new QShortcut(key, this); connect(s, &QShortcut::activated, this, &ToolEditDialog::on_accept); - addContent(dbbox); + hlayout->addWidget(dbbox, 0, Qt::AlignRight); + addContent(w); + + refreshIcon(); } ToolStructInfo ToolEditDialog::getResult() { return res; } void ToolEditDialog::on_accept() { + res.icon = sicon.isNull() ? ficon : sicon; + if (res.icon.isNull()) { + DMessageManager::instance()->sendMessage(this, ProgramIcon, + tr("NoVaildIconSet")); + return; + } + res.isPlugin = ps->getSelectedIndex() >= 0; res.enabled = true; // 指示该信息有效,否则会被忽略 @@ -83,15 +170,16 @@ void ToolEditDialog::on_accept() { res.provider = plgsys->pluginProvider(sel); res.pluginIndex = ps->getSelectedIndex(); } else { - res.process = fcedit->text(); - if (res.process.isEmpty()) { + res.process = fcedit->text().trimmed(); + if (res.process.isEmpty() || !QFile::exists(res.process)) { DMessageManager::instance()->sendMessage(this, ProgramIcon, - tr("NoProcessSet")); + tr("NoVaildProcessSet")); return; } } - res.params = dledit->text(); + res.fakename = dlfkname->text().trimmed(); + res.params = dledit->text().trimmed(); manager->blockSignals(false); // 恢复能力 done(1); @@ -102,8 +190,19 @@ void ToolEditDialog::on_reject() { done(0); } +void ToolEditDialog::refreshIcon() { + if (sicon.isNull()) { + if (!ficon.isNull()) { + iconpre->setIcon(ficon); + } + } else { + iconpre->setIcon(sicon); + } +} + void ToolEditDialog::closeEvent(QCloseEvent *event) { Q_UNUSED(event); + sm->saveFileDialogCurrent(lastusedpath); manager->blockSignals(false); // 恢复能力 done(0); } diff --git a/dialog/tooleditdialog.h b/dialog/tooleditdialog.h index 83384d5..4fe5b51 100644 --- a/dialog/tooleditdialog.h +++ b/dialog/tooleditdialog.h @@ -4,11 +4,13 @@ #include "utilities.h" #include "class/appmanager.h" +#include "class/settingmanager.h" #include "control/pluginselector.h" #include #include #include #include +#include #include #include #include @@ -27,20 +29,28 @@ private: void on_accept(); void on_reject(); + void refreshIcon(); + protected: void closeEvent(QCloseEvent *event) override; private: AppManager *manager; PluginSystem *plgsys; + SettingManager *sm; ToolStructInfo res; PluginSelector *ps; DFileChooserEdit *fcedit; - DLineEdit *dledit; + DFileChooserEdit *fcicon; + DLineEdit *dledit, *dlfkname; DLabel *lblp; DComboBox *cbService; + DIconButton *iconpre; + + QString lastusedpath; + QIcon ficon, sicon; }; #endif // TOOLWINEDITDIALOG_H diff --git a/dialog/toolwindow.cpp b/dialog/toolwindow.cpp index 4b045d0..2d251fc 100644 --- a/dialog/toolwindow.cpp +++ b/dialog/toolwindow.cpp @@ -1,7 +1,9 @@ #include "toolwindow.h" #include "class/settingmanager.h" #include "utilities.h" +#include #include +#include ToolWindow::ToolWindow(DDialog *parent) : DDialog(parent) { @@ -22,12 +24,16 @@ ToolWindow::ToolWindow(DDialog *parent) : DDialog(parent) { auto lbl = new DIconButton(this); lbl->setFixedSize(gridsize - 2, gridsize - 2); lbl->setIconSize(QSize(gridsize / 2, gridsize / 2)); + lbl->setEnabled(false); auto in = std::div(i, 3); mlayout->addWidget(lbl, in.quot, in.rem, Qt::AlignCenter); lbls[i] = lbl; + connect(lbl, &DIconButton::pressed, this, + [=] { QToolTip::showText(QCursor::pos(), lbl->toolTip()); }); } lbls[4]->setIcon(ICONRES("close")); + lbls[4]->setEnabled(true); } void ToolWindow::loadSettings() { @@ -44,39 +50,41 @@ void ToolWindow::loadSettings() { }); } -void ToolWindow::setIcons(QVector icons) { - for (int i = 0; i < icons.count(); i++) { - if (i < 4) { - lbls[i]->setIcon(icons[i]); - } else { - lbls[i + 1]->setIcon(icons[i]); - } - } -} - -void ToolWindow::setIcon(int index, QIcon icon) { +void ToolWindow::setIcon(int index, QIcon icon, QString tip) { // index 取值 0-8 ,但是索引 4 被保留不做处理,是正中间的按钮 if (index < 0 || index >= 8) return; - lbls[index]->setIcon(icon); + + auto lbl = lbls[index]; + lbl->setIcon(icon); + lbl->setEnabled(!icon.isNull()); + lbl->setToolTip(tip); } void ToolWindow::popup(QPoint pos) { this->move(pos.x() - gridtotal / 2, pos.y() - gridtotal / 2); show(); + raise(); } void ToolWindow::sendMousePosUpdated() { + bool found = false; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { - auto res = - mlayout->cellRect(x, y).contains(mapFromGlobal(QCursor::pos())); + auto pos = QCursor::pos(); + auto res = mlayout->cellRect(x, y).contains(mapFromGlobal(pos)); + auto lbl = lbls[x * 3 + y]; if (res) { m_sel = QPoint(x, y); + lbl->pressed(); + found = true; } - lbls[x * 3 + y]->setDown(res); + lbl->setDown(res); } } + if (!found) { + m_sel = QPoint(1, 1); + } } void ToolWindow::finished() { diff --git a/dialog/toolwindow.h b/dialog/toolwindow.h index 5042495..53329fb 100644 --- a/dialog/toolwindow.h +++ b/dialog/toolwindow.h @@ -15,9 +15,7 @@ public: public slots: void loadSettings(); - - void setIcons(QVector icons); - void setIcon(int index, QIcon icon); + void setIcon(int index, QIcon icon, QString tip); void popup(QPoint pos); diff --git a/images/README.md b/images/README.md index 174f3c0..21f141e 100644 --- a/images/README.md +++ b/images/README.md @@ -1,8 +1,8 @@ ## WingTool -  `WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪、选词等相关借口。通过开发强大的对应的插件,就可以大大提高生产力。 +  `WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪等基本接口。通过开发强大的对应的插件,就可以大大提高生产力。 -  该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Ctrl`键可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。 +  该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Super`键(在`Windows`系统中称之为`Win`键)可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。 ### 协议 diff --git a/lang/zh.qm b/lang/zh.qm index 5c18fe9..f0b61be 100644 Binary files a/lang/zh.qm and b/lang/zh.qm differ diff --git a/lang/zh.ts b/lang/zh.ts index daf4878..ee3f4ab 100644 --- a/lang/zh.ts +++ b/lang/zh.ts @@ -127,33 +127,33 @@ - - + + Add 添加 - - + + Remove 删除 - - - + + + Edit 编辑 - - + + Clear 清空 @@ -195,156 +195,173 @@ + + FakeName: + 别名: + + + Service: 服务: - - + + Params: 参数: - - + + NoTool 暂无工具相关信息…… - + [File] 【文件】 - + FileName: 文件名: - + Swap 交换 - + Delete 删除 - - + + Up 上移 - - + + Down 下移 - + TopMost 置顶 - + DownMost 置底 - + ToolBox 工具箱 - - + + No selected plugin. 没有选择插件,故无法显示插件信息。 - + Setting 设置 - + Name: 名称: - + RegisteredHotkey: 注册的热键: - + Plugins 插件 - + About 关于 - + ThanksForSponsor 感谢大家的赞助和支持! - + Sponsor 赞助 - + + runErr 执行失败 - + err 错误 - + openErr 打开失败! - - + + ClearSuccess 数据清空完毕 - + HotkeyRegisterFail 注册热键失败! - + PleaseSelectOne 请选择一个项目 - - + + Config (*.wtcfg) 羽云工具箱配置文件 (*.wtcfg) - + ExportSuccess 导出成功! - + ImportSuccess 倒入成功! + + + Warn + 警告 + + + + ResetSettings + 你将要进行重置操作,原有的将不会保留,你确认吗? + PluginSelDialog @@ -387,63 +404,84 @@ PluginSystem - + + PluginLoadingBegin : %1 + 开始加载插件:%1 + + + ErrLoadPluginSign 由于插件签名不正确,插件加载失败! - + ErrLoadPluginSDKVersion 由于插件 SDK 版本不匹配,插件加载失败! - + ErrLoadPluginNoName 由于插件没有名称,插件加载失败! - + ErrLoadPluginNoHandler 由于插件没有服务句柄,插件加载失败! - - + + ErrLoadPluginProvider 由于插件没有提供者,插件加载失败! + + + [InvaildPlgSrvArg] + 【无效的插件服务,参数过多】 + ErLoadPluginService 由于插件没有服务,插件加载失败! - + ErrLoadInitPlugin 由于插件初始化失败,插件加载失败! - + PluginInitRegister 插件注册开始 - - ErrLoadPluginLoc - 插件加载失败错误位置: + + InvaildPlgMenu in loading %1 + 加载 %1 插件中含有非法注册托盘菜单组件 - + + PluginLoaded : %1 %2 + 插件已加载完毕:%1 %2 + + + + PluginLoadingEx + 加载插件出现异常 + + + + [remoteCallVaildErr] 【插件远程调用失败】 - + [remoteCallArgErr] 【插件远程调用参数错误】 - + [remoteCallEx] 【插件远程调用异常】 @@ -469,41 +507,41 @@ 插件名: - - + + Catagory: 分类: - - + + Version: 版本: - - + + Author: 作者: - - + + Comment: 说明: - - + + Provider: 提供者: - + Services: 服务: @@ -514,54 +552,58 @@ 版本 - - - + + + WingTool 羽云工具箱 - + + A powerful plugin toolbox for Deepin. + 一个用于 Deepin 上强大的插件工具箱 + + + + ErrorLoadingSettings + 加载配置失败,将重置配置尝试启动程序! + + + ShowMain 显示主窗体 - + + Err + 出错啦 + + + + ErrResetSettings + 加载的配置文件错误,可能是配置文件损坏或者老版本不支持,现已经存放到桌面上。 + + + About 关于 - + Sponsor 赞助 - - + + Exit 退出 - + ConfirmExit 你确认继续关闭该程序吗? - - - Process:%1 -Service:%2 -Params:%3 - 进程:%1 -服务:%2 -参数:%3 - - - - Process:%1 -Params:%2 - 进程:%1 -参数:%2 - Explor @@ -592,6 +634,26 @@ Params:%2 Creative 创造力 + + + FakeName:%1 +Process:%2 +Service:%3 +Params:%4 + 别名:%1 +进程:%2 +服务:%3 +参数:%4 + + + + FakeName:%1 +Process:%2 +Params:%3 + 别名:%1 +进程:%2 +参数:%3 + RunDialog @@ -624,44 +686,49 @@ Params:%2 编辑热键 - + Enabled 启用 - + ShortCut 快捷键 - + Plugin 插件 - - + + Service 服务 - - + + FilePath 文件路径 - + Param 参数 - + + FakeName + 别名 + + + NoHotkeySet 没有设置热键 - + NoProcessSet 没有设置进程 @@ -678,10 +745,15 @@ Params:%2 Process: 进程: + + + FakeName: + 别名: + Service: - 服务:服务: + 服务: @@ -692,36 +764,66 @@ Params:%2 ToolEditDialog - + ToolWinEdit 工具设置 - + Plugin 插件 - - + + Service 服务 - - + + FilePath 文件路径 - + + Icon + 图标 + + + + Image Format (*.png *.svg *.jpg *.jpeg) + 图像 (*.png *.svg *.jpg *.jpeg) + + + + InvalidIcon + 无效图标! + + + Param 参数 - - NoProcessSet - 没有设置进程 + + FakeName + 别名 + + + + IconPreview + 图标预览 + + + + NoVaildIconSet + 没有有效的图标设置! + + + + NoVaildProcessSet + 没有有效的进程设置! diff --git a/main.cpp b/main.cpp index 20c8d7b..6dde08e 100644 --- a/main.cpp +++ b/main.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -22,6 +23,7 @@ int main(int argc, char *argv[]) { qputenv("XDG_CURRENT_DESKTOP", "Deepin"); QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setQuitOnLastWindowClosed(false); + qRegisterMetaType("MouseButton"); // 程序内强制添加 -platformtheme // deepin 参数喂给 Qt 让 Qt 正确使用 Deepin 主题修复各种奇怪样式问题 @@ -56,7 +58,8 @@ int main(int argc, char *argv[]) { QIcon picon = ProgramIcon; a.setProductIcon(picon); a.setProductName(QObject::tr("WingTool")); - a.setApplicationDescription("This is a dtk template application."); + a.setApplicationDescription( + QObject::tr("A powerful plugin toolbox for Deepin.")); a.loadTranslator(); a.setApplicationDisplayName("WingTool"); @@ -65,20 +68,36 @@ int main(int argc, char *argv[]) { return -1; } - // 单例传参 - auto instance = DGuiApplicationHelper::instance(); - QObject::connect(instance, &DGuiApplicationHelper::newProcessInstance, - [=](qint64 pid, const QStringList &arguments) { - Q_UNUSED(pid); - Q_UNUSED(arguments); - }); - // 保存程序的窗口主题设置 DApplicationSettings as; Q_UNUSED(as) CenterWindow w; + // 单例传参 + auto instance = DGuiApplicationHelper::instance(); + QObject::connect(instance, &DGuiApplicationHelper::newProcessInstance, + [&](qint64 pid, const QStringList &arguments) { + Q_UNUSED(pid); + Q_UNUSED(arguments); + w.show(); + w.activateWindow(); + w.raise(); + }); + + // 初始化托盘,前半部分 + QSystemTrayIcon systray; + QMenu sysmenu; + auto menu = &sysmenu; + auto ac = new QAction(QObject::tr("ShowMain"), menu); + QObject::connect(ac, &QAction::triggered, [&w] { + w.show(CenterWindow::TabPage::General); + w.activateWindow(); + w.raise(); + }); + sysmenu.addAction(ac); + sysmenu.addSeparator(); + /*== 以下在主函数初始化确保单例 ==*/ /* 之后不得使用构造函数的方式使用 */ @@ -87,7 +106,7 @@ int main(int argc, char *argv[]) { w.initAppManger(); // 初始化插件系统 - PluginSystem plgsys; + PluginSystem plgsys(menu); w.initPluginSys(); // 初始化软件配置 @@ -108,35 +127,48 @@ int main(int argc, char *argv[]) { QObject::connect(&sm, &SettingManager::sigReset, &w, &CenterWindow::resetConfig); - sm.loadSettings(); + // 载入配置,并进行检查,非法重置 + if (!sm.loadSettings()) { + dError(QObject::tr("ErrorLoadingSettings")); + auto path = sm.backupOrignSetting(); + sm.resetSettings(); + sm.saveSettings(); + DMessageBox::critical(nullptr, QObject::tr("Err"), + QObject::tr("ErrResetSettings") + '\n' + path); + } QObject::connect(&manager, &AppManager::checkToolShow, [&sm, &manager](Qt::MouseButton btn) { - auto mod = manager.getKeyModifier(); - return sm.toolwinEnabled() && mod == sm.toolwinMod() && + auto mods = manager.getKeyModifiers(); + return sm.toolwinEnabled() && mods == sm.toolwinMod() && sm.toolwinMouseBtn() == btn; }); /*===========================*/ - // 初始化托盘 - QSystemTrayIcon systray; - QMenu sysmenu; - auto menu = &sysmenu; - auto ac = new QAction(QObject::tr("ShowMain"), menu); - QObject::connect(ac, &QAction::triggered, - [&w] { w.show(CenterWindow::TabPage::General); }); - sysmenu.addAction(ac); - sysmenu.addSeparator(); + // 初始化托盘,后半部分 + if (plgsys.hasRegisteredMenu()) + sysmenu.addSeparator(); ac = new QAction(QObject::tr("About"), menu); - QObject::connect(ac, &QAction::triggered, - [&w] { w.show(CenterWindow::TabPage::AboutAuthor); }); + QObject::connect(ac, &QAction::triggered, [&w] { + w.show(CenterWindow::TabPage::AboutAuthor); + w.activateWindow(); + w.raise(); + }); sysmenu.addAction(ac); ac = new QAction(QObject::tr("Sponsor"), menu); - QObject::connect(ac, &QAction::triggered, - [&w] { w.show(CenterWindow::TabPage::Sponsor); }); + QObject::connect(ac, &QAction::triggered, [&w] { + w.show(CenterWindow::TabPage::Sponsor); + w.activateWindow(); + w.raise(); + }); sysmenu.addAction(ac); ac = new QAction(QObject::tr("Exit"), menu); + + sysmenu.addAction(ac); + systray.setContextMenu(menu); + systray.setToolTip(QObject::tr("WingTool")); + systray.setIcon(picon); QObject::connect(ac, &QAction::triggered, [&w, &sm] { if (DMessageBox::question(&w, QObject::tr("Exit"), QObject::tr("ConfirmExit")) == DMessageBox::Yes) { @@ -144,19 +176,15 @@ int main(int argc, char *argv[]) { QApplication::exit(0); } }); - sysmenu.addAction(ac); - systray.setContextMenu(menu); - systray.setToolTip(QObject::tr("WingTool")); - systray.setIcon(picon); - systray.show(); - QObject::connect(&systray, &QSystemTrayIcon::activated, [&w](QSystemTrayIcon::ActivationReason reason) { if (reason == QSystemTrayIcon::ActivationReason::Trigger) { - w.show(CenterWindow::TabPage::General); + w.show(); + w.activateWindow(); w.raise(); } }); + systray.show(); Dtk::Widget::moveToCenter(&w); diff --git a/plugin/iwingtoolplg.h b/plugin/iwingtoolplg.h index d46060d..5e40932 100644 --- a/plugin/iwingtoolplg.h +++ b/plugin/iwingtoolplg.h @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -121,6 +122,10 @@ public: // 指示是否作为工具,如果 false,则不在工具选择中显示 // 但这不意味着不在插件列表显示 virtual bool isTool() { return true; } + // 注册在程序右键托盘菜单,这个对于某些功能会十分方便 + // 但非必要不要弄,因为这样的插件多了,反而麻烦了,一个插件仅有一项 + // 类型仅支持 QMenu* 或者 QAction* 否则不载入 + virtual QObject *trayRegisteredMenu() { return nullptr; } signals: // 注册热键,如果被占用则返回 -1 表示失败(通常是重复), diff --git a/plugin/pluginsystem.cpp b/plugin/pluginsystem.cpp index 1a11b0d..a6f95f7 100644 --- a/plugin/pluginsystem.cpp +++ b/plugin/pluginsystem.cpp @@ -7,8 +7,8 @@ PluginSystem *PluginSystem::m_instance = nullptr; -PluginSystem::PluginSystem(QObject *parent) - : QObject(parent), manager(AppManager::instance()) { +PluginSystem::PluginSystem(QMenu *systray, QObject *parent) + : QObject(parent), manager(AppManager::instance()), traymenu(systray) { // init plugin dispathcer #define InitDispathcer(hookindex) \ @@ -135,8 +135,6 @@ void PluginSystem::UnloadPlugin() {} QList PluginSystem::plugins() { return m_plgs; } void PluginSystem::loadPlugin(QFileInfo fileinfo) { - LP lp(LP::begin); - if (fileinfo.exists()) { QPluginLoader loader(fileinfo.absoluteFilePath()); QList loadedplginfos; @@ -144,27 +142,24 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { try { auto p = qobject_cast(loader.instance()); + dInfo(tr("PluginLoadingBegin : %1").arg(p->pluginName())); if (p) { - lp = LP::signature; if (p->signature() != WINGSUMMER) { dError(tr("ErrLoadPluginSign")); loader.unload(); return; } - lp = LP::sdkVersion; if (p->sdkVersion() != SDKVERSION) { dError(tr("ErrLoadPluginSDKVersion")); loader.unload(); return; } - lp = LP::pluginName; if (!p->pluginName().trimmed().length()) { dError(tr("ErrLoadPluginNoName")); loader.unload(); return; } - lp = LP::handler; auto handler = p->serviceHandler(); if (handler.isNull()) { dError(tr("ErrLoadPluginNoHandler")); @@ -172,7 +167,6 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { return; } - lp = LP::provider; auto meta = p->serviceMeta(); auto clsname = meta->className(); if (clsname == nullptr) { @@ -191,7 +185,6 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { // 筹备一个临时容器 PluginRecord record; - lp = LP::service; // 插件至少含有一种有效服务 auto srvc = meta->methodCount(); @@ -203,6 +196,13 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { if (strcmp(PLUGINSRVTAG, m.tag())) { continue; } + + if (m.parameterCount() > 10) { + dError(tr("[InvaildPlgSrvArg]") + + QString("%1/10").arg(m.parameterCount())); + continue; + } + // 记录有效服务函数 record.services.append(m); tmpfunc.append(m.name()); @@ -216,8 +216,6 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { } // 检查完毕后,就可以进入真正的加载环节 - - lp = LP::plugin2MessagePipe; emit p->pluginServicePipe(HostService, {LoadingPluginMsg}); if (!p->init(loadedplginfos)) { @@ -245,6 +243,25 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { dWarning(tr("PluginInitRegister")); + // 看看有没有要注册的托盘 + + auto menuobj = p->trayRegisteredMenu(); + if (menuobj) { + auto menu = qobject_cast(menuobj); + if (menu) { + traymenu->addMenu(menu); + plgmenuCount++; + } else { + auto amenu = qobject_cast(menuobj); + if (amenu) { + traymenu->addAction(amenu); + plgmenuCount++; + } else { + dError(tr("InvaildPlgMenu in loading %1").arg(p->pluginName())); + } + } + } + // 初始化插件容器 record.provider = provider; m_plgrec.insert(p, record); @@ -343,13 +360,13 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) { }); emit p->pluginServicePipe(HostService, {LoadedPluginMsg}); + dInfo(tr("PluginLoaded : %1 %2").arg(p->pluginName()).arg(provider)); } else { dError(loader.errorString()); loader.unload(); } } catch (...) { - auto m = QMetaEnum::fromType(); - dError(QString(tr("ErrLoadPluginLoc") + m.valueToKey(int(lp)))); + dError(tr("PluginLoadingEx")); loader.unload(); } } @@ -416,6 +433,8 @@ QString PluginSystem::pluginProvider(IWingToolPlg *plg) { return QString(); } +bool PluginSystem::hasRegisteredMenu() { return plgmenuCount > 0; } + IWingToolPlg *PluginSystem::loopUpHotkey(QUuid uuid, int &index) { for (auto plg : m_plgs) { auto res = m_plgrec[plg].hotkeyuid.indexOf(uuid); @@ -475,6 +494,16 @@ int PluginSystem::remoteCall(IWingToolPlg *plg, int callID, .arg(QString::fromUtf8(caller.name()))); return CALL_INVALID; } + auto len = caller.parameterCount(); + if (params.count() < len) { + dError(tr("[remoteCallVaildErr]") + + QString("%1 : %2 [%3/%4]") + .arg(m_plgrec[plg].provider) + .arg(QString::fromUtf8(caller.name())) + .arg(params.count()) + .arg(len)); + return CALL_ARG_ERROR; + } try { @@ -485,13 +514,15 @@ int PluginSystem::remoteCall(IWingToolPlg *plg, int callID, params.resize(10); - auto len = caller.parameterCount(); for (auto i = 0; i < len; i++) { if (!params[i].convert(caller.parameterType(i))) { dError(tr("[remoteCallArgErr]") + - QString("%1 : %2") + QString("%1 : %2 [%3:%4|%5]") .arg(m_plgrec[plg].provider) - .arg(QString::fromUtf8(caller.name()))); + .arg(QString::fromUtf8(caller.name())) + .arg(i) + .arg(QMetaType::typeName(caller.parameterType(i))) + .arg(params[i].typeName())); return CALL_ARG_ERROR; } } diff --git a/plugin/pluginsystem.h b/plugin/pluginsystem.h index 687f4cb..0cf40a4 100644 --- a/plugin/pluginsystem.h +++ b/plugin/pluginsystem.h @@ -19,21 +19,7 @@ DCORE_USE_NAMESPACE class PluginSystem : public QObject { Q_OBJECT public: - enum class LP { - begin, - signature, - sdkVersion, - pluginName, - handler, - provider, - service, - plugin2MessagePipe, - init, - }; - Q_ENUM(LP) - -public: - explicit PluginSystem(QObject *parent = nullptr); + explicit PluginSystem(QMenu *systray, QObject *parent = nullptr); ~PluginSystem(); static PluginSystem *instance(); @@ -60,6 +46,8 @@ public: const QStringList &pluginServicetrNames(IWingToolPlg *plg); QString pluginProvider(IWingToolPlg *plg); + bool hasRegisteredMenu(); + private: IWingToolPlg *loopUpHotkey(QUuid uuid, int &index); int remoteCall(IWingToolPlg *plg, QString &callback, QVector params, @@ -93,6 +81,10 @@ private: QMap> dispatcher; // Hook 消息订阅 QList m_plgsMD5s; // 已加载的插件 HASH + + QMenu *traymenu; + + uint plgmenuCount = 0; }; #endif // PLUGINSYSTEM_H diff --git a/screenshot.gif b/screenshot.gif index f88b4f8..99f0300 100644 Binary files a/screenshot.gif and b/screenshot.gif differ diff --git a/utilities.h b/utilities.h index c8c40e0..2e7acc2 100644 --- a/utilities.h +++ b/utilities.h @@ -4,6 +4,7 @@ #include "plugin/iwingtoolplg.h" #include #include +#include #include #include #include @@ -16,9 +17,16 @@ // 也并不是所有的成员在同一个场合用到的 struct ToolStructInfo { bool enabled = false; - QKeySequence seq = QKeySequence(); + QKeySequence seq = QKeySequence(); // 不是热键,就不会使用 QString process = QString(); // 如果是文件是路径,如果是插件是插件名 - QString params = QString(); + QString params = QString(); // 参数传参 + QString fakename = QString(); // 别名,用于代替默认显示 + + // 接下来这个部分非热键部分使用 + // 作用是自定义 icon + + QString iconpath = QString(); // 图标路径 + QIcon icon = QIcon(); // 缓存 // 以下仅供插件使用 int serviceID = -1; @@ -97,20 +105,63 @@ public: return true; } - static QIcon trimIconFromInfo(IWingToolPlg *plg, ToolStructInfo &info) { - if (info.isPlugin) { - if (plg == nullptr) - return QIcon(); - return plg->pluginIcon(); + static bool isIconExist(QString name) { + QMimeDatabase db; + auto t = db.mimeTypeForFile(name); + if (QIcon::hasThemeIcon(name)) { + return true; + } + + if (QFile::exists(name)) { + QImageReader r(name); + return r.canRead(); + } + return false; + } + + static QIcon trimIconFromFile(QString filename) { + if (filename.isEmpty()) + return QIcon(); + + if (QFile::exists(filename)) { + QPixmap img; + if (img.load(filename)) + return QIcon(img.width() > 64 || img.height() > 64 + ? img.scaled(64, 64, Qt::KeepAspectRatio) + : img); + } + // 我不信你如果使用 theme 图标的路径含有 / 字符 + // 据我多次观察 + if (filename.indexOf('/') < 0) { + if (QIcon::hasThemeIcon(filename)) + return QIcon::fromTheme(filename); } else { QMimeDatabase db; - auto t = db.mimeTypeForFile(info.process); - return QIcon::fromTheme(t.iconName(), QIcon(t.iconName())); + auto t = db.mimeTypeForFile(filename); + if (QIcon::hasThemeIcon(t.iconName())) + return QIcon::fromTheme(t.iconName()); + } + return QIcon(); + } + + static QIcon trimIconFromInfo(IWingToolPlg *plg, ToolStructInfo &info) { + if (info.icon.isNull()) { + if (info.isPlugin) { + if (plg == nullptr) + return QIcon(); + return plg->pluginIcon(); + } else { + return trimIconFromFile(info.process); + } + } else { + return info.icon; } } static QString getProgramName(const QStringList &services, ToolStructInfo &info) { + if (info.fakename.length()) + return info.fakename; return info.isPlugin ? info.process + " | " + services[info.serviceID] : QFileInfo(info.process).fileName(); } @@ -118,12 +169,14 @@ public: static QString getToolTipContent(const QStringList &services, ToolStructInfo &info) { if (info.isPlugin) { - return QObject::tr("Process:%1\nService:%2\nParams:%3") + return QObject::tr("FakeName:%1\nProcess:%2\nService:%3\nParams:%4") + .arg(info.fakename) .arg(info.process) .arg(services[info.serviceID]) .arg(info.params); } else { - return QObject::tr("Process:%1\nParams:%2") + return QObject::tr("FakeName:%1\nProcess:%2\nParams:%3") + .arg(info.fakename) .arg(info.process) .arg(info.params); } @@ -148,6 +201,14 @@ public: } return args; } + + static bool isVaildString(QByteArray &arr, QString &output) { + QTextCodec *codec = QTextCodec::codecForName("UTF-8"); + QTextCodec::ConverterState state; + + output = codec->toUnicode(arr.constData(), arr.size(), &state); + return state.invalidChars == 0; + } }; #endif // UTILIES_H diff --git a/更新日志.log b/更新日志.log index 19880ea..1331000 100644 --- a/更新日志.log +++ b/更新日志.log @@ -1,4 +1,18 @@ 更新日志(由寂静的羽夏编写): 1.0.0 -1. 更新插件接口 +1. 重新设计插件接口,降低开发难度,提高易用性 +2. 增加严格的配置校验流程,避免非法配置 +3. 添加的工具可以自定义图标,且图标是必须 +4. 优化工具窗口的 UI 交互 +5. 优化全局检查按下的修饰键响应逻辑,修复因此导致的问题 +6. 增加丰富的程序日志,方便后续排查问题 +7. 增加日志和配置相关 UI 显示,方便查看或者导出 +8. 增加运行插件窗体,可以像 Win 运行一样调用插件功能 +9. 优化工具提示显示内容,增加用户体验 +10. 软件文本内容彻底本地化 +11. 修复软件执行调用相关逻辑,避免误判导致打开方式错误 +12. 增加插件注册托盘菜单 + +1.0.0 beta +1. 完成软件基本功能设计