From 2a5190f67faca68ab591c07900ce4cdeefa99512 Mon Sep 17 00:00:00 2001 From: "Zheng, Lei" Date: Sat, 12 Mar 2022 13:16:34 +0800 Subject: [PATCH] Gui: move CommandCompleter into its own source file --- src/Gui/Action.cpp | 275 ++++++++--------------------------- src/Gui/Action.h | 38 +++-- src/Gui/CMakeLists.txt | 2 + src/Gui/CommandCompleter.cpp | 239 ++++++++++++++++++++++++++++++ src/Gui/CommandCompleter.h | 59 ++++++++ src/Gui/DlgKeyboardImp.cpp | 20 +-- src/Gui/DlgToolbarsImp.cpp | 9 +- 7 files changed, 393 insertions(+), 249 deletions(-) create mode 100644 src/Gui/CommandCompleter.cpp create mode 100644 src/Gui/CommandCompleter.h diff --git a/src/Gui/Action.cpp b/src/Gui/Action.cpp index 9c33eb0c19..262ca3ec80 100644 --- a/src/Gui/Action.cpp +++ b/src/Gui/Action.cpp @@ -213,11 +213,12 @@ void Action::setToolTip(const QString & s, const QString & title) title.isEmpty() ? _action->text() : title, _action->font(), _action->shortcut().toString(QKeySequence::NativeText), - this)); + _pcCmd)); } -static QString & actionTitle(QString & title) +QString Action::cleanTitle(const QString & text) { + QString title(text); // Deal with QAction title mnemonic static QRegularExpression re(QStringLiteral("&(.)")); title.replace(re, QStringLiteral("\\1")); @@ -227,19 +228,63 @@ static QString & actionTitle(QString & title) return title; } -static inline QString actionTitle(const QString &title) +QString Action::commandToolTip(const Command *cmd, bool richFormat) { - QString text(title); - return actionTitle(text); + if (!cmd) + return QString(); + + if (richFormat) { + if (auto action = cmd->getAction()) + return action->_action->toolTip(); + } + + QString title, tooltip; + if (dynamic_cast(cmd)) { + if (auto txt = cmd->getMenuText()) + title = QString::fromUtf8(txt); + if (auto txt = cmd->getToolTipText()) + tooltip = QString::fromUtf8(txt); + } else { + if (auto txt = cmd->getMenuText()) + title = qApp->translate(cmd->className(), txt); + if (auto txt = cmd->getToolTipText()) + tooltip = qApp->translate(cmd->className(), txt); + } + + if (!richFormat) + return tooltip; + return createToolTip(tooltip, title, QFont(), cmd->getShortcut(), cmd); +} + +QString Action::commandMenuText(const Command *cmd) +{ + if (!cmd) + return QString(); + + QString title; + if (auto action = cmd->getAction()) + title = action->text(); + else if (dynamic_cast(cmd)) { + if (auto txt = cmd->getMenuText()) + title = QString::fromUtf8(txt); + } else { + if (auto txt = cmd->getMenuText()) + title = qApp->translate(cmd->className(), txt); + } + if (title.isEmpty()) + title = QString::fromUtf8(cmd->getName()); + else + title = cleanTitle(title); + return title; } QString Action::createToolTip(QString _tooltip, const QString & title, const QFont &font, const QString &sc, - Action *act) + const Command *pcCmd) { - QString text = actionTitle(title); + QString text = cleanTitle(title); if (text.isEmpty()) return _tooltip; @@ -263,17 +308,18 @@ QString Action::createToolTip(QString _tooltip, text.toHtmlEscaped(), shortcut.toHtmlEscaped()); QString cmdName; - auto pcCmd = act ? act->_pcCmd : nullptr; if (pcCmd && pcCmd->getName()) { cmdName = QString::fromLatin1(pcCmd->getName()); - if (auto groupcmd = dynamic_cast(pcCmd)) { - int idx = act->property("defaultAction").toInt(); - auto cmd = groupcmd->getCommand(idx); - if (cmd && cmd->getName()) - cmdName = QStringLiteral("%1 (%2:%3)") - .arg(QString::fromLatin1(cmd->getName())) - .arg(cmdName) - .arg(idx); + if (auto groupcmd = dynamic_cast(pcCmd)) { + if (auto act = pcCmd->getAction()) { + int idx = act->property("defaultAction").toInt(); + auto cmd = groupcmd->getCommand(idx); + if (cmd && cmd->getName()) + cmdName = QStringLiteral("%1 (%2:%3)") + .arg(QString::fromLatin1(cmd->getName())) + .arg(cmdName) + .arg(idx); + } } cmdName = QStringLiteral("

%1

") .arg(cmdName.toHtmlEscaped()); @@ -1367,201 +1413,4 @@ void WindowAction::addTo ( QWidget * w ) } } -// -------------------------------------------------------------------- - -struct CmdInfo { - Command *cmd = nullptr; - QString text; - QString tooltip; - QIcon icon; - bool iconChecked = false; -}; -static std::vector _Commands; -static int _CommandRevision; -static const int CommandNameRole = Qt::UserRole; - -class CommandModel : public QAbstractItemModel -{ -public: - CommandModel(QObject* parent) - : QAbstractItemModel(parent) - { - update(); - } - - void update() - { - auto &manager = Application::Instance->commandManager(); - if (_CommandRevision == manager.getRevision()) - return; - beginResetModel(); - _CommandRevision = manager.getRevision(); - _Commands.clear(); - for (auto &v : manager.getCommands()) { - _Commands.emplace_back(); - auto &info = _Commands.back(); - info.cmd = v.second; - } - endResetModel(); - } - - virtual QModelIndex parent(const QModelIndex &) const - { - return QModelIndex(); - } - - virtual QVariant data(const QModelIndex & index, int role) const - { - if (index.row() < 0 || index.row() >= (int)_Commands.size()) - return QVariant(); - - auto &info = _Commands[index.row()]; - - switch(role) { - case Qt::DisplayRole: - case Qt::EditRole: - if (info.text.isEmpty()) { - info.text = QStringLiteral("%2 (%1)").arg( - QString::fromLatin1(info.cmd->getName()), - qApp->translate(info.cmd->className(), info.cmd->getMenuText())); - actionTitle(info.text); - if (info.text.isEmpty()) - info.text = QString::fromLatin1(info.cmd->getName()); - } - return info.text; - - case Qt::DecorationRole: - if (!info.iconChecked) { - info.iconChecked = true; - if(info.cmd->getPixmap()) - info.icon = BitmapFactory().iconFromTheme(info.cmd->getPixmap()); - } - return info.icon; - - case Qt::ToolTipRole: - if (info.tooltip.isEmpty()) { - info.tooltip = QString::fromLatin1("%1: %2").arg( - QString::fromLatin1(info.cmd->getName()), - qApp->translate(info.cmd->className(), info.cmd->getMenuText())); - QString tooltip = qApp->translate(info.cmd->className(), info.cmd->getToolTipText()); - if (tooltip.size()) - info.tooltip += QString::fromLatin1("\n\n") + tooltip; - } - return info.tooltip; - - case CommandNameRole: - return QByteArray(info.cmd->getName()); - - default: - return QVariant(); - } - } - - virtual QModelIndex index(int row, int, const QModelIndex &) const - { - return this->createIndex(row, 0); - } - - virtual int rowCount(const QModelIndex &) const - { - return (int)(_Commands.size()); - } - - virtual int columnCount(const QModelIndex &) const - { - return 1; - } -}; - - -// -------------------------------------------------------------------- - -CommandCompleter::CommandCompleter(QLineEdit *lineedit, QObject *parent) - : QCompleter(parent) -{ - this->setModel(new CommandModel(this)); - this->setFilterMode(Qt::MatchContains); - this->setCaseSensitivity(Qt::CaseInsensitive); - this->setCompletionMode(QCompleter::PopupCompletion); - this->setWidget(lineedit); - connect(lineedit, SIGNAL(textEdited(QString)), this, SLOT(onTextChanged(QString))); - connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(onCommandActivated(QModelIndex))); - connect(this, SIGNAL(highlighted(QString)), lineedit, SLOT(setText(QString))); -} - -bool CommandCompleter::eventFilter(QObject *o, QEvent *ev) -{ - if (ev->type() == QEvent::KeyPress - && (o == this->widget() || o == this->popup())) - { - QKeyEvent * ke = static_cast(ev); - switch(ke->key()) { - case Qt::Key_Escape: { - auto edit = qobject_cast(this->widget()); - if (edit && edit->text().size()) { - edit->setText(QString()); - popup()->hide(); - return true; - } else if (popup()->isVisible()) { - popup()->hide(); - return true; - } - break; - } - case Qt::Key_Tab: { - if (this->popup()->isVisible()) { - QKeyEvent kevent(ke->type(),Qt::Key_Down,0); - qApp->sendEvent(this->popup(), &kevent); - return true; - } - break; - } - case Qt::Key_Backtab: { - if (this->popup()->isVisible()) { - QKeyEvent kevent(ke->type(),Qt::Key_Up,0); - qApp->sendEvent(this->popup(), &kevent); - return true; - } - break; - } - case Qt::Key_Enter: - case Qt::Key_Return: - if (o == this->widget()) { - auto index = currentIndex(); - if (index.isValid()) - onCommandActivated(index); - else - complete(); - ev->setAccepted(true); - return true; - } - default: - break; - } - } - return QCompleter::eventFilter(o, ev); -} - -void CommandCompleter::onCommandActivated(const QModelIndex &index) -{ - QByteArray name = completionModel()->data(index, CommandNameRole).toByteArray(); - Q_EMIT commandActivated(name); -} - -void CommandCompleter::onTextChanged(const QString &txt) -{ - // Do not activate completer if less than 3 characters for better - // performance. - if (txt.size() < 3 || !widget()) - return; - - static_cast(this->model())->update(); - - this->setCompletionPrefix(txt); - QRect rect = widget()->rect(); - if (rect.width() < 300) - rect.setWidth(300); - this->complete(rect); -} - #include "moc_Action.cpp" diff --git a/src/Gui/Action.h b/src/Gui/Action.h index a9ec0b359d..e1a4ae1141 100644 --- a/src/Gui/Action.h +++ b/src/Gui/Action.h @@ -81,7 +81,23 @@ public: const QString &title, const QFont &font, const QString &shortcut, - Action *action = nullptr); + const Command *cmd = nullptr); + + /** Obtain tool tip of a given command + * @param cmd: input command + * @param richFormat: whether to output rich text formatted tooltip + */ + static QString commandToolTip(const Command *cmd, bool richFormat = true); + + /** Obtain the menu text of a given command + * @param cmd: input command + * @return Return the command menu text that is stripped with its mnemonic + * symbol '&' and ending punctuations + */ + static QString commandMenuText(const Command *cmd); + + /// Clean the title by stripping the mnemonic symbol '&' and ending punctuations + static QString cleanTitle(const QString &title); Command *command() const { return _pcCmd; @@ -371,26 +387,6 @@ private: QMenu* _menu; }; -/** - * Command name completer. - */ -class GuiExport CommandCompleter : public QCompleter -{ - Q_OBJECT -public: - CommandCompleter(QLineEdit *edit, QObject *parent = nullptr); - -Q_SIGNALS: - void commandActivated(const QByteArray &name); - -protected Q_SLOTS: - void onTextChanged(const QString &); - void onCommandActivated(const QModelIndex &); - -protected: - bool eventFilter(QObject *, QEvent *ev); -}; - } // namespace Gui #endif // GUI_ACTION_H diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt index 68b07a0044..053b701e8c 100644 --- a/src/Gui/CMakeLists.txt +++ b/src/Gui/CMakeLists.txt @@ -385,6 +385,7 @@ SET(Command_CPP_SRCS CommandLink.cpp CommandPyImp.cpp ShortcutManager.cpp + CommandCompleter.cpp ) SET(Command_SRCS ${Command_CPP_SRCS} @@ -393,6 +394,7 @@ SET(Command_SRCS Command.h CommandT.h ShortcutManager.h + CommandCompleter.h ) SOURCE_GROUP("Command" FILES ${Command_SRCS}) diff --git a/src/Gui/CommandCompleter.cpp b/src/Gui/CommandCompleter.cpp new file mode 100644 index 0000000000..aa12acd94d --- /dev/null +++ b/src/Gui/CommandCompleter.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** + * Copyright (c) 2022 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +# include +# include +#endif + +#include "Application.h" +#include "ShortcutManager.h" +#include "Command.h" +#include "Action.h" +#include "BitmapFactory.h" +#include "CommandCompleter.h" + +using namespace Gui; + +namespace { + +struct CmdInfo { + Command *cmd = nullptr; + QIcon icon; + bool iconChecked = false; +}; +std::vector _Commands; +int _CommandRevision; +const int CommandNameRole = Qt::UserRole; +bool _ShortcutSignalConnected = false; + +class CommandModel : public QAbstractItemModel +{ + int revision = 0; + +public: + CommandModel(QObject* parent) + : QAbstractItemModel(parent) + { + update(); + if (!_ShortcutSignalConnected) { + _ShortcutSignalConnected = true; + QObject::connect(ShortcutManager::instance(), &ShortcutManager::shortcutChanged, []{_CommandRevision = 0;}); + } + } + + void update() + { + auto &manager = Application::Instance->commandManager(); + if (revision == _CommandRevision && _CommandRevision == manager.getRevision()) + return; + beginResetModel(); + revision = manager.getRevision(); + if (revision != _CommandRevision) { + _CommandRevision = revision; + _CommandRevision = manager.getRevision(); + _Commands.clear(); + for (auto &v : manager.getCommands()) { + _Commands.emplace_back(); + auto &info = _Commands.back(); + info.cmd = v.second; + } + } + endResetModel(); + } + + virtual QModelIndex parent(const QModelIndex &) const + { + return QModelIndex(); + } + + virtual QVariant data(const QModelIndex & index, int role) const + { + if (index.row() < 0 || index.row() >= (int)_Commands.size()) + return QVariant(); + + auto &info = _Commands[index.row()]; + + switch(role) { + case Qt::DisplayRole: + case Qt::EditRole: { + QString title = QStringLiteral("%1 (%2)").arg( + Action::commandMenuText(info.cmd), + QString::fromUtf8(info.cmd->getName())); + QString shortcut = info.cmd->getShortcut(); + if (!shortcut.isEmpty()) + title += QStringLiteral(" (%1)").arg(shortcut); + return title; + } + case Qt::ToolTipRole: + return Action::commandToolTip(info.cmd); + + case Qt::DecorationRole: + if (!info.iconChecked) { + info.iconChecked = true; + if(info.cmd->getPixmap()) + info.icon = BitmapFactory().iconFromTheme(info.cmd->getPixmap()); + } + return info.icon; + + case CommandNameRole: + return QByteArray(info.cmd->getName()); + + default: + break; + } + return QVariant(); + } + + virtual QModelIndex index(int row, int, const QModelIndex &) const + { + return this->createIndex(row, 0); + } + + virtual int rowCount(const QModelIndex &) const + { + return (int)(_Commands.size()); + } + + virtual int columnCount(const QModelIndex &) const + { + return 1; + } +}; + +} // anonymous namespace + +// -------------------------------------------------------------------- + +CommandCompleter::CommandCompleter(QLineEdit *lineedit, QObject *parent) + : QCompleter(parent) +{ + this->setModel(new CommandModel(this)); + this->setFilterMode(Qt::MatchContains); + this->setCaseSensitivity(Qt::CaseInsensitive); + this->setCompletionMode(QCompleter::PopupCompletion); + this->setWidget(lineedit); + connect(lineedit, SIGNAL(textEdited(QString)), this, SLOT(onTextChanged(QString))); + connect(this, SIGNAL(activated(QModelIndex)), this, SLOT(onCommandActivated(QModelIndex))); + connect(this, SIGNAL(highlighted(QString)), lineedit, SLOT(setText(QString))); +} + +bool CommandCompleter::eventFilter(QObject *o, QEvent *ev) +{ + if (ev->type() == QEvent::KeyPress + && (o == this->widget() || o == this->popup())) + { + QKeyEvent * ke = static_cast(ev); + switch(ke->key()) { + case Qt::Key_Escape: { + auto edit = qobject_cast(this->widget()); + if (edit && edit->text().size()) { + edit->setText(QString()); + popup()->hide(); + return true; + } else if (popup()->isVisible()) { + popup()->hide(); + return true; + } + break; + } + case Qt::Key_Tab: { + if (this->popup()->isVisible()) { + QKeyEvent kevent(ke->type(),Qt::Key_Down,0); + qApp->sendEvent(this->popup(), &kevent); + return true; + } + break; + } + case Qt::Key_Backtab: { + if (this->popup()->isVisible()) { + QKeyEvent kevent(ke->type(),Qt::Key_Up,0); + qApp->sendEvent(this->popup(), &kevent); + return true; + } + break; + } + case Qt::Key_Enter: + case Qt::Key_Return: + if (o == this->widget()) { + auto index = currentIndex(); + if (index.isValid()) + onCommandActivated(index); + else + complete(); + ev->setAccepted(true); + return true; + } + default: + break; + } + } + return QCompleter::eventFilter(o, ev); +} + +void CommandCompleter::onCommandActivated(const QModelIndex &index) +{ + QByteArray name = completionModel()->data(index, CommandNameRole).toByteArray(); + Q_EMIT commandActivated(name); +} + +void CommandCompleter::onTextChanged(const QString &txt) +{ + // Do not activate completer if less than 3 characters for better + // performance. + if (txt.size() < 3 || !widget()) + return; + + static_cast(this->model())->update(); + + this->setCompletionPrefix(txt); + QRect rect = widget()->rect(); + if (rect.width() < 300) + rect.setWidth(300); + this->complete(rect); +} + +#include "moc_CommandCompleter.cpp" diff --git a/src/Gui/CommandCompleter.h b/src/Gui/CommandCompleter.h new file mode 100644 index 0000000000..a2edd07236 --- /dev/null +++ b/src/Gui/CommandCompleter.h @@ -0,0 +1,59 @@ +/**************************************************************************** + * Copyright (c) 2022 Zheng Lei (realthunder) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ****************************************************************************/ + +#ifndef GUI_COMMAND_COMPLETER_H +#define GUI_COMMAND_COMPLETER_H + +#include + +class QLineEdit; + +namespace Gui { + +/** + * Command name auto completer. + * + * This class provides an auto completer for a QLineEdit widget. The auto + * completer supports keyword search in command title, internal name, and + * shortcut. + */ +class GuiExport CommandCompleter : public QCompleter +{ + Q_OBJECT +public: + CommandCompleter(QLineEdit *edit, QObject *parent = nullptr); + +Q_SIGNALS: + /// Triggered when a command is selected in the completer + void commandActivated(const QByteArray &name); + +protected Q_SLOTS: + void onTextChanged(const QString &); + void onCommandActivated(const QModelIndex &); + +protected: + bool eventFilter(QObject *, QEvent *ev); +}; + +} // namespace Gui + +#endif diff --git a/src/Gui/DlgKeyboardImp.cpp b/src/Gui/DlgKeyboardImp.cpp index 5a65721d3b..e95aa6b8b5 100644 --- a/src/Gui/DlgKeyboardImp.cpp +++ b/src/Gui/DlgKeyboardImp.cpp @@ -43,6 +43,7 @@ #include "Window.h" #include "PrefWidgets.h" #include "ShortcutManager.h" +#include "CommandCompleter.h" using namespace Gui::Dialog; @@ -146,19 +147,14 @@ DlgCustomKeyboardImp::initCommandList(QTreeWidget *commandTreeWidget, QComboBox commandTreeWidget->clear(); CommandManager & cCmdMgr = Application::Instance->commandManager(); - QString group = combo->itemData(index, Qt::UserRole).toString(); - auto cmds = group == QStringLiteral("All") ? cCmdMgr.getAllCommands() - : cCmdMgr.getGroupCommands(group.toLatin1()); + auto group = combo->itemData(index, Qt::UserRole).toByteArray(); + auto cmds = group == "All" ? cCmdMgr.getAllCommands() + : cCmdMgr.getGroupCommands(group.constData()); QTreeWidgetItem *currentItem = nullptr; for (const Command *cmd : cmds) { QTreeWidgetItem* item = new QTreeWidgetItem(commandTreeWidget); - if (dynamic_cast(cmd)) { - item->setText(1, QString::fromUtf8(cmd->getMenuText())); - item->setToolTip(1, QString::fromUtf8(cmd->getToolTipText())); - } else { - item->setText(1, qApp->translate(cmd->className(), cmd->getMenuText())); - item->setToolTip(1, qApp->translate(cmd->className(), cmd->getToolTipText())); - } + item->setText(1, Action::commandMenuText(cmd)); + item->setToolTip(1, Action::commandToolTip(cmd)); item->setData(1, Qt::UserRole, QByteArray(cmd->getName())); item->setSizeHint(0, QSize(32, 32)); if (auto pixmap = cmd->getPixmap()) @@ -287,7 +283,7 @@ void DlgCustomKeyboardImp::populatePriorityList(QTreeWidget *priorityList, continue; QTreeWidgetItem* item = new QTreeWidgetItem(priorityList); item->setText(0, QString::fromUtf8(info.first)); - item->setText(1, info.second->text()); + item->setText(1, Action::cleanTitle(info.second->text())); item->setToolTip(0, info.second->toolTip()); item->setIcon(0, info.second->icon()); item->setData(0, Qt::UserRole, info.first); @@ -374,7 +370,7 @@ void DlgCustomKeyboardImp::on_commandTreeWidget_currentItemChanged(QTreeWidgetIt ui->buttonReset->setEnabled((ks != ks2)); } - ui->textLabelDescription->setText(item->toolTip(1)); + ui->textLabelDescription->setText(Action::commandToolTip(cmd, false)); } /** Shows all commands of this category */ diff --git a/src/Gui/DlgToolbarsImp.cpp b/src/Gui/DlgToolbarsImp.cpp index 89e881f802..9d6ced20e2 100644 --- a/src/Gui/DlgToolbarsImp.cpp +++ b/src/Gui/DlgToolbarsImp.cpp @@ -36,6 +36,8 @@ #include "Application.h" #include "BitmapFactory.h" #include "Command.h" +#include "Action.h" +#include "ToolBarManager.h" #include "MainWindow.h" #include "ToolBarManager.h" #include "Widgets.h" @@ -205,9 +207,10 @@ void DlgCustomToolbars::importCustomToolbars(const QByteArray& name) Command* pCmd = rMgr.getCommandByName(it2.first.c_str()); if (pCmd) { // command name - auto item = new QTreeWidgetItem(toplevel); - item->setText(0, qApp->translate(pCmd->className(), pCmd->getMenuText())); - item->setData(0, Qt::UserRole, QByteArray(it2.first.c_str())); + auto* item = new QTreeWidgetItem(toplevel); + item->setText(0, Action::commandMenuText(pCmd)); + item->setToolTip(0, Action::commandToolTip(pCmd)); + item->setData(0, Qt::UserRole, QByteArray(it2->first.c_str())); if (pCmd->getPixmap()) item->setIcon(0, BitmapFactory().iconFromTheme(pCmd->getPixmap())); item->setSizeHint(0, QSize(32, 32));