MauiKit Calendar

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

KDE's Doxygen guidelines are available online.