File 2000-commandbar-checkmarks.patch of Package kf6-kconfigwidgets
diff --git a/src/kcommandbar.cpp b/src/kcommandbar.cpp
index 2c33df738cf2f8b1aae3c2b9f22f970997890c5f..16f78e90c6eec29de2baccc40ba40135385a2316 100644
--- a/src/kcommandbar.cpp
+++ b/src/kcommandbar.cpp
@@ -8,6 +8,7 @@
#include "kconfigwidgets_debug.h"
#include <QAction>
+#include <QActionGroup>
#include <QCoreApplication>
#include <QGraphicsOpacityEffect>
#include <QHeaderView>
@@ -95,6 +96,7 @@ public:
{
connect(this, &CommandBarFilterModel::modelAboutToBeReset, this, [this]() {
m_hasActionsWithIcons = false;
+ m_hasCheckableActions = false;
});
}
@@ -103,6 +105,11 @@ public:
return m_hasActionsWithIcons;
}
+ bool hasCheckableActions() const
+ {
+ return m_hasCheckableActions;
+ }
+
Q_SLOT void setFilterString(const QString &string)
{
// MUST reset the model here, we want to repopulate
@@ -141,8 +148,14 @@ protected:
accept = resAction.matched;
}
- if (accept && !m_hasActionsWithIcons) {
- m_hasActionsWithIcons |= !index.data(Qt::DecorationRole).isNull();
+ if (accept) {
+ if (!m_hasActionsWithIcons) {
+ m_hasActionsWithIcons |= !index.data(Qt::DecorationRole).isNull();
+ }
+
+ if (!m_hasCheckableActions) {
+ m_hasCheckableActions |= !index.data(Qt::CheckStateRole).isNull();
+ }
}
return accept;
@@ -151,6 +164,7 @@ protected:
private:
QString m_pattern;
mutable bool m_hasActionsWithIcons = false;
+ mutable bool m_hasCheckableActions = false;
};
// END CommandBarFilterModel
@@ -216,20 +230,56 @@ public:
initStyleOption(&option, index);
option.text.clear(); // clear old text
QStyle *style = option.widget->style();
- style->drawControl(QStyle::CE_ItemViewItem, &option, painter, option.widget);
-
- const int hMargin = style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, option.widget);
-
- QRect textRect = option.rect;
+ style->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter);
const CommandBarFilterModel *model = static_cast<const CommandBarFilterModel *>(index.model());
+ const bool isRightToLeft = option.direction == Qt::RightToLeft;
+ const int hMargin = 2 * style->pixelMetric(QStyle::PM_FocusFrameHMargin, &option, option.widget);
+
+ QRect outputRect = option.rect;
+ outputRect.adjust(hMargin, 0, -hMargin, 0);
+
+ if (model->hasCheckableActions()) {
+ // draw checkbox
+ QRect checkMarkRect = style->subElementRect(QStyle::SE_CheckBoxIndicator, &option);
+ if (option.features & QStyleOptionViewItem::HasCheckIndicator) {
+ checkMarkRect = QStyle::alignedRect(option.direction, option.displayAlignment, checkMarkRect.size(), outputRect);
+ QStyleOptionViewItem optionCopy = option;
+ optionCopy.rect = checkMarkRect;
+ optionCopy.state = option.state & ~QStyle::State_HasFocus;
+ switch (option.checkState) {
+ case Qt::Unchecked:
+ optionCopy.state |= QStyle::State_Off;
+ break;
+ case Qt::PartiallyChecked:
+ optionCopy.state |= QStyle::State_NoChange;
+ break;
+ case Qt::Checked:
+ optionCopy.state |= QStyle::State_On;
+ break;
+ }
+ const QAction *action = index.data(Qt::UserRole).value<QAction *>();
+ Q_ASSERT(action);
+ const QActionGroup *actionGroup = action->actionGroup();
+ if (actionGroup && actionGroup->isExclusive()) {
+ style->drawPrimitive(QStyle::PE_IndicatorRadioButton, &optionCopy, painter);
+ } else {
+ style->drawPrimitive(QStyle::PE_IndicatorItemViewItemCheck, &optionCopy, painter);
+ }
+ }
+ adjustRect(outputRect, checkMarkRect.width() + hMargin, isRightToLeft);
+ }
+
if (model->hasActionsWithIcons()) {
- const int iconWidth = option.decorationSize.width() + (hMargin * 2);
- if (option.direction == Qt::RightToLeft) {
- textRect.adjust(0, 0, -iconWidth, 0);
- } else {
- textRect.adjust(iconWidth, 0, 0, 0);
+ // draw icon
+ QRect iconRect(QPoint(0, 0), option.decorationSize);
+ if (option.features & QStyleOptionViewItem::HasDecoration) {
+ iconRect = QStyle::alignedRect(option.direction, option.displayAlignment, iconRect.size(), outputRect);
+ const QIcon::Mode iconMode = option.state & QStyle::State_Selected ? QIcon::Selected : QIcon::Normal;
+ const QIcon::State iconState = option.state & QStyle::State_Open ? QIcon::On : QIcon::Off;
+ option.icon.paint(painter, iconRect, option.decorationAlignment, iconMode, iconState);
}
+ adjustRect(outputRect, iconRect.width() + hMargin, isRightToLeft);
}
const QString original = index.data().toString();
@@ -264,8 +314,7 @@ public:
return QTextLayout::FormatRange{fr.start + actionNameStart, fr.length, f};
});
- textRect.adjust(hMargin, 0, -hMargin, 0);
- paintItemText(painter, original, textRect, option, std::move(formats));
+ paintItemText(painter, original, outputRect, option, std::move(formats));
painter->restore();
}
@@ -277,6 +326,19 @@ public Q_SLOTS:
}
private:
+ /**
+ * Increases rect.left or decreases rect.right by x
+ * depending on the layout direction
+ */
+ static void adjustRect(QRect &rect, int x, bool isRightToLeft)
+ {
+ if (isRightToLeft) {
+ rect.adjust(0, 0, -x, 0);
+ } else {
+ rect.adjust(x, 0, 0, 0);
+ }
+ }
+
QString m_filterString;
};
@@ -451,7 +513,7 @@ private:
int horizontalMargin(const QStyleOptionViewItem &option) const
{
- return option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option) + 2;
+ return 2 * option.widget->style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option);
}
};
diff --git a/src/kcommandbarmodel_p.cpp b/src/kcommandbarmodel_p.cpp
index 08e793845a98b4bb85de89c8f26c3438ce3e238c..8be23ee6969e0dde7ec5e1a566e65cd65cf4e944 100644
--- a/src/kcommandbarmodel_p.cpp
+++ b/src/kcommandbarmodel_p.cpp
@@ -112,6 +112,20 @@ void KCommandBarModel::refresh(const QList<KCommandBar::ActionGroup> &actionGrou
endResetModel();
}
+Qt::ItemFlags KCommandBarModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid()) {
+ return Qt::NoItemFlags;
+ }
+
+ Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren;
+ if (m_rows.at(index.row()).action->isCheckable()) {
+ flags |= Qt::ItemIsUserCheckable;
+ }
+
+ return flags;
+}
+
QVariant KCommandBarModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
@@ -141,6 +155,12 @@ QVariant KCommandBarModel::data(const QModelIndex &index, int role) const
}
return toolTip;
}
+ case Qt::CheckStateRole: {
+ if (entry.action->isCheckable()) {
+ return entry.action->isChecked() ? Qt::Checked : Qt::Unchecked;
+ }
+ break;
+ }
case Qt::UserRole: {
return QVariant::fromValue(entry.action);
}
diff --git a/src/kcommandbarmodel_p.h b/src/kcommandbarmodel_p.h
index 655b1a81e7be39a2d38b7e05f8bbed4f802e4605..b0bec68f21f554ff010f42d28a5d4e80782404d0 100644
--- a/src/kcommandbarmodel_p.h
+++ b/src/kcommandbarmodel_p.h
@@ -53,6 +53,8 @@ public:
return Column_Count;
}
+ Qt::ItemFlags flags(const QModelIndex &index) const override;
+
/**
* reimplemented function to update score that is calculated by KFuzzyMatcher
*/