This commit is contained in:
寂静的羽夏 2022-10-11 22:23:13 +08:00
parent b3c7852bfd
commit 203b718622
30 changed files with 855 additions and 384 deletions

View File

@ -14,9 +14,9 @@
## WingTool
  `WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪、选词等相关借口。通过开发强大的对应的插件,就可以大大提高生产力。
  `WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪等基本接口。通过开发强大的对应的插件,就可以大大提高生产力。
  该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Ctrl`键可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。
  该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Super`键(在`Windows`系统中称之为`Win`键)可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。
### 协议

View File

@ -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<WingPluginInfo> 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<QVariant> params) {
switch (serviceID) {
case HostService:

View File

@ -62,6 +62,8 @@ public:
const QPointer<QObject> serviceHandler() override;
HookIndex getHookSubscribe() override;
QObject *trayRegisteredMenu() override;
public slots:
QVariant pluginServicePipe(int serviceID, QList<QVariant> params) override;
virtual void onSetting() override;
@ -73,6 +75,8 @@ private:
TestService *services;
QTranslator translator;
QAction *testmenu;
};
#endif // GENERICPLUGIN_H

View File

@ -8,6 +8,8 @@ TEMPLATE = app
QT += x11extras
LIBS += -lX11 -lXext -lXtst
CONFIG += exception
SOURCES += \
main.cpp \
class/eventmonitor.cpp \

View File

@ -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<QIcon> 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);
}

View File

@ -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<QIcon> icons);
void setToolIcon(int index, QIcon icon);
void setToolIcon(int index, QIcon icon, QString tip);
private:
EventMonitor monitor;

View File

@ -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;
}

View File

@ -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

View File

@ -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; }

View File

@ -21,6 +21,10 @@ public:
bool saveSettings();
bool exportSettings(QString filename);
void resetSettings();
QString backupOrignSetting();
void saveFileDialogCurrent(QString path);
QString loadFileDialogCurrent();
public:
void setModified();

View File

@ -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();

View File

@ -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);

View File

@ -1,68 +0,0 @@
#include "rundialog.h"
#include <DDialogButtonBox>
#include <QScreen>
#include <QShortcut>
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<QVariant> 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);
}

View File

@ -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);
}

View File

@ -4,6 +4,7 @@
#include "utilities.h"
#include "class/appmanager.h"
#include "class/settingmanager.h"
#include "control/pluginselector.h"
#include "plugin/pluginsystem.h"
#include <DCheckBox>
@ -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

View File

@ -7,6 +7,8 @@
#include <QVBoxLayout>
#include <QWidget>
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);

View File

@ -1,17 +1,21 @@
#include "tooleditdialog.h"
#include <DDialogButtonBox>
#include <DMessageManager>
#include <QHBoxLayout>
#include <QShortcut>
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);
}

View File

@ -4,11 +4,13 @@
#include "utilities.h"
#include "class/appmanager.h"
#include "class/settingmanager.h"
#include "control/pluginselector.h"
#include <DCheckBox>
#include <DComboBox>
#include <DDialog>
#include <DFileChooserEdit>
#include <DIconButton>
#include <DKeySequenceEdit>
#include <DLabel>
#include <DLineEdit>
@ -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

View File

@ -1,7 +1,9 @@
#include "toolwindow.h"
#include "class/settingmanager.h"
#include "utilities.h"
#include <QDebug>
#include <QMouseEvent>
#include <QToolTip>
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<QIcon> 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() {

View File

@ -15,9 +15,7 @@ public:
public slots:
void loadSettings();
void setIcons(QVector<QIcon> icons);
void setIcon(int index, QIcon icon);
void setIcon(int index, QIcon icon, QString tip);
void popup(QPoint pos);

View File

@ -1,8 +1,8 @@
## WingTool
&emsp;&emsp;`WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪、选词等相关借口。通过开发强大的对应的插件,就可以大大提高生产力。
&emsp;&emsp;`WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪等基本接口。通过开发强大的对应的插件,就可以大大提高生产力。
&emsp;&emsp;该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Ctrl`键可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。
&emsp;&emsp;该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Super`键(在`Windows`系统中称之为`Win`键)可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。
### 协议

Binary file not shown.

View File

@ -127,33 +127,33 @@
<message>
<location filename="../dialog/centerwindow.cpp" line="154"/>
<location filename="../dialog/centerwindow.cpp" line="193"/>
<location filename="../dialog/centerwindow.cpp" line="368"/>
<location filename="../dialog/centerwindow.cpp" line="406"/>
<location filename="../dialog/centerwindow.cpp" line="370"/>
<location filename="../dialog/centerwindow.cpp" line="408"/>
<source>Add</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="157"/>
<location filename="../dialog/centerwindow.cpp" line="196"/>
<location filename="../dialog/centerwindow.cpp" line="374"/>
<location filename="../dialog/centerwindow.cpp" line="409"/>
<location filename="../dialog/centerwindow.cpp" line="376"/>
<location filename="../dialog/centerwindow.cpp" line="411"/>
<source>Remove</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="160"/>
<location filename="../dialog/centerwindow.cpp" line="194"/>
<location filename="../dialog/centerwindow.cpp" line="304"/>
<location filename="../dialog/centerwindow.cpp" line="380"/>
<location filename="../dialog/centerwindow.cpp" line="407"/>
<location filename="../dialog/centerwindow.cpp" line="306"/>
<location filename="../dialog/centerwindow.cpp" line="382"/>
<location filename="../dialog/centerwindow.cpp" line="409"/>
<source>Edit</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="163"/>
<location filename="../dialog/centerwindow.cpp" line="198"/>
<location filename="../dialog/centerwindow.cpp" line="398"/>
<location filename="../dialog/centerwindow.cpp" line="411"/>
<location filename="../dialog/centerwindow.cpp" line="400"/>
<location filename="../dialog/centerwindow.cpp" line="413"/>
<source>Clear</source>
<translation></translation>
</message>
@ -195,156 +195,173 @@
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="261"/>
<location filename="../dialog/centerwindow.cpp" line="283"/>
<source>FakeName:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="262"/>
<source>Service:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="263"/>
<location filename="../dialog/centerwindow.cpp" line="283"/>
<location filename="../dialog/centerwindow.cpp" line="264"/>
<location filename="../dialog/centerwindow.cpp" line="285"/>
<source>Params:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="277"/>
<location filename="../dialog/centerwindow.cpp" line="285"/>
<location filename="../dialog/centerwindow.cpp" line="278"/>
<location filename="../dialog/centerwindow.cpp" line="287"/>
<source>NoTool</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="281"/>
<location filename="../dialog/centerwindow.cpp" line="282"/>
<source>[File]</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="282"/>
<location filename="../dialog/centerwindow.cpp" line="284"/>
<source>FileName:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="318"/>
<location filename="../dialog/centerwindow.cpp" line="320"/>
<source>Swap</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="346"/>
<location filename="../dialog/centerwindow.cpp" line="348"/>
<source>Delete</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="386"/>
<location filename="../dialog/centerwindow.cpp" line="413"/>
<location filename="../dialog/centerwindow.cpp" line="388"/>
<location filename="../dialog/centerwindow.cpp" line="415"/>
<source>Up</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="392"/>
<location filename="../dialog/centerwindow.cpp" line="415"/>
<location filename="../dialog/centerwindow.cpp" line="394"/>
<location filename="../dialog/centerwindow.cpp" line="417"/>
<source>Down</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="417"/>
<location filename="../dialog/centerwindow.cpp" line="419"/>
<source>TopMost</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="450"/>
<location filename="../dialog/centerwindow.cpp" line="452"/>
<source>DownMost</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="501"/>
<location filename="../dialog/centerwindow.cpp" line="503"/>
<source>ToolBox</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="513"/>
<location filename="../dialog/centerwindow.cpp" line="526"/>
<location filename="../dialog/centerwindow.cpp" line="515"/>
<location filename="../dialog/centerwindow.cpp" line="528"/>
<source>No selected plugin.</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="516"/>
<location filename="../dialog/centerwindow.cpp" line="518"/>
<source>Setting</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="533"/>
<location filename="../dialog/centerwindow.cpp" line="535"/>
<source>Name:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="556"/>
<location filename="../dialog/centerwindow.cpp" line="558"/>
<source>RegisteredHotkey:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="562"/>
<location filename="../dialog/centerwindow.cpp" line="564"/>
<source>Plugins</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="581"/>
<location filename="../dialog/centerwindow.cpp" line="583"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="586"/>
<location filename="../dialog/centerwindow.cpp" line="588"/>
<source>ThanksForSponsor</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="594"/>
<location filename="../dialog/centerwindow.cpp" line="596"/>
<source>Sponsor</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="624"/>
<location filename="../dialog/centerwindow.cpp" line="623"/>
<location filename="../dialog/centerwindow.cpp" line="639"/>
<source>runErr</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="629"/>
<location filename="../dialog/centerwindow.cpp" line="644"/>
<source>err</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="629"/>
<location filename="../dialog/centerwindow.cpp" line="644"/>
<source>openErr</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="695"/>
<location filename="../dialog/centerwindow.cpp" line="784"/>
<location filename="../dialog/centerwindow.cpp" line="713"/>
<location filename="../dialog/centerwindow.cpp" line="805"/>
<source>ClearSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="705"/>
<location filename="../dialog/centerwindow.cpp" line="723"/>
<source>HotkeyRegisterFail</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="739"/>
<location filename="../dialog/centerwindow.cpp" line="759"/>
<source>PleaseSelectOne</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="889"/>
<location filename="../dialog/centerwindow.cpp" line="901"/>
<location filename="../dialog/centerwindow.cpp" line="911"/>
<location filename="../dialog/centerwindow.cpp" line="923"/>
<source>Config (*.wtcfg)</source>
<translation> (*.wtcfg)</translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="895"/>
<location filename="../dialog/centerwindow.cpp" line="917"/>
<source>ExportSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="907"/>
<location filename="../dialog/centerwindow.cpp" line="929"/>
<source>ImportSuccess</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="934"/>
<source>Warn</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="934"/>
<source>ResetSettings</source>
<translation></translation>
</message>
</context>
<context>
<name>PluginSelDialog</name>
@ -387,63 +404,84 @@
<context>
<name>PluginSystem</name>
<message>
<location filename="../plugin/pluginsystem.cpp" line="150"/>
<location filename="../plugin/pluginsystem.cpp" line="145"/>
<source>PluginLoadingBegin : %1</source>
<translation>%1</translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="148"/>
<source>ErrLoadPluginSign</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="156"/>
<location filename="../plugin/pluginsystem.cpp" line="153"/>
<source>ErrLoadPluginSDKVersion</source>
<translation> SDK </translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="162"/>
<location filename="../plugin/pluginsystem.cpp" line="158"/>
<source>ErrLoadPluginNoName</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="170"/>
<location filename="../plugin/pluginsystem.cpp" line="165"/>
<source>ErrLoadPluginNoHandler</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="179"/>
<location filename="../plugin/pluginsystem.cpp" line="186"/>
<location filename="../plugin/pluginsystem.cpp" line="173"/>
<location filename="../plugin/pluginsystem.cpp" line="180"/>
<source>ErrLoadPluginProvider</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="201"/>
<source>[InvaildPlgSrvArg]</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="213"/>
<source>ErLoadPluginService</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="224"/>
<location filename="../plugin/pluginsystem.cpp" line="222"/>
<source>ErrLoadInitPlugin</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="246"/>
<location filename="../plugin/pluginsystem.cpp" line="244"/>
<source>PluginInitRegister</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="352"/>
<source>ErrLoadPluginLoc</source>
<translation></translation>
<location filename="../plugin/pluginsystem.cpp" line="260"/>
<source>InvaildPlgMenu in loading %1</source>
<translation> %1 </translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="472"/>
<location filename="../plugin/pluginsystem.cpp" line="363"/>
<source>PluginLoaded : %1 %2</source>
<translation>%1 %2</translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="369"/>
<source>PluginLoadingEx</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="491"/>
<location filename="../plugin/pluginsystem.cpp" line="499"/>
<source>[remoteCallVaildErr]</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="491"/>
<location filename="../plugin/pluginsystem.cpp" line="519"/>
<source>[remoteCallArgErr]</source>
<translation></translation>
</message>
<message>
<location filename="../plugin/pluginsystem.cpp" line="515"/>
<location filename="../plugin/pluginsystem.cpp" line="546"/>
<source>[remoteCallEx]</source>
<translation></translation>
</message>
@ -469,41 +507,41 @@
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="268"/>
<location filename="../dialog/centerwindow.cpp" line="537"/>
<location filename="../dialog/centerwindow.cpp" line="269"/>
<location filename="../dialog/centerwindow.cpp" line="539"/>
<location filename="../dialog/pluginseldialog.cpp" line="41"/>
<source>Catagory:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="270"/>
<location filename="../dialog/centerwindow.cpp" line="539"/>
<location filename="../dialog/centerwindow.cpp" line="271"/>
<location filename="../dialog/centerwindow.cpp" line="541"/>
<source>Version:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="272"/>
<location filename="../dialog/centerwindow.cpp" line="541"/>
<location filename="../dialog/centerwindow.cpp" line="273"/>
<location filename="../dialog/centerwindow.cpp" line="543"/>
<location filename="../dialog/pluginseldialog.cpp" line="45"/>
<source>Author:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="273"/>
<location filename="../dialog/centerwindow.cpp" line="542"/>
<location filename="../dialog/centerwindow.cpp" line="274"/>
<location filename="../dialog/centerwindow.cpp" line="544"/>
<location filename="../dialog/pluginseldialog.cpp" line="46"/>
<source>Comment:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="274"/>
<location filename="../dialog/centerwindow.cpp" line="543"/>
<location filename="../dialog/centerwindow.cpp" line="275"/>
<location filename="../dialog/centerwindow.cpp" line="545"/>
<location filename="../dialog/pluginseldialog.cpp" line="47"/>
<source>Provider:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/centerwindow.cpp" line="545"/>
<location filename="../dialog/centerwindow.cpp" line="547"/>
<location filename="../dialog/pluginseldialog.cpp" line="48"/>
<source>Services:</source>
<translation></translation>
@ -514,54 +552,58 @@
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="52"/>
<location filename="../main.cpp" line="58"/>
<location filename="../main.cpp" line="149"/>
<location filename="../main.cpp" line="54"/>
<location filename="../main.cpp" line="60"/>
<location filename="../main.cpp" line="170"/>
<source>WingTool</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="126"/>
<location filename="../main.cpp" line="62"/>
<source>A powerful plugin toolbox for Deepin.</source>
<translation> Deepin </translation>
</message>
<message>
<location filename="../main.cpp" line="132"/>
<source>ErrorLoadingSettings</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="92"/>
<source>ShowMain</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="131"/>
<location filename="../main.cpp" line="136"/>
<source>Err</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="137"/>
<source>ErrResetSettings</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="152"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="135"/>
<location filename="../main.cpp" line="159"/>
<source>Sponsor</source>
<translation></translation>
</message>
<message>
<location filename="../main.cpp" line="139"/>
<location filename="../main.cpp" line="141"/>
<location filename="../main.cpp" line="166"/>
<location filename="../main.cpp" line="173"/>
<source>Exit</source>
<translation>退</translation>
</message>
<message>
<location filename="../main.cpp" line="142"/>
<location filename="../main.cpp" line="174"/>
<source>ConfirmExit</source>
<translation></translation>
</message>
<message>
<location filename="../utilities.h" line="121"/>
<source>Process:%1
Service:%2
Params:%3</source>
<translation>%1
%2
%3</translation>
</message>
<message>
<location filename="../utilities.h" line="126"/>
<source>Process:%1
Params:%2</source>
<translation>%1
%2</translation>
</message>
<message>
<location filename="../class/settings.cpp" line="4"/>
<source>Explor</source>
@ -592,6 +634,26 @@ Params:%2</source>
<source>Creative</source>
<translation></translation>
</message>
<message>
<location filename="../utilities.h" line="172"/>
<source>FakeName:%1
Process:%2
Service:%3
Params:%4</source>
<translation>%1
%2
%3
%4</translation>
</message>
<message>
<location filename="../utilities.h" line="178"/>
<source>FakeName:%1
Process:%2
Params:%3</source>
<translation>%1
%2
%3</translation>
</message>
</context>
<context>
<name>RunDialog</name>
@ -624,44 +686,49 @@ Params:%2</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="16"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="18"/>
<source>Enabled</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="26"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="28"/>
<source>ShortCut</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="33"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="35"/>
<source>Plugin</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="39"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="54"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="41"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="56"/>
<source>Service</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="45"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="54"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="47"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="56"/>
<source>FilePath</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="73"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="81"/>
<source>Param</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="100"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="87"/>
<source>FakeName</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="113"/>
<source>NoHotkeySet</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/shortcuteditdialog.cpp" line="116"/>
<location filename="../dialog/shortcuteditdialog.cpp" line="129"/>
<source>NoProcessSet</source>
<translation></translation>
</message>
@ -678,10 +745,15 @@ Params:%2</source>
<source>Process:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/toolboxwindow.cpp" line="48"/>
<source>FakeName:</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/toolboxwindow.cpp" line="53"/>
<source>Service:</source>
<translation></translation>
<translation></translation>
</message>
<message>
<location filename="../dialog/toolboxwindow.cpp" line="55"/>
@ -692,36 +764,66 @@ Params:%2</source>
<context>
<name>ToolEditDialog</name>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="13"/>
<location filename="../dialog/tooleditdialog.cpp" line="15"/>
<source>ToolWinEdit</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="16"/>
<location filename="../dialog/tooleditdialog.cpp" line="20"/>
<source>Plugin</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="22"/>
<location filename="../dialog/tooleditdialog.cpp" line="37"/>
<location filename="../dialog/tooleditdialog.cpp" line="26"/>
<location filename="../dialog/tooleditdialog.cpp" line="88"/>
<source>Service</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="28"/>
<location filename="../dialog/tooleditdialog.cpp" line="37"/>
<location filename="../dialog/tooleditdialog.cpp" line="32"/>
<location filename="../dialog/tooleditdialog.cpp" line="88"/>
<source>FilePath</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="56"/>
<location filename="../dialog/tooleditdialog.cpp" line="44"/>
<source>Icon</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="48"/>
<source>Image Format (*.png *.svg *.jpg *.jpeg)</source>
<translation> (*.png *.svg *.jpg *.jpeg)</translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="71"/>
<source>InvalidIcon</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="120"/>
<source>Param</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="89"/>
<source>NoProcessSet</source>
<translation></translation>
<location filename="../dialog/tooleditdialog.cpp" line="126"/>
<source>FakeName</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="135"/>
<source>IconPreview</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="159"/>
<source>NoVaildIconSet</source>
<translation></translation>
</message>
<message>
<location filename="../dialog/tooleditdialog.cpp" line="176"/>
<source>NoVaildProcessSet</source>
<translation></translation>
</message>
</context>
<context>

View File

@ -7,6 +7,7 @@
#include <DApplication>
#include <DApplicationSettings>
#include <DGuiApplicationHelper>
#include <DNotifySender>
#include <DWidgetUtil>
#include <QMenu>
#include <QMessageBox>
@ -22,6 +23,7 @@ int main(int argc, char *argv[]) {
qputenv("XDG_CURRENT_DESKTOP", "Deepin");
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setQuitOnLastWindowClosed(false);
qRegisterMetaType<Qt::MouseButton>("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);

View File

@ -4,6 +4,7 @@
#include <QApplication>
#include <QIcon>
#include <QKeySequence>
#include <QMenu>
#include <QObject>
#include <QPointer>
#include <QUuid>
@ -121,6 +122,10 @@ public:
// 指示是否作为工具,如果 false则不在工具选择中显示
// 但这不意味着不在插件列表显示
virtual bool isTool() { return true; }
// 注册在程序右键托盘菜单,这个对于某些功能会十分方便
// 但非必要不要弄,因为这样的插件多了,反而麻烦了,一个插件仅有一项
// 类型仅支持 QMenu* 或者 QAction* 否则不载入
virtual QObject *trayRegisteredMenu() { return nullptr; }
signals:
// 注册热键,如果被占用则返回 -1 表示失败(通常是重复),

View File

@ -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<IWingToolPlg *> PluginSystem::plugins() { return m_plgs; }
void PluginSystem::loadPlugin(QFileInfo fileinfo) {
LP lp(LP::begin);
if (fileinfo.exists()) {
QPluginLoader loader(fileinfo.absoluteFilePath());
QList<WingPluginInfo> loadedplginfos;
@ -144,27 +142,24 @@ void PluginSystem::loadPlugin(QFileInfo fileinfo) {
try {
auto p = qobject_cast<IWingToolPlg *>(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<QMenu *>(menuobj);
if (menu) {
traymenu->addMenu(menu);
plgmenuCount++;
} else {
auto amenu = qobject_cast<QAction *>(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<LP>();
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;
}
}

View File

@ -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<QVariant> params,
@ -93,6 +81,10 @@ private:
QMap<HookIndex, QList<IWingToolPlg *>> dispatcher; // Hook 消息订阅
QList<QByteArray> m_plgsMD5s; // 已加载的插件 HASH
QMenu *traymenu;
uint plgmenuCount = 0;
};
#endif // PLUGINSYSTEM_H

Binary file not shown.

Before

Width:  |  Height:  |  Size: 850 KiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@ -4,6 +4,7 @@
#include "plugin/iwingtoolplg.h"
#include <QComboBox>
#include <QIcon>
#include <QImageReader>
#include <QKeySequence>
#include <QMimeDatabase>
#include <QString>
@ -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

View File

@ -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. 完成软件基本功能设计