File indexing completed on 2024-12-22 04:12:36
0001 /* 0002 * This file is part of the KDE project 0003 * SPDX-FileCopyrightText: 2013 Arjen Hiemstra <ahiemstra@heimr.nl> 0004 * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "kis_input_configuration_page.h" 0009 #include "ui_kis_input_configuration_page.h" 0010 0011 #include <QDebug> 0012 #include <QDir> 0013 #include <QMap> 0014 0015 #include "input/kis_input_profile_manager.h" 0016 #include "input/kis_input_profile.h" 0017 #include "input/kis_shortcut_configuration.h" 0018 #include "input/kis_abstract_input_action.h" 0019 #include "kis_edit_profiles_dialog.h" 0020 #include "kis_input_profile_model.h" 0021 #include "kis_input_configuration_page_item.h" 0022 #include <KoResourcePaths.h> 0023 0024 0025 #include "kis_icon_utils.h" 0026 0027 struct KisInputConfigurationPage::Private { 0028 QMap<KisAbstractInputAction *, KisInputConfigurationPageItem*> actionInputConfigurationMap; 0029 }; 0030 0031 KisInputConfigurationPage::KisInputConfigurationPage(QWidget *parent, Qt::WindowFlags f) 0032 : QWidget(parent, f) 0033 , m_d(new Private) 0034 { 0035 ui = new Ui::KisInputConfigurationPage; 0036 ui->setupUi(this); 0037 0038 ui->profileComboBox->setModel(new KisInputProfileModel(ui->profileComboBox)); 0039 updateSelectedProfile(); 0040 connect(ui->profileComboBox, SIGNAL(currentIndexChanged(QString)), SLOT(changeCurrentProfile(QString))); 0041 0042 ui->editProfilesButton->setIcon(KisIconUtils::loadIcon("document-edit")); 0043 0044 connect(ui->editProfilesButton, SIGNAL(clicked(bool)), SLOT(editProfilesButtonClicked())); 0045 connect(KisInputProfileManager::instance(), SIGNAL(profilesChanged()), SLOT(updateSelectedProfile())); 0046 connect(KisInputProfileManager::instance(), 0047 &KisInputProfileManager::currentProfileChanged, 0048 this, 0049 &KisInputConfigurationPage::checkForConflicts); 0050 0051 QList<KisAbstractInputAction *> actions = KisInputProfileManager::instance()->actions(); 0052 Q_FOREACH(KisAbstractInputAction * action, actions) { 0053 KisInputConfigurationPageItem *item = new KisInputConfigurationPageItem(this); 0054 item->setAction(action); 0055 ui->configurationItemsArea->addWidget(item); 0056 m_d->actionInputConfigurationMap.insert(action, item); 0057 connect(item, 0058 &KisInputConfigurationPageItem::inputConfigurationChanged, 0059 this, 0060 &KisInputConfigurationPage::checkForConflicts, 0061 Qt::UniqueConnection); 0062 } 0063 checkForConflicts(); 0064 ui->configurationItemsArea->addStretch(20); // ensures listed input are on top 0065 0066 QScroller *scroller = KisKineticScroller::createPreconfiguredScroller(ui->scrollArea); 0067 if (scroller) { 0068 connect(scroller, SIGNAL(stateChanged(QScroller::State)), 0069 this, SLOT(slotScrollerStateChanged(QScroller::State))); 0070 } 0071 } 0072 0073 KisInputConfigurationPage::~KisInputConfigurationPage() = default; 0074 0075 void KisInputConfigurationPage::saveChanges() 0076 { 0077 KisInputProfileManager::instance()->saveProfiles(); 0078 } 0079 0080 void KisInputConfigurationPage::revertChanges() 0081 { 0082 KisInputProfileManager::instance()->loadProfiles(); 0083 } 0084 0085 void KisInputConfigurationPage::checkForConflicts() 0086 { 0087 // reset all of them first. 0088 Q_FOREACH (KisInputConfigurationPageItem *pageItem, m_d->actionInputConfigurationMap.values()) { 0089 pageItem->setWarningEnabled(false); 0090 } 0091 const QList<KisShortcutConfiguration *> conflictingShortcuts = 0092 KisInputProfileManager::instance()->getConflictingShortcuts( 0093 KisInputProfileManager::instance()->currentProfile()); 0094 0095 if (conflictingShortcuts.isEmpty()) { 0096 return; 0097 } 0098 0099 struct ShortcutInfo { 0100 QVector<KisShortcutConfiguration *> shortcutObjects; 0101 QStringList actionTexts; 0102 }; 0103 QMap<QString, ShortcutInfo> conflictingShortcutsMap; 0104 0105 Q_FOREACH (KisShortcutConfiguration *shortcut, conflictingShortcuts) { 0106 if (shortcut->action()) { 0107 if (m_d->actionInputConfigurationMap.contains(shortcut->action())) { 0108 ShortcutInfo &shortcutInfo = conflictingShortcutsMap[shortcut->getInputText()]; 0109 shortcutInfo.shortcutObjects.append(shortcut); 0110 const QString subActionName = shortcut->action()->shortcutIndexes().key(shortcut->mode()); 0111 shortcutInfo.actionTexts.append(shortcut->action()->name() + " → " + subActionName); 0112 } else { 0113 qWarning() << "KisInputConfigurationPageItem does not exist for the specified action:" 0114 << shortcut->action()->name(); 0115 } 0116 } else { 0117 qWarning() << "Action not set for the given shortcut."; 0118 } 0119 } 0120 0121 QMap<KisAbstractInputAction *, QSet<QString>> infoTexts; 0122 Q_FOREACH (const ShortcutInfo &shortcutInfo, conflictingShortcutsMap) { 0123 const QString text = "<b>" + shortcutInfo.shortcutObjects.first()->getInputText() + "</b>" + "<br> " 0124 + shortcutInfo.actionTexts.join("<br> "); 0125 Q_FOREACH (KisShortcutConfiguration *shortcut, shortcutInfo.shortcutObjects) { 0126 infoTexts[shortcut->action()] << text; 0127 } 0128 } 0129 0130 QMapIterator<KisAbstractInputAction *, QSet<QString>> it(infoTexts); 0131 while (it.hasNext()) { 0132 it.next(); 0133 QSetIterator<QString> it2(it.value()); 0134 if (!it2.hasNext()) { 0135 continue; 0136 } 0137 QString text = "<ul> <li>" + it2.next() + "</li>"; 0138 while (it2.hasNext()) { 0139 text += "<li>" + it2.next() + "</li>"; 0140 } 0141 text += "</ul>"; 0142 m_d->actionInputConfigurationMap[it.key()]->setWarningEnabled(true, text); 0143 } 0144 } 0145 0146 void KisInputConfigurationPage::setDefaults() 0147 { 0148 QDir profileDir(KoResourcePaths::saveLocation("data", "input/", false)); 0149 0150 if (profileDir.exists()) { 0151 QStringList entries = profileDir.entryList(QStringList() << "*.profile", QDir::Files | QDir::NoDotAndDotDot); 0152 Q_FOREACH(const QString & file, entries) { 0153 profileDir.remove(file); 0154 } 0155 0156 KisInputProfileManager::instance()->loadProfiles(); 0157 } 0158 } 0159 0160 void KisInputConfigurationPage::editProfilesButtonClicked() 0161 { 0162 KisEditProfilesDialog dialog; 0163 dialog.exec(); 0164 } 0165 0166 void KisInputConfigurationPage::updateSelectedProfile() 0167 { 0168 if (KisInputProfileManager::instance()->currentProfile()) { 0169 ui->profileComboBox->setCurrentItem(KisInputProfileManager::instance()->currentProfile()->name()); 0170 } 0171 } 0172 0173 void KisInputConfigurationPage::changeCurrentProfile(const QString &newProfile) 0174 { 0175 KisInputProfileManager::instance()->setCurrentProfile(KisInputProfileManager::instance()->profile(newProfile)); 0176 }