File indexing completed on 2024-07-21 12:12:56

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 &currentStructure, 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 &registeredService : 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 }