File indexing completed on 2024-04-21 13:03:17

0001 /*
0002  *   SPDX-FileCopyrightText: 2000 Matthias Elter <elter@kde.org>
0003  *   SPDX-FileCopyrightText: 2001-2002 Raffaele Sandrini <sandrini@kde.org>
0004  *
0005  *   SPDX-License-Identifier: GPL-2.0-or-later
0006  *
0007  */
0008 #include "kmenuedit.h"
0009 
0010 #include <QFrame>
0011 #include <QSplitter>
0012 #include <QVBoxLayout>
0013 
0014 #include <KActionCollection>
0015 #include <KActionMenu>
0016 #include <KLocalizedString>
0017 #include <KMessageBox>
0018 #include <KStandardAction>
0019 #include <KStandardShortcut>
0020 #include <KTreeWidgetSearchLine>
0021 #include <KXMLGUIFactory>
0022 #include <QAction>
0023 #include <QIcon>
0024 #include <sonnet/configdialog.h>
0025 
0026 #include "basictab.h"
0027 #include "configurationmanager.h"
0028 #include "kmenueditadaptor.h"
0029 #include "preferencesdlg.h"
0030 #include "treeview.h"
0031 
0032 KMenuEdit::KMenuEdit()
0033     : KXmlGuiWindow(nullptr)
0034 {
0035     // dbus
0036     (void)new KmenueditAdaptor(this);
0037     QDBusConnection::sessionBus().registerObject(QStringLiteral("/KMenuEdit"), this);
0038 
0039     m_showHidden = ConfigurationManager::getInstance()->hiddenEntriesVisible();
0040 
0041     // setup GUI
0042     setupActions();
0043     slotChangeView();
0044 }
0045 
0046 KMenuEdit::~KMenuEdit()
0047 {
0048     ConfigurationManager::getInstance()->setSplitterSizes(m_splitter->sizes());
0049 }
0050 
0051 void KMenuEdit::setupActions()
0052 {
0053     QAction *action = actionCollection()->addAction(NEW_SUBMENU_ACTION_NAME);
0054     action->setIcon(QIcon::fromTheme(QStringLiteral("menu_new")));
0055     action->setText(i18n("&New Submenu..."));
0056     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_N));
0057     action = actionCollection()->addAction(NEW_ITEM_ACTION_NAME);
0058     action->setIcon(QIcon::fromTheme(QStringLiteral("document-new")));
0059     action->setText(i18n("New &Item..."));
0060     actionCollection()->setDefaultShortcuts(action, KStandardShortcut::openNew());
0061     action = actionCollection()->addAction(NEW_SEPARATOR_ACTION_NAME);
0062     action->setIcon(QIcon::fromTheme(QStringLiteral("menu_new_sep")));
0063     action->setText(i18n("New S&eparator"));
0064     actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_I));
0065 
0066     // "sort selection" menu
0067     KActionMenu *sortMenu = new KActionMenu(QIcon::fromTheme(QStringLiteral("view-sort-ascending")), i18n("&Sort"), this);
0068     sortMenu->setPopupMode(QToolButton::InstantPopup);
0069     actionCollection()->addAction(SORT_ACTION_NAME, sortMenu);
0070     action = actionCollection()->addAction(SORT_BY_NAME_ACTION_NAME);
0071     action->setText(i18n("&Sort selection by Name"));
0072     sortMenu->addAction(action);
0073     action = actionCollection()->addAction(SORT_BY_DESCRIPTION_ACTION_NAME);
0074     action->setText(i18n("&Sort selection by Description"));
0075     sortMenu->addAction(action);
0076     sortMenu->addSeparator();
0077     action = actionCollection()->addAction(SORT_ALL_BY_NAME_ACTION_NAME);
0078     action->setText(i18n("&Sort all by Name"));
0079     sortMenu->addAction(action);
0080     action = actionCollection()->addAction(SORT_ALL_BY_DESCRIPTION_ACTION_NAME);
0081     action->setText(i18n("&Sort all by Description"));
0082     sortMenu->addAction(action);
0083 
0084     // move up/down
0085     action = actionCollection()->addAction(MOVE_UP_ACTION_NAME);
0086     action->setIcon(QIcon::fromTheme(QStringLiteral("go-up")));
0087     action->setText(i18n("Move &Up"));
0088     action = actionCollection()->addAction(MOVE_DOWN_ACTION_NAME);
0089     action->setIcon(QIcon::fromTheme(QStringLiteral("go-down")));
0090     action->setText(i18n("Move &Down"));
0091 
0092     actionCollection()->addAction(KStandardAction::Save, this, SLOT(slotSave()));
0093     actionCollection()->addAction(KStandardAction::Quit, this, SLOT(close()));
0094     actionCollection()->addAction(KStandardAction::Cut);
0095     actionCollection()->addAction(KStandardAction::Copy);
0096     actionCollection()->addAction(KStandardAction::Paste);
0097 
0098     action = new QAction(i18n("Restore to System Menu"), this);
0099     actionCollection()->addAction(QStringLiteral("restore_system_menu"), action);
0100     connect(action, &QAction::triggered, this, &KMenuEdit::slotRestoreMenu);
0101 
0102     KStandardAction::preferences(this, SLOT(slotConfigure()), actionCollection());
0103 }
0104 
0105 void KMenuEdit::slotConfigure()
0106 {
0107     PreferencesDialog dialog(this);
0108     if (dialog.exec()) {
0109         bool newShowHiddenValue = ConfigurationManager::getInstance()->hiddenEntriesVisible();
0110         if (newShowHiddenValue != m_showHidden) {
0111             m_showHidden = newShowHiddenValue;
0112             m_tree->updateTreeView(m_showHidden);
0113             m_basicTab->updateHiddenEntry(m_showHidden);
0114         }
0115     }
0116 }
0117 
0118 void KMenuEdit::setupView()
0119 {
0120     // setup search and tree view
0121     m_tree = new TreeView(actionCollection(), this);
0122 
0123     m_searchLine = new KTreeWidgetSearchLine(this, m_tree);
0124     m_searchLine->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
0125     m_searchLine->setKeepParentsVisible(true);
0126     m_searchLine->setPlaceholderText(i18n("Search..."));
0127     m_searchLine->setToolTip(i18n("Search through the list of applications below"));
0128 
0129     QVBoxLayout *treeLayout = new QVBoxLayout;
0130     treeLayout->addWidget(m_searchLine);
0131     treeLayout->addWidget(m_tree);
0132     treeLayout->setContentsMargins(0, 0, 0, 0); // no padding, fixes alignment issues
0133     QFrame *treeFrame = new QFrame; // required to insert tree + search into splitter
0134     treeFrame->setLayout(treeLayout);
0135 
0136     m_splitter = new QSplitter(this);
0137     m_splitter->setOrientation(Qt::Horizontal);
0138     m_splitter->addWidget(treeFrame);
0139 
0140     // setup info tab view
0141     m_basicTab = new BasicTab;
0142     m_splitter->addWidget(m_basicTab);
0143 
0144     // add padding to splitter
0145     m_splitter->setContentsMargins(/*left=*/5, /*top=*/0, /*right=*/5, /*bottom=*/0);
0146 
0147     // clang-format off
0148     connect(m_tree, SIGNAL(entrySelected(MenuFolderInfo*)), m_basicTab, SLOT(setFolderInfo(MenuFolderInfo*)));
0149     connect(m_tree, SIGNAL(entrySelected(MenuEntryInfo*)), m_basicTab, SLOT(setEntryInfo(MenuEntryInfo*)));
0150     connect(m_tree, &TreeView::disableAction, m_basicTab, &BasicTab::slotDisableAction);
0151 
0152     connect(m_basicTab, SIGNAL(changed(MenuFolderInfo*)), m_tree, SLOT(currentDataChanged(MenuFolderInfo*)));
0153     connect(m_basicTab, SIGNAL(changed(MenuEntryInfo*)), m_tree, SLOT(currentDataChanged(MenuEntryInfo*)));
0154     // clang-format on
0155 
0156     connect(m_basicTab, &BasicTab::findServiceShortcut, m_tree, &TreeView::findServiceShortcut);
0157 
0158     connect(m_searchLine, &KTreeWidgetSearchLine::searchUpdated, m_tree, &TreeView::searchUpdated);
0159     // restore splitter sizes
0160     QList<int> sizes = ConfigurationManager::getInstance()->getSplitterSizes();
0161     if (sizes.isEmpty()) {
0162         sizes << 1 << 3;
0163     }
0164     m_splitter->setSizes(sizes);
0165     m_searchLine->setFocus();
0166 
0167     setCentralWidget(m_splitter);
0168 }
0169 
0170 void KMenuEdit::selectMenu(const QString &menu)
0171 {
0172     m_tree->selectMenu(menu);
0173 }
0174 
0175 void KMenuEdit::selectMenuEntry(const QString &menuEntry)
0176 {
0177     m_tree->selectMenuEntry(menuEntry);
0178 }
0179 
0180 void KMenuEdit::slotChangeView()
0181 {
0182     guiFactory()->removeClient(this);
0183 
0184     delete m_actionDelete;
0185 
0186     m_actionDelete = actionCollection()->addAction(DELETE_ACTION_NAME);
0187     m_actionDelete->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
0188     m_actionDelete->setText(i18n("&Delete"));
0189     actionCollection()->setDefaultShortcut(m_actionDelete, QKeySequence(Qt::Key_Delete));
0190 
0191     if (!m_splitter) {
0192         setupView();
0193     }
0194     setupGUI(KXmlGuiWindow::ToolBar | Keys | Save | Create, QStringLiteral("kmenueditui.rc"));
0195 
0196     m_tree->setViewMode(m_showHidden);
0197     m_basicTab->updateHiddenEntry(m_showHidden);
0198 }
0199 
0200 void KMenuEdit::slotSave()
0201 {
0202     m_tree->save();
0203 }
0204 
0205 bool KMenuEdit::queryClose()
0206 {
0207     if (!m_tree->dirty()) {
0208         return true;
0209     }
0210 
0211     int result;
0212     result = KMessageBox::warningTwoActionsCancel(this,
0213                                                   i18n("You have made changes to the menu.\n"
0214                                                        "Do you want to save the changes or discard them?"),
0215                                                   i18n("Save Menu Changes?"),
0216                                                   KStandardGuiItem::save(),
0217                                                   KStandardGuiItem::discard());
0218 
0219     switch (result) {
0220     case KMessageBox::PrimaryAction:
0221         return m_tree->save();
0222 
0223     case KMessageBox::SecondaryAction:
0224         return true;
0225 
0226     default:
0227         break;
0228     }
0229     return false;
0230 }
0231 
0232 void KMenuEdit::slotRestoreMenu()
0233 {
0234     m_tree->restoreMenuSystem();
0235 }
0236 
0237 void KMenuEdit::restoreSystemMenu()
0238 {
0239     m_tree->restoreMenuSystem();
0240 }