File indexing completed on 2024-05-19 05:06:01

0001 /***********************************************************************************
0002   Copyright (C) 2011-2012 by Holger Danielsson (holger.danielsson@versanet.de)
0003             (C) 2018 by Michel Ludwig (michel.ludwig@kdemail.net)
0004  ***********************************************************************************/
0005 
0006 /***************************************************************************
0007  *                                                                         *
0008  *   This program is free software; you can redistribute it and/or modify  *
0009  *   it under the terms of the GNU General Public License as published by  *
0010  *   the Free Software Foundation; either version 2 of the License, or     *
0011  *   (at your option) any later version.                                   *
0012  *                                                                         *
0013  ***************************************************************************/
0014 
0015 #include <QDialogButtonBox>
0016 #include <QFileDialog>
0017 #include <QInputDialog>
0018 #include <QKeySequence>
0019 #include <QPushButton>
0020 #include <QVBoxLayout>
0021 
0022 #include <KLocalizedString>
0023 #include <KIconDialog>
0024 #include <KMessageBox>
0025 #include <KXMLGUIClient>
0026 #include <KXMLGUIFactory>
0027 #include <KConfigGroup>
0028 
0029 #include "dialogs/usermenu/usermenudialog.h"
0030 #include "dialogs/usermenu/usermenutree.h"
0031 #include "dialogs/usermenu/usermenuitem.h"
0032 #include "usermenu/usermenu.h"
0033 
0034 #include "kiledebug.h"
0035 #include "utilities.h"
0036 
0037 namespace KileMenu {
0038 
0039 #define CHOOSABLE_MENUTYPES   3
0040 
0041 UserMenuDialog::UserMenuDialog(KConfig *config, KileInfo *ki, KileMenu::UserMenu *userMenu, const QString &xmlfile, QWidget *parent)
0042     : KileDialog::Wizard(config, parent, Q_NULLPTR, i18n("Edit User Menu"))
0043     , m_ki(ki)
0044     , m_userMenu(userMenu)
0045 {
0046     QWidget *page = new QWidget();
0047     QVBoxLayout *mainLayout = new QVBoxLayout;
0048     setLayout(mainLayout);
0049 
0050     m_UserMenuDialog.setupUi(page);
0051 
0052     m_menutree = m_UserMenuDialog.m_twUserMenu;
0053     m_menutree->setHeaderLabels(QStringList() << i18n("Menu Entry") << i18n("Shortcut"));
0054 
0055     // Indexes must be identical to MenuType. Only the first three of them are choosable (see CHOOSABLE_MENUTYPES)
0056     m_listMenutypes << i18n("Text") << i18n("Insert file contents") << i18n("Execute program") << i18n("Separator") << i18n("Submenu");
0057 
0058     // some text
0059     m_UserMenuDialog.m_teText->setWhatsThis(i18n("Text, which will be inserted, if the action is executed. Some placeholders are available: <ul><li>%M - selected (marked) text</li><li>%C - cursor position</li><li>%B - bullet</li><li>%E - indentation in environments</li><li>%R - select label from list</li><li>%T - select citation key from list</li></ul>"));
0060     m_UserMenuDialog.m_teText->setToolTip(i18n("Available placeholders:\n%M: Selected (marked) text\n%C: Cursor position\n%B: Bullet\n%E: Indentation in environments\n%R: Select label from list\n%T: Select citation key from list\n%S: Source file name without extension"));
0061 
0062     // search for all action collections (needed for shortcut conflicts)
0063     QList<KActionCollection *> allCollections;
0064     foreach (KXMLGUIClient *client, m_ki->mainWindow()->guiFactory()->clients()) {
0065         KILE_DEBUG_MAIN << "collection count: " << client->actionCollection()->count() ;
0066         allCollections += client->actionCollection();
0067     }
0068     m_UserMenuDialog.m_keyChooser->setCheckActionCollections(allCollections);
0069     KILE_DEBUG_MAIN << "total collections: " << allCollections.count();
0070 
0071     m_UserMenuDialog.m_pbInsertBelow->setIcon(QIcon::fromTheme("usermenu-insert-below.png"));
0072     m_UserMenuDialog.m_pbInsertSubmenu->setIcon(QIcon::fromTheme("usermenu-submenu-below.png"));
0073     m_UserMenuDialog.m_pbInsertSeparator->setIcon(QIcon::fromTheme("usermenu-separator-below.png"));
0074     m_UserMenuDialog.m_pbDelete->setIcon(QIcon::fromTheme("usermenu-delete.png"));
0075     m_UserMenuDialog.m_pbUp->setIcon(QIcon::fromTheme("usermenu-up.png"));
0076     m_UserMenuDialog.m_pbDown->setIcon(QIcon::fromTheme("usermenu-down.png"));
0077     m_UserMenuDialog.m_pbIconDelete->setIcon(QIcon::fromTheme("edit-clear-locationbar-rtl.png"));
0078 
0079     connect(m_UserMenuDialog.m_pbInsertBelow, &QPushButton::clicked, this, &UserMenuDialog::slotInsertMenuItem);
0080     connect(m_UserMenuDialog.m_pbInsertSubmenu, &QPushButton::clicked, this, &UserMenuDialog::slotInsertSubmenu);
0081     connect(m_UserMenuDialog.m_pbInsertSeparator, &QPushButton::clicked, this, &UserMenuDialog::slotInsertSeparator);
0082     connect(m_UserMenuDialog.m_pbUp, &QPushButton::clicked, this, &UserMenuDialog::slotUp);
0083     connect(m_UserMenuDialog.m_pbDown, &QPushButton::clicked, this, &UserMenuDialog::slotDown);
0084     connect(m_UserMenuDialog.m_pbDelete, &QPushButton::clicked, this, &UserMenuDialog::slotDelete);
0085 
0086     connect(m_menutree, &QTreeWidget::currentItemChanged, this, &UserMenuDialog::slotCurrentItemChanged);
0087 
0088     connect(m_UserMenuDialog.m_pbMenuentryType, &QPushButton::clicked, this, &UserMenuDialog::slotMenuentryTypeClicked);
0089     connect(m_UserMenuDialog.m_leMenuEntry, &KLineEdit::textEdited, this, &UserMenuDialog::slotMenuentryTextChanged);
0090     connect(m_UserMenuDialog.m_urlRequester, &KUrlRequester::textChanged, this, &UserMenuDialog::slotUrlTextChanged);
0091     connect(m_UserMenuDialog.m_urlRequester, &KUrlRequester::urlSelected, this, [=]() {
0092         setModified();
0093     });
0094     connect(m_UserMenuDialog.m_leParameter, &KLineEdit::textEdited, this, [=]() {
0095         setModified();
0096     });
0097     connect(m_UserMenuDialog.m_teText, &QPlainTextEdit::textChanged, this, [=]() {
0098         setModified();
0099     });
0100     connect(m_UserMenuDialog.m_pbIcon, &QPushButton::clicked, this, &UserMenuDialog::slotIconClicked);
0101     connect(m_UserMenuDialog.m_pbIconDelete, &QPushButton::clicked, this, &UserMenuDialog::slotIconDeleteClicked);
0102     connect(m_UserMenuDialog.m_keyChooser, &KKeySequenceWidget::keySequenceChanged, this, &UserMenuDialog::slotKeySequenceChanged);
0103 
0104     connect(m_UserMenuDialog.m_cbNeedsSelection,   &QCheckBox::stateChanged, this, &UserMenuDialog::slotSelectionStateChanged);
0105     connect(m_UserMenuDialog.m_cbContextMenu,      &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged);
0106     connect(m_UserMenuDialog.m_cbReplaceSelection, &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged);
0107     connect(m_UserMenuDialog.m_cbSelectInsertion,  &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged);
0108     connect(m_UserMenuDialog.m_cbInsertOutput,     &QCheckBox::stateChanged, this, &UserMenuDialog::slotCheckboxStateChanged);
0109 
0110     connect(m_UserMenuDialog.m_pbInstall, &QPushButton::clicked, this, &UserMenuDialog::slotInstallClicked);
0111     connect(m_UserMenuDialog.m_pbNew,     &QPushButton::clicked, this, &UserMenuDialog::slotNewClicked);
0112 
0113     connect(m_UserMenuDialog.m_pbLoad,   &QPushButton::clicked, this, &UserMenuDialog::slotLoadClicked);
0114     connect(m_UserMenuDialog.m_pbSave,   &QPushButton::clicked, this, &UserMenuDialog::slotSaveClicked);
0115     connect(m_UserMenuDialog.m_pbSaveAs, &QPushButton::clicked, this, &UserMenuDialog::slotSaveAsClicked);
0116 
0117     // set context menu handler for the menutree
0118     m_menutree->setContextMenuPolicy(Qt::CustomContextMenu);
0119     connect(m_menutree, &QWidget::customContextMenuRequested, this, &UserMenuDialog::slotCustomContextMenuRequested);
0120 
0121     // adjust some widths
0122     const int w = m_UserMenuDialog.m_pbInsertBelow->sizeHint().width();
0123     m_UserMenuDialog.m_pbUp->setMinimumWidth(w);
0124     m_UserMenuDialog.m_pbDown->setMinimumWidth(w);
0125     m_UserMenuDialog.m_lbIconChosen->setMinimumWidth(m_UserMenuDialog.m_pbIcon->sizeHint().width());
0126 
0127     setFocusProxy(m_menutree);
0128     setModal(false);
0129 
0130     // TODO: currently all dialog actions are in an extra widget
0131     // for usability some of those actions should be connect to the main dialog controls,
0132     // e.g. automatic install when pressing OK
0133     buttonBox()->clear();
0134     buttonBox()->addButton(QDialogButtonBox::Close);
0135     buttonBox()->addButton(QDialogButtonBox::Help);
0136 
0137     mainLayout->addWidget(page);
0138     mainLayout->addWidget(buttonBox());
0139     connect(buttonBox(), &QDialogButtonBox::helpRequested, this, &UserMenuDialog::slotShowHelp);
0140 
0141     KILE_DEBUG_MAIN << "start dialog with xmfile " << xmlfile;
0142 
0143     if (!xmlfile.isEmpty() && QFile::exists(xmlfile)) {
0144         m_modified = false;
0145         loadXmlFile(xmlfile,true);
0146     }
0147     else {
0148         startDialog();
0149     }
0150 
0151     resize(minimumSize());
0152 }
0153 
0154 void UserMenuDialog::startDialog()
0155 {
0156     initDialog();
0157 
0158     m_modified = false;
0159     setXmlFile(QString(), false);
0160     updateDialogButtons();
0161     m_UserMenuDialog.m_pbNew->setEnabled(false);
0162 }
0163 
0164 void UserMenuDialog::initDialog()
0165 {
0166     updateTreeButtons();
0167 
0168     QTreeWidgetItem *current = m_menutree->currentItem();
0169     if (current) {
0170         m_menutree->setCurrentItem(current);
0171     }
0172 
0173     // init first entry
0174     m_currentIcon.clear();
0175     showMenuentryData(dynamic_cast<UserMenuItem *>(current));
0176 }
0177 
0178 void UserMenuDialog::setXmlFile(const QString &filename, bool installed)
0179 {
0180     m_currentXmlInstalled = installed;
0181     m_currentXmlFile = filename;
0182     m_UserMenuDialog.m_lbXmlFile->setText(i18n("File:") + QLatin1String("   ") + QFileInfo(m_currentXmlFile).fileName());
0183     if (m_currentXmlInstalled) {
0184         m_UserMenuDialog.m_lbXmlInstalled->show();
0185     } else {
0186         m_UserMenuDialog.m_lbXmlInstalled->hide();
0187     }
0188 }
0189 
0190 void UserMenuDialog::setModified()
0191 {
0192     if (!m_modified) {
0193         m_modified = true;
0194     }
0195 
0196     updateDialogButtons();
0197 }
0198 
0199 void UserMenuDialog::updateDialogButtons()
0200 {
0201     bool installedFile = (!m_currentXmlFile.isEmpty());
0202     bool menutreeState = !m_menutree->isEmpty();
0203 
0204     bool installState = !m_modified && installedFile && !m_currentXmlInstalled;
0205     bool saveState = m_modified && installedFile;
0206     bool saveAsState = m_modified || (!m_modified && installedFile && m_currentXmlInstalled);
0207 
0208     m_UserMenuDialog.m_pbInstall->setEnabled(installState && menutreeState);
0209     m_UserMenuDialog.m_pbSave->setEnabled(saveState && menutreeState);
0210     m_UserMenuDialog.m_pbSaveAs->setEnabled(saveAsState && menutreeState);
0211     m_UserMenuDialog.m_pbNew->setEnabled(true);
0212 }
0213 
0214 void UserMenuDialog::slotShowHelp()
0215 {
0216     const QString message = i18n("<p>You can create, change and install a user-defined menu, which will appear as a part of Kile's menu. "
0217                                  "To create or change this menu, use the six buttons on the left side. "
0218                                  "Even more possible actions are available in the context menu of already existing menu items.</p>"
0219                                  "<p>Like a standard menu, three different kinds of menu items are available:</p>"
0220                                  "<ul>"
0221                                  "<li><i>standard entries</i>, which are assigned to an action</li>"
0222                                  "<li><i>submenus</i>, which contain more menu items</li>"
0223                                  "<li><i>separators</i>, to get a visible structure of all entries</li>"
0224                                  "</ul>"
0225                                  "<p>Each standard menu item is assigned to one of three action types:</p>"
0226                                  "<ul>"
0227                                  "<li><i>insert text</i>: this action will insert your text at the current cursor position. "
0228                                  "Some metachars are available: <tt>%M</tt>, <tt>%C</tt>, <tt>%B</tt>, <tt>%E</tt>, <tt>%R</tt>, <tt>%T</tt>, <tt>%S</tt>: "
0229                                  "see the <i>What's This</i> or <i>Tool Tip</i> feature of this widget to get more information.</li>"
0230                                  "<li><i>file content</i>: inserts the complete contents of a given file (metachars are also available)</li>"
0231                                  "<li><i>run an external program</i>: The output of this program can be inserted into the opened document. "
0232                                  "Metachar <tt>%M</tt> is also possible in the commandline of this program, as the selected text will be saved in a temporary file. "
0233                                  "Use <tt>%M</tt> for the filename of this temporary file.</li>"
0234                                  "</ul>"
0235                                  "<p>If some  important information for an action is missing, menu items are colored red. "
0236                                  "More information is available using the <i>What's this</i> feature of most widgets.</p>");
0237 
0238     KMessageBox::information(this, message, i18n("UserMenu Dialog"));
0239 }
0240 
0241 
0242 ///////////////////////////// Button slots (Install/New) //////////////////////////////
0243 
0244 void UserMenuDialog::slotInstallClicked()
0245 {
0246     KILE_DEBUG_MAIN << "install " << m_currentXmlFile << "...";
0247 
0248     if (!m_modified && !m_currentXmlFile.isEmpty()) {
0249         m_userMenu->installXmlFile(m_currentXmlFile);
0250         setXmlFile(m_currentXmlFile,true);
0251         updateDialogButtons();
0252     }
0253 }
0254 
0255 void UserMenuDialog::slotNewClicked()
0256 {
0257     KILE_DEBUG_MAIN << "start new menutree ... ";
0258 
0259     if (!m_menutree->isEmpty() && m_modified) {
0260         if (KMessageBox::questionTwoActions(this, i18n("Current menu tree was modified, but not saved.\nDiscard this tree?"),
0261                                             i18n("Discard tree"),
0262                                             KStandardGuiItem::discard(), KStandardGuiItem::cancel()) == KMessageBox::SecondaryAction) {
0263             return;
0264         }
0265     }
0266 
0267     m_menutree->clear();
0268     m_modified = false;
0269     startDialog();   // includes updating of buttons
0270 }
0271 
0272 
0273 ///////////////////////////// Button slots (Load) //////////////////////////////
0274 
0275 void UserMenuDialog::slotLoadClicked()
0276 {
0277     KILE_DEBUG_MAIN << "load xml file ";
0278 
0279     if (!m_menutree->isEmpty() && m_modified) {
0280         if (KMessageBox::questionTwoActions(this, i18n("Current menu tree was modified, but not saved.\nDiscard this tree?"),
0281                                             i18n("Discard tree"),
0282                                             KStandardGuiItem::discard(), KStandardGuiItem::cancel()) == KMessageBox::SecondaryAction) {
0283             return;
0284         }
0285     }
0286 
0287     QString directory = UserMenu::selectUserMenuDir();
0288     QString filter = i18n("User Menu Files (*.xml)");
0289 
0290     QString filename = QFileDialog::getOpenFileName(this, i18n("Select Menu File"), directory, filter);
0291     if (filename.isEmpty()) {
0292         return;
0293     }
0294 
0295     if (QFile::exists(filename)) {
0296         loadXmlFile(filename,false); // includes updating of buttons
0297     }
0298     else {
0299         KMessageBox::error(this, i18n("File '%1' does not exist.", filename));
0300     }
0301 }
0302 
0303 void UserMenuDialog::loadXmlFile(const QString &filename, bool installed)
0304 {
0305     KILE_DEBUG_MAIN << "load xml started ...";
0306     m_menutree->readXml(filename);
0307     initDialog();
0308     m_modified = false;
0309     setXmlFile(filename,installed);
0310     updateDialogButtons();
0311     KILE_DEBUG_MAIN << "load xml finished ...";
0312 }
0313 
0314 ///////////////////////////// Button slots (Save) //////////////////////////////
0315 
0316 void UserMenuDialog::slotSaveClicked()
0317 {
0318     if (saveClicked()) {
0319         m_modified = false;
0320         if (m_currentXmlInstalled) {
0321             slotInstallClicked();   // includes all updates
0322         }
0323         else {
0324             setXmlFile(m_currentXmlFile,false);
0325         }
0326         updateDialogButtons();
0327     }
0328 }
0329 
0330 bool UserMenuDialog::saveClicked()
0331 {
0332     if (m_currentXmlFile.isEmpty()) {
0333         return false;
0334     }
0335     KILE_DEBUG_MAIN << "save menutree: " << m_currentXmlFile;
0336 
0337     // read current entry
0338     QTreeWidgetItem *current = m_menutree->currentItem();
0339     if (current) {
0340         KILE_DEBUG_MAIN << "read current item ...";
0341         readMenuentryData( dynamic_cast<UserMenuItem *>(current) );
0342     }
0343 
0344     if (saveCheck() == false) {
0345         return false;
0346     }
0347 
0348     // force to save file in local directory
0349     QStringList dirs = KileUtilities::locateAll(QStandardPaths::AppDataLocation, "usermenu", QStandardPaths::LocateDirectory);
0350     if (dirs.size() > 1) {
0351         if (m_currentXmlFile.startsWith(dirs[1])) {
0352             m_currentXmlFile.replace(dirs[1],dirs[0]);
0353             KILE_DEBUG_MAIN << "change filename to local directory:" << m_currentXmlFile;
0354         }
0355     }
0356 
0357     // save file
0358     m_menutree->writeXml(m_currentXmlFile);
0359     return true;
0360 }
0361 
0362 void UserMenuDialog::slotSaveAsClicked()
0363 {
0364     const QString filename = saveAsClicked();
0365     if (!filename.isEmpty()) {
0366         // set new state: current file is not installed anymore
0367         m_modified = false;
0368         setXmlFile(filename,false);
0369         updateDialogButtons();
0370     }
0371 }
0372 
0373 QString UserMenuDialog::saveAsClicked()
0374 {
0375     KILE_DEBUG_MAIN << "menutree should be saved as ...";
0376 
0377     // read current entry
0378     QTreeWidgetItem *current = m_menutree->currentItem();
0379     if (current) {
0380         KILE_DEBUG_MAIN << "read current item ...";
0381         readMenuentryData(dynamic_cast<UserMenuItem *>(current));
0382     }
0383 
0384     if (saveCheck() == false) {
0385         return QString();
0386     }
0387 
0388     const QString directory = KileUtilities::writableLocation(QStandardPaths::AppDataLocation) + QLatin1Char('/') + "usermenu/";
0389     const QString filter = i18n("User Menu Files (*.xml)");
0390 
0391     QString filename = QFileDialog::getSaveFileName(this, i18n("Save Menu File"), directory, filter);
0392     if (filename.isEmpty()) {
0393         return QString();
0394     }
0395 
0396     if (QFile::exists(filename)) {
0397         if (KMessageBox::questionTwoActions(this, i18n("File '%1' does already exist.\nOverwrite this file?", filename),
0398                                             i18n("Overwrite file"),
0399                                             KStandardGuiItem::overwrite(), KStandardGuiItem::cancel()) == KMessageBox::SecondaryAction) {
0400             return QString();
0401         }
0402     }
0403 
0404     // save file
0405     m_menutree->writeXml(filename);
0406     return filename;
0407 }
0408 
0409 bool UserMenuDialog::saveCheck()
0410 {
0411     if (m_menutree->errorCheck() == false) {
0412         if (KMessageBox::questionTwoActions(this, i18n("The menu tree contains some errors and installing this file may lead to unpredictable results.\nDo you really want to save this file?"),
0413                                             i18n("Menu tree errors"),
0414                                             KStandardGuiItem::save(), KStandardGuiItem::cancel()) == KMessageBox::SecondaryAction) {
0415             return false;
0416         }
0417     }
0418 
0419     return true;
0420 }
0421 
0422 ///////////////////////////// Button slots (left widget) //////////////////////////////
0423 
0424 void UserMenuDialog::slotCustomContextMenuRequested(const QPoint &pos)
0425 {
0426     m_menutree->contextMenuRequested(pos);
0427     updateAfterDelete();
0428 }
0429 
0430 void UserMenuDialog::slotInsertMenuItem()
0431 {
0432     if (m_menutree->insertMenuItem(m_menutree->currentItem())) {
0433         updateTreeButtons();
0434         setModified();
0435     }
0436 }
0437 
0438 void UserMenuDialog::slotInsertSubmenu()
0439 {
0440     QTreeWidgetItem *current = m_menutree->currentItem();
0441     if (current && m_menutree->insertSubmenu(current)) {
0442         updateTreeButtons();
0443         setModified();
0444     }
0445 }
0446 
0447 void UserMenuDialog::slotInsertSeparator()
0448 {
0449     QTreeWidgetItem *current = m_menutree->currentItem();
0450     if (current && m_menutree->insertSeparator(current)) {
0451         updateTreeButtons();
0452         setModified();
0453     }
0454 }
0455 
0456 void UserMenuDialog::slotDelete()
0457 {
0458     QTreeWidgetItem *current = m_menutree->currentItem();
0459     if (current) {
0460         m_menutree->itemDelete(current);
0461         updateAfterDelete();
0462     }
0463 }
0464 
0465 void UserMenuDialog::slotUp()
0466 {
0467     QTreeWidgetItem *current = m_menutree->currentItem();
0468     if (current) {
0469         m_menutree->itemUp();
0470         updateTreeButtons();
0471         setModified();
0472     }
0473 }
0474 
0475 void UserMenuDialog::slotDown()
0476 {
0477     QTreeWidgetItem *current = m_menutree->currentItem();
0478     if (current) {
0479         m_menutree->itemDown();
0480         updateTreeButtons();
0481         setModified();
0482     }
0483 }
0484 
0485 void UserMenuDialog::updateTreeButtons()
0486 {
0487     UserMenuItem *current = dynamic_cast<UserMenuItem *>(m_menutree->currentItem());
0488     if (current) {
0489         bool state = (current->menutype() == UserMenuData::Separator) ? false : true;
0490         m_UserMenuDialog.m_pbInsertSeparator->setEnabled(state);
0491         m_UserMenuDialog.m_pbDelete->setEnabled(true);
0492 
0493         bool upstate = (m_menutree->indexOfTopLevelItem(current) == 0) ? false : true;
0494         m_UserMenuDialog.m_pbUp->setEnabled(upstate);
0495 
0496         bool downstate = (m_menutree->itemBelow(current)) ? true : false;
0497         if (!downstate && current->parent()) {
0498             downstate = true;
0499         }
0500         m_UserMenuDialog.m_pbDown->setEnabled(downstate);
0501     }
0502     else {
0503         m_UserMenuDialog.m_pbInsertSeparator->setEnabled(false);
0504         m_UserMenuDialog.m_pbDelete->setEnabled(false);
0505         m_UserMenuDialog.m_pbUp->setEnabled(false);
0506         m_UserMenuDialog.m_pbDown->setEnabled(false);
0507     }
0508 }
0509 
0510 void UserMenuDialog::updateAfterDelete()
0511 {
0512     if (m_menutree->isEmpty()) {
0513         initDialog();
0514     }
0515 
0516     updateTreeButtons();
0517     setModified();
0518 
0519 }
0520 
0521 ////////////////////////////// TreeWidget slots (left widget)  //////////////////////////////
0522 
0523 void UserMenuDialog::slotCurrentItemChanged(QTreeWidgetItem *current,QTreeWidgetItem *previous)
0524 {
0525     QString from = (previous) ? previous->text(0) : "---";
0526     QString to   = (current)  ? current->text(0)  : "---";
0527 
0528     KILE_DEBUG_MAIN << "currentItemChanged: from=" << from << "  to=" << to;
0529     bool modifiedState = m_modified;
0530     bool installState = m_UserMenuDialog.m_pbInstall->isEnabled();
0531     bool saveState = m_UserMenuDialog.m_pbSave->isEnabled();
0532     bool saveAsState = m_UserMenuDialog.m_pbSaveAs->isEnabled();
0533 
0534     // read old data
0535     readMenuentryData(dynamic_cast<UserMenuItem *>(previous));
0536 
0537     // set new data
0538     showMenuentryData(dynamic_cast<UserMenuItem *>(current));
0539 
0540     // update buttons for treewidget
0541     updateTreeButtons();
0542 
0543     // restore saved states
0544     m_modified = modifiedState;
0545     m_UserMenuDialog.m_pbInstall->setEnabled(installState);
0546     m_UserMenuDialog.m_pbSave->setEnabled(saveState);
0547     m_UserMenuDialog.m_pbSaveAs->setEnabled(saveAsState);
0548 }
0549 
0550 //////////////////////////////  MenuentryType slots (right widget) //////////////////////////////
0551 
0552 void UserMenuDialog::slotMenuentryTypeClicked()
0553 {
0554     UserMenuItem *current = dynamic_cast<UserMenuItem *>(m_menutree->currentItem());
0555     if (!current) {
0556         return;
0557     }
0558 
0559     KILE_DEBUG_MAIN << "change menu item type of current item: " << current->text(0);
0560     QStringList typelist;
0561     for (int i = 0; i < CHOOSABLE_MENUTYPES; ++i) {
0562         typelist << m_listMenutypes[i];
0563     }
0564 
0565     int oldtype = current->menutype();
0566     bool ok = false;
0567 
0568     QString item = QInputDialog::getItem(this, i18n("Menutype"), i18n("Please choose a menutype"),
0569                                          typelist, oldtype, false, &ok);
0570     if (!ok) {
0571         return;
0572     }
0573 
0574     int newtype = m_listMenutypes.indexOf(item);
0575     if (newtype == -1 || newtype == oldtype) {
0576         return;
0577     }
0578 
0579     // set new values
0580     current->setMenutype( UserMenuData::MenuType(newtype) );
0581     m_UserMenuDialog.m_lbMenuentryType->setText(item);
0582     if (newtype == UserMenuData::Text) {
0583         setMenuentryFileChooser(current,false);
0584         setMenuentryFileParameter(current,false);
0585         setMenuentryTextEdit(current,true);
0586         setMenuentryCheckboxes(current,false);
0587     }
0588     else if (newtype == UserMenuData::FileContent) {
0589         setMenuentryFileChooser(current,true);
0590         setMenuentryFileParameter(current,false);
0591         setMenuentryTextEdit(current,false);
0592         setMenuentryCheckboxes(current,false);
0593     }
0594     else { /* if (newtype == UserMenuData::Program) */
0595         setMenuentryFileChooser(current,true);
0596         setMenuentryFileParameter(current,true);
0597         setMenuentryTextEdit(current,false);
0598         setMenuentryCheckboxes(current,true);
0599     }
0600 
0601     setModified();
0602 }
0603 
0604 ////////////////////////////// Menuentry slot (right widget) //////////////////////////////
0605 
0606 void UserMenuDialog::slotMenuentryTextChanged(const QString &text)
0607 {
0608     UserMenuItem *current = dynamic_cast<UserMenuItem *>( m_menutree->currentItem() );
0609     if (current) {
0610         current->setText(0,text);
0611     }
0612     setModified();
0613 }
0614 
0615 ////////////////////////////// KUrlRequester slots (right widget) //////////////////////////////
0616 
0617 void UserMenuDialog::slotUrlTextChanged(const QString &)
0618 {
0619     UserMenuItem *current = dynamic_cast<UserMenuItem *>(m_menutree->currentItem());
0620     if (!current) {
0621         return;
0622     }
0623 
0624     QString file = m_UserMenuDialog.m_urlRequester->text().trimmed();
0625 
0626     QString color = "black";
0627     int type = current->menutype();
0628     if (type == UserMenuData::FileContent) {
0629         if (file.isEmpty() || !QFile::exists(file)) {
0630             color = "red";
0631         }
0632     }
0633     else if (type == UserMenuData::Program) {
0634         if (file.isEmpty() || !m_menutree->isItemExecutable(file)) {
0635             color= "red";
0636         }
0637     }
0638 
0639     m_UserMenuDialog.m_urlRequester->setStyleSheet( "QLineEdit { color: " + color + "; }" );
0640     setModified();
0641 }
0642 
0643 ////////////////////////////// Icon slots (right widget) //////////////////////////////
0644 
0645 void  UserMenuDialog::slotIconClicked()
0646 {
0647     QString iconname = KIconDialog::getIcon(KIconLoader::Small, KIconLoader::Any,true);
0648     if (iconname!=m_currentIcon && !iconname.isEmpty()) {
0649         QString iconpath = KIconLoader::global()->iconPath(iconname,KIconLoader::Small);
0650         KILE_DEBUG_MAIN << "icon changed: " << iconname << " path=" << iconpath;
0651         m_currentIcon = iconpath;
0652         setMenuentryIcon(m_currentIcon);
0653         setModified();
0654     }
0655 }
0656 
0657 void  UserMenuDialog::slotIconDeleteClicked()
0658 {
0659     m_currentIcon.clear();
0660     setMenuentryIcon(m_currentIcon);
0661     setModified();
0662 }
0663 
0664 void UserMenuDialog::setMenuentryIcon(const QString &icon)
0665 {
0666     UserMenuItem *current = dynamic_cast<UserMenuItem *>(m_menutree->currentItem());
0667     if (current) {
0668         if (icon.isEmpty()) {
0669             current->setIcon(0, QIcon::fromTheme(QString()));
0670         } else {
0671             current->setIcon(0, QIcon::fromTheme(icon));
0672         }
0673         current->setMenuicon(icon);
0674 
0675         // update icon widgets
0676         setMenuentryIcon(current,true,icon);
0677         setModified();
0678     }
0679 }
0680 
0681 ////////////////////////////// Shortcut slots (right widget) //////////////////////////////
0682 
0683 void UserMenuDialog::slotKeySequenceChanged(const QKeySequence &seq)
0684 {
0685     QString shortcut = seq.toString(QKeySequence::NativeText);
0686     KILE_DEBUG_MAIN << "key sequence changed: " << shortcut;
0687 
0688     UserMenuItem *current = dynamic_cast<UserMenuItem *>( m_menutree->currentItem() );
0689     if (current) {
0690         current->setText(1, shortcut);
0691         current->setShortcut(shortcut);
0692 
0693         m_UserMenuDialog.m_keyChooser->applyStealShortcut();
0694         setModified();
0695     }
0696 }
0697 
0698 //////////////////////////////  Selection checkbox slots (right widget) //////////////////////////////
0699 
0700 void UserMenuDialog::slotSelectionStateChanged(int state)
0701 {
0702     m_UserMenuDialog.m_cbContextMenu->setEnabled(state);
0703     if(!state) {
0704         m_UserMenuDialog.m_cbContextMenu->setChecked(state);
0705     }
0706     setModified();
0707 }
0708 
0709 void UserMenuDialog::slotCheckboxStateChanged(int)
0710 {
0711     setModified();
0712 }
0713 
0714 ////////////////////////////// read menu item data //////////////////////////////
0715 
0716 void UserMenuDialog::readMenuentryData(UserMenuItem *item)
0717 {
0718     KILE_DEBUG_MAIN << "read current menu item ...";
0719     if (!item) {
0720         return;
0721     }
0722 
0723     UserMenuData::MenuType type = UserMenuData::MenuType( m_listMenutypes.indexOf(m_UserMenuDialog.m_lbMenuentryType->text()) );
0724     item->setMenutype(type);
0725     if (type == UserMenuData::Separator) {
0726         return;
0727     }
0728 
0729     item->setMenutitle(m_UserMenuDialog.m_leMenuEntry->text().trimmed());
0730     item->setFilename(m_UserMenuDialog.m_urlRequester->text().trimmed());
0731     item->setParameter(m_UserMenuDialog.m_leParameter->text().trimmed());
0732     item->setPlaintext(m_UserMenuDialog.m_teText->toPlainText());
0733 
0734     item->setMenuicon(m_currentIcon);
0735     item->setShortcut(m_UserMenuDialog.m_keyChooser->keySequence().toString(QKeySequence::NativeText));
0736 
0737     item->setNeedsSelection(m_UserMenuDialog.m_cbNeedsSelection->checkState());
0738     item->setUseContextMenu(m_UserMenuDialog.m_cbContextMenu->checkState());
0739     item->setReplaceSelection(m_UserMenuDialog.m_cbReplaceSelection->checkState());
0740     item->setSelectInsertion(m_UserMenuDialog.m_cbSelectInsertion->checkState());
0741     item->setInsertOutput(m_UserMenuDialog.m_cbInsertOutput->checkState());
0742 
0743     bool executable = (type==UserMenuData::Program && m_menutree->isItemExecutable(item->filename()));
0744     item->setModelData(executable);
0745 
0746     item->setText(0, item->updateMenutitle());
0747 }
0748 
0749 ////////////////////////////// show menu item data //////////////////////////////
0750 
0751 void UserMenuDialog::showMenuentryData(UserMenuItem *item)
0752 {
0753     KILE_DEBUG_MAIN << "show new menu item ...";
0754     if (!item) {
0755         disableMenuEntryData();
0756         return;
0757     }
0758 
0759     UserMenuData::MenuType type = item->menutype();
0760 
0761     blockSignals(true);
0762     switch (type) {
0763     case UserMenuData::Text:
0764         setTextEntry(item);
0765         break;
0766     case UserMenuData::FileContent:
0767         setFileContentEntry(item);
0768         break;
0769     case UserMenuData::Program:
0770         setProgramEntry(item);
0771         break;
0772     case UserMenuData::Separator:
0773         setSeparatorEntry(item);
0774         break;
0775     case UserMenuData::Submenu:
0776         setSubmenuEntry(item);
0777         break;
0778     default:
0779         disableMenuEntryData();    // should not happen
0780     }
0781     blockSignals(false);
0782 }
0783 
0784 void UserMenuDialog::setTextEntry(UserMenuItem *item)
0785 {
0786     setMenuentryText(item, true);
0787     setMenuentryType(item, true, true);
0788     setMenuentryFileChooser(item, false);
0789     setMenuentryFileParameter(item, false);
0790     setMenuentryTextEdit(item, true);
0791     setMenuentryIcon(item, true);
0792     setMenuentryShortcut(item, true);
0793     setParameterGroupbox(true);
0794     setMenuentryCheckboxes(item, false);
0795 }
0796 
0797 void UserMenuDialog::setFileContentEntry(UserMenuItem *item)
0798 {
0799     setMenuentryText(item, true);
0800     setMenuentryType(item, true, true);
0801     setMenuentryFileChooser(item, true);
0802     setMenuentryFileParameter(item, false);
0803     setMenuentryTextEdit(item, false);
0804     setMenuentryIcon(item, true);
0805     setMenuentryShortcut(item, true);
0806     setParameterGroupbox(true);
0807     setMenuentryCheckboxes(item, false);
0808 }
0809 
0810 void UserMenuDialog::setProgramEntry(UserMenuItem *item)
0811 {
0812     setMenuentryText(item, true);
0813     setMenuentryType(item, true, true);
0814     setMenuentryFileChooser(item, true);
0815     setMenuentryFileParameter(item, true);
0816     setMenuentryTextEdit(item, false);
0817     setMenuentryIcon(item, true);
0818     setMenuentryShortcut(item, true);
0819     setParameterGroupbox(true);
0820     setMenuentryCheckboxes(item, true);
0821 }
0822 
0823 void UserMenuDialog::setSeparatorEntry(UserMenuItem *item)
0824 {
0825     disableMenuEntryData();
0826     setMenuentryType(item, true, false);
0827 }
0828 
0829 void UserMenuDialog::setSubmenuEntry(UserMenuItem *item)
0830 {
0831     setMenuentryText(item, true);
0832     setMenuentryType(item, true, false);
0833     setMenuentryFileChooser(Q_NULLPTR, false);
0834     setMenuentryFileParameter(Q_NULLPTR, false);
0835     setMenuentryTextEdit(Q_NULLPTR, false);
0836     setMenuentryIcon(Q_NULLPTR, false);
0837     setMenuentryShortcut(Q_NULLPTR, false);
0838     setParameterGroupbox(false);
0839     setMenuentryCheckboxes(Q_NULLPTR, false);
0840 }
0841 
0842 ////////////////////////////// update data widgets//////////////////////////////
0843 
0844 void UserMenuDialog::setMenuentryType(UserMenuItem *item, bool state1, bool state2)
0845 {
0846     const QString s = (item && state1) ? m_listMenutypes[item->menutype()] : QString();
0847     m_UserMenuDialog.m_lbMenuentryType->setText(s);
0848     m_UserMenuDialog.m_lbMenuentryType->setEnabled(state1);
0849     m_UserMenuDialog.m_pbMenuentryType->setEnabled(state2);
0850 }
0851 
0852 void UserMenuDialog::setMenuentryText(UserMenuItem *item, bool state)
0853 {
0854     const QString s = (item && state) ? item->menutitle() : QString();
0855     m_UserMenuDialog.m_leMenuEntry->setText(s);
0856 
0857     m_UserMenuDialog.m_lbMenuEntry->setEnabled(state);
0858     m_UserMenuDialog.m_leMenuEntry->setEnabled(state);
0859 }
0860 
0861 void UserMenuDialog::setMenuentryFileChooser(UserMenuItem *item, bool state)
0862 {
0863     const QString s = (item && state) ? item->filename() : QString();
0864     m_UserMenuDialog.m_urlRequester->setText(s);
0865 
0866     m_UserMenuDialog.m_lbFile->setEnabled(state);
0867     m_UserMenuDialog.m_urlRequester->setEnabled(state);
0868 }
0869 
0870 void UserMenuDialog::setMenuentryFileParameter(UserMenuItem *item, bool state)
0871 {
0872     const QString s = (item && state) ? item->parameter() : QString();
0873     m_UserMenuDialog.m_leParameter->setText(s);
0874 
0875     m_UserMenuDialog.m_lbParameter->setEnabled(state);
0876     m_UserMenuDialog.m_leParameter->setEnabled(state);
0877 
0878 }
0879 
0880 void UserMenuDialog::setMenuentryTextEdit(UserMenuItem *item, bool state)
0881 {
0882     const QString s = (item && state) ? item->plaintext() : QString();
0883     m_UserMenuDialog.m_teText->setPlainText(s);
0884 
0885     m_UserMenuDialog.m_lbText->setEnabled(state);
0886     m_UserMenuDialog.m_teText->setEnabled(state);
0887 }
0888 
0889 void UserMenuDialog::setMenuentryIcon(UserMenuItem *item, bool state, const QString &icon)
0890 {
0891     if (item && state) {
0892         m_currentIcon = (icon.isEmpty()) ? item->menuicon() : icon;
0893     }
0894     else {
0895         m_currentIcon.clear();
0896     }
0897 
0898     // update widgets
0899     if (m_currentIcon.isEmpty()) {
0900         m_UserMenuDialog.m_lbIconChosen->setText(m_currentIcon);
0901         m_UserMenuDialog.m_lbIconChosen->hide();
0902         m_UserMenuDialog.m_pbIcon->show();
0903     }
0904     else {
0905         QString iconpath = KIconLoader::global()->iconPath(m_currentIcon,KIconLoader::Small);
0906         m_UserMenuDialog.m_lbIconChosen->setText("<img src=\"" +  iconpath +"\" />");
0907         m_UserMenuDialog.m_lbIconChosen->show();
0908         m_UserMenuDialog.m_pbIcon->hide();
0909     }
0910 
0911     m_UserMenuDialog.m_lbIcon->setEnabled(state);
0912     m_UserMenuDialog.m_pbIcon->setEnabled(state);
0913     m_UserMenuDialog.m_lbIconChosen->setEnabled(state);
0914     bool deleteIconState = ( state && !m_currentIcon.isEmpty() );
0915     m_UserMenuDialog.m_pbIconDelete->setEnabled(deleteIconState);
0916 }
0917 
0918 void UserMenuDialog::setMenuentryShortcut(UserMenuItem *item, bool state)
0919 {
0920     if (item && state) {
0921         QString shortcut = item->shortcut();
0922         if (shortcut.isEmpty()) {
0923             m_UserMenuDialog.m_keyChooser->clearKeySequence();
0924         }
0925         else {
0926             m_UserMenuDialog.m_keyChooser->setKeySequence(QKeySequence(shortcut));
0927         }
0928         item->setText(1, shortcut);
0929     }
0930     else {
0931         m_UserMenuDialog.m_keyChooser->clearKeySequence();
0932     }
0933 
0934     m_UserMenuDialog.m_lbShortcut->setEnabled(state);
0935     m_UserMenuDialog.m_keyChooser->setEnabled(state);
0936 }
0937 
0938 void UserMenuDialog::setParameterGroupbox(bool state)
0939 {
0940     m_UserMenuDialog.m_gbParameter->setEnabled(state);
0941 }
0942 
0943 void UserMenuDialog::setMenuentryCheckboxes(UserMenuItem *item, bool useInsertOutput)
0944 {
0945     bool selectionState, insertionState, outputState, replaceState, contextState;
0946     if (item) {
0947         selectionState = item->needsSelection();
0948         replaceState   = item->replaceSelection();
0949         insertionState = item->selectInsertion();
0950         outputState    = (useInsertOutput) ? item->insertOutput() : false;
0951         contextState   = (selectionState) ? item->useContextMenu() : false;
0952     }
0953     else {
0954         selectionState = false;
0955         replaceState   = false;
0956         insertionState = false;
0957         outputState    = false;
0958         contextState   = false;
0959     }
0960 
0961     // m_cbNeedsSelection and m_cbSelectInsertion are always enabled
0962     m_UserMenuDialog.m_cbNeedsSelection->setChecked(selectionState);
0963 
0964     // m_cbContextMenu needs a selection to be enabled
0965     m_UserMenuDialog.m_cbContextMenu->setEnabled(selectionState);
0966 
0967     m_UserMenuDialog.m_cbContextMenu->setChecked(contextState);
0968     m_UserMenuDialog.m_cbReplaceSelection->setChecked(replaceState);
0969     m_UserMenuDialog.m_cbSelectInsertion->setChecked(insertionState);
0970     m_UserMenuDialog.m_cbInsertOutput->setChecked(outputState);
0971     m_UserMenuDialog.m_cbInsertOutput->setEnabled(useInsertOutput);
0972 }
0973 
0974 void UserMenuDialog::clearMenuEntryData()
0975 {
0976     m_UserMenuDialog.m_leMenuEntry->clear();
0977     m_UserMenuDialog.m_lbMenuentryType->clear();
0978     m_UserMenuDialog.m_urlRequester->clear();
0979     m_UserMenuDialog.m_teText->clear();
0980     m_UserMenuDialog.m_pbIcon->setIcon(QIcon::fromTheme(i18n("Choose")));
0981     m_UserMenuDialog.m_keyChooser->clearKeySequence();
0982 
0983     m_UserMenuDialog.m_cbNeedsSelection->setChecked(false);
0984     m_UserMenuDialog.m_cbReplaceSelection->setChecked(false);
0985     m_UserMenuDialog.m_cbContextMenu->setChecked(false);
0986     m_UserMenuDialog.m_cbSelectInsertion->setChecked(false);
0987     m_UserMenuDialog.m_cbInsertOutput->setChecked(false);
0988 }
0989 
0990 void UserMenuDialog::disableMenuEntryData()
0991 {
0992     setMenuentryText(Q_NULLPTR, false);
0993     setMenuentryType(Q_NULLPTR, false, false);
0994     setMenuentryFileChooser(Q_NULLPTR, false);
0995     setMenuentryFileParameter(Q_NULLPTR, false);
0996     setMenuentryTextEdit(Q_NULLPTR, false);
0997     setMenuentryIcon(Q_NULLPTR, false);
0998     setMenuentryShortcut(Q_NULLPTR, false);
0999     setParameterGroupbox(false);
1000     setMenuentryCheckboxes(Q_NULLPTR, false);
1001 }
1002 
1003 }