Files
qad/libs/widgets/shortcuts.cpp
Andrey 728c132f2b refactoring qad widgets part 1
c++ cast, nullptr, forward declaration, agregate ui, connect to member functions, order and clear includes
2022-12-11 16:27:04 +03:00

335 lines
6.7 KiB
C++

#include "shortcuts.h"
#include <QPainter>
#include <QAction>
#include <QKeyEvent>
#include <QHeaderView>
#include <QMenu>
#include <QScrollBar>
#include <QShortcut>
#include <QWidgetAction>
#include <QMainWindow>
#include <QToolBar>
/// 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<QMainWindow * >(w)) && (w->parentWidget())) {
w = w->parentWidget();
}
aw = qobject_cast<QMainWindow * >(w);
updateShortcuts();
}
QStringList Shortcuts::actionTree(QAction * a) {
QStringList tree;
QList<QWidget * > aw = a->associatedWidgets();
if (aw.size() == 0) {
return tree;
}
for (QWidget * i : aw) {
auto tm = qobject_cast<QMenu * >(i);
if (!tm) {
continue;
}
auto cw = i;
while (cw) {
tm = qobject_cast<QMenu * >(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<QToolBar * >(i);
if (!tt) {
continue;
}
if (!tt->windowTitle().isEmpty()) {
tree.push_front(tt->windowTitle());
}
break;
}
return tree;
}
QList<QPair<QString, QKeySequence> > Shortcuts::shortcuts() {
QList<QPair<QString, QKeySequence> > l;
for (const ShortcutEdit * i : edits) {
if (i->action()->objectName().isEmpty()) {
continue;
}
l << QPair<QString, QKeySequence>(i->action()->objectName(), i->text());
}
return l;
}
void Shortcuts::clear() {
foreach (ShortcutEdit * i, edits)
delete i;
edits.clear();
hide();
QList<QTreeWidgetItem * > 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<QWidgetAction * >(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<QAction * > al = aw->findChildren<QAction * >();
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)));
}
}