diff --git a/README.md b/README.md index 2576d10..42793e4 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ ## WingTool   `WingTool`是一个强大的插件工具箱,中文名`羽云工具箱`,支持热键响应、鼠标跟踪、选词等相关借口。通过开发强大的对应的插件,就可以大大提高生产力。 +   该软件如果没有任何插件,仅支持添加热键使用默认方式打开任何文件。插件的强大决定着该软件的上限,通过热键可以配置使用热键调用插件借口;默认通过鼠标中键配合`Ctrl`键可以调出工具窗口,选择合适的工具;也可以通过热键调出窗口工具,点击打开所需的文件或者软件,而不必从启动器翻找,避免任务栏图标过多以及桌面文件过多的情况。 ## TODO @@ -22,15 +23,14 @@   现在工具处于开发状态,很多功能并没有完成: 1. 配置相关(已完成 90%) -2. 窗口工具(已完成 40%) -3. 语言本地化(已完成 0%) -4. 软件 UI 相关(已完成 90%) +2. 语言本地化(已完成 0%)   如下是已完成的功能: 1. 插件系统的设计 2. 热键调用功能 3. 工具窗口 +4. 窗口工具   待功能基本完成的时候,我会同步到我使用的所有代码托管平台。 diff --git a/TestPlugin/testplugin.cpp b/TestPlugin/testplugin.cpp index f7a9203..5dfb784 100644 --- a/TestPlugin/testplugin.cpp +++ b/TestPlugin/testplugin.cpp @@ -1,4 +1,5 @@ #include "testplugin.h" +#include TestPlugin::TestPlugin(QObject *parent) { Q_UNUSED(parent) } @@ -93,6 +94,10 @@ QVariant TestPlugin::pluginServicePipe(int serviceID, QList params) { return QVariant(); } +void TestPlugin::onSetting() { + QMessageBox::information(nullptr, "Settings", "You Clicked Settings!"); +} + #if QT_VERSION < 0x050000 Q_EXPORT_PLUGIN2(TestPlugin, IWingToolPlg) #endif // QT_VERSION < 0x050000 diff --git a/TestPlugin/testplugin.h b/TestPlugin/testplugin.h index 084b4ca..8440121 100644 --- a/TestPlugin/testplugin.h +++ b/TestPlugin/testplugin.h @@ -33,6 +33,7 @@ public: public slots: QVariant pluginServicePipe(int serviceID, QList params) override; + virtual void onSetting() override; private: QUuid testhotkey; diff --git a/WingTool.pro b/WingTool.pro index 6fa8ee3..46975d4 100644 --- a/WingTool.pro +++ b/WingTool.pro @@ -26,8 +26,7 @@ SOURCES += \ dialog/pluginseldialog.cpp \ dialog/tooleditdialog.cpp \ class/hotkey.cpp \ - dialog/toolswapdialog.cpp \ - control/wintoolitem.cpp + dialog/toolswapdialog.cpp RESOURCES += resources.qrc HEADERS += \ @@ -48,5 +47,4 @@ HEADERS += \ utilities.h \ dialog/tooleditdialog.h \ class/hotkey.h \ - dialog/toolswapdialog.h \ - control/wintoolitem.h + dialog/toolswapdialog.h diff --git a/control/wintoolitem.cpp b/control/wintoolitem.cpp deleted file mode 100644 index 42ec59d..0000000 --- a/control/wintoolitem.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "wintoolitem.h" -#include -#include - -WinToolItem::WinToolItem(QWidget *parent) : QWidget(parent) { - setFixedHeight(30); - auto layout = new QHBoxLayout(this); - lbl = new DLabel(this); - lbl->setFixedSize(25, 25); - lbl->setScaledContents(true); - layout->addWidget(lbl); - auto ilayout = new QVBoxLayout(this); - layout->addLayout(ilayout, 1); - m_name = new DLabel(this); - ilayout->addWidget(m_name); - m_srv = new DLabel(this); - ilayout->addWidget(m_srv); - m_param = new DLabel(this); - ilayout->addWidget(m_param); -} - -WinToolItem::WinToolItem(const QPixmap pix, const QString &name, - const QString &srv, const QString ¶ms, - QWidget *parent) - : QWidget(parent) { - setFixedHeight(30); - auto layout = new QHBoxLayout(this); - lbl = new DLabel(this); - lbl->setPixmap(pix); - lbl->setFixedSize(25, 25); - lbl->setScaledContents(true); - layout->addWidget(lbl); - auto ilayout = new QVBoxLayout(this); - layout->addLayout(ilayout, 1); - m_name = new DLabel(name, this); - ilayout->addWidget(m_name); - m_srv = new DLabel(srv, this); - ilayout->addWidget(m_srv); - m_param = new DLabel(params, this); - ilayout->addWidget(m_param); -} - -void WinToolItem::setIcon(QPixmap pix) { lbl->setPixmap(pix); } - -void WinToolItem::setName(const QString &name) { m_name->setText(name); } - -void WinToolItem::setSrvName(const QString &srv) { m_srv->setText(srv); } - -void WinToolItem::setParams(const QString ¶ms) { m_param->setText(params); } diff --git a/control/wintoolitem.h b/control/wintoolitem.h deleted file mode 100644 index e7cefb8..0000000 --- a/control/wintoolitem.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef WINTOOLITEM_H -#define WINTOOLITEM_H - -#include -#include -#include - -DWIDGET_USE_NAMESPACE - -class WinToolItem : public QWidget { - Q_OBJECT -public: - explicit WinToolItem(QWidget *parent = nullptr); - explicit WinToolItem(const QPixmap pix, const QString &name, - const QString &srv, const QString ¶ms, - QWidget *parent = nullptr); - -public slots: - void setIcon(const QPixmap pix); - void setName(const QString &name); - void setSrvName(const QString &srv); - void setParams(const QString ¶ms); - -private: - DLabel *lbl, *m_name, *m_srv, *m_param; -}; - -#endif // WINTOOLITEM_H diff --git a/dialog/centerwindow.cpp b/dialog/centerwindow.cpp index 29d6ba9..f3eff43 100644 --- a/dialog/centerwindow.cpp +++ b/dialog/centerwindow.cpp @@ -181,7 +181,7 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { tbhotkeys->setContextMenuPolicy(Qt::CustomContextMenu); connect(tbhotkeys, &DTabWidget::customContextMenuRequested, this, [=] { - auto flag = tbhotkeys->currentRow() >= 0; + auto flag = tbhotkeys->selectedItems().count() > 0; for (auto item : hkcmenu) { item->setEnabled(flag); } @@ -349,61 +349,122 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { b->setIconSize(QSize(20, 20)); b->setParent(this); b->setToolTip(tr("Add")); - connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_addToolWin); + connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_addWinTool); blist.append(b); b = new DButtonBoxButton(ICONRES2("del")); b->setIconSize(QSize(20, 20)); b->setParent(this); b->setToolTip(tr("Remove")); - connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_removeToolWin); + connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_removeWinTool); blist.append(b); b = new DButtonBoxButton(ICONRES2("edit")); b->setIconSize(QSize(20, 20)); b->setParent(this); b->setToolTip(tr("Edit")); - connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_editToolWin); + connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_editWinTool); blist.append(b); b = new DButtonBoxButton(ICONRES2("up")); b->setIconSize(QSize(20, 20)); b->setParent(this); b->setToolTip(tr("Up")); - connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_upToolWin); + connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_upWinTool); blist.append(b); b = new DButtonBoxButton(ICONRES2("down")); b->setIconSize(QSize(20, 20)); b->setParent(this); b->setToolTip(tr("Down")); - connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_downToolWin); + connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_downWinTool); blist.append(b); b = new DButtonBoxButton(ICONRES2("clear")); b->setIconSize(QSize(20, 20)); b->setParent(this); b->setToolTip(tr("Clear")); - connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_clearToolWin); + connect(b, &DButtonBoxButton::clicked, this, &CenterWindow::on_clearWinTool); blist.append(b); group->setButtonList(blist, false); tvlayout->addWidget(group); lstoolwin = new DListWidget(w); menu = new DMenu(lstoolwin); - AddMenuAction(tr("Add"), &CenterWindow::on_addToolWin); - AddMenuAction(tr("Edit"), &CenterWindow::on_editToolWin); - AddMenuAction(tr("Remove"), &CenterWindow::on_removeToolWin); - AddMenuAction(tr("Clear"), &CenterWindow::on_clearToolWin); + AddMenuAction(tr("Add"), &CenterWindow::on_addWinTool); + AddMenuAction(tr("Edit"), &CenterWindow::on_editWinTool); + lscmenu.append(a); + AddMenuAction(tr("Remove"), &CenterWindow::on_removeWinTool); + lscmenu.append(a); + AddMenuAction(tr("Clear"), &CenterWindow::on_clearWinTool); menu->addSeparator(); - AddMenuAction(tr("Up"), &CenterWindow::on_upToolWin); - AddMenuAction(tr("Down"), &CenterWindow::on_downToolWin); + AddMenuAction(tr("Up"), &CenterWindow::on_upWinTool); + lscmenu.append(a); + AddMenuAction(tr("Down"), &CenterWindow::on_downWinTool); + lscmenu.append(a); AddMenuAction(tr("TopMost"), [=] { + auto sels = lstoolwin->selectionModel()->selectedRows(); + QVector nums; + for (auto &item : sels) { + nums.append(item.row()); + } + std::sort(nums.begin(), nums.end()); + + // 过滤掉不需移动的选项 + int i = 0; + auto len = nums.count(); + for (; i < len; i++) { + if (nums[i] != i) + break; + } + + // 下面就开始乾坤大挪移 + for (auto p = nums.rbegin(); p != nums.rend() - i; p++) { + auto pi = *p; + wintoolinfos.move(pi, i); + auto item = lstoolwin->takeItem(pi); + lstoolwin->insertItem(i, item); + wintool.mvItem(pi, i); + } }); + lscmenu.append(a); AddMenuAction(tr("DownMost"), [=] { + auto sels = lstoolwin->selectionModel()->selectedRows(); + QVector nums; + for (auto &item : sels) { + nums.append(item.row()); + } + std::sort(nums.begin(), nums.end(), std::greater()); + + // 过滤掉不需移动的选项 + int i = 0; + auto len = nums.count(); + if (nums.first() == lstoolwin->count() - 1) { + int pi = nums.first(); + for (; i < len; i++) { + pi--; + if (nums[i] != pi) + break; + } + } + + // 下面就开始乾坤大挪移 + for (auto p = nums.rbegin(); p != nums.rend() - i; p++) { + auto pi = *p; + wintoolinfos.move(pi, i); + auto item = lstoolwin->takeItem(pi); + lstoolwin->insertItem(i, item); + wintool.mvItem(pi, i); + } }); + lscmenu.append(a); lstoolwin->setContextMenuPolicy(Qt::CustomContextMenu); lstoolwin->setSelectionMode(QListWidget::SelectionMode::ExtendedSelection); lstoolwin->setDragDropMode(QListWidget::DragDropMode::NoDragDrop); - connect(lstoolwin, &DListWidget::customContextMenuRequested, this, - [=] { menu->popup(QCursor::pos()); }); + connect(lstoolwin, &DListWidget::customContextMenuRequested, this, [=] { + auto flag = lstoolwin->selectedItems().count() > 0; + for (auto item : lscmenu) { + item->setEnabled(flag); + } + menu->popup(QCursor::pos()); + }); tvlayout->addWidget(lstoolwin); tlayout->addLayout(tvlayout); @@ -412,15 +473,32 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { // Plugins w = new QWidget(this); auto playout = new QHBoxLayout(w); + auto pvlayout = new QVBoxLayout; lwplgs = new DListWidget(w); playout->addWidget(lwplgs); + playout->addLayout(pvlayout); tbplginfo = new DTextBrowser(w); tbplginfo->setUndoRedoEnabled(false); tbplginfo->setText(tr("No selected plugin.")); + pvlayout->addWidget(tbplginfo, 1); + auto btnplgset = new DPushButton(tr("Setting"), w); + connect(btnplgset, &DPushButton::clicked, this, [=] { + auto plg = plgsys->plugin(lwplgs->currentRow()); + plg->onSetting(); + }); + btnplgset->setEnabled(false); + pvlayout->addWidget(btnplgset); + connect(lwplgs, &DListWidget::itemSelectionChanged, this, [=] { + if (lwplgs->currentRow() < 0) { + tbplginfo->setText(tr("No selected plugin.")); + btnplgset->setEnabled(false); + return; + } tbplginfo->clear(); + btnplgset->setEnabled(true); auto plg = plgsys->plugin(lwplgs->currentRow()); tbplginfo->append(tr("Name:") + plg->pluginName()); @@ -445,7 +523,7 @@ CenterWindow::CenterWindow(DMainWindow *parent) : DMainWindow(parent) { tbplginfo->append(QString("\t%1").arg(item.toString())); } }); - playout->addWidget(tbplginfo); + tabs->addTab(w, tr("Plugins")); // AboutAuthor @@ -634,7 +712,7 @@ void CenterWindow::enableSelectedHotkeys(bool enable) { } } -void CenterWindow::on_editToolWin() { +void CenterWindow::on_editWinTool() { auto sels = lstoolwin->selectedItems().count(); if (sels != 1) { DMessageManager::instance()->sendMessage(this, ProgramIcon, @@ -654,7 +732,7 @@ void CenterWindow::on_editToolWin() { } } -void CenterWindow::on_removeToolWin() { +void CenterWindow::on_removeWinTool() { auto sels = lstoolwin->selectionModel()->selectedRows(); QVector nums; for (auto &item : sels) { @@ -667,17 +745,19 @@ void CenterWindow::on_removeToolWin() { wintoolinfos.removeAt(index); auto item = lstoolwin->takeItem(index); delete item; + wintool.rmItem(index); } } -void CenterWindow::on_clearToolWin() { +void CenterWindow::on_clearWinTool() { lstoolwin->clear(); wintoolinfos.clear(); + wintool.rmItem(-1); // 清空数据 DMessageManager::instance()->sendMessage(this, ProgramIcon, tr("ClearSuccess")); } -void CenterWindow::on_addToolWin() { +void CenterWindow::on_addWinTool() { ToolEditDialog d; if (d.exec()) { auto res = d.getResult(); @@ -689,6 +769,7 @@ void CenterWindow::on_addToolWin() { Utilities::getProgramName(res)); item->setToolTip(res.process); lstoolwin->addItem(item); + wintool.addItem(res); } else { wintoolinfos.insert(index + 1, res); @@ -697,13 +778,68 @@ void CenterWindow::on_addToolWin() { Utilities::getProgramName(res)); item->setToolTip(res.process); lstoolwin->insertItem(index + 1, item); + wintool.addItem(res, index + 1); } } } -void CenterWindow::on_upToolWin() {} +void CenterWindow::on_upWinTool() { + auto sels = lstoolwin->selectionModel()->selectedRows(); + QVector nums; + for (auto &item : sels) { + nums.append(item.row()); + } -void CenterWindow::on_downToolWin() {} + std::sort(nums.begin(), nums.end()); + + // 过滤掉不需移动的选项 + int i = 0; + auto len = nums.count(); + for (; i < len; i++) { + if (nums[i] != i) + break; + } + + // 下面就开始乾坤大挪移 + for (; i < len; i++) { + auto p = nums[i]; + wintoolinfos.move(p, p - 1); + auto item = lstoolwin->takeItem(p); + lstoolwin->insertItem(p - 1, item); + wintool.mvItem(p, p - 1); + } +} + +void CenterWindow::on_downWinTool() { + auto sels = lstoolwin->selectionModel()->selectedRows(); + QVector nums; + for (auto &item : sels) { + nums.append(item.row()); + } + + std::sort(nums.begin(), nums.end(), std::greater()); + + // 过滤掉不需移动的选项 + int i = 0; + auto len = nums.count(); + if (nums.first() == lstoolwin->count() - 1) { + int pi = nums.first(); + for (; i < len; i++) { + pi--; + if (nums[i] != pi) + break; + } + } + + // 下面就开始乾坤大挪移 + for (; i < len; i++) { + auto p = nums[i]; + wintoolinfos.move(p, p + 1); + auto item = lstoolwin->takeItem(p); + lstoolwin->insertItem(p + 1, item); + wintool.mvItem(p, p + 1); + } +} void CenterWindow::on_exportSettings() { auto path = DFileDialog::getSaveFileName(this, tr(""), QString(), @@ -796,6 +932,10 @@ void CenterWindow::initGeneralSettings() { connect(sbGridsize, QOverload::of(&DSpinBox::valueChanged), sm, &SettingManager::setToolGridSize); + // WinTool 相关 + wintool.setModal(true); + connect(&wintool, &ToolBoxWindow::sigRun, this, + [=](int index) { this->runTask(wintoolinfos[index]); }); auto seq = sm->toolBoxHotkey(); kseqTool->setKeySequence(seq); hkwintool = manager->registerHotkey(seq, false); diff --git a/dialog/centerwindow.h b/dialog/centerwindow.h index 464fae9..ecafe04 100644 --- a/dialog/centerwindow.h +++ b/dialog/centerwindow.h @@ -52,12 +52,12 @@ private: void on_addHotkey(); void enableSelectedHotkeys(bool enable); - void on_editToolWin(); - void on_removeToolWin(); - void on_clearToolWin(); - void on_addToolWin(); - void on_upToolWin(); - void on_downToolWin(); + void on_editWinTool(); + void on_removeWinTool(); + void on_clearWinTool(); + void on_addWinTool(); + void on_upWinTool(); + void on_downWinTool(); void on_exportSettings(); void on_importSettings(); @@ -77,7 +77,7 @@ protected: void closeEvent(QCloseEvent *event) override; private: - QList hkcmenu; + QList hkcmenu, lscmenu; private: AppManager *manager; diff --git a/dialog/pluginseldialog.cpp b/dialog/pluginseldialog.cpp index f96272f..3c89a4b 100644 --- a/dialog/pluginseldialog.cpp +++ b/dialog/pluginseldialog.cpp @@ -61,12 +61,12 @@ PluginSelDialog::PluginSelDialog(DDialog *parent) : DDialog(parent) { auto b = new DButtonBoxButton(tr("Select"), this); connect(b, &DButtonBoxButton::clicked, this, [=] { auto item = lsplgs->currentItem(); - auto sel = item->data(Qt::UserRole).toInt(); - if (sel < 0) { + if (!item) { DMessageManager::instance()->sendMessage(this, ProgramIcon, tr("NoSelection")); return; } + auto sel = item->data(Qt::UserRole).toInt(); this->done(sel); }); blist.append(b); diff --git a/dialog/toolboxwindow.cpp b/dialog/toolboxwindow.cpp index 91add59..1005b2d 100644 --- a/dialog/toolboxwindow.cpp +++ b/dialog/toolboxwindow.cpp @@ -1,19 +1,64 @@ #include "toolboxwindow.h" -#include "control/wintoolitem.h" +#include "plugin/pluginsystem.h" #include +#include +#include #include #include #include ToolBoxWindow::ToolBoxWindow(DMainWindow *parent) : DDialog(parent) { + setWindowTitle(tr("PleaseChoose")); + setWindowFlag(Qt::Tool); + setWindowFlag(Qt::WindowStaysOnTopHint); + setCloseButtonVisible(false); lstool = new DListWidget(this); + lstool->setMouseTracking(true); + auto pe = lstool->palette(); + pe.setColor(QPalette::AlternateBase, + DGuiApplicationHelper::instance()->themeType() == + DGuiApplicationHelper::LightType + ? pe.base().color().darker(125) + : pe.base().color().lighter(125)); + lstool->setPalette(pe); + lstool->setAlternatingRowColors(true); + itemheight = lstool->fontMetrics().lineSpacing() * 4; + lstool->setMinimumHeight(itemheight * 5); addContent(lstool); + + connect(DGuiApplicationHelper::instance(), + &DGuiApplicationHelper::themeTypeChanged, this, + &ToolBoxWindow::setTheme); + + connect(lstool, &DListWidget::clicked, this, [=](const QModelIndex &index) { + emit this->sigRun(index.row()); + lstool->clearSelection(); + this->hide(); + }); + + connect(lstool, &DListWidget::itemEntered, this, + [=](QListWidgetItem *item) { item->setSelected(true); }); } void ToolBoxWindow::addItem(ToolStructInfo &info, int index) { - auto pitem = new QListWidgetItem; + auto plgsys = PluginSystem::instance(); + auto plg = plgsys->plugin(info.pluginIndex); + auto icon = Utilities::trimIconFromInfo(plg, info); + QString content = tr("Process:") + Utilities::getProgramName(info) + '\n'; - auto item = new WinToolItem(this); + if (info.isPlugin) + content += (tr("Service:") + plg->pluginServices()[info.serviceID]); + if (info.params.length()) + content += ('\n' + tr("Params:") + info.params); + + auto pitem = new QListWidgetItem(icon, content); + pitem->setTextAlignment(Qt::AlignCenter); + pitem->setSizeHint(QSize(0, itemheight)); + + if (index < 0) + lstool->addItem(pitem); + else + lstool->insertItem(index, pitem); } void ToolBoxWindow::rmItem(int index) { @@ -34,4 +79,25 @@ void ToolBoxWindow::mvItem(int from, int to) { auto len = lstool->count(); if (from < 0 || from >= len || to < 0 || to >= len) return; + + auto item = lstool->takeItem(from); + lstool->insertItem(to, item); +} + +void ToolBoxWindow::setTheme(DGuiApplicationHelper::ColorType theme) { + auto pe = lstool->palette(); + pe.setColor(QPalette::AlternateBase, theme == DGuiApplicationHelper::LightType + ? pe.base().color().darker(125) + : pe.base().color().lighter(125)); + lstool->setPalette(pe); +} + +void ToolBoxWindow::leaveEvent(QEvent *e) { + Q_UNUSED(e); + hide(); +} + +void ToolBoxWindow::focusOutEvent(QFocusEvent *event) { + Q_UNUSED(event); + hide(); } diff --git a/dialog/toolboxwindow.h b/dialog/toolboxwindow.h index 5f6f6ab..9b65524 100644 --- a/dialog/toolboxwindow.h +++ b/dialog/toolboxwindow.h @@ -3,6 +3,7 @@ #include "utilities.h" #include +#include #include #include @@ -11,15 +12,26 @@ DWIDGET_USE_NAMESPACE class ToolBoxWindow : public DDialog { Q_OBJECT public: - ToolBoxWindow(DMainWindow *parent = nullptr); + explicit ToolBoxWindow(DMainWindow *parent = nullptr); public: void addItem(ToolStructInfo &info, int index = -1); // -1 表示追加 void rmItem(int index); // -1 表示清空 void mvItem(int from, int to); +private: + void setTheme(DGuiApplicationHelper::ColorType theme); + +protected: + void leaveEvent(QEvent *e) override; + void focusOutEvent(QFocusEvent *event) override; + +signals: + void sigRun(int index); + private: DListWidget *lstool; + int itemheight; }; #endif // TOOLBOXWINDOW_H diff --git a/plugin/iwingtoolplg.h b/plugin/iwingtoolplg.h index 10c63d3..8bb2c86 100644 --- a/plugin/iwingtoolplg.h +++ b/plugin/iwingtoolplg.h @@ -124,6 +124,9 @@ public slots: // 宿主开始回调函数时候使用,第一个参数是函数服务索引,第二个是参数集合 virtual QVariant pluginServicePipe(int serviceID, QList params) = 0; + // 当插件窗口选中该插件点击设置按钮时触发,以供插件调用自身设置对话框 + virtual void onSetting() {} + // 当鼠标任何一个键被按下就会触发该函数,如果想处理重载 virtual void buttonPress(Qt::MouseButton btn, int x, int y) { Q_UNUSED(btn);