File indexing completed on 2024-05-12 16:34:58

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2011 C. Boemann <cbo@boemann.dk>
0003  * Copyright (C) 2013 Aman Madaan <madaan.amanmadaan@gmail.com>
0004  *
0005  * This library is free software; you can redistribute it and/or
0006  * modify it under the terms of the GNU Library General Public
0007  * License as published by the Free Software Foundation; either
0008  * version 2 of the License, or (at your option) any later version.
0009  *
0010  * This library is distributed in the hope that it will be useful,
0011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013  * Library General Public License for more details.
0014  *
0015  * You should have received a copy of the GNU Library General Public License
0016  * along with this library; see the file COPYING.LIB.  If not, write to
0017  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019  */
0020 
0021 #include "ReferencesTool.h"
0022 #include "TextShape.h"
0023 #include "dialogs/SimpleTableOfContentsWidget.h"
0024 #include "dialogs/SimpleCitationBibliographyWidget.h"
0025 #include "dialogs/SimpleFootEndNotesWidget.h"
0026 #include "dialogs/SimpleCaptionsWidget.h"
0027 #include "dialogs/SimpleLinksWidget.h"
0028 #include "dialogs/TableOfContentsConfigure.h"
0029 #include "dialogs/NotesConfigurationDialog.h"
0030 #include "dialogs/CitationInsertionDialog.h"
0031 #include "dialogs/InsertBibliographyDialog.h"
0032 #include "dialogs/BibliographyConfigureDialog.h"
0033 #include "dialogs/LinkInsertionDialog.h"
0034 
0035 #include <KoTextLayoutRootArea.h>
0036 #include <KoCanvasBase.h>
0037 #include <KoTextEditor.h>
0038 #include <KoParagraphStyle.h>
0039 #include <KoTableOfContentsGeneratorInfo.h>
0040 #include <KoBookmark.h>
0041 #include <KoInlineNote.h>
0042 #include <KoTextDocumentLayout.h>
0043 #include <KoIcon.h>
0044 #include <QMessageBox>
0045 
0046 #include <QDebug>
0047 #include <QAction>
0048 #include <QTextDocument>
0049 #include <QLineEdit>
0050 #include <QBoxLayout>
0051 #include <QMenu>
0052 #include <QWidgetAction>
0053 
0054 LabeledWidget::LabeledWidget(QAction *action, const QString &label, LabelPosition lb, bool warningLabelRequired)
0055     : QWidget()
0056     , m_action(action)
0057 {
0058     setMouseTracking(true);
0059     QBoxLayout *layout;
0060     QLabel *l = new QLabel(label);
0061     l->setWordWrap(true);
0062     m_lineEdit = new QLineEdit();
0063     if (lb == LabeledWidget::INLINE) { // label followed by line edit
0064         layout = new QHBoxLayout();
0065         l->setIndent(l->style()->pixelMetric(QStyle::PM_SmallIconSize)
0066                     + l->style()->pixelMetric(QStyle::PM_MenuPanelWidth) + 4);
0067     } else { //Label goes above the text edit
0068         layout = new QVBoxLayout();
0069         m_lineEdit->setFixedWidth(300); //TODO : assuming a reasonable width, is there a better way?
0070     }
0071     layout->addWidget(l);
0072     layout->addWidget(m_lineEdit);
0073     if (warningLabelRequired) {
0074         m_warningLabel[0] = new QLabel("");
0075         m_warningLabel[1] = new QLabel("");
0076         m_warningLabel[0]->setWordWrap(true);
0077         m_warningLabel[1]->setWordWrap(true);
0078         layout->addWidget(m_warningLabel[0]);
0079         layout->addWidget(m_warningLabel[1]);
0080     }
0081     layout->setMargin(0);
0082     setLayout(layout);
0083     connect(m_lineEdit, SIGNAL(returnPressed()), this, SLOT(returnPressed()));
0084     connect(m_lineEdit, SIGNAL(textChanged(QString)), this, SIGNAL(lineEditChanged(QString)));
0085 }
0086 
0087 void LabeledWidget::returnPressed()
0088 {
0089     emit triggered(m_lineEdit->text());
0090 }
0091 
0092 void LabeledWidget::enterEvent(QEvent *event)
0093 {
0094     m_action->activate(QAction::Hover);
0095     QWidget::enterEvent(event);
0096 }
0097 
0098 void LabeledWidget::setWarningText(int pos, const QString& warning)
0099 {
0100     if (m_warningLabel[pos] == nullptr) {
0101         return;
0102     }
0103     m_warningLabel[pos]->setText(warning);
0104 }
0105 
0106 void LabeledWidget::clearLineEdit()
0107 {
0108     m_lineEdit->setText("");
0109 }
0110 
0111 ReferencesTool::ReferencesTool(KoCanvasBase* canvas): TextTool(canvas),
0112     m_configure(0),
0113     m_stocw(0),
0114     m_canvas(canvas)
0115 {
0116     createActions();
0117 }
0118 
0119 ReferencesTool::~ReferencesTool()
0120 {
0121 }
0122 
0123 void ReferencesTool::createActions()
0124 {
0125     QWidgetAction *wAction = 0;
0126 
0127     QAction *action = new QAction(i18n("Insert"), this);
0128     addAction("insert_tableofcontents", action);
0129     action->setToolTip(i18n("Insert a Table of Contents into the document."));
0130 
0131     action = new QAction(i18n("Insert Custom..."), this);
0132     addAction("insert_configure_tableofcontents", action);
0133     action->setToolTip(i18n("Insert a custom Table of Contents into the document."));
0134 
0135     action = new QAction(koIcon("configure"), i18n("Configure..."), this);
0136     addAction("format_tableofcontents", action);
0137     action->setToolTip(i18n("Configure the Table of Contents"));
0138     connect(action, SIGNAL(triggered()), this, SLOT(formatTableOfContents()));
0139 
0140     action = new QAction(i18n("Insert footnote with auto number"),this);
0141     addAction("insert_autofootnote",action);
0142     connect(action, SIGNAL(triggered()), this, SLOT(insertAutoFootNote()));
0143 
0144     wAction = new QWidgetAction(this);
0145     wAction->setText(i18n("Insert Labeled Footnote"));
0146     QWidget *w = new LabeledWidget(wAction, i18n("Insert with label:"), LabeledWidget::INLINE, false);
0147     wAction->setDefaultWidget(w);
0148     addAction("insert_labeledfootnote", wAction);
0149     connect(w, SIGNAL(triggered(QString)), this, SLOT(insertLabeledFootNote(QString)));
0150 
0151     action = new QAction(i18n("Insert endnote with auto number"),this);
0152     addAction("insert_autoendnote",action);
0153     connect(action, SIGNAL(triggered()), this, SLOT(insertAutoEndNote()));
0154 
0155     wAction = new QWidgetAction(this);
0156     wAction->setText(i18n("Insert Labeled Endnote"));
0157     w = new LabeledWidget(wAction, i18n("Insert with label:"), LabeledWidget::INLINE, false);
0158     wAction->setDefaultWidget(w);
0159     addAction("insert_labeledendnote", wAction); connect(w, SIGNAL(triggered(QString)), this, SLOT(insertLabeledEndNote(QString)));
0160 
0161     action = new QAction(koIcon("configure"), i18n("Settings..."), this);
0162     addAction("format_footnotes",action);
0163     connect(action, SIGNAL(triggered()), this, SLOT(showFootnotesConfigureDialog()));
0164 
0165     action = new QAction(koIcon("configure"), i18n("Settings..."), this);
0166     addAction("format_endnotes",action);
0167     connect(action, SIGNAL(triggered()), this, SLOT(showEndnotesConfigureDialog()));
0168 
0169     action = new QAction(i18n("Insert Citation"), this);
0170     addAction("insert_citation",action);
0171     action->setToolTip(i18n("Insert a citation into the document."));
0172     connect(action, SIGNAL(triggered()), this, SLOT(insertCitation()));
0173 
0174     action = new QAction(i18n("Insert Bibliography"), this);
0175     addAction("insert_bibliography",action);
0176     action->setToolTip(i18n("Insert a bibliography into the document."));
0177 
0178     action = new QAction(i18n("Insert Custom Bibliography"), this);
0179     addAction("insert_custom_bibliography", action);
0180     action->setToolTip(i18n("Insert a custom Bibliography into the document."));
0181 
0182     action = new QAction(i18n("Configure"),this);
0183     addAction("configure_bibliography",action);
0184     action->setToolTip(i18n("Configure the bibliography"));
0185     connect(action, SIGNAL(triggered()), this, SLOT(configureBibliography()));
0186 
0187     action = new QAction(i18n("Insert Link"), this);
0188     addAction("insert_link", action);
0189     action->setToolTip(i18n("Insert a weblink or link to a bookmark."));
0190     connect(action, SIGNAL(triggered()), this, SLOT(insertLink()));
0191 
0192     wAction = new QWidgetAction(this);
0193     wAction->setText(i18n("Add Bookmark"));
0194     m_bmark = new LabeledWidget(wAction, i18n("Add Bookmark :"), LabeledWidget::ABOVE, true);
0195     connect(m_bmark, SIGNAL(lineEditChanged(QString)), this, SLOT(validateBookmark(QString)));
0196     wAction->setDefaultWidget(m_bmark);
0197     addAction("insert_bookmark", wAction);
0198     connect(m_bmark, SIGNAL(triggered(QString)), this, SLOT(insertBookmark(QString)));
0199     wAction->setToolTip(i18n("Insert a Bookmark. This is useful to create links that point to areas within the document"));
0200 
0201     action = new QAction(i18n("Bookmarks"), this);
0202     addAction("invoke_bookmark_handler", action);
0203     action->setToolTip(i18n("Display a pop up that hosts the options to add new Bookmark or handle existing Bookmarks"));
0204 
0205     action = new QAction(i18n("Manage Bookmarks"), this);
0206     addAction("manage_bookmarks", action);
0207     action->setToolTip(i18n("Manage your Bookmarks. Check where are they pointing to, Delete or Rename."));
0208 }
0209 
0210 
0211 void ReferencesTool::activate(ToolActivation toolActivation, const QSet<KoShape*> &shapes)
0212 {
0213     TextTool::activate(toolActivation, shapes);
0214 }
0215 
0216 void ReferencesTool::deactivate()
0217 {
0218     TextTool::deactivate();
0219     canvas()->canvasWidget()->setFocus();
0220 }
0221 
0222 QList<QPointer<QWidget> > ReferencesTool::createOptionWidgets()
0223 {
0224     QList<QPointer<QWidget> > widgets;
0225     m_stocw = new SimpleTableOfContentsWidget(this, 0);
0226 
0227     m_sfenw = new SimpleFootEndNotesWidget(this, 0);
0228 
0229     m_scbw = new SimpleCitationBibliographyWidget(this, 0);
0230 
0231     m_slw = new SimpleLinksWidget(this, 0);
0232     // Connect to/with simple table of contents option widget
0233     connect(m_stocw, SIGNAL(doneWithFocus()), this, SLOT(returnFocusToCanvas()));
0234 
0235     // Connect to/with simple citation index option widget
0236     //connect(scw, SIGNAL(doneWithFocus()), this, SLOT(returnFocusToCanvas()));
0237 
0238     // Connect to/with simple citation index option widget
0239     connect(m_sfenw, SIGNAL(doneWithFocus()), this, SLOT(returnFocusToCanvas()));
0240 
0241     connect(m_slw, SIGNAL(doneWithFocus()), this, SLOT(returnFocusToCanvas()));
0242 
0243     m_stocw->setWindowTitle(i18nc("as in table of contents, list of pictures, index", "Tables, Lists & Indexes"));
0244     widgets.append(m_stocw);
0245 
0246     m_sfenw->setWindowTitle(i18n("Footnotes and Endnotes"));
0247     widgets.append(m_sfenw);
0248 
0249     m_scbw->setWindowTitle(i18n("Citations and Bibliography"));
0250     widgets.append(m_scbw);
0251 
0252     m_slw->setWindowTitle(i18n("Links and Bookmarks"));
0253     widgets.append(m_slw);
0254     //widgets.insert(i18n("Captions"), scapw);
0255     connect(textEditor(), SIGNAL(cursorPositionChanged()), this, SLOT(updateButtons()));
0256     return widgets;
0257 }
0258 
0259 void ReferencesTool::insertCitation()
0260 {
0261     new CitationInsertionDialog(textEditor(), m_scbw);
0262 }
0263 
0264 void ReferencesTool::insertCustomBibliography(KoBibliographyInfo *defaultTemplate)
0265 {
0266     Q_UNUSED(defaultTemplate);
0267     new InsertBibliographyDialog(textEditor(), m_scbw);
0268 }
0269 
0270 void ReferencesTool::configureBibliography()
0271 {
0272     new BibliographyConfigureDialog(textEditor()->document(), m_scbw);
0273 }
0274 
0275 void ReferencesTool::formatTableOfContents()
0276 {
0277     if (textEditor()->block().blockFormat().hasProperty(KoParagraphStyle::TableOfContentsData)) {
0278         m_configure = new TableOfContentsConfigure(textEditor(), textEditor()->block(), m_stocw);
0279         connect(m_configure, SIGNAL(finished(int)), this, SLOT(hideCofigureDialog()));
0280     }
0281 }
0282 
0283 void ReferencesTool::showConfigureDialog(QAction *action)
0284 {
0285     m_configure = new TableOfContentsConfigure(textEditor(), action->data().value<QTextBlock>(), m_stocw);
0286     connect(m_configure, SIGNAL(finished(int)), this, SLOT(hideCofigureDialog()));
0287 }
0288 
0289 void ReferencesTool::hideCofigureDialog()
0290 {
0291     disconnect(m_configure, SIGNAL(finished(int)), this, SLOT(hideCofigureDialog()));
0292     m_configure->deleteLater();
0293 }
0294 
0295 void ReferencesTool::insertAutoFootNote()
0296 {
0297     m_note = textEditor()->insertFootNote();
0298     m_note->setAutoNumbering(true);
0299 }
0300 
0301 void ReferencesTool::insertLabeledFootNote(const QString &label)
0302 {
0303     m_note = textEditor()->insertFootNote();
0304     m_note->setAutoNumbering(false);
0305     m_note->setLabel(label);
0306 }
0307 
0308 void ReferencesTool::insertAutoEndNote()
0309 {
0310     m_note = textEditor()->insertEndNote();
0311     m_note->setAutoNumbering(true);
0312 }
0313 
0314 void ReferencesTool::insertLabeledEndNote(const QString &label)
0315 {
0316     m_note = textEditor()->insertEndNote();
0317     m_note->setAutoNumbering(false);
0318     m_note->setLabel(label);
0319 }
0320 
0321 void ReferencesTool::showFootnotesConfigureDialog()
0322 {
0323     NotesConfigurationDialog *dialog = new NotesConfigurationDialog((QTextDocument *)textEditor()->document(), true);
0324     dialog->exec();
0325 }
0326 
0327 void ReferencesTool::showEndnotesConfigureDialog()
0328 {
0329     NotesConfigurationDialog *dialog = new NotesConfigurationDialog((QTextDocument *)textEditor()->document(), false);
0330     dialog->exec();
0331 }
0332 
0333 void ReferencesTool::updateButtons()
0334 {
0335     if (textEditor()->currentFrame()->format().intProperty(KoText::SubFrameType) == KoText::NoteFrameType) {
0336         m_sfenw->widget.addFootnote->setEnabled(false);
0337         m_sfenw->widget.addEndnote->setEnabled(false);
0338     } else {
0339         m_sfenw->widget.addFootnote->setEnabled(true);
0340         m_sfenw->widget.addEndnote->setEnabled(true);
0341     }
0342     if (textEditor()->block().blockFormat().hasProperty(KoParagraphStyle::TableOfContentsData)) {
0343         action("format_tableofcontents")->setEnabled(true);
0344     } else {
0345         action("format_tableofcontents")->setEnabled(false);
0346     }
0347 
0348 }
0349 
0350 KoTextEditor *ReferencesTool::editor()
0351 {
0352     return textEditor();
0353 }
0354 
0355 void ReferencesTool::insertCustomToC(KoTableOfContentsGeneratorInfo *defaultTemplate)
0356 {
0357     m_configure = new TableOfContentsConfigure(textEditor(), defaultTemplate, m_stocw);
0358     connect(m_configure, SIGNAL(accepted()), this, SLOT(customToCGenerated()));
0359     connect(m_configure, SIGNAL(finished(int)), this, SLOT(hideCofigureDialog()));
0360 }
0361 
0362 void ReferencesTool::customToCGenerated()
0363 {
0364     if (m_configure) {
0365         textEditor()->insertTableOfContents(m_configure->currentToCData());
0366     }
0367 }
0368 
0369 void ReferencesTool::insertLink()
0370 {
0371     new LinkInsertionDialog(textEditor(), m_slw);
0372 }
0373 
0374 bool ReferencesTool::validateBookmark(QString bookmarkName)
0375 {
0376     bookmarkName = bookmarkName.trimmed();
0377     if (bookmarkName.isEmpty()) {
0378         m_bmark->setWarningText(0, i18n("Bookmark cannot be empty"));
0379         return false;
0380     }
0381     const KoBookmarkManager *manager = KoTextDocument(editor()->document()).textRangeManager()->bookmarkManager();
0382     QStringList existingBookmarks = manager->bookmarkNameList();
0383     int position = existingBookmarks.indexOf(bookmarkName);
0384     if (position != -1) {
0385         m_bmark->setWarningText(0, i18n("Duplicate Name. Click \"Manage Bookmarks\""));
0386         m_bmark->setWarningText(1, i18n("to Rename or Delete Bookmarks"));
0387         return false;
0388     } else {
0389         m_bmark->setWarningText(0, "");
0390         m_bmark->setWarningText(1, "");
0391         return true;
0392     }
0393 }
0394 
0395 void ReferencesTool::insertBookmark(QString bookMarkName)
0396 {
0397     bookMarkName = bookMarkName.trimmed();
0398     m_bmark->setWarningText(0, "");
0399     m_bmark->setWarningText(1, "");
0400     if (validateBookmark(bookMarkName)) {
0401         editor()->addBookmark(bookMarkName);
0402         m_bmark->clearLineEdit();
0403     }
0404 }