File indexing completed on 2025-04-27 14:17:51
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 }