File indexing completed on 2025-02-16 05:01:42
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 auto wrapper = new QWidget(this); 0124 wrapper->setContentsMargins(wrapper->style()->pixelMetric(QStyle::PM_LayoutLeftMargin), 0125 wrapper->style()->pixelMetric(QStyle::PM_LayoutTopMargin), 0126 wrapper->style()->pixelMetric(QStyle::PM_LayoutRightMargin), 0127 wrapper->style()->pixelMetric(QStyle::PM_LayoutBottomMargin)); 0128 auto wrapperLayout = new QVBoxLayout(wrapper); 0129 wrapperLayout->setContentsMargins({}); 0130 0131 m_searchLine = new KTreeWidgetSearchLine(wrapper, m_tree); 0132 m_searchLine->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive); 0133 m_searchLine->setKeepParentsVisible(true); 0134 m_searchLine->setPlaceholderText(i18n("Search...")); 0135 m_searchLine->setToolTip(i18n("Search through the list of applications below")); 0136 0137 wrapperLayout->addWidget(m_searchLine); 0138 0139 auto horizontalSeparator = new QFrame(this); 0140 horizontalSeparator->setFrameStyle(QFrame::HLine); 0141 0142 QVBoxLayout *treeLayout = new QVBoxLayout; 0143 treeLayout->addWidget(wrapper); 0144 treeLayout->addWidget(horizontalSeparator); 0145 treeLayout->addWidget(m_tree); 0146 treeLayout->setSpacing(0); 0147 treeLayout->setContentsMargins(0, 0, 0, 0); // no padding, fixes alignment issues 0148 QFrame *treeFrame = new QFrame; // required to insert tree + search into splitter 0149 treeFrame->setLayout(treeLayout); 0150 0151 m_splitter = new QSplitter(this); 0152 m_splitter->setOrientation(Qt::Horizontal); 0153 m_splitter->addWidget(treeFrame); 0154 0155 // setup info tab view 0156 m_basicTab = new BasicTab; 0157 m_splitter->addWidget(m_basicTab); 0158 0159 // add padding to splitter 0160 m_splitter->setContentsMargins(0, 0, 0, 0); 0161 0162 // clang-format off 0163 connect(m_tree, SIGNAL(entrySelected(MenuFolderInfo*)), m_basicTab, SLOT(setFolderInfo(MenuFolderInfo*))); 0164 connect(m_tree, SIGNAL(entrySelected(MenuEntryInfo*)), m_basicTab, SLOT(setEntryInfo(MenuEntryInfo*))); 0165 connect(m_tree, &TreeView::disableAction, m_basicTab, &BasicTab::slotDisableAction); 0166 0167 connect(m_basicTab, SIGNAL(changed(MenuFolderInfo*)), m_tree, SLOT(currentDataChanged(MenuFolderInfo*))); 0168 connect(m_basicTab, SIGNAL(changed(MenuEntryInfo*)), m_tree, SLOT(currentDataChanged(MenuEntryInfo*))); 0169 // clang-format on 0170 0171 connect(m_basicTab, &BasicTab::findServiceShortcut, m_tree, &TreeView::findServiceShortcut); 0172 0173 connect(m_searchLine, &KTreeWidgetSearchLine::searchUpdated, m_tree, &TreeView::searchUpdated); 0174 // restore splitter sizes 0175 QList<int> sizes = ConfigurationManager::getInstance()->getSplitterSizes(); 0176 if (sizes.isEmpty()) { 0177 sizes << 1 << 3; 0178 } 0179 m_splitter->setSizes(sizes); 0180 m_searchLine->setFocus(); 0181 0182 setCentralWidget(m_splitter); 0183 } 0184 0185 void KMenuEdit::selectMenu(const QString &menu) 0186 { 0187 m_tree->selectMenu(menu); 0188 } 0189 0190 void KMenuEdit::selectMenuEntry(const QString &menuEntry) 0191 { 0192 m_tree->selectMenuEntry(menuEntry); 0193 } 0194 0195 void KMenuEdit::slotChangeView() 0196 { 0197 guiFactory()->removeClient(this); 0198 0199 delete m_actionDelete; 0200 0201 m_actionDelete = actionCollection()->addAction(DELETE_ACTION_NAME); 0202 m_actionDelete->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete"))); 0203 m_actionDelete->setText(i18n("&Delete")); 0204 actionCollection()->setDefaultShortcut(m_actionDelete, QKeySequence(Qt::Key_Delete)); 0205 0206 if (!m_splitter) { 0207 setupView(); 0208 } 0209 setupGUI(KXmlGuiWindow::ToolBar | Keys | Save | Create, QStringLiteral("kmenueditui.rc")); 0210 0211 m_tree->setViewMode(m_showHidden); 0212 m_basicTab->updateHiddenEntry(m_showHidden); 0213 } 0214 0215 void KMenuEdit::slotSave() 0216 { 0217 m_tree->save(); 0218 } 0219 0220 bool KMenuEdit::queryClose() 0221 { 0222 if (!m_tree->dirty()) { 0223 return true; 0224 } 0225 0226 int result; 0227 result = KMessageBox::warningTwoActionsCancel(this, 0228 i18n("You have made changes to the menu.\n" 0229 "Do you want to save the changes or discard them?"), 0230 i18n("Save Menu Changes?"), 0231 KStandardGuiItem::save(), 0232 KStandardGuiItem::discard()); 0233 0234 switch (result) { 0235 case KMessageBox::PrimaryAction: 0236 return m_tree->save(); 0237 0238 case KMessageBox::SecondaryAction: 0239 return true; 0240 0241 default: 0242 break; 0243 } 0244 return false; 0245 } 0246 0247 void KMenuEdit::slotRestoreMenu() 0248 { 0249 m_tree->restoreMenuSystem(); 0250 } 0251 0252 void KMenuEdit::restoreSystemMenu() 0253 { 0254 m_tree->restoreMenuSystem(); 0255 }