Kirigami-addons

actionsmodel.cpp
1// SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com>
2// SPDX-License-Identifier: LGPL-2.0-or-later
3
4#include "actionsmodel_p.h"
5
6#include <KLocalizedString>
7
8#include <QAction>
9
10#include <unordered_set>
11
12KCommandBarModel::KCommandBarModel(QObject *parent)
13 : QAbstractTableModel(parent)
14{
15}
16
17void fillRows(QList<KCommandBarModel::Item> &rows, const QString &title, const QList<QAction *> &actions, std::unordered_set<QAction *> &uniqueActions)
18{
19 for (const auto &action : actions) {
20 // We don't want disabled actions
21 if (!action->isEnabled()) {
22 continue;
23 }
24
25 if (uniqueActions.insert(action).second) {
26 rows.push_back(KCommandBarModel::Item{title, action, -1});
27 }
28 }
29}
30
31void KCommandBarModel::refresh(const QList<ActionGroup> &actionGroups)
32{
33 QSet<QString> groupNames;
34 int totalActions = std::accumulate(actionGroups.begin(), actionGroups.end(), 0, [&groupNames](int a, const ActionGroup &ag) {
35 groupNames << ag.name;
36 return ag.actions.count() + a;
37 });
38 m_hasMultipleGroup = groupNames.count() > 1;
39
40 QList<Item> temp_rows;
41 std::unordered_set<QAction *> uniqueActions;
42 temp_rows.reserve(totalActions);
43 for (const auto &ag : actionGroups) {
44 const auto &agActions = ag.actions;
45 fillRows(temp_rows, ag.name, agActions, uniqueActions);
46 }
47
48 /**
49 * For each action in last triggered actions,
50 * - Find it in the actions
51 * - Use the score variable to set its score
52 *
53 * Items in m_lastTriggered are stored in descending order
54 * by their usage i.e., the first item in the vector is the most
55 * recently invoked action.
56 *
57 * Here we traverse them in reverse order, i.e., from least recent to
58 * most recent and then assign a score to them in a way that most recent
59 * ends up having the highest score. Thus when proxy model does the sorting
60 * later, most recent item will end up on the top
61 */
62 int score = 0;
63 std::for_each(m_lastTriggered.crbegin(), m_lastTriggered.crend(), [&score, &temp_rows](const QString &act) {
64 auto it = std::find_if(temp_rows.begin(), temp_rows.end(), [act](const KCommandBarModel::Item &i) {
65 return i.action->text() == act;
66 });
67 if (it != temp_rows.end()) {
68 it->score = score++;
69 }
70 });
71
72 beginResetModel();
73 m_rows = std::move(temp_rows);
74 endResetModel();
75}
76
77QVariant KCommandBarModel::data(const QModelIndex &index, int role) const
78{
79 if (!index.isValid()) {
80 return {};
81 }
82
83 const auto &entry = m_rows[index.row()];
84 const int col = index.column();
85
86 switch (role) {
87 case Qt::DisplayRole:
88 case DisplayNameRole:
89 if (col == 0) {
90 QString actionText = KLocalizedString::removeAcceleratorMarker(entry.action->text());
91 if (m_hasMultipleGroup) {
92 const QString groupName = KLocalizedString::removeAcceleratorMarker(entry.groupName);
93 return QString(groupName + QStringLiteral(": ") + actionText);
94 } else {
95 return actionText;
96 }
97 } else {
98 return entry.action->shortcut().toString(QKeySequence::NativeText);
99 }
100 case ShortcutRole:
101 return entry.action->shortcut().toString(QKeySequence::NativeText);
103 if (col == 0) {
104 return entry.action->icon().name();
105 }
106 break;
108 if (col == 0) {
109 return Qt::AlignLeft;
110 } else {
111 return Qt::AlignRight;
112 }
113 case Qt::UserRole: {
114 return QVariant::fromValue(entry.action);
115 }
116 case Role::Score:
117 return entry.score;
118 }
119
120 return {};
121}
122
123void KCommandBarModel::actionTriggered(const QString &name)
124{
125 if (m_lastTriggered.size() == 6) {
126 m_lastTriggered.pop_back();
127 }
128 m_lastTriggered.push_front(name);
129}
130
131QStringList KCommandBarModel::lastUsedActions() const
132{
133 return m_lastTriggered;
134}
135
136void KCommandBarModel::setLastUsedActions(const QStringList &actionNames)
137{
138 m_lastTriggered = actionNames;
139
140 while (m_lastTriggered.size() > 6) {
141 m_lastTriggered.pop_back();
142 }
143}
144
145QHash<int, QByteArray> KCommandBarModel::roleNames() const
146{
147 auto roles = QAbstractTableModel::roleNames();
148 roles[Qt::UserRole] = QByteArrayLiteral("qaction");
149 roles[Score] = QByteArrayLiteral("score");
150 roles[ShortcutRole] = QByteArrayLiteral("shortcut");
151 roles[DisplayNameRole] = QByteArrayLiteral("displayName");
152 return roles;
153}
154
155#include "moc_actionsmodel_p.cpp"
static QString removeAcceleratorMarker(const QString &label)
virtual QHash< int, QByteArray > roleNames() const const
iterator begin()
iterator end()
void push_back(parameter_type value)
void reserve(qsizetype size)
int column() const const
bool isValid() const const
int row() const const
qsizetype count() const const
AlignLeft
DisplayRole
QVariant fromValue(T &&value)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:49:11 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.