KConfigWidgets

kcommandbar.cpp
1/*
2 SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6#include "kcommandbar.h"
7#include "kcommandbarmodel_p.h"
8#include "kconfigwidgets_debug.h"
9
10#include <QAction>
11#include <QCoreApplication>
12#include <QGraphicsOpacityEffect>
13#include <QHeaderView>
14#include <QKeyEvent>
15#include <QLabel>
16#include <QLineEdit>
17#include <QMainWindow>
18#include <QMenu>
19#include <QPainter>
20#include <QPointer>
21#include <QScreen>
22#include <QSortFilterProxyModel>
23#include <QStatusBar>
24#include <QStyledItemDelegate>
25#include <QTextLayout>
26#include <QToolBar>
27#include <QTreeView>
28#include <QVBoxLayout>
29
30#include <KConfigGroup>
31#include <KFuzzyMatcher>
32#include <KLocalizedString>
33#include <KSharedConfig>
34
35static QRect getCommandBarBoundingRect(KCommandBar *commandBar)
36{
37 QWidget *parentWidget = commandBar->parentWidget();
38 Q_ASSERT(parentWidget);
39
40 const QMainWindow *mainWindow = qobject_cast<const QMainWindow *>(parentWidget);
41 if (!mainWindow) {
42 return parentWidget->geometry();
43 }
44
45 QRect boundingRect = mainWindow->contentsRect();
46
47 // exclude the menu bar from the bounding rect
48 if (const QWidget *menuWidget = mainWindow->menuWidget()) {
49 if (!menuWidget->isHidden()) {
50 boundingRect.setTop(boundingRect.top() + menuWidget->height());
51 }
52 }
53
54 // exclude the status bar from the bounding rect
55 if (const QStatusBar *statusBar = mainWindow->findChild<QStatusBar *>()) {
56 if (!statusBar->isHidden()) {
57 boundingRect.setBottom(boundingRect.bottom() - statusBar->height());
58 }
59 }
60
61 // exclude any undocked toolbar from the bounding rect
62 const QList<QToolBar *> toolBars = mainWindow->findChildren<QToolBar *>();
63 for (QToolBar *toolBar : toolBars) {
64 if (toolBar->isHidden() || toolBar->isFloating()) {
65 continue;
66 }
67
68 switch (mainWindow->toolBarArea(toolBar)) {
70 boundingRect.setTop(std::max(boundingRect.top(), toolBar->geometry().bottom()));
71 break;
73 boundingRect.setRight(std::min(boundingRect.right(), toolBar->geometry().left()));
74 break;
76 boundingRect.setBottom(std::min(boundingRect.bottom(), toolBar->geometry().top()));
77 break;
79 boundingRect.setLeft(std::max(boundingRect.left(), toolBar->geometry().right()));
80 break;
81 default:
82 break;
83 }
84 }
85
86 return boundingRect;
87}
88
89// BEGIN CommandBarFilterModel
90class CommandBarFilterModel final : public QSortFilterProxyModel
91{
92public:
93 CommandBarFilterModel(QObject *parent = nullptr)
95 {
97 m_hasActionsWithIcons = false;
98 });
99 }
100
101 bool hasActionsWithIcons() const
102 {
103 return m_hasActionsWithIcons;
104 }
105
106 Q_SLOT void setFilterString(const QString &string)
107 {
108 // MUST reset the model here, we want to repopulate
109 // invalidateFilter() will not work here
111 m_pattern = string;
113 }
114
115protected:
116 bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override
117 {
118 const int scoreLeft = sourceLeft.data(KCommandBarModel::Score).toInt();
119 const int scoreRight = sourceRight.data(KCommandBarModel::Score).toInt();
120 if (scoreLeft == scoreRight) {
121 const QString textLeft = sourceLeft.data().toString();
122 const QString textRight = sourceRight.data().toString();
123
124 return textRight.localeAwareCompare(textLeft) < 0;
125 }
126
127 return scoreLeft < scoreRight;
128 }
129
130 bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
131 {
132 const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
133
134 bool accept = false;
135 if (m_pattern.isEmpty()) {
136 accept = true;
137 } else {
140 sourceModel()->setData(index, resAction.score, KCommandBarModel::Score);
141 accept = resAction.matched;
142 }
143
144 if (accept && !m_hasActionsWithIcons) {
145 m_hasActionsWithIcons |= !index.data(Qt::DecorationRole).isNull();
146 }
147
148 return accept;
149 }
150
151private:
152 QString m_pattern;
153 mutable bool m_hasActionsWithIcons = false;
154};
155// END CommandBarFilterModel
156
157class CommandBarStyleDelegate final : public QStyledItemDelegate
158{
159public:
160 CommandBarStyleDelegate(QObject *parent = nullptr)
162 {
163 }
164
165 /**
166 * Paints a single item's text
167 */
168 static void
169 paintItemText(QPainter *p, const QString &textt, const QRect &rect, const QStyleOptionViewItem &options, QList<QTextLayout::FormatRange> formats)
170 {
171 QString text = options.fontMetrics.elidedText(textt, Qt::ElideRight, rect.width());
172
173 // set formats and font
174 QTextLayout textLayout(text, options.font);
175 formats.append(textLayout.formats());
176 textLayout.setFormats(formats);
177
178 // set alignment, rtls etc
179 QTextOption textOption;
180 textOption.setTextDirection(options.direction);
181 textOption.setAlignment(QStyle::visualAlignment(options.direction, options.displayAlignment));
182 textLayout.setTextOption(textOption);
183
184 // layout the text
185 textLayout.beginLayout();
186
187 QTextLine line = textLayout.createLine();
188 if (!line.isValid()) {
189 return;
190 }
191
192 const int lineWidth = rect.width();
193 line.setLineWidth(lineWidth);
194 line.setPosition(QPointF(0, 0));
195
196 textLayout.endLayout();
197
198 /**
199 * get "Y" so that we can properly V-Center align the text in row
200 */
201 const int y = QStyle::alignedRect(Qt::LeftToRight, Qt::AlignVCenter, textLayout.boundingRect().size().toSize(), rect).y();
202
203 // draw the text
204 const QPointF pos(rect.x(), y);
205 textLayout.draw(p, pos);
206 }
207
208 void paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &index) const override
209 {
210 painter->save();
211
212 /**
213 * Draw everything, (widget, icon etc) except the text
214 */
215 QStyleOptionViewItem option = opt;
216 initStyleOption(&option, index);
217 option.text.clear(); // clear old text
218 QStyle *style = option.widget->style();
219 style->drawControl(QStyle::CE_ItemViewItem, &option, painter, option.widget);
220
221 const int hMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, option.widget);
222
223 QRect textRect = option.rect;
224
225 const CommandBarFilterModel *model = static_cast<const CommandBarFilterModel *>(index.model());
226 if (model->hasActionsWithIcons()) {
227 const int iconWidth = option.decorationSize.width() + (hMargin * 2);
228 if (option.direction == Qt::RightToLeft) {
229 textRect.adjust(0, 0, -iconWidth, 0);
230 } else {
231 textRect.adjust(iconWidth, 0, 0, 0);
232 }
233 }
234
235 const QString original = index.data().toString();
237 int componentIdx = original.indexOf(QLatin1Char(':'));
238 int actionNameStart = 0;
239 if (componentIdx > 0) {
241 // + 2 because there is a space after colon
242 str = str.mid(actionNameStart);
243 }
244
246 if (componentIdx > 0) {
248 gray.setForeground(option.palette.placeholderText());
249 formats.append({0, componentIdx, gray});
250 }
251
253 fmt.setForeground(option.palette.link());
254 fmt.setFontWeight(QFont::Bold);
255
256 /**
257 * Highlight matches from fuzzy matcher
258 */
259 const auto fmtRanges = KFuzzyMatcher::matchedRanges(m_filterString, str);
261 f.setForeground(option.palette.link());
262 formats.reserve(formats.size() + fmtRanges.size());
263 std::transform(fmtRanges.begin(), fmtRanges.end(), std::back_inserter(formats), [f, actionNameStart](const KFuzzyMatcher::Range &fr) {
264 return QTextLayout::FormatRange{fr.start + actionNameStart, fr.length, f};
265 });
266
267 textRect.adjust(hMargin, 0, -hMargin, 0);
268 paintItemText(painter, original, textRect, option, std::move(formats));
269
270 painter->restore();
271 }
272
273public Q_SLOTS:
274 void setFilterString(const QString &text)
275 {
276 m_filterString = text;
277 }
278
279private:
280 QString m_filterString;
281};
282
283class ShortcutStyleDelegate final : public QStyledItemDelegate
284{
285public:
286 ShortcutStyleDelegate(QObject *parent = nullptr)
288 {
289 }
290
291 void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override
292 {
293 // draw background
294 option.widget->style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter);
295
296 const QString shortcutString = index.data().toString();
297 if (shortcutString.isEmpty()) {
298 return;
299 }
300
301 const ShortcutSegments shortcutSegments = splitShortcut(shortcutString);
302 if (shortcutSegments.isEmpty()) {
303 return;
304 }
305
306 struct Button {
307 int textWidth;
308 QString text;
309 };
310
311 // compute the width of each shortcut segment
313 btns.reserve(shortcutSegments.count());
314 const int hMargin = horizontalMargin(option);
315 for (const QString &text : shortcutSegments) {
316 int textWidth = option.fontMetrics.horizontalAdvance(text);
317 textWidth += 2 * hMargin;
318 btns.append({textWidth, text});
319 }
320
321 int textHeight = option.fontMetrics.lineSpacing();
322 // this happens on gnome so we manually decrease the height a bit
323 if (textHeight == option.rect.height()) {
324 textHeight -= 4;
325 }
326
327 const int y = option.rect.y() + (option.rect.height() - textHeight) / 2;
328 int x;
329 if (option.direction == Qt::RightToLeft) {
330 x = option.rect.x() + hMargin;
331 } else {
332 x = option.rect.right() - shortcutDrawingWidth(option, shortcutSegments, hMargin) - hMargin;
333 }
334
335 painter->save();
336 painter->setPen(option.palette.buttonText().color());
338 for (int i = 0, n = btns.count(); i < n; ++i) {
339 const Button &button = btns.at(i);
340
341 QRect outputRect(x, y, button.textWidth, textHeight);
342
343 // an even element indicates that it is a key
344 if (i % 2 == 0) {
345 painter->save();
346 painter->setPen(Qt::NoPen);
347
348 // draw rounded rect shadow
349 auto shadowRect = outputRect.translated(0, 1);
350 painter->setBrush(option.palette.shadow());
351 painter->drawRoundedRect(shadowRect, 3.0, 3.0);
352
353 // draw rounded rect itself
354 painter->setBrush(option.palette.window());
355 painter->drawRoundedRect(outputRect, 3.0, 3.0);
356
357 painter->restore();
358 }
359
360 // draw shortcut segment
361 painter->drawText(outputRect, Qt::AlignCenter, button.text);
362
363 x += outputRect.width();
364 }
365
366 painter->restore();
367 }
368
369 QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override
370 {
371 if (index.isValid() && index.column() == KCommandBarModel::Column_Shortcut) {
372 const QString shortcut = index.data().toString();
373 if (!shortcut.isEmpty()) {
374 const ShortcutSegments shortcutSegments = splitShortcut(shortcut);
375 if (!shortcutSegments.isEmpty()) {
376 const int hMargin = horizontalMargin(option);
377 int width = shortcutDrawingWidth(option, shortcutSegments, hMargin);
378
379 // add left and right margins
380 width += 2 * hMargin;
381
382 return QSize(width, 0);
383 }
384 }
385 }
386
387 return QStyledItemDelegate::sizeHint(option, index);
388 }
389
390private:
391 using ShortcutSegments = QStringList;
392
393 // split shortcut into segments i.e. will return
394 // ["Ctrl", "+", "A", ", ", "Ctrl", "+", "K"] for "Ctrl+A, Ctrl+K"
395 // twice as fast as using regular expressions
396 static ShortcutSegments splitShortcut(const QString &shortcut)
397 {
398 ShortcutSegments segments;
399 if (!shortcut.isEmpty()) {
400 const int shortcutLength = shortcut.length();
401 int start = 0;
402 for (int i = 0; i < shortcutLength; ++i) {
403 const QChar c = shortcut.at(i);
404 if (c == QLatin1Char('+')) {
405 if (i > start) {
406 segments << shortcut.mid(start, i - start);
407 }
408 segments << shortcut.at(i);
409 start = i + 1;
410 } else if (c == QLatin1Char(',')) {
411 if (i > start) {
412 segments << shortcut.mid(start, i - start);
413 start = i;
414 }
415 const int j = i + 1;
416 if (j < shortcutLength && shortcut.at(j) == QLatin1Char(' ')) {
417 segments << shortcut.mid(start, j - start + 1);
418 i = j;
419 } else {
420 segments << shortcut.at(i);
421 }
422 start = i + 1;
423 }
424 }
425 if (start < shortcutLength) {
426 segments << shortcut.mid(start);
427 }
428
429 // check we have successfully parsed the shortcut
430 if (segments.isEmpty()) {
431 qCWarning(KCONFIG_WIDGETS_LOG) << "Splitting shortcut failed" << shortcut;
432 }
433 }
434
435 return segments;
436 }
437
438 // returns the width needed to draw the shortcut
439 static int shortcutDrawingWidth(const QStyleOptionViewItem &option, const ShortcutSegments &shortcutSegments, int hMargin)
440 {
441 int width = 0;
442 if (!shortcutSegments.isEmpty()) {
443 width = option.fontMetrics.horizontalAdvance(shortcutSegments.join(QString()));
444
445 // add left and right margins for each segment
446 width += shortcutSegments.count() * 2 * hMargin;
447 }
448
449 return width;
450 }
451
452 int horizontalMargin(const QStyleOptionViewItem &option) const
453 {
454 return option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option) + 2;
455 }
456};
457
458// BEGIN KCommandBarPrivate
459class KCommandBarPrivate
460{
461public:
462 QTreeView m_treeView;
463 QLineEdit m_lineEdit;
464 KCommandBarModel m_model;
465 CommandBarFilterModel m_proxyModel;
466
467 /**
468 * selects first item in treeview
469 */
470 void reselectFirst()
471 {
472 const QModelIndex index = m_proxyModel.index(0, 0);
473 m_treeView.setCurrentIndex(index);
474 }
475
476 /**
477 * blocks signals before clearing line edit to ensure
478 * we don't trigger filtering / sorting
479 */
480 void clearLineEdit()
481 {
482 const QSignalBlocker blocker(m_lineEdit);
483 m_lineEdit.clear();
484 }
485
486 void slotReturnPressed(KCommandBar *q);
487
488 void setLastUsedActions();
489
490 QStringList lastUsedActions() const;
491};
492
493void KCommandBarPrivate::slotReturnPressed(KCommandBar *q)
494{
495 auto act = m_proxyModel.data(m_treeView.currentIndex(), Qt::UserRole).value<QAction *>();
496 if (act) {
497 // if the action is a menu, we take all its actions
498 // and reload our dialog with these instead.
499 if (auto menu = act->menu()) {
500 auto menuActions = menu->actions();
502
503 // if there are no actions, trigger load actions
504 // this happens with some menus that are loaded on demand
505 if (menuActions.size() == 0) {
506 Q_EMIT menu->aboutToShow();
507 ag.actions = menu->actions();
508 }
509
510 QString groupName = KLocalizedString::removeAcceleratorMarker(act->text());
511 ag.name = groupName;
512
513 m_model.refresh({ag});
514 reselectFirst();
515 /**
516 * We want the "textChanged" signal here
517 * so that proxy model triggers filtering again
518 * so don't use d->clearLineEdit()
519 */
520 m_lineEdit.clear();
521 return;
522 } else {
523 m_model.actionTriggered(act->text());
524 q->hide();
525 act->trigger();
526 }
527 }
528
529 clearLineEdit();
530 q->hide();
531 q->deleteLater();
532}
533
534void KCommandBarPrivate::setLastUsedActions()
535{
537 KConfigGroup cg(cfg, QStringLiteral("General"));
538
539 QStringList actionNames = cg.readEntry(QStringLiteral("CommandBarLastUsedActions"), QStringList());
540
541 return m_model.setLastUsedActions(actionNames);
542}
543
544QStringList KCommandBarPrivate::lastUsedActions() const
545{
546 return m_model.lastUsedActions();
547}
548// END KCommandBarPrivate
549
550// BEGIN KCommandBar
552 : QFrame(parent)
553 , d(new KCommandBarPrivate)
554{
556 e->setColor(palette().color(QPalette::Shadow));
557 e->setOffset(2.);
558 e->setBlurRadius(8.);
560
564
566 layout->setSpacing(0);
567 layout->setContentsMargins(2, 2, 2, 2);
569
570 setFocusProxy(&d->m_lineEdit);
571
572 layout->addWidget(&d->m_lineEdit);
573
574 layout->addWidget(&d->m_treeView);
575 d->m_treeView.setTextElideMode(Qt::ElideLeft);
576 d->m_treeView.setUniformRowHeights(true);
577
578 CommandBarStyleDelegate *delegate = new CommandBarStyleDelegate(this);
579 ShortcutStyleDelegate *del = new ShortcutStyleDelegate(this);
580 d->m_treeView.setItemDelegateForColumn(KCommandBarModel::Column_Command, delegate);
581 d->m_treeView.setItemDelegateForColumn(KCommandBarModel::Column_Shortcut, del);
582
583 connect(&d->m_lineEdit, &QLineEdit::returnPressed, this, [this]() {
584 d->slotReturnPressed(this);
585 });
586 connect(&d->m_lineEdit, &QLineEdit::textChanged, &d->m_proxyModel, &CommandBarFilterModel::setFilterString);
587 connect(&d->m_lineEdit, &QLineEdit::textChanged, delegate, &CommandBarStyleDelegate::setFilterString);
588 connect(&d->m_lineEdit, &QLineEdit::textChanged, this, [this]() {
589 d->m_treeView.viewport()->update();
590 d->reselectFirst();
591 });
592 connect(&d->m_treeView, &QTreeView::clicked, this, [this]() {
593 d->slotReturnPressed(this);
594 });
595
596 d->m_proxyModel.setSourceModel(&d->m_model);
597 d->m_treeView.setSortingEnabled(true);
598 d->m_treeView.setModel(&d->m_proxyModel);
599
600 d->m_treeView.header()->setMinimumSectionSize(0);
601 d->m_treeView.header()->setStretchLastSection(false);
602 d->m_treeView.header()->setSectionResizeMode(KCommandBarModel::Column_Command, QHeaderView::Stretch);
603 d->m_treeView.header()->setSectionResizeMode(KCommandBarModel::Column_Shortcut, QHeaderView::ResizeToContents);
604
606 d->m_treeView.installEventFilter(this);
607 d->m_lineEdit.installEventFilter(this);
608
609 d->m_treeView.setHeaderHidden(true);
610 d->m_treeView.setRootIsDecorated(false);
611 d->m_treeView.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
612 d->m_treeView.setSelectionMode(QTreeView::SingleSelection);
613
615 placeholderLabel->setAlignment(Qt::AlignCenter);
616 placeholderLabel->setTextInteractionFlags(Qt::NoTextInteraction);
617 placeholderLabel->setWordWrap(true);
618 placeholderLabel->setText(i18n("No commands matching the filter"));
619 // To match the size of a level 2 Heading/KTitleWidget
621 placeholderLabelFont.setPointSize(qRound(placeholderLabelFont.pointSize() * 1.3));
623 // Match opacity of QML placeholder label component
625 opacityEffect->setOpacity(0.5);
626 placeholderLabel->setGraphicsEffect(opacityEffect);
627
630 d->m_treeView.setLayout(placeholderLayout);
631
632 connect(&d->m_proxyModel, &CommandBarFilterModel::modelReset, this, [this, placeholderLabel]() {
633 placeholderLabel->setHidden(d->m_proxyModel.rowCount() > 0);
634 });
635
636 setHidden(true);
637
638 // Migrate last used action config to new location
639 KConfigGroup cg(KSharedConfig::openConfig(), QStringLiteral("General"));
640 if (cg.hasKey("CommandBarLastUsedActions")) {
641 const QStringList actionNames = cg.readEntry("CommandBarLastUsedActions", QStringList());
642
643 KConfigGroup stateCg(KSharedConfig::openStateConfig(), QStringLiteral("General"));
644 stateCg.writeEntry(QStringLiteral("CommandBarLastUsedActions"), actionNames);
645
646 cg.deleteEntry(QStringLiteral("CommandBarLastUsedActions"));
647 }
648}
649
650/**
651 * Destructor defined here to make unique_ptr work
652 */
654{
655 auto lastUsedActions = d->lastUsedActions();
657 KConfigGroup cg(cfg, QStringLiteral("General"));
658 cg.writeEntry("CommandBarLastUsedActions", lastUsedActions);
659
660 // Explicitly remove installed event filters of children of d-pointer
661 // class, otherwise while KCommandBar is being torn down, an event could
662 // fire and the eventFilter() accesses d, which would cause a crash
663 // bug 452527
664 d->m_treeView.removeEventFilter(this);
665 d->m_lineEdit.removeEventFilter(this);
666}
667
669{
670 // First set last used actions in the model
671 d->setLastUsedActions();
672
673 d->m_model.refresh(actions);
674 d->reselectFirst();
675
676 show();
677 setFocus();
678}
679
680void KCommandBar::show()
681{
682 const QRect boundingRect = getCommandBarBoundingRect(this);
683
684 static constexpr int minWidth = 500;
685 const int maxWidth = boundingRect.width();
686 const int preferredWidth = maxWidth / 2.4;
687
688 static constexpr int minHeight = 250;
689 const int maxHeight = boundingRect.height();
690 const int preferredHeight = maxHeight / 2;
691
692 const QSize size{std::min(maxWidth, std::max(preferredWidth, minWidth)), std::min(maxHeight, std::max(preferredHeight, minHeight))};
693
695
696 // set the position to the top-center of the parent
697 // just below the menubar/toolbar (if any)
698 const QPoint position{boundingRect.center().x() - size.width() / 2, boundingRect.y()};
699 move(position);
700
702}
703
704bool KCommandBar::eventFilter(QObject *obj, QEvent *event)
705{
706 if (event->type() == QEvent::KeyPress || event->type() == QEvent::ShortcutOverride) {
707 QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
708 if (obj == &d->m_lineEdit) {
709 const int key = keyEvent->key();
710 const bool forward2list = (key == Qt::Key_Up) || (key == Qt::Key_Down) || (key == Qt::Key_PageUp) || (key == Qt::Key_PageDown);
711 if (forward2list) {
712 QCoreApplication::sendEvent(&d->m_treeView, event);
713 return true;
714 }
715 } else if (obj == &d->m_treeView) {
716 const int key = keyEvent->key();
717 const bool forward2input = (key != Qt::Key_Up) && (key != Qt::Key_Down) && (key != Qt::Key_PageUp) && (key != Qt::Key_PageDown)
718 && (key != Qt::Key_Tab) && (key != Qt::Key_Backtab);
719 if (forward2input) {
720 QCoreApplication::sendEvent(&d->m_lineEdit, event);
721 return true;
722 }
723 }
724
725 if (keyEvent->key() == Qt::Key_Escape) {
726 hide();
727 deleteLater();
728 return true;
729 }
730 }
731
732 // hide on focus out, if neither input field nor list have focus!
733 else if (event->type() == QEvent::FocusOut && isVisible() && !(d->m_lineEdit.hasFocus() || d->m_treeView.hasFocus())) {
734 d->clearLineEdit();
735 deleteLater();
736 hide();
737 return true;
738 }
739
740 // handle resizing
741 if (parent() == obj && event->type() == QEvent::Resize) {
742 show();
743 }
744
746}
747// END KCommandBar
748
749#include "moc_kcommandbar.cpp"
A hud style menu which allows listing and executing actions.
Definition kcommandbar.h:48
KCommandBar(QWidget *parent)
constructor
void setActions(const QList< ActionGroup > &actions)
actions is a list of {GroupName, QAction}.
~KCommandBar() override
Destructor defined here to make unique_ptr work.
static QString removeAcceleratorMarker(const QString &label)
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
static KSharedConfig::Ptr openStateConfig(const QString &fileName=QString())
Q_SCRIPTABLE Q_NOREPLY void start()
QString i18n(const char *text, const TYPE &arg...)
KCOREADDONS_EXPORT Result match(QStringView pattern, QStringView str)
KCOREADDONS_EXPORT QList< KFuzzyMatcher::Range > matchedRanges(QStringView pattern, QStringView str, RangeType type=RangeType::FullyMatched)
const QList< QKeySequence > & shortcut(StandardShortcut id)
void modelAboutToBeReset()
void clicked(const QModelIndex &index)
QModelIndex currentIndex() const const
void setCurrentIndex(const QModelIndex &index)
bool sendEvent(QObject *receiver, QEvent *event)
virtual bool event(QEvent *e) override
void setFrameShadow(Shadow)
void setFrameShape(Shape)
void setBlurRadius(qreal blurRadius)
void setColor(const QColor &color)
void setOffset(const QPointF &ofs)
void addWidget(QWidget *w)
void setContentsMargins(const QMargins &margins)
virtual void setSpacing(int)
void clear()
void returnPressed()
void textChanged(const QString &text)
void append(QList< T > &&value)
void reserve(qsizetype size)
qsizetype size() const const
QWidget * menuWidget() const const
Qt::ToolBarArea toolBarArea(const QToolBar *toolbar) const const
int column() const const
QVariant data(int role) const const
bool isValid() const const
const QAbstractItemModel * model() const const
Q_SLOTQ_SLOT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
virtual bool eventFilter(QObject *watched, QEvent *event)
T findChild(const QString &name, Qt::FindChildOptions options) const const
QList< T > findChildren(Qt::FindChildOptions options) const const
void installEventFilter(QObject *filterObj)
QObject * parent() const const
T qobject_cast(QObject *object)
void drawRoundedRect(const QRect &rect, qreal xRadius, qreal yRadius, Qt::SizeMode mode)
void drawText(const QPoint &position, const QString &text)
void restore()
void save()
void setBrush(Qt::BrushStyle style)
void setPen(Qt::PenStyle style)
void setRenderHint(RenderHint hint, bool on)
int x() const const
int bottom() const const
QPoint center() const const
int height() const const
int left() const const
int right() const const
void setBottom(int y)
void setLeft(int x)
void setRight(int x)
void setTop(int y)
int top() const const
int width() const const
int x() const const
int y() const const
virtual QVariant data(const QModelIndex &index, int role) const const override
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const override
bool isEmpty() const const
PM_FocusFrameHMargin
PE_PanelItemViewItem
QRect alignedRect(Qt::LayoutDirection direction, Qt::Alignment alignment, const QSize &size, const QRect &rectangle)
virtual void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const const=0
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const=0
Qt::Alignment visualAlignment(Qt::LayoutDirection direction, Qt::Alignment alignment)
virtual void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const const
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const const override
AlignVCenter
DisplayRole
LeftToRight
ScrollBarAlwaysOff
ElideRight
NoTextInteraction
TopToolBarArea
void keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay)
bool isValid() const const
void setLineWidth(qreal width)
void setPosition(const QPointF &pos)
void setAlignment(Qt::Alignment alignment)
void setTextDirection(Qt::LayoutDirection direction)
bool isNull() const const
QString toString() const const
T value() const const
QList< QAction * > actions() const const
void setAutoFillBackground(bool enabled)
QRect contentsRect() const const
void hide()
QLayout * layout() const const
QWidget * parentWidget() const const
void move(const QPoint &)
void setFixedSize(const QSize &s)
void setFocus()
void setFocusProxy(QWidget *w)
void setGraphicsEffect(QGraphicsEffect *effect)
void setHidden(bool hidden)
void setLayout(QLayout *layout)
void show()
bool isVisible() const const
Represents a list of action that belong to the same group.
Definition kcommandbar.h:57
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:13:01 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.