File indexing completed on 2025-02-16 13:09:07
0001 /* 0002 SPDX-FileCopyrightText: 2015 Gregor Mi <codestruct@posteo.org> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "kmoretoolsconfigdialog_p.h" 0008 0009 #include "ui_kmoretoolsconfigwidget.h" 0010 0011 #include <QDebug> 0012 #include <QStandardItemModel> 0013 0014 #include <KLocalizedString> 0015 0016 class KMoreToolsConfigDialogPrivate 0017 { 0018 public: 0019 /** 0020 * menu defined by code 0021 */ 0022 KmtMenuStructureDto defaultStructure; 0023 0024 /** 0025 * resulting menu (default merged with configured) and then maybe edited via GUI 0026 */ 0027 KmtMenuStructureDto currentStructure; 0028 0029 Ui::KMoreToolsConfigWidget *configUi = nullptr; 0030 0031 QAction *moveUpAction = nullptr; 0032 QAction *moveDownAction = nullptr; 0033 QAction *moveToMoreSectionAction = nullptr; 0034 QAction *moveToMainSectionAction = nullptr; 0035 0036 public: 0037 QAction *createActionForButton(QAbstractButton *button, QObject *parent) 0038 { 0039 auto action = new QAction(button->icon(), button->text(), parent); 0040 return action; 0041 } 0042 0043 QListWidgetItem *selectedItemMainSection() 0044 { 0045 auto items = configUi->listMainSection->selectedItems(); 0046 if (items.isEmpty()) { 0047 return nullptr; 0048 } else { 0049 return items[0]; 0050 } 0051 } 0052 0053 QListWidgetItem *selectedItemMoreSection() 0054 { 0055 auto items = configUi->listMoreSection->selectedItems(); 0056 if (items.isEmpty()) { 0057 return nullptr; 0058 } else { 0059 return items[0]; 0060 } 0061 } 0062 0063 /** 0064 * Only one section has a selection at a time. 0065 * @return the id of the item in one of the sections (main or more) or empty string 0066 */ 0067 QString uiSelectedItemId() 0068 { 0069 auto mainItem = selectedItemMainSection(); 0070 auto moreItem = selectedItemMoreSection(); 0071 if (mainItem) { 0072 return mainItem->data(Qt::UserRole).toString(); 0073 } else if (moreItem) { 0074 return moreItem->data(Qt::UserRole).toString(); 0075 } else { 0076 return QString(); 0077 } 0078 } 0079 0080 void updateMoveButtonsState() 0081 { 0082 bool hasSelectedMain = selectedItemMainSection(); 0083 if (hasSelectedMain) { 0084 auto listMain = configUi->listMainSection; 0085 moveUpAction->setEnabled(hasSelectedMain && listMain->currentRow() > 0); 0086 moveDownAction->setEnabled(hasSelectedMain && listMain->currentRow() < listMain->count() - 1); 0087 } 0088 0089 bool hasSelectedMore = selectedItemMoreSection(); 0090 if (hasSelectedMore) { 0091 auto listMore = configUi->listMoreSection; 0092 moveUpAction->setEnabled(hasSelectedMore && listMore->currentRow() > 0); 0093 moveDownAction->setEnabled(hasSelectedMore && listMore->currentRow() < listMore->count() - 1); 0094 } 0095 0096 moveToMoreSectionAction->setEnabled(hasSelectedMain); 0097 moveToMainSectionAction->setEnabled(hasSelectedMore); 0098 } 0099 0100 /** 0101 * refill lists and restore selection 0102 */ 0103 void updateListViews(const QString &idToSelect = QString()) 0104 { 0105 configUi->listMainSection->clear(); 0106 configUi->listMoreSection->clear(); 0107 0108 // restore item selection 0109 QListWidgetItem *mainSelItem = nullptr; 0110 QListWidgetItem *moreSelItem = nullptr; 0111 0112 for (const auto &item : std::as_const(currentStructure.list)) { 0113 QIcon icon = item.icon; 0114 if (icon.isNull()) { 0115 QPixmap pix(16, 16); // TODO: should same size as other icons in the listview 0116 pix.fill(QColor(0, 0, 0, 0)); // transparent 0117 icon = QIcon(pix); 0118 } 0119 0120 if (item.isInstalled) { 0121 auto listItem = new QListWidgetItem(icon, KmtMenuItemDto::removeMenuAmpersand(item.text) /*+ " - " + item.id*/); 0122 listItem->setData(Qt::UserRole, item.id); 0123 if (item.menuSection == KMoreTools::MenuSection_Main) { 0124 configUi->listMainSection->addItem(listItem); 0125 if (item.id == idToSelect) { 0126 mainSelItem = listItem; 0127 } 0128 } else if (item.menuSection == KMoreTools::MenuSection_More) { 0129 configUi->listMoreSection->addItem(listItem); 0130 if (item.id == idToSelect) { 0131 moreSelItem = listItem; 0132 } 0133 } else { 0134 Q_ASSERT(false); 0135 } 0136 } 0137 } 0138 0139 // 0140 // restore selection 0141 // "current vs. selected?" see http://doc.qt.digia.com/4.6/model-view-selection.html 0142 // 0143 if (mainSelItem) { 0144 mainSelItem->setSelected(true); 0145 configUi->listMainSection->setCurrentItem(mainSelItem); // for focus and keyboard handling 0146 configUi->listMainSection->setFocus(); 0147 } 0148 0149 if (moreSelItem) { 0150 moreSelItem->setSelected(true); 0151 configUi->listMoreSection->setCurrentItem(moreSelItem); // for focus and keyboard handling 0152 configUi->listMoreSection->setFocus(); 0153 } 0154 0155 updateMoveButtonsState(); 0156 } 0157 }; 0158 0159 /** 0160 * for merging strategy see KMoreToolsMenuBuilderPrivate::createMenuStructure(mergeWithUserConfig=true) 0161 */ 0162 KMoreToolsConfigDialog::KMoreToolsConfigDialog(const KmtMenuStructureDto &defaultStructure, const KmtMenuStructureDto ¤tStructure, const QString &title) 0163 : d(new KMoreToolsConfigDialogPrivate()) 0164 { 0165 d->defaultStructure = defaultStructure; 0166 d->currentStructure = currentStructure; 0167 0168 QWidget *configPage = new QWidget(); 0169 if (title.isEmpty()) { 0170 addPage(configPage, i18n("Configure menu")); 0171 } else { 0172 addPage(configPage, i18n("Configure menu - %1", title)); 0173 } 0174 d->configUi = new Ui::KMoreToolsConfigWidget(); 0175 d->configUi->setupUi(configPage); 0176 0177 // 0178 // show or don't show not-installed section depending if there are any 0179 // 0180 auto notInstalledServices = defaultStructure.notInstalledServices(); 0181 d->configUi->frameNotInstalledTools->setVisible(!notInstalledServices.empty()); 0182 if (!notInstalledServices.empty()) { 0183 auto menu = new QMenu(this); 0184 for (const KmtMenuItemDto ®isteredService : notInstalledServices) { 0185 QMenu *submenuForNotInstalled = KmtNotInstalledUtil::createSubmenuForNotInstalledApp(registeredService.text, 0186 menu, 0187 registeredService.icon, 0188 registeredService.homepageUrl, 0189 registeredService.appstreamId); 0190 menu->addMenu(submenuForNotInstalled); 0191 } 0192 d->configUi->buttonNotInstalledTools->setMenu(menu); 0193 } 0194 0195 // 0196 // connect signals 0197 // 0198 { 0199 auto configUi = d->configUi; 0200 0201 // 0202 // actions 0203 // 0204 d->moveUpAction = d->createActionForButton(configUi->buttonMoveUp, this); 0205 d->moveUpAction->setEnabled(false); 0206 configUi->buttonMoveUp->setDefaultAction(d->moveUpAction); 0207 connect(d->moveUpAction, &QAction::triggered, this, [this]() { 0208 QString selectedItemId = d->uiSelectedItemId(); 0209 if (!selectedItemId.isEmpty()) { 0210 d->currentStructure.moveWithinSection(selectedItemId, -1); 0211 d->updateListViews(selectedItemId); 0212 } 0213 }); 0214 0215 d->moveDownAction = d->createActionForButton(configUi->buttonMoveDown, this); 0216 d->moveDownAction->setEnabled(false); 0217 configUi->buttonMoveDown->setDefaultAction(d->moveDownAction); 0218 connect(d->moveDownAction, &QAction::triggered, this, [this]() { 0219 QString selectedItemId = d->uiSelectedItemId(); 0220 if (!selectedItemId.isEmpty()) { 0221 d->currentStructure.moveWithinSection(selectedItemId, 1); 0222 d->updateListViews(selectedItemId); 0223 } 0224 }); 0225 0226 d->moveToMoreSectionAction = d->createActionForButton(configUi->buttonMoveToMore, this); 0227 d->moveToMoreSectionAction->setEnabled(false); 0228 configUi->buttonMoveToMore->setDefaultAction(d->moveToMoreSectionAction); 0229 connect(d->moveToMoreSectionAction, &QAction::triggered, this, [this]() { 0230 QString selectedItemId = d->selectedItemMainSection()->data(Qt::UserRole).toString(); 0231 d->currentStructure.moveToOtherSection(selectedItemId); 0232 d->selectedItemMainSection()->setSelected(false); 0233 d->updateListViews(selectedItemId); 0234 }); 0235 0236 d->moveToMainSectionAction = d->createActionForButton(configUi->buttonMoveToMain, this); 0237 d->moveToMainSectionAction->setEnabled(false); 0238 configUi->buttonMoveToMain->setDefaultAction(d->moveToMainSectionAction); 0239 connect(d->moveToMainSectionAction, &QAction::triggered, this, [this]() { 0240 QString selectedItemId = d->selectedItemMoreSection()->data(Qt::UserRole).toString(); 0241 d->currentStructure.moveToOtherSection(selectedItemId); 0242 d->selectedItemMoreSection()->setSelected(false); 0243 d->updateListViews(selectedItemId); 0244 }); 0245 0246 connect(configUi->buttonReset, &QAbstractButton::clicked, this, [this]() { 0247 d->currentStructure = d->defaultStructure; 0248 d->updateListViews(); 0249 }); 0250 0251 // 0252 // widgets enabled or not 0253 // 0254 connect(configUi->listMainSection, &QListWidget::itemSelectionChanged, this, [this]() { 0255 if (!d->selectedItemMainSection()) { 0256 d->moveToMoreSectionAction->setEnabled(false); 0257 d->moveUpAction->setEnabled(false); 0258 d->moveDownAction->setEnabled(false); 0259 return; 0260 } else { 0261 d->moveToMoreSectionAction->setEnabled(true); 0262 } 0263 0264 d->updateMoveButtonsState(); 0265 }); 0266 0267 connect(configUi->listMainSection, &QListWidget::currentItemChanged, this, [this, configUi](QListWidgetItem *current, QListWidgetItem *previous) { 0268 Q_UNUSED(previous) 0269 if (current && d->selectedItemMoreSection()) { 0270 d->selectedItemMoreSection()->setSelected(false); 0271 configUi->listMoreSection->setCurrentItem(nullptr); 0272 } 0273 d->updateMoveButtonsState(); 0274 }); 0275 0276 connect(configUi->listMoreSection, &QListWidget::itemSelectionChanged, this, [this]() { 0277 if (!d->selectedItemMoreSection()) { 0278 d->moveToMainSectionAction->setEnabled(false); 0279 d->moveUpAction->setEnabled(false); 0280 d->moveDownAction->setEnabled(false); 0281 return; 0282 } else { 0283 d->moveToMainSectionAction->setEnabled(true); 0284 } 0285 0286 d->updateMoveButtonsState(); 0287 }); 0288 0289 connect(configUi->listMoreSection, &QListWidget::currentItemChanged, this, [this, configUi](QListWidgetItem *current, QListWidgetItem *previous) { 0290 Q_UNUSED(previous) 0291 if (current && d->selectedItemMainSection()) { 0292 d->selectedItemMainSection()->setSelected(false); 0293 configUi->listMainSection->setCurrentItem(nullptr); 0294 } 0295 d->updateMoveButtonsState(); 0296 }); 0297 } 0298 0299 d->updateListViews(); 0300 } 0301 0302 KMoreToolsConfigDialog::~KMoreToolsConfigDialog() = default; 0303 0304 KmtMenuStructureDto KMoreToolsConfigDialog::currentStructure() 0305 { 0306 return d->currentStructure; 0307 }