File indexing completed on 2024-11-24 04:50:43
0001 // SPDX-FileCopyrightText: 2023 Carl Schwan <carlschwan@kde.org> 0002 // SPDX-License-Identifier: LGPL-2.1-or-later 0003 0004 #include "abstractapplication.h" 0005 #include "commandbarfiltermodel.h" 0006 #include <KAboutData> 0007 #include <KAuthorized> 0008 #include <KConfigGroup> 0009 #include <KLocalizedString> 0010 #include <KSharedConfig> 0011 #include <KShortcutsDialog> 0012 #include <QDebug> 0013 #include <QGuiApplication> 0014 #include <QMenu> 0015 0016 AbstractApplication::AbstractApplication(QObject *parent) 0017 : QObject(parent) 0018 , mCollection(new KActionCollection(parent)) 0019 { 0020 } 0021 0022 AbstractApplication::~AbstractApplication() 0023 { 0024 if (m_actionModel) { 0025 auto lastUsedActions = m_actionModel->lastUsedActions(); 0026 auto cfg = KSharedConfig::openConfig(); 0027 KConfigGroup cg(cfg, QStringLiteral("General")); 0028 cg.writeEntry("CommandBarLastUsedActions", lastUsedActions); 0029 } 0030 } 0031 0032 /** 0033 * A helper function that takes a list of KActionCollection* and converts it 0034 * to KCommandBar::ActionGroup 0035 */ 0036 static QList<KalCommandBarModel::ActionGroup> actionCollectionToActionGroup(const QList<KActionCollection *> &actionCollections) 0037 { 0038 using ActionGroup = KalCommandBarModel::ActionGroup; 0039 0040 QList<ActionGroup> actionList; 0041 actionList.reserve(actionCollections.size()); 0042 0043 for (const auto collection : actionCollections) { 0044 const auto collectionActions = collection->actions(); 0045 const auto componentName = collection->componentDisplayName(); 0046 0047 ActionGroup ag; 0048 ag.name = componentName; 0049 ag.actions.reserve(collection->count()); 0050 for (const auto action : collectionActions) { 0051 /** 0052 * If this action is a menu, fetch all its child actions 0053 * and skip the menu action itself 0054 */ 0055 if (const auto menu = action->menu()) { 0056 const auto menuActions = menu->actions(); 0057 0058 ActionGroup menuActionGroup; 0059 menuActionGroup.name = KLocalizedString::removeAcceleratorMarker(action->text()); 0060 menuActionGroup.actions.reserve(menuActions.size()); 0061 for (const auto mAct : menuActions) { 0062 if (mAct) { 0063 menuActionGroup.actions.append(mAct); 0064 } 0065 } 0066 0067 /** 0068 * If there were no actions in the menu, we 0069 * add the menu to the list instead because it could 0070 * be that the actions are created on demand i.e., aboutToShow() 0071 */ 0072 if (!menuActions.isEmpty()) { 0073 actionList.append(menuActionGroup); 0074 continue; 0075 } 0076 } 0077 0078 if (action && !action->text().isEmpty()) { 0079 ag.actions.append(action); 0080 } 0081 } 0082 actionList.append(ag); 0083 } 0084 return actionList; 0085 } 0086 0087 QSortFilterProxyModel *AbstractApplication::actionsModel() 0088 { 0089 if (!m_proxyModel) { 0090 m_actionModel = new KalCommandBarModel(this); 0091 m_proxyModel = new CommandBarFilterModel(this); 0092 m_proxyModel->setSortRole(KalCommandBarModel::Score); 0093 m_proxyModel->setFilterRole(Qt::DisplayRole); 0094 m_proxyModel->setSourceModel(m_actionModel); 0095 } 0096 0097 // setLastUsedActions 0098 auto cfg = KSharedConfig::openConfig(); 0099 KConfigGroup cg(cfg, QStringLiteral("General")); 0100 0101 const auto actionNames = cg.readEntry(QStringLiteral("CommandBarLastUsedActions"), QStringList()); 0102 0103 m_actionModel->setLastUsedActions(actionNames); 0104 m_actionModel->refresh(actionCollectionToActionGroup(actionCollections())); 0105 return m_proxyModel; 0106 } 0107 0108 void AbstractApplication::configureShortcuts() 0109 { 0110 // TODO replace with QML version 0111 KShortcutsDialog dlg(KShortcutsEditor::ApplicationAction, KShortcutsEditor::LetterShortcutsAllowed, nullptr); 0112 dlg.setModal(true); 0113 const auto collections = actionCollections(); 0114 for (const auto collection : collections) { 0115 dlg.addCollection(collection); 0116 } 0117 dlg.configure(); 0118 } 0119 0120 QAction *AbstractApplication::action(const QString &name) 0121 { 0122 const auto collections = actionCollections(); 0123 for (const auto collection : collections) { 0124 auto resultAction = collection->action(name); 0125 if (resultAction) { 0126 return resultAction; 0127 } 0128 } 0129 0130 qWarning() << "Not found action for name" << name; 0131 0132 return nullptr; 0133 } 0134 0135 void AbstractApplication::setupActions() 0136 { 0137 auto actionName = QLatin1StringView("open_kcommand_bar"); 0138 if (KAuthorized::authorizeAction(actionName)) { 0139 auto openKCommandBarAction = mCollection->addAction(actionName, this, &AbstractApplication::openKCommandBarAction); 0140 openKCommandBarAction->setText(i18n("Open Command Bar")); 0141 openKCommandBarAction->setIcon(QIcon::fromTheme(QStringLiteral("new-command-alarm"))); 0142 0143 mCollection->addAction(openKCommandBarAction->objectName(), openKCommandBarAction); 0144 mCollection->setDefaultShortcut(openKCommandBarAction, QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I)); 0145 } 0146 0147 actionName = QLatin1StringView("file_quit"); 0148 if (KAuthorized::authorizeAction(actionName)) { 0149 auto action = KStandardAction::quit(this, &AbstractApplication::quit, this); 0150 mCollection->addAction(action->objectName(), action); 0151 } 0152 0153 actionName = QLatin1StringView("switch_application_language"); 0154 if (KAuthorized::authorizeAction(actionName)) { 0155 auto action = KStandardAction::switchApplicationLanguage(this, &AbstractApplication::openLanguageSwitcher, this); 0156 mCollection->addAction(action->objectName(), action); 0157 } 0158 0159 actionName = QLatin1StringView("options_configure_keybinding"); 0160 if (KAuthorized::authorizeAction(actionName)) { 0161 auto keyBindingsAction = KStandardAction::keyBindings(this, &AbstractApplication::configureShortcuts, this); 0162 mCollection->addAction(keyBindingsAction->objectName(), keyBindingsAction); 0163 } 0164 0165 actionName = QLatin1StringView("open_about_page"); 0166 if (KAuthorized::authorizeAction(actionName)) { 0167 auto action = mCollection->addAction(actionName, this, &AbstractApplication::openAboutPage); 0168 action->setText(i18n("About %1", KAboutData::applicationData().displayName())); 0169 action->setIcon(QIcon::fromTheme(QStringLiteral("help-about"))); 0170 } 0171 0172 actionName = QLatin1StringView("open_about_kde_page"); 0173 if (KAuthorized::authorizeAction(actionName)) { 0174 auto action = mCollection->addAction(actionName, this, &AbstractApplication::openAboutKDEPage); 0175 action->setText(i18n("About KDE")); 0176 action->setIcon(QIcon::fromTheme(QStringLiteral("kde"))); 0177 } 0178 0179 actionName = QLatin1StringView("options_configure"); 0180 if (KAuthorized::authorizeAction(actionName)) { 0181 auto action = KStandardAction::preferences(this, &AbstractApplication::openSettings, this); 0182 mCollection->addAction(action->objectName(), action); 0183 } 0184 0185 actionName = QLatin1StringView("open_tag_manager"); 0186 if (KAuthorized::authorizeAction(actionName)) { 0187 auto openTagManagerAction = mCollection->addAction(actionName, this, &AbstractApplication::openTagManager); 0188 openTagManagerAction->setText(i18n("Manage Tagsā¦")); 0189 openTagManagerAction->setIcon(QIcon::fromTheme(QStringLiteral("action-rss_tag"))); 0190 } 0191 } 0192 0193 void AbstractApplication::quit() 0194 { 0195 qGuiApp->exit(); 0196 } 0197 0198 #include "moc_abstractapplication.cpp"