Advance Wayland and KDE package bring-up
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.0-or-later
|
||||
*/
|
||||
#include "kcommandbarmodel_p.h"
|
||||
#include "kcommandbar.h" // For ActionGroup
|
||||
#include "kconfigwidgets_debug.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QAction>
|
||||
#include <QMenu>
|
||||
|
||||
#include <unordered_set>
|
||||
|
||||
QString KCommandBarModel::Item::displayName() const
|
||||
{
|
||||
const QString group = KLocalizedString::removeAcceleratorMarker(groupName);
|
||||
const QString command = KLocalizedString::removeAcceleratorMarker(action->text());
|
||||
|
||||
return group + QStringLiteral(": ") + command;
|
||||
}
|
||||
|
||||
KCommandBarModel::KCommandBarModel(QObject *parent)
|
||||
: QAbstractTableModel(parent)
|
||||
{
|
||||
m_clearHistoryAction = new QAction(tr("Clear History"), this);
|
||||
m_clearHistoryAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-history")));
|
||||
connect(m_clearHistoryAction, &QAction::triggered, this, [this]() {
|
||||
m_lastTriggered.clear();
|
||||
});
|
||||
}
|
||||
|
||||
void fillRows(QList<KCommandBarModel::Item> &rows, const QString &title, const QList<QAction *> &actions, std::unordered_set<QAction *> &uniqueActions)
|
||||
{
|
||||
for (const auto &action : actions) {
|
||||
// We don't want diabled actions
|
||||
if (!action->isEnabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is this action actually a menu?
|
||||
if (auto menu = action->menu()) {
|
||||
auto menuActionList = menu->actions();
|
||||
|
||||
// Empty? => Maybe the menu loads action on aboutToShow()?
|
||||
if (menuActionList.isEmpty()) {
|
||||
Q_EMIT menu->aboutToShow();
|
||||
menuActionList = menu->actions();
|
||||
}
|
||||
|
||||
const QString menuTitle = menu->title();
|
||||
fillRows(rows, menuTitle, menuActionList, uniqueActions);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (action->text().isEmpty() && !action->isSeparator()) {
|
||||
qCWarning(KCONFIG_WIDGETS_LOG) << "Action" << action << "in group" << title << "has no text";
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uniqueActions.insert(action).second) {
|
||||
rows.push_back(KCommandBarModel::Item{title, action, -1});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KCommandBarModel::refresh(const QList<KCommandBar::ActionGroup> &actionGroups)
|
||||
{
|
||||
int totalActions = std::accumulate(actionGroups.begin(), actionGroups.end(), 0, [](int a, const KCommandBar::ActionGroup &ag) {
|
||||
return a + ag.actions.count();
|
||||
});
|
||||
++totalActions; // for m_clearHistoryAction
|
||||
|
||||
QList<Item> temp_rows;
|
||||
std::unordered_set<QAction *> uniqueActions;
|
||||
temp_rows.reserve(totalActions);
|
||||
for (const auto &ag : actionGroups) {
|
||||
const auto &agActions = ag.actions;
|
||||
fillRows(temp_rows, ag.name, agActions, uniqueActions);
|
||||
}
|
||||
|
||||
temp_rows.push_back({tr("Command Bar"), m_clearHistoryAction, -1});
|
||||
|
||||
/**
|
||||
* For each action in last triggered actions,
|
||||
* - Find it in the actions
|
||||
* - Use the score variable to set its score
|
||||
*
|
||||
* Items in m_lastTriggered are stored in descending order
|
||||
* by their usage i.e., the first item in the vector is the most
|
||||
* recently invoked action.
|
||||
*
|
||||
* Here we traverse them in reverse order, i.e., from least recent to
|
||||
* most recent and then assign a score to them in a way that most recent
|
||||
* ends up having the highest score. Thus when proxy model does the sorting
|
||||
* later, most recent item will end up on the top
|
||||
*/
|
||||
int score = 0;
|
||||
std::for_each(m_lastTriggered.crbegin(), m_lastTriggered.crend(), [&score, &temp_rows](const QString &act) {
|
||||
auto it = std::find_if(temp_rows.begin(), temp_rows.end(), [act](const KCommandBarModel::Item &i) {
|
||||
return i.action->text() == act;
|
||||
});
|
||||
if (it != temp_rows.end()) {
|
||||
it->score = score++;
|
||||
}
|
||||
});
|
||||
|
||||
beginResetModel();
|
||||
m_rows = std::move(temp_rows);
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QVariant KCommandBarModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (!index.isValid()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto &entry = m_rows[index.row()];
|
||||
const int col = index.column();
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
if (col == Column_Command) {
|
||||
return entry.displayName();
|
||||
}
|
||||
Q_ASSERT(col == Column_Shortcut);
|
||||
return entry.action->shortcut().toString();
|
||||
case Qt::DecorationRole:
|
||||
if (col == Column_Command) {
|
||||
return entry.action->icon();
|
||||
}
|
||||
break;
|
||||
case Qt::ToolTipRole: {
|
||||
QString toolTip = entry.displayName();
|
||||
if (!entry.action->shortcut().isEmpty()) {
|
||||
toolTip += QLatin1Char('\n');
|
||||
toolTip += entry.action->shortcut().toString();
|
||||
}
|
||||
return toolTip;
|
||||
}
|
||||
case Qt::UserRole: {
|
||||
return QVariant::fromValue(entry.action);
|
||||
}
|
||||
case Role::Score:
|
||||
return entry.score;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void KCommandBarModel::actionTriggered(const QString &name)
|
||||
{
|
||||
if (m_lastTriggered.size() == 6) {
|
||||
m_lastTriggered.pop_back();
|
||||
}
|
||||
m_lastTriggered.push_front(name);
|
||||
}
|
||||
|
||||
QStringList KCommandBarModel::lastUsedActions() const
|
||||
{
|
||||
return m_lastTriggered;
|
||||
}
|
||||
|
||||
void KCommandBarModel::setLastUsedActions(const QStringList &actionNames)
|
||||
{
|
||||
m_lastTriggered = actionNames;
|
||||
|
||||
while (m_lastTriggered.size() > 6) {
|
||||
m_lastTriggered.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_kcommandbarmodel_p.cpp"
|
||||
Reference in New Issue
Block a user