#include "shortcuts.h" #include #include #include #include #include #include #include #include #include #include /// ShortcutEdit ShortcutEdit::ShortcutEdit(QWidget * parent): CLineEdit(parent) { ti = nullptr; ca = nullptr; connect(this, &CLineEdit::textChanged, this, &ShortcutEdit::textChangedSlot); } void ShortcutEdit::keyPressEvent(QKeyEvent * e) { Qt::KeyboardModifiers km = e->modifiers(); km &= ~Qt::KeypadModifier; km &= ~Qt::GroupSwitchModifier; if (e->key() != Qt::Key_Control && e->key() != Qt::Key_Shift && e->key() != Qt::Key_Alt && e->key() != Qt::Key_Meta) { setText(QKeySequence(km | e->key()).toString()); } } void ShortcutEdit::assignAction(QAction * a) { clear(); ca = a; reset(); } QAction * ShortcutEdit::action() const { return ca; } bool ShortcutEdit::isEmpty() const { return text().isEmpty(); } void ShortcutEdit::commit() { if (!ca) { return; } ca->setShortcut(QKeySequence(text())); } void ShortcutEdit::reset() { if (!ca) { return; } setText(ca->shortcut().toString()); } void ShortcutEdit::textChangedSlot(QString t) { if (ti) { ti->setText(1, t); } } /// Shortcuts Shortcuts::Shortcuts(QWidget * parent, bool on): QTreeWidget(parent) { aw = nullptr; QImage ti(QSize(16, 16), QImage::Format_ARGB32_Premultiplied); QPainter p(&ti); p.setCompositionMode(QPainter::CompositionMode_Clear); p.eraseRect(ti.rect()); p.end(); empty_icon = QPixmap::fromImage(ti); bfont = font(); bfont.setWeight(QFont::Bold); active = on; setColumnCount(2); #if QT_VERSION < 0x050000 header()->setResizeMode(0, QHeaderView::ResizeToContents); header()->setResizeMode(1, QHeaderView::ResizeToContents); #else header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); header()->setSectionResizeMode(1, QHeaderView::ResizeToContents); #endif header()->setStretchLastSection(true); setColumnWidth(1, 200); setSortingEnabled(true); QStringList l; l << tr("Command") << tr("Shortcut"); setHeaderLabels(l); assignWindow(parent); } Shortcuts::~Shortcuts() { for (ShortcutEdit * i: edits) { delete i; } edits.clear(); } void Shortcuts::changeEvent(QEvent * e) { QTreeWidget::changeEvent(e); if (e->type() == QEvent::LanguageChange) { QStringList l; l << tr("Command") << tr("Shortcut"); setHeaderLabels(l); return; } } void Shortcuts::assignWindow(QWidget * w) { if (!w) { return; } while (!(qobject_cast(w)) && (w->parentWidget())) { w = w->parentWidget(); } aw = qobject_cast(w); updateShortcuts(); } QStringList Shortcuts::actionTree(QAction * a) { QStringList tree; QList aw = a->associatedWidgets(); if (aw.size() == 0) { return tree; } for (QWidget * i: aw) { auto tm = qobject_cast(i); if (!tm) { continue; } auto cw = i; while (cw) { tm = qobject_cast(cw); if (tm) { if (!tm->title().isEmpty()) { tree.push_front(tm->title()); } cw = cw->parentWidget(); } else { break; } } if (!tree.isEmpty()) { return tree; } } for (QWidget * i: aw) { auto tt = qobject_cast(i); if (!tt) { continue; } if (!tt->windowTitle().isEmpty()) { tree.push_front(tt->windowTitle()); } break; } return tree; } QList> Shortcuts::shortcuts() { QList> l; for (const ShortcutEdit * i: edits) { if (i->action()->objectName().isEmpty()) { continue; } l << QPair(i->action()->objectName(), i->text()); } return l; } void Shortcuts::clear() { foreach(ShortcutEdit * i, edits) delete i; edits.clear(); hide(); QList tl = findItems("", Qt::MatchContains); foreach(QTreeWidgetItem * i, tl) delete i; show(); } bool Shortcuts::checkAction(QAction * a) { if (a->menu() || a->isSeparator() || a->text().isEmpty()) { return false; } if (a->associatedWidgets().isEmpty()) { return false; } if (QString(a->metaObject()->className()) != "QAction") { return false; } if (qobject_cast(a)) { return false; } return true; } void Shortcuts::updateShortcuts() { if (!aw || !active) { return; } hide(); int cpos = verticalScrollBar()->value(); clear(); #if QT_VERSION < 0x050000 header()->setResizeMode(0, QHeaderView::Fixed); #else header()->setSectionResizeMode(0, QHeaderView::Fixed); #endif QList al = aw->findChildren(); QTreeWidgetItem *pi, *ci; QStringList tree; bool s = isSortingEnabled(), isFound; setSortingEnabled(false); for (QAction * i: al) { if (!checkAction(i)) continue; edits.push_back(new ShortcutEdit()); tree = actionTree(i); pi = invisibleRootItem(); for (const QString & t: tree) { isFound = false; for (int j = 0; j < pi->childCount(); ++j) { if (pi->child(j)->text(0) == t) { pi = pi->child(j); isFound = true; break; } } if (isFound) continue; ci = new QTreeWidgetItem(pi); ci->setText(0, t); ci->setToolTip(0, t); ci->setFont(0, bfont); pi->addChild(ci); pi = ci; } ci = new QTreeWidgetItem(pi); ci->setText(0, i->text()); ci->setToolTip(0, i->text()); if (i->icon().isNull()) ci->setIcon(0, empty_icon); else ci->setIcon(0, i->icon()); edits.back()->ti = ci; edits.back()->assignAction(i); pi->addChild(ci); // qDebug() << "set widget" << edits.back(); setItemWidget(ci, 1, edits.back()); } setSortingEnabled(s); #if QT_VERSION < 0x050000 header()->setResizeMode(0, QHeaderView::ResizeToContents); #else header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); #endif expandAll(); verticalScrollBar()->setValue(cpos); show(); } void Shortcuts::commit() { for (ShortcutEdit * i: edits) { i->commit(); } } void Shortcuts::resetShortcuts() { for (ShortcutEdit * i: edits) { i->reset(); } updateShortcuts(); } void Shortcuts::filter(const QString & what) { hide(); for (int i = 0; i < topLevelItemCount(); ++i) { filterTree(topLevelItem(i), what); } show(); } bool Shortcuts::filterTree(QTreeWidgetItem * ti, QString f) { if (f.isEmpty()) { for (int i = 0; i < ti->childCount(); ++i) { filterTree(ti->child(i), f); } ti->setHidden(false); return true; } bool isFound = false; for (int i = 0; i < ti->childCount(); ++i) { if (filterTree(ti->child(i), f)) { isFound = true; } } if (ti->text(0).indexOf(f, 0, Qt::CaseInsensitive) >= 0 || ti->text(1).indexOf(f, 0, Qt::CaseInsensitive) >= 0) { isFound = true; } ti->setHidden(!isFound); return isFound; } void Shortcuts::updateEditorGeometries() { for (ShortcutEdit * i: edits) { i->setGeometry(visualRect(indexFromItem(i->ti, 1))); } }