File indexing completed on 2024-04-28 05:50:45

0001 /*
0002     SPDX-FileCopyrightText: 2006-2008 Robert Knight <robertknight@gmail.com>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 // Own
0008 #include "ProfileList.h"
0009 
0010 // Qt
0011 #include <QActionGroup>
0012 #include <QWidget>
0013 
0014 // KDE
0015 #include <KLocalizedString>
0016 
0017 // Konsole
0018 #include "ProfileManager.h"
0019 
0020 #include <algorithm>
0021 
0022 using Konsole::Profile;
0023 using Konsole::ProfileList;
0024 
0025 ProfileList::ProfileList(bool addShortcuts, QObject *parent)
0026     : QObject(parent)
0027     , _group(nullptr)
0028     , _addShortcuts(addShortcuts)
0029     , _emptyListAction(nullptr)
0030     , _registeredWidgets(QSet<QWidget *>())
0031 {
0032     // construct the list of favorite profiles
0033     _group = new QActionGroup(this);
0034 
0035     // Even when there are no favorite profiles, allow user to
0036     // create new tabs using the default profile from the menu
0037     _emptyListAction = new QAction(i18n("Default profile"), _group);
0038 
0039     connect(_group, &QActionGroup::triggered, this, &ProfileList::triggered);
0040 
0041     for (const auto &profile : ProfileManager::instance()->allProfiles()) {
0042         addShortcutAction(profile);
0043     }
0044 
0045     // TODO - Handle re-sorts when user changes profile names
0046     ProfileManager *manager = ProfileManager::instance();
0047     connect(manager, &ProfileManager::shortcutChanged, this, &ProfileList::shortcutChanged);
0048     connect(manager, &ProfileManager::profileChanged, this, &ProfileList::profileChanged);
0049     connect(manager, &ProfileManager::profileRemoved, this, &ProfileList::removeShortcutAction);
0050     connect(manager, &ProfileManager::profileAdded, this, &ProfileList::addShortcutAction);
0051 }
0052 
0053 void ProfileList::updateEmptyAction()
0054 {
0055     Q_ASSERT(_group);
0056     Q_ASSERT(_emptyListAction);
0057 
0058     // show this action only when it is the only action in the group
0059     const bool showEmptyAction = (_group->actions().count() == 1);
0060 
0061     if (showEmptyAction != _emptyListAction->isVisible()) {
0062         _emptyListAction->setVisible(showEmptyAction);
0063     }
0064 }
0065 QAction *ProfileList::actionForProfile(const Profile::Ptr &profile) const
0066 {
0067     const QList<QAction *> actionsList = _group->actions();
0068     for (QAction *action : actionsList) {
0069         if (action->data().value<Profile::Ptr>() == profile) {
0070             return action;
0071         }
0072     }
0073     return nullptr; // not found
0074 }
0075 
0076 void ProfileList::profileChanged(const Profile::Ptr &profile)
0077 {
0078     QAction *action = actionForProfile(profile);
0079     if (action != nullptr) {
0080         updateAction(action, profile);
0081     }
0082 }
0083 
0084 void ProfileList::updateAction(QAction *action, Profile::Ptr profile)
0085 {
0086     Q_ASSERT(action);
0087     Q_ASSERT(profile);
0088 
0089     action->setText(profile->name());
0090     action->setIcon(QIcon::fromTheme(profile->icon()));
0091 
0092     Q_EMIT actionsChanged(actions());
0093 }
0094 void ProfileList::shortcutChanged(const Profile::Ptr &profile, const QKeySequence &sequence)
0095 {
0096     if (!_addShortcuts) {
0097         return;
0098     }
0099 
0100     QAction *action = actionForProfile(profile);
0101 
0102     if (action != nullptr) {
0103         action->setShortcut(sequence);
0104     }
0105 }
0106 void ProfileList::syncWidgetActions(QWidget *widget, bool sync)
0107 {
0108     if (!sync) {
0109         _registeredWidgets.remove(widget);
0110         return;
0111     }
0112 
0113     _registeredWidgets.insert(widget);
0114 
0115     const QList<QAction *> currentActions = widget->actions();
0116     for (QAction *currentAction : currentActions) {
0117         widget->removeAction(currentAction);
0118     }
0119 
0120     widget->addActions(actions());
0121 }
0122 
0123 void ProfileList::addShortcutAction(const Profile::Ptr &profile)
0124 {
0125     ProfileManager *manager = ProfileManager::instance();
0126 
0127     auto action = new QAction(_group);
0128     action->setData(QVariant::fromValue(profile));
0129 
0130     if (_addShortcuts) {
0131         action->setShortcut(manager->shortcut(profile));
0132     }
0133 
0134     updateAction(action, profile);
0135 
0136     for (QWidget *widget : std::as_const(_registeredWidgets)) {
0137         widget->addAction(action);
0138     }
0139     Q_EMIT actionsChanged(actions());
0140 
0141     updateEmptyAction();
0142 }
0143 
0144 void ProfileList::removeShortcutAction(const Profile::Ptr &profile)
0145 {
0146     QAction *action = actionForProfile(profile);
0147 
0148     if (action != nullptr) {
0149         _group->removeAction(action);
0150         for (QWidget *widget : std::as_const(_registeredWidgets)) {
0151             widget->removeAction(action);
0152         }
0153         Q_EMIT actionsChanged(actions());
0154     }
0155     updateEmptyAction();
0156 }
0157 
0158 void ProfileList::triggered(QAction *action)
0159 {
0160     Q_EMIT profileSelected(action->data().value<Profile::Ptr>());
0161 }
0162 
0163 QList<QAction *> ProfileList::actions()
0164 {
0165     auto actionsList = _group->actions();
0166     std::sort(actionsList.begin(), actionsList.end(), [](QAction *a, QAction *b) {
0167         // Remove '&', which is added by KAcceleratorManager
0168         const QString aName = a->text().remove(QLatin1Char('&'));
0169         const QString bName = b->text().remove(QLatin1Char('&'));
0170 
0171         if (aName == QLatin1String("Default")) {
0172             return true;
0173         } else if (bName == QLatin1String("Default")) {
0174             return false;
0175         }
0176 
0177         return QString::localeAwareCompare(aName, bName) < 0;
0178     });
0179 
0180     return actionsList;
0181 }
0182 
0183 #include "moc_ProfileList.cpp"