File indexing completed on 2024-04-21 15:55:37

0001 /**************************************************************************************
0002     begin                :  2003-07-01 17:33:00 CEST 2003
0003     copyright            : (C) 2003 by Jeroen Wijnhout (Jeroen.Wijnhout@kdemail.net)
0004                                2008-2016 by Michel Ludwig (michel.ludwig@kdemail.net)
0005  **************************************************************************************/
0006 
0007 /***************************************************************************
0008  *                                                                         *
0009  *   This program is free software; you can redistribute it and/or modify  *
0010  *   it under the terms of the GNU General Public License as published by  *
0011  *   the Free Software Foundation; either version 2 of the License, or     *
0012  *   (at your option) any later version.                                   *
0013  *                                                                         *
0014  ***************************************************************************/
0015 
0016 // 2005-07-26 dani
0017 //  - cleanup dialog
0018 //  - added new action 'ShowLabel'
0019 
0020 // 2007-03-12 dani
0021 //  - use KileDocument::Extensions
0022 
0023 #include "kileactions.h"
0024 
0025 #include <QCheckBox>
0026 #include <QFileInfo>
0027 #include <QGridLayout>
0028 #include <QLabel>
0029 #include <QLayout>
0030 #include <QLineEdit>
0031 #include <QPushButton>
0032 #include <QString>
0033 #include <QStringList>
0034 #include <QToolBar>
0035 
0036 #include <QMenu>
0037 
0038 #include <KComboBox>
0039 #include <KCompletion>
0040 #include <KLocalizedString>
0041 #include <KConfigGroup>
0042 #include <QDialogButtonBox>
0043 #include <QVBoxLayout>
0044 #include <QFileDialog>
0045 
0046 #include "kiledebug.h"
0047 #include "kileextensions.h"
0048 #include "kileinfo.h"
0049 #include "kiledocmanager.h"
0050 
0051 namespace KileAction
0052 {
0053 
0054 ////////////////
0055 //    Tag     //
0056 ////////////////
0057 Tag::Tag(const QString &text, const QString& iconText, const QKeySequence &shortcut, const QObject *receiver, const char *slot, KActionCollection *parent,
0058          const QString& name, const QString &tagBegin, const QString &tagEnd,
0059          int dx, int dy, const QString &description)
0060     : QAction(text, parent),
0061       m_data(text,tagBegin, tagEnd, dx, dy, description)
0062 {
0063     parent->addAction(name, this);
0064     setIconText(iconText);
0065     if(!shortcut.isEmpty()) {
0066         parent->setDefaultShortcut(this, shortcut);
0067     }
0068     init(receiver, slot);
0069 }
0070 
0071 Tag::Tag(const QString &text, const QString& iconText, const QString& pix, const QKeySequence &shortcut, const QObject *receiver, const char *slot, KActionCollection *parent,
0072          const QString& name, const QString &tagBegin, const QString &tagEnd,
0073          int dx, int dy, const QString &description)
0074     : QAction(QIcon::fromTheme(pix), text, parent),
0075       m_data(text,tagBegin, tagEnd, dx, dy, description)
0076 {
0077     parent->addAction(name, this);
0078     setIconText(iconText);
0079     if(!shortcut.isEmpty()) {
0080         parent->setDefaultShortcut(this, shortcut);
0081     }
0082     init(receiver,slot);
0083 }
0084 
0085 Tag::Tag(const QString &text, const QString& iconText, const QKeySequence &shortcut, const QObject *receiver, const char *slot, KActionCollection *parent,
0086          const QString& name, const TagData& data)
0087     : QAction(text, parent),
0088       m_data(data)
0089 {
0090     parent->addAction(name, this);
0091     setIconText(iconText);
0092     if(!shortcut.isEmpty()) {
0093         parent->setDefaultShortcut(this, shortcut);
0094     }
0095     init(receiver,slot);
0096 }
0097 
0098 Tag::Tag(const QString &text, const QString& iconText, const QString& pix, const QKeySequence &shortcut, const QObject *receiver, const char *slot, KActionCollection *parent,
0099          const QString& name, const TagData& data)
0100     : QAction(QIcon::fromTheme(pix), text, parent),
0101       m_data(data)
0102 {
0103     parent->addAction(name, this);
0104     if(!shortcut.isEmpty()) {
0105         parent->setDefaultShortcut(this, shortcut);
0106     }
0107     setIconText(iconText);
0108     init(receiver,slot);
0109 }
0110 
0111 Tag::~Tag()
0112 {
0113 }
0114 
0115 void Tag::init(const QObject *receiver, const char *slot)
0116 {
0117     connect(this, SIGNAL(triggered()), SLOT(emitData()));
0118     connect(this, SIGNAL(triggered(KileAction::TagData)), receiver, slot);
0119 }
0120 
0121 void Tag::emitData()
0122 {
0123     emit(triggered(m_data));
0124 }
0125 
0126 ////////////////
0127 //    InputTag     //
0128 ////////////////
0129 InputTag::InputTag(KileInfo* ki, const QString &text, const QString &iconText, const QKeySequence &cut, const QObject *receiver, const char *slot, KActionCollection *parent, const QString& name, QWidget *wparent, uint options,
0130                    const QString &tagBegin, const QString &tagEnd,
0131                    int dx, int dy, const QString &description, const QString &hint, const QString &alter)
0132     : Tag(text, iconText, cut, receiver, slot, parent, name, tagBegin, tagEnd, dx, dy, description), m_ki(ki),
0133       m_parent(wparent), m_options(options), m_hint(hint), m_alter(alter)
0134 {
0135     init();
0136 }
0137 
0138 InputTag::InputTag(KileInfo* ki, const QString &text, const QString &iconText, const QString& pix, const QKeySequence &cut, const QObject *receiver, const char *slot, KActionCollection *parent, const QString& name, QWidget *wparent, uint options,
0139                    const QString &tagBegin, const QString &tagEnd,
0140                    int dx, int dy, const QString &description, const QString &hint, const QString &alter)
0141     : Tag(text, iconText, pix, cut, receiver, slot, parent, name, tagBegin, tagEnd, dx, dy, description), m_ki(ki),
0142       m_parent(wparent), m_options(options), m_hint(hint), m_alter(alter)
0143 {
0144     init();
0145 }
0146 
0147 InputTag::InputTag(KileInfo* ki, const QString &text, const QString &iconText, const QKeySequence &cut, const QObject *receiver, const char *slot, KActionCollection *parent, const QString& name, QWidget *wparent, uint options,
0148                    const TagData& data, const QString &hint, const QString &alter)
0149     : Tag(text, iconText, cut, receiver, slot, parent, name,data),  m_ki(ki),
0150       m_parent(wparent), m_options(options), m_hint(hint), m_alter(alter)
0151 {
0152     init();
0153 }
0154 
0155 InputTag::InputTag(KileInfo* ki, const QString &text, const QString &iconText, const QString& pix, const QKeySequence &cut, const QObject *receiver, const char *slot, KActionCollection *parent, const QString& name, QWidget *wparent, uint options,
0156                    const TagData& data, const QString &hint, const QString &alter)
0157     : Tag(text, iconText, pix, cut,receiver, slot, parent, name,data), m_ki(ki),
0158       m_parent(wparent), m_options(options), m_hint(hint), m_alter(alter)
0159 {
0160     init();
0161 }
0162 
0163 InputTag::~InputTag()
0164 {
0165 }
0166 
0167 void InputTag::init()
0168 {
0169     m_history.clear();
0170 }
0171 
0172 void InputTag::addToHistory(const QString& str)
0173 {
0174     if(!m_history.contains(str)) {
0175         m_history.prepend(str);
0176     }
0177 }
0178 
0179 void InputTag::emitData()
0180 {
0181     KILE_DEBUG_MAIN << "InputTag::emitData() " << m_ki->getName();
0182 
0183     InputDialog *dlg = new InputDialog(m_data.text, m_options, m_history, m_hint, m_alter, m_ki, m_parent, "input_dialog");
0184     if (dlg->exec()) {
0185         if((!dlg->tag().isEmpty()) && hasHistory()) {
0186             addToHistory(dlg->tag());
0187         }
0188 
0189         TagData td(m_data);
0190 
0191         td.tagBegin.replace("%R",dlg->tag());
0192         td.tagEnd.replace("%R",dlg->tag());
0193 
0194         QString alt = dlg->useAlternative() ? "*" : "";
0195         td.tagBegin.replace("%A", alt);
0196         td.tagEnd.replace("%A", alt);
0197 
0198         if(dlg->useLabel()) {
0199             td.tagEnd += dlg->label();
0200             td.dy++;
0201         }
0202 
0203         if(dlg->usedSelection()) {
0204             m_ki->clearSelection();
0205         }
0206 
0207         // if a filename was given for a \input- or \include-command,
0208         // the cursor is moved out of the braces
0209         if ( (m_options & (KileAction::ShowBrowseButton | KileAction::FromLabelList | KileAction::FromBibItemList)) && !dlg->tag().isEmpty() ) {
0210             td.dx += dlg->tag().length() + 1;
0211         }
0212 
0213         // insert tag
0214         emit(triggered(td));
0215         // refresh document structure and project tree when a file was inserted
0216         if(dlg->useAddProjectFile()) {
0217             m_ki->docManager()->projectAddFile(QFileInfo(m_ki->getCompileName()).absolutePath() + '/' + dlg->tag());
0218         }
0219     }
0220     delete dlg;
0221 }
0222 
0223 /*
0224     InputDialog
0225 */
0226 InputDialog::InputDialog(const QString &caption, uint options, const QStringList& history, const QString& hint, const QString& alter, KileInfo *ki, QWidget *parent, const char *name)
0227     : QDialog (parent), m_ki(ki)
0228 {
0229     setModal(true);
0230 
0231     QVBoxLayout *mainLayout = new QVBoxLayout;
0232     setLayout(mainLayout);
0233     setObjectName(name);
0234 
0235     QString newcaption = caption;
0236     setWindowTitle(newcaption.remove('&'));
0237 
0238     m_labelprefix = (newcaption == "chapter") ? "chap:" : "sec:";
0239     m_usedSelection = false;
0240 
0241     QGridLayout *gbox = new QGridLayout(this);
0242     QWidget *page = new QWidget(this);
0243     page->setLayout(gbox);
0244     mainLayout->addWidget(page);
0245 
0246     QLabel *lb = new QLabel(hint, this);
0247     gbox->addWidget(lb, 0, 0, 1, 3);
0248 
0249     m_tag.clear();
0250     QWidget *focus;
0251     if((options & KileAction::KeepHistory) || (options & KileAction::FromLabelList) || (options & KileAction::FromBibItemList)) {
0252         KComboBox *input = new KComboBox(true, this);
0253         input->setObjectName("input_dialog_input");
0254         input->setCompletionMode(KCompletion::CompletionAuto);
0255         input->setMinimumWidth(300);
0256         focus = input;
0257 
0258         connect(input, SIGNAL(textChanged(QString)), this, SLOT(setTag(QString)));
0259         connect(this,  SIGNAL(setInput(QString)), input, SLOT(setEditText(QString)));
0260         if(options & KileAction::ShowBrowseButton) {
0261             gbox->addWidget(input, 1, 0);
0262         }
0263         else {
0264             gbox->addWidget(input, 1, 0, 1, 3);
0265         }
0266 
0267         QStringList list;
0268 
0269         if(options & KileAction::FromLabelList) {
0270             list = ki->allLabels();
0271             if(list.size() > 0) {
0272                 input->addItems(list);
0273                 m_tag = list.first();
0274             }
0275         }
0276         else if(options & KileAction::FromBibItemList) {
0277             list = ki->allBibItems();
0278             if(list.size() > 0) {
0279                 input->addItems(list);
0280                 m_tag = list.first();
0281             }
0282         }
0283         else {
0284             if(history.size() > 0) {
0285                 input->addItems(history);
0286                 m_tag = history.first();
0287             }
0288         }
0289     }
0290     else {
0291         QLineEdit *input = new QLineEdit(this);
0292         gbox->addWidget(input);
0293         input->setMinimumWidth(300);
0294         focus = input;
0295 
0296         connect(input, SIGNAL(textChanged(QString)), this, SLOT(setTag(QString)));
0297         connect(this,  SIGNAL(setInput(QString)), input, SLOT(setText(QString)));
0298         if(options & KileAction::ShowBrowseButton) {
0299             gbox->addWidget(input, 1, 0);
0300         }
0301         else {
0302             gbox->addWidget(input, 1, 0, 1, 3);
0303         }
0304 
0305         input->setText(ki->getSelection());
0306         m_usedSelection=true;
0307     }
0308 
0309     if(focus) {
0310         lb->setBuddy(focus);
0311     }
0312 
0313     if(options & KileAction::ShowBrowseButton) {
0314         QPushButton *pbutton = new QPushButton(QString(), this);
0315         mainLayout->addWidget(pbutton);
0316         pbutton->setIcon(QIcon::fromTheme("document-open"));
0317         gbox->addWidget(pbutton, 1, 2);
0318         gbox->setColumnMinimumWidth(1, 8);
0319         gbox->setColumnMinimumWidth(2, pbutton->sizeHint().width() + 5);
0320         connect(pbutton, SIGNAL(clicked()), this, SLOT(slotBrowse()));
0321     }
0322 
0323     if(options & KileAction::ShowAlternative) {
0324         QCheckBox *m_checkbox = new QCheckBox(alter, this);
0325         mainLayout->addWidget(m_checkbox);
0326         m_checkbox->setObjectName("input_dialog_checkbox");
0327         connect(m_checkbox, SIGNAL(clicked()), this, SLOT(slotAltClicked()));
0328         m_useAlternative=false;
0329         gbox->addWidget(m_checkbox, 2, 0, 1, 3);
0330     }
0331 
0332     m_edLabel = Q_NULLPTR;
0333     m_useLabel = (options & KileAction::ShowLabel);
0334     if(m_useLabel) {
0335         // Label
0336         QLabel *uiLabel = new QLabel(i18n("&Label:"),this);
0337         mainLayout->addWidget(uiLabel);
0338         m_edLabel = new QLineEdit(this);
0339         mainLayout->addWidget(m_edLabel);
0340         m_edLabel->setMinimumWidth(300);
0341         m_edLabel->setText(m_labelprefix);
0342         uiLabel->setBuddy(m_edLabel);
0343         gbox->addWidget(uiLabel, 3, 0, 1, 3);
0344         gbox->addWidget(m_edLabel, 4, 0, 1, 3);
0345     }
0346 
0347     m_useAddProjectFile = (options & KileAction::AddProjectFile);
0348 
0349     gbox->setRowStretch(5, 1);
0350     gbox->setColumnStretch(0, 1);
0351 
0352     // add buttons
0353     QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
0354     mainLayout->addWidget(buttonBox);
0355     QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
0356     okButton->setDefault(true);
0357     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0358     connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
0359     connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0360 
0361     focus->setFocus();
0362 }
0363 
0364 
0365 InputDialog::~InputDialog()
0366 {
0367 }
0368 
0369 void InputDialog::slotBrowse()
0370 {
0371     QString fn;
0372     QFileInfo fi(m_ki->getCompileName());
0373 
0374     // Called from InputDialog after a \input- or \include command:
0375     // so we are only looking for a LaTeX source document
0376     QString filter = m_ki->extensions()->fileFilterQtStyle(true, {KileDocument::Extensions::TEX});
0377 
0378     fn = QFileDialog::getOpenFileName(this, i18n("Select File"), fi.absoluteFilePath(), filter);
0379     if(!fn.isEmpty()) {
0380         QString path = QDir(fi.path()).relativeFilePath(fn);
0381 
0382         // if the file has no extension, we add the default TeX extension
0383         if(QFileInfo(path).completeSuffix().isEmpty()) {
0384             path += m_ki->extensions()->latexDocumentDefault();
0385         }
0386 
0387         setTag(path);
0388         emit(setInput(path));
0389     }
0390 }
0391 
0392 void InputDialog::slotAltClicked()
0393 {
0394     m_useAlternative = !m_useAlternative;
0395 }
0396 
0397 void InputDialog::setTag(const QString &tag)
0398 {
0399     m_tag = tag;
0400 }
0401 
0402 QString InputDialog::label()
0403 {
0404     if(m_edLabel) {
0405         QString labelString = m_edLabel->text().trimmed();
0406         if(!labelString.isEmpty() && labelString != m_labelprefix) {
0407             return "\\label{" + labelString + "}\n";
0408         }
0409     }
0410 
0411     return QString();
0412 }
0413 
0414 /////////////////
0415 //  SelectTag  //
0416 /////////////////
0417 
0418 Select::Select(const QString &text, const QKeySequence &shortcut, KActionCollection *parent, const char *name)
0419     : KSelectAction(text, parent)
0420 {
0421     parent->addAction(name, this);
0422     parent->setDefaultShortcut(this, shortcut);
0423 }
0424 
0425 void Select::setItems(const QList<QAction *>& list)
0426 {
0427     removeAllActions();
0428 
0429     for(QList<QAction *>::const_iterator i = list.begin(); i != list.end(); ++i) {
0430         addAction(*i);
0431     }
0432 }
0433 
0434 /////////////////////////
0435 //  VariantSelection   //
0436 /////////////////////////
0437 
0438 VariantSelection::VariantSelection(const QString &text, const QVariant& value, QObject *parent)
0439     : QAction(text, parent), m_variant(value)
0440 {
0441     connect(this, SIGNAL(triggered(bool)), this, SLOT(slotTriggered()));
0442 }
0443 
0444 void VariantSelection::slotTriggered()
0445 {
0446     emit(triggered(m_variant));
0447 
0448     if(m_variant.canConvert<QUrl>()) {
0449         emit(triggered(m_variant.value<QUrl>()));
0450     }
0451 
0452     if(m_variant.canConvert<QString>()) {
0453         emit(triggered(m_variant.value<QString>()));
0454     }
0455 }
0456 
0457 }
0458 
0459 // ToolbarSelectAction
0460 // based on 'KActionMenu', therefore our thanks go to
0461 // Copyright (C) 1999 Reginald Stadlbauer <reggie@kde.org>
0462 //           (C) 1999 Simon Hausmann <hausmann@kde.org>
0463 //           (C) 2000 Nicolas Hadacek <haadcek@kde.org>
0464 //           (C) 2000 Kurt Granroth <granroth@kde.org>
0465 //           (C) 2000 Michael Koch <koch@kde.org>
0466 //           (C) 2001 Holger Freyther <freyther@kde.org>
0467 //           (C) 2002 Ellis Whitehead <ellis@kde.org>
0468 //           (C) 2002 Joseph Wenninger <jowenn@kde.org>
0469 //           (C) 2003 Andras Mantia <amantia@kde.org>
0470 //           (C) 2005-2006 Hamish Rodda <rodda@kde.org>
0471 
0472 ToolbarSelectAction::ToolbarSelectAction(const QString& text, QObject* parent,
0473         bool changeMainActionOnTriggering /*= true */)
0474     : QWidgetAction(parent), m_currentItem(-1), m_mainText(text), m_savedCurrentAction(Q_NULLPTR)
0475 {
0476     setText(text);
0477     if(changeMainActionOnTriggering) {
0478         connect(menu(), SIGNAL(triggered(QAction*)), this, SLOT(slotTriggered(QAction*)));
0479     }
0480 }
0481 
0482 int ToolbarSelectAction::actionIndex(QAction *action)
0483 {
0484     int counter = -1;
0485     QList<QAction*> actionList = menu()->actions();
0486     for(QList<QAction*>::iterator i = actionList.begin(); i != actionList.end(); ++i) {
0487         if(*i == action) {
0488             return counter + 1;
0489         }
0490         ++counter;
0491     }
0492     return counter;
0493 }
0494 
0495 void ToolbarSelectAction::addAction(QAction *action)
0496 {
0497     menu()->addAction(action);
0498 }
0499 
0500 void ToolbarSelectAction::addSeparator()
0501 {
0502     menu()->addSeparator();
0503 }
0504 
0505 QAction* ToolbarSelectAction::action(int i)
0506 {
0507     QList<QAction*> actionList = menu()->actions();
0508     if(i < 0 || i >= actionList.size()) {
0509         return Q_NULLPTR;
0510     }
0511     return actionList.at(i);
0512 }
0513 
0514 int ToolbarSelectAction::currentItem() const
0515 {
0516     return m_currentItem;
0517 }
0518 
0519 QAction* ToolbarSelectAction::currentAction()
0520 {
0521     return action(m_currentItem);
0522 }
0523 
0524 bool ToolbarSelectAction::containsAction(QAction *action)
0525 {
0526     return actionIndex(action) >= 0;
0527 }
0528 
0529 void ToolbarSelectAction::setCurrentItem(int i)
0530 {
0531     setCurrentAction(action(i));
0532 }
0533 
0534 void ToolbarSelectAction::setCurrentAction(QAction *action)
0535 {
0536     if(!action) {
0537         return;
0538     }
0539     int index = actionIndex(action);
0540     if(index < 0) {
0541         return;
0542     }
0543     setIcon(action->icon());
0544     setText(action->text());
0545     m_currentItem = index;
0546 }
0547 
0548 void ToolbarSelectAction::removeAllActions()
0549 {
0550     menu()->clear();
0551     m_currentItem = -1;
0552     setText(m_mainText);
0553     setIcon(QIcon());
0554 }
0555 
0556 void ToolbarSelectAction::slotTriggered(QAction* action) {
0557 
0558     KILE_DEBUG_MAIN << "triggered with " << action->text();
0559 
0560     if( currentAction() != action ) {
0561         setIcon(action->icon());
0562         setText(action->text());
0563         setCurrentAction(action);
0564     }
0565 }
0566 
0567 void ToolbarSelectAction::slotMainActionTriggered()
0568 {
0569     QAction *curAction = currentAction();
0570     if (curAction) {
0571         curAction->trigger();
0572     }
0573 }
0574 
0575 void ToolbarSelectAction::slotMainButtonPressed()
0576 {
0577     QAction *curAction = currentAction();
0578     if (!curAction) {
0579         emit(mainButtonWithNoActionPressed());
0580     }
0581 }
0582 
0583 QMenu* ToolbarSelectAction::menu()
0584 {
0585     if(!QAction::menu()) {
0586         QMenu *uiMenu = new QMenu();
0587         setMenu(uiMenu);
0588     }
0589 
0590     return qobject_cast<QMenu*>(QAction::menu());
0591 }
0592 
0593 QWidget* ToolbarSelectAction::createWidget(QWidget *parent)
0594 {
0595     QToolBar *parentToolBar = qobject_cast<QToolBar*>(parent);
0596     if (!parentToolBar) {
0597         return QWidgetAction::createWidget(parent);
0598     }
0599     QToolButton* button = new QToolButton(parent);
0600     button->setAutoRaise(true);
0601     button->setFocusPolicy(Qt::NoFocus);
0602     button->setPopupMode(QToolButton::MenuButtonPopup);
0603     button->setIconSize(parentToolBar->iconSize());
0604     button->setToolButtonStyle(parentToolBar->toolButtonStyle());
0605     connect(parent, SIGNAL(iconSizeChanged(QSize)),
0606             button, SLOT(setIconSize(QSize)));
0607     connect(parent, SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
0608             button, SLOT(setToolButtonStyle(Qt::ToolButtonStyle)));
0609     button->setDefaultAction(this);
0610     connect(button, SIGNAL(clicked(bool)), this, SLOT(slotMainActionTriggered()));
0611     connect(button, SIGNAL(pressed()), this, SLOT(slotMainButtonPressed()));
0612     connect(this, SIGNAL(mainButtonWithNoActionPressed()), button, SLOT(showMenu()));
0613     return button;
0614 }
0615 
0616 void ToolbarSelectAction::saveCurrentAction()
0617 {
0618     m_savedCurrentAction = currentAction();
0619 }
0620 
0621 void ToolbarSelectAction::restoreCurrentAction()
0622 {
0623     if(!m_savedCurrentAction) {
0624         return;
0625     }
0626     setCurrentAction(m_savedCurrentAction);
0627     m_savedCurrentAction = Q_NULLPTR;
0628 }
0629