diff --git a/src/KJotsMain.cpp b/src/KJotsMain.cpp index 31f9d97..f35b71e 100644 --- a/src/KJotsMain.cpp +++ b/src/KJotsMain.cpp @@ -1,93 +1,92 @@ // // kjots // // Copyright (C) 1997 Christoph Neerfeld // Copyright (C) 2002, 2003 Aaron J. Seigo // Copyright (C) 2003 Stanislav Kljuhhin // Copyright (C) 2005-2006 Jaison Lee // Copyright (C) 2007-2008 Stephen Kelly // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #include "KJotsMain.h" #include #include #include #include #include "KJotsSettings.h" #include "kjotsbookmarks.h" #include "kjotsedit.h" #include "kjotsbrowser.h" #include "kjotswidget.h" #include #include //---------------------------------------------------------------------- // KJOTSMAIN //---------------------------------------------------------------------- KJotsMain::KJotsMain() { // Main widget // - KStandardAction::quit(this, SLOT(onQuit()), actionCollection()); + KStandardAction::quit(this, &KJotsMain::onQuit, actionCollection()); component = new KJotsWidget(this, this); setCentralWidget(component); - connect(component, SIGNAL(activeAnchorChanged(QString,QString)), - SLOT(activeAnchorChanged(QString,QString))); + connect(component, &KJotsWidget::activeAnchorChanged, this, &KJotsMain::activeAnchorChanged); setupGUI(); connect(component, &KJotsWidget::captionChanged, this, &KJotsMain::updateCaption); } /*! Sets the window caption. */ void KJotsMain::updateCaption(QString caption) { setCaption(caption); } void KJotsMain::activeAnchorChanged(const QString &anchorTarget, const QString &anchorText) { if (!anchorTarget.isEmpty()) { statusBar()->showMessage(i18nc("@info:status Link information; %1 is displayed text, %2 is link destination", "%1 -> %2", anchorText, anchorTarget)); } else { statusBar()->clearMessage(); } } bool KJotsMain::queryClose() { return component->queryClose(); } void KJotsMain::onQuit() { // component->queryClose(); deleteLater(); qApp->quit(); } diff --git a/src/kjotsbrowser.h b/src/kjotsbrowser.h index 66e6965..c639256 100644 --- a/src/kjotsbrowser.h +++ b/src/kjotsbrowser.h @@ -1,46 +1,43 @@ // // kjots // // Copyright (C) 1997 Christoph Neerfeld // Copyright (C) 2002, 2003 Aaron J. Seigo // Copyright (C) 2003 Stanislav Kljuhhin // Copyright (C) 2005-2006 Jaison Lee // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #ifndef KJOTSBROWSER_H #define KJOTSBROWSER_H #include class QItemSelectionModel; class KJotsBrowser : public QTextBrowser { Q_OBJECT public: explicit KJotsBrowser(QWidget *); void delayedInitialization(); Q_SIGNALS: void linkClicked(const QUrl &); - -private: - QItemSelectionModel *m_itemSelectionModel; }; #endif /* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/kjotsconfigdlg.cpp b/src/kjotsconfigdlg.cpp index 301d210..413e004 100644 --- a/src/kjotsconfigdlg.cpp +++ b/src/kjotsconfigdlg.cpp @@ -1,77 +1,77 @@ /* Copyright (c) 2009 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kjotsconfigdlg.h" #include #include #include #include KJotsConfigDlg::KJotsConfigDlg(const QString &title, QWidget *parent) : KCMultiDialog(parent) { setWindowTitle(title); setFaceType(KPageDialog::List); setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel | QDialogButtonBox::RestoreDefaults); button(QDialogButtonBox::Ok)->setDefault(true); addModule(QLatin1String("kjots_config_misc")); connect(button(QDialogButtonBox::Ok), &QPushButton::clicked, this, &KJotsConfigDlg::slotOk); } void KJotsConfigDlg::slotOk() { } KJotsConfigMisc::KJotsConfigMisc(QWidget *parent, const QVariantList &args) : KCModule(parent, args) { QHBoxLayout *lay = new QHBoxLayout(this); miscPage = new confPageMisc(nullptr); lay->addWidget(miscPage); - connect(miscPage->autoSaveInterval, static_cast(&QSpinBox::valueChanged), this, &KJotsConfigMisc::modified); + connect(miscPage->autoSaveInterval, qOverload(&QSpinBox::valueChanged), this, &KJotsConfigMisc::modified); connect(miscPage->autoSave, &QCheckBox::stateChanged, this, &KJotsConfigMisc::modified); load(); } void KJotsConfigMisc::modified() { Q_EMIT changed(true); } void KJotsConfigMisc::load() { KConfig config(QLatin1String("kjotsrc")); KConfigGroup group = config.group("kjots"); miscPage->autoSaveInterval->setValue(group.readEntry("AutoSaveInterval", 5)); miscPage->autoSave->setChecked(group.readEntry("AutoSave", true)); Q_EMIT changed(false); } void KJotsConfigMisc::save() { KConfig config(QLatin1String("kjotsrc")); KConfigGroup group = config.group("kjots"); group.writeEntry("AutoSaveInterval", miscPage->autoSaveInterval->value()); group.writeEntry("AutoSave", miscPage->autoSave->isChecked()); group.sync(); Q_EMIT changed(false); } #include "moc_kjotsconfigdlg.cpp" diff --git a/src/kjotsedit.cpp b/src/kjotsedit.cpp index 18972f0..6c338fe 100644 --- a/src/kjotsedit.cpp +++ b/src/kjotsedit.cpp @@ -1,418 +1,418 @@ // // kjots // // Copyright (C) 1997 Christoph Neerfeld // Copyright (C) 2002, 2003 Aaron J. Seigo // Copyright (C) 2003 Stanislav Kljuhhin // Copyright (C) 2005-2006 Jaison Lee // Copyright (C) 2007-2008 Stephen Kelly // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //Own Header #include "kjotsedit.h" #include #include #include #include #include #include #include #include #include #include #include #include #include //#include #include "kjotslinkdialog.h" #include #include #include #include #include "kjotsmodel.h" #include "noteshared/notelockattribute.h" #include "noteshared/noteeditorutils.h" Q_DECLARE_METATYPE(QTextCursor) using namespace Akonadi; KJotsEdit::KJotsEdit(QWidget *parent) : KRichTextWidget(parent), actionCollection(nullptr), allowAutoDecimal(false) { setMouseTracking(true); setAcceptRichText(true); setWordWrapMode(QTextOption::WordWrap); setCheckSpellingEnabled(true); setRichTextSupport(FullTextFormattingSupport | FullListSupport | SupportAlignment | SupportRuleLine | SupportFormatPainting); setFocusPolicy(Qt::StrongFocus); } void KJotsEdit::contextMenuEvent(QContextMenuEvent *event) { QMenu *popup = mousePopupMenu(); if (popup) { popup->addSeparator(); QAction *act = actionCollection->action(QLatin1String("copyIntoTitle")); popup->addAction(act); act = actionCollection->action(QLatin1String("insert_checkmark")); act->setEnabled(!isReadOnly()); popup->addAction(act); if (!qApp->clipboard()->text().isEmpty()) { act = actionCollection->action(QLatin1String("paste_plain_text")); act->setEnabled(!isReadOnly()); popup->addAction(act); } if (!anchorAt(event->pos()).isNull()) { popup->addAction(actionCollection->action(QStringLiteral("manage_link"))); } aboutToShowContextMenu(popup); popup->exec(event->globalPos()); delete popup; } } void KJotsEdit::delayedInitialization(KActionCollection *collection) { actionCollection = collection; - connect(actionCollection->action(QLatin1String("auto_bullet")), SIGNAL(triggered()), SLOT(onAutoBullet())); - connect(actionCollection->action(QLatin1String("auto_decimal")), SIGNAL(triggered()), SLOT(onAutoDecimal())); //auto decimal list - connect(actionCollection->action(QLatin1String("manage_link")), SIGNAL(triggered()), SLOT(onLinkify())); - connect(actionCollection->action(QLatin1String("insert_checkmark")), SIGNAL(triggered()), SLOT(addCheckmark())); - connect(actionCollection->action(QLatin1String("manual_save")), SIGNAL(triggered()), SLOT(savePage())); - connect(actionCollection->action(QLatin1String("insert_date")), SIGNAL(triggered()), SLOT(insertDate())); - connect(actionCollection->action(QLatin1String("insert_image")), SIGNAL(triggered()), SLOT(insertImage())); + connect(actionCollection->action(QLatin1String("auto_bullet")), &QAction::triggered, this, &KJotsEdit::onAutoBullet); + connect(actionCollection->action(QLatin1String("auto_decimal")), &QAction::triggered, this, &KJotsEdit::onAutoDecimal); + connect(actionCollection->action(QLatin1String("manage_link")), &QAction::triggered, this, &KJotsEdit::onLinkify); + connect(actionCollection->action(QLatin1String("insert_checkmark")), &QAction::triggered, this, &KJotsEdit::addCheckmark); + connect(actionCollection->action(QLatin1String("manual_save")), &QAction::triggered, this, &KJotsEdit::savePage); + connect(actionCollection->action(QLatin1String("insert_date")), &QAction::triggered, this, &KJotsEdit::insertDate); + connect(actionCollection->action(QLatin1String("insert_image")), &QAction::triggered, this, &KJotsEdit::insertImage); } void KJotsEdit::insertDate() { NoteShared::NoteEditorUtils().insertDate(this); } void KJotsEdit::insertImage() { QTextCursor cursor = textCursor(); NoteShared::NoteEditorUtils().insertImage(document(), cursor, this); } bool KJotsEdit::setModelIndex(const QModelIndex &index) { bool newDocument = m_index && (*m_index != index); // Saving the old document, if it wa changed if (newDocument) { savePage(); } m_index = std::make_unique(index); // Loading document auto document = m_index->data(KJotsModel::DocumentRole).value(); if (!document) { setReadOnly(true); return false; } setDocument(document); // Setting cursor auto cursor = document->property("textCursor").value(); if (!cursor.isNull()) { setTextCursor(cursor); } else { // This is a work-around for QTextEdit bug. If the first letter of the document is formatted, // QTextCursor doesn't follow this format. One can either move the cursor 1 symbol to the right // and then 1 symbol to the left as a workaround, or just explicitly move it to the start. // Submitted to qt-bugs, id 192886. // -- (don't know the fate of this bug, as for April 2020 it is unaccessible) moveCursor(QTextCursor::Start); } // Setting focus if document was changed if (newDocument) { setFocus(); } // Setting ReadOnly auto item = m_index->data(EntityTreeModel::ItemRole).value(); if (!item.isValid()) { setReadOnly(true); return false; } else if (item.hasAttribute()) { setReadOnly(true); return true; } else { setReadOnly(false); return true; } } void KJotsEdit::onAutoBullet(void) { KTextEdit::AutoFormatting currentFormatting = autoFormatting(); //TODO: set line spacing properly. if (currentFormatting == KTextEdit::AutoBulletList) { setAutoFormatting(KTextEdit::AutoNone); actionCollection->action(QLatin1String("auto_bullet"))->setChecked(false); } else { setAutoFormatting(KTextEdit::AutoBulletList); actionCollection->action(QLatin1String("auto_bullet"))->setChecked(true); } } void KJotsEdit::createAutoDecimalList(void) { //this is an adaptation of Qt's createAutoBulletList() function for creating a bulleted list, except in this case I use it to create a decimal list. QTextCursor cursor = textCursor(); cursor.beginEditBlock(); QTextBlockFormat blockFmt = cursor.blockFormat(); QTextListFormat listFmt; listFmt.setStyle(QTextListFormat::ListDecimal); listFmt.setIndent(blockFmt.indent() + 1); blockFmt.setIndent(0); cursor.setBlockFormat(blockFmt); cursor.createList(listFmt); cursor.endEditBlock(); setTextCursor(cursor); } void KJotsEdit::DecimalList(void) { QTextCursor cursor = textCursor(); if (cursor.currentList()) { return; } QString blockText = cursor.block().text(); if (blockText.length() == 2 && blockText == QLatin1String("1.")) { cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); cursor.removeSelectedText(); createAutoDecimalList(); } } void KJotsEdit::onAutoDecimal(void) { if (allowAutoDecimal == true) { allowAutoDecimal = false; disconnect(this, &KJotsEdit::textChanged, this, &KJotsEdit::DecimalList); actionCollection->action(QLatin1String("auto_decimal"))->setChecked(false); } else { allowAutoDecimal = true; connect(this, &KJotsEdit::textChanged, this, &KJotsEdit::DecimalList); actionCollection->action(QLatin1String("auto_decimal"))->setChecked(true); } } void KJotsEdit::onLinkify(void) { // Nothing is yet opened, ignoring if (!m_index) { return; } selectLinkText(); QPointer linkDialog = new KJotsLinkDialog(const_cast(m_index->model()), this); linkDialog->setLinkText(currentLinkText()); linkDialog->setLinkUrl(currentLinkUrl()); if (linkDialog->exec()) { updateLink(linkDialog->linkUrl(), linkDialog->linkText()); } delete linkDialog; } void KJotsEdit::addCheckmark(void) { QTextCursor cursor = textCursor(); NoteShared::NoteEditorUtils().addCheckmark(cursor); } bool KJotsEdit::canInsertFromMimeData(const QMimeData *source) const { if (source->hasUrls()) { return true; } else { return KTextEdit::canInsertFromMimeData(source); } } void KJotsEdit::insertFromMimeData(const QMimeData *source) { // Nothing is opened, ignoring if (!m_index) { return; } if (source->hasUrls()) { const QList urls = source->urls(); for (const QUrl &url : urls) { if (url.scheme() == QStringLiteral("akonadi")) { QModelIndex idx = KJotsModel::modelIndexForUrl(m_index->model(), url); if (idx.isValid()) { insertHtml(QStringLiteral("%2").arg(idx.data(KJotsModel::EntityUrlRole).toString(), idx.data().toString())); } } else { QString text = source->hasText() ? source->text() : url.toString(QUrl::RemovePassword); insertHtml(QStringLiteral("%2").arg(QString::fromUtf8(url.toEncoded()), text)); } } } else if (source->hasHtml()) { // Don't have an action to set top and bottom margins on paragraphs yet. // Remove the margins for all inserted html. QTextDocument dummy; dummy.setHtml(source->html()); QTextCursor c(&dummy); QTextBlockFormat fmt = c.blockFormat(); fmt.setTopMargin(0); fmt.setBottomMargin(0); fmt.setLeftMargin(0); fmt.setRightMargin(0); c.movePosition(QTextCursor::End, QTextCursor::KeepAnchor); c.mergeBlockFormat(fmt); textCursor().insertFragment(QTextDocumentFragment(c)); ensureCursorVisible(); } else { KRichTextEdit::insertFromMimeData(source); } } void KJotsEdit::mouseMoveEvent(QMouseEvent *event) { if ((event->modifiers() & Qt::ControlModifier) && !anchorAt(event->pos()).isEmpty()) { if (!m_cursorChanged) { QApplication::setOverrideCursor(Qt::PointingHandCursor); m_cursorChanged = true; } } else { if (m_cursorChanged) { QApplication::restoreOverrideCursor(); m_cursorChanged = false; } } KRichTextEdit::mouseMoveEvent(event); } void KJotsEdit::leaveEvent(QEvent *event) { if (m_cursorChanged) { QApplication::restoreOverrideCursor(); m_cursorChanged = false; } KRichTextEdit::leaveEvent(event); } void KJotsEdit::mousePressEvent(QMouseEvent *event) { QUrl url = anchorAt(event->pos()); if ((event->modifiers() & Qt::ControlModifier) && (event->button() & Qt::LeftButton) && !url.isEmpty()) { Q_EMIT linkClicked(url); } else { KRichTextEdit::mousePressEvent(event); } } void KJotsEdit::pastePlainText() { QString text = qApp->clipboard()->text(); if (!text.isEmpty()) { insertPlainText(text); } } bool KJotsEdit::event(QEvent *event) { if (event->type() == QEvent::WindowDeactivate) { savePage(); } else if (event->type() == QEvent::ToolTip) { tooltipEvent(static_cast(event)); } return KRichTextWidget::event(event); } void KJotsEdit::tooltipEvent(QHelpEvent *event) { // Nothing is opened, ignoring if (!m_index) { return; } QUrl url(anchorAt(event->pos())); QString message; if (url.isValid()) { if (url.scheme() == QStringLiteral("akonadi")) { const QModelIndex idx = KJotsModel::modelIndexForUrl(m_index->model(), url); if (idx.data(EntityTreeModel::ItemRole).value().isValid()) { message = i18nc("@info:tooltip %1 is page name", "Ctrl+click to open page: %1", idx.data().toString()); } else if (idx.data(EntityTreeModel::CollectionRole).value().isValid()) { message = i18nc("@info:tooltip %1 is book name", "Ctrl+click to open book: %1", idx.data().toString()); } } else { message = i18nc("@info:tooltip %1 is hyperlink address", "Ctrl+click to follow the hyperlink: %1", url.toString(QUrl::RemovePassword)); } } if (!message.isEmpty()) { QToolTip::showText(event->globalPos(), message); } else { QToolTip::hideText(); } } void KJotsEdit::focusOutEvent(QFocusEvent *event) { savePage(); KRichTextWidget::focusOutEvent(event); } void KJotsEdit::savePage() { if (!document()->isModified() || !m_index) { return; } auto item = m_index->data(EntityTreeModel::ItemRole).value(); if (!item.isValid() || !item.hasPayload()) { return; } auto model = const_cast(m_index->model()); document()->setModified(false); document()->setProperty("textCursor", QVariant::fromValue(textCursor())); model->setData(*m_index, QVariant::fromValue(document()), KJotsModel::DocumentRole); } /* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/kjotslinkdialog.cpp b/src/kjotslinkdialog.cpp index 5d2351e..c46bd65 100644 --- a/src/kjotslinkdialog.cpp +++ b/src/kjotslinkdialog.cpp @@ -1,168 +1,167 @@ // // kjots // // Copyright (C) 2008 Stephen Kelly // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #include "kjotslinkdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "KJotsSettings.h" #include "kjotsbookshelfentryvalidator.h" #include "kjotsmodel.h" #include #include KJotsLinkDialog::KJotsLinkDialog(QAbstractItemModel *kjotsModel, QWidget *parent) : QDialog(parent), m_kjotsModel(kjotsModel) { setWindowTitle(i18n("Manage Link")); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &KJotsLinkDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &KJotsLinkDialog::reject); okButton->setDefault(true); setModal(true); KDescendantsProxyModel *proxyModel = new KDescendantsProxyModel(this); proxyModel->setSourceModel(kjotsModel); proxyModel->setAncestorSeparator(QLatin1String(" / ")); m_descendantsProxyModel = proxyModel; QWidget *entries = new QWidget(this); QGridLayout *layout = new QGridLayout(entries); textLabel = new QLabel(i18n("Link Text:"), this); textLineEdit = new QLineEdit(this); textLineEdit->setClearButtonEnabled(true); linkUrlLabel = new QLabel(i18n("Link URL:"), this); linkUrlLineEdit = new QLineEdit(this); hrefCombo = new QComboBox(this); linkUrlLineEdit->setClearButtonEnabled(true); tree = new QTreeView(); tree->setModel(proxyModel); tree->expandAll(); tree->setColumnHidden(1, true); hrefCombo->setModel(proxyModel); hrefCombo->setView(tree); hrefCombo->setEditable(true); QCompleter *completer = new QCompleter(proxyModel, this); completer->setCaseSensitivity(Qt::CaseInsensitive); hrefCombo->setCompleter(completer); KJotsBookshelfEntryValidator *validator = new KJotsBookshelfEntryValidator(proxyModel, this); hrefCombo->setValidator(validator); QGridLayout *linkLayout = new QGridLayout(); linkUrlLineEditRadioButton = new QRadioButton(entries); hrefComboRadioButton = new QRadioButton(entries); connect(linkUrlLineEditRadioButton, &QRadioButton::toggled, linkUrlLineEdit, &QLineEdit::setEnabled); connect(hrefComboRadioButton, &QRadioButton::toggled, hrefCombo, &QComboBox::setEnabled); hrefCombo->setEnabled(false); linkUrlLineEditRadioButton->setChecked(true); linkLayout->addWidget(linkUrlLineEditRadioButton, 0, 0); linkLayout->addWidget(linkUrlLineEdit, 0, 1); linkLayout->addWidget(hrefComboRadioButton, 1, 0); linkLayout->addWidget(hrefCombo, 1, 1); layout->addWidget(textLabel, 0, 0); layout->addWidget(textLineEdit, 0, 1); layout->addWidget(linkUrlLabel, 1, 0); layout->addLayout(linkLayout, 1, 1); mainLayout->addWidget(entries); mainLayout->addWidget(buttonBox); textLineEdit->setFocus(); - connect(hrefCombo, SIGNAL(editTextChanged(QString)), - this, SLOT(trySetEntry(QString))); + connect(hrefCombo, &QComboBox::editTextChanged, this, &KJotsLinkDialog::trySetEntry); } void KJotsLinkDialog::setLinkText(const QString &linkText) { textLineEdit->setText(linkText); if (!linkText.trimmed().isEmpty()) { linkUrlLineEdit->setFocus(); } } void KJotsLinkDialog::setLinkUrl(const QString &linkUrl) { const QUrl url(linkUrl); if (url.scheme() == QStringLiteral("akonadi")) { QModelIndex idx = KJotsModel::modelIndexForUrl(m_descendantsProxyModel, url); if (idx.isValid()) { hrefComboRadioButton->setChecked(true); hrefCombo->view()->setCurrentIndex(idx); hrefCombo->setCurrentIndex(idx.row()); } } else { linkUrlLineEdit->setText(linkUrl); linkUrlLineEditRadioButton->setChecked(true); return; } } QString KJotsLinkDialog::linkText() const { return textLineEdit->text().trimmed(); } void KJotsLinkDialog::trySetEntry(const QString &text) { QString t(text); int pos = hrefCombo->lineEdit()->cursorPosition(); if (hrefCombo->validator()->validate(t, pos) == KJotsBookshelfEntryValidator::Acceptable) { int row = hrefCombo->findText(t, Qt::MatchFixedString); QModelIndex index = hrefCombo->model()->index(row, 0); hrefCombo->view()->setCurrentIndex(index); hrefCombo->setCurrentIndex(row); } } QString KJotsLinkDialog::linkUrl() const { if (hrefComboRadioButton->isChecked()) { return hrefCombo->view()->currentIndex().data(KJotsModel::EntityUrlRole).toString(); } else { return linkUrlLineEdit->text(); } } diff --git a/src/kjotsmodel.cpp b/src/kjotsmodel.cpp index b03f6c3..f9c0165 100644 --- a/src/kjotsmodel.cpp +++ b/src/kjotsmodel.cpp @@ -1,289 +1,289 @@ /* This file is part of KJots. Copyright (c) 2009 Stephen Kelly This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kjotsmodel.h" #include #include #include #include #include #include #include "noteshared/notelockattribute.h" #include #include #include #include #include Q_DECLARE_METATYPE(QTextDocument *) KJotsEntity::KJotsEntity(const QModelIndex &index, QObject *parent) : QObject(parent) + , m_index(index) { - m_index = QPersistentModelIndex(index); } void KJotsEntity::setIndex(const QModelIndex &index) { m_index = QPersistentModelIndex(index); } QString KJotsEntity::title() const { return m_index.data().toString(); } QString KJotsEntity::content() const { QTextDocument *document = m_index.data(KJotsModel::DocumentRole).value(); if (!document) { return QString(); } Grantlee::TextHTMLBuilder builder; Grantlee::MarkupDirector director(&builder); director.processDocument(document); QString result = builder.getResult(); return result; } QString KJotsEntity::plainContent() const { QTextDocument *document = m_index.data(KJotsModel::DocumentRole).value(); if (!document) { return QString(); } Grantlee::PlainTextMarkupBuilder builder; Grantlee::MarkupDirector director(&builder); director.processDocument(document); QString result = builder.getResult(); return result; } QString KJotsEntity::url() const { return m_index.data(KJotsModel::EntityUrlRole).toString(); } qint64 KJotsEntity::entityId() const { Item item = m_index.data(EntityTreeModel::ItemRole).value(); if (!item.isValid()) { Collection col = m_index.data(EntityTreeModel::CollectionRole).value(); if (!col.isValid()) { return -1; } return col.id(); } return item.id(); } bool KJotsEntity::isBook() const { Collection col = m_index.data(EntityTreeModel::CollectionRole).value(); if (col.isValid()) { return col.contentMimeTypes().contains(Akonadi::NoteUtils::noteMimeType()); } return false; } bool KJotsEntity::isPage() const { Item item = m_index.data(EntityTreeModel::ItemRole).value(); if (item.isValid()) { return item.hasPayload(); } return false; } QVariantList KJotsEntity::entities() const { const QAbstractItemModel *model = m_index.model(); QVariantList list; int row = 0; const int column = 0; QModelIndex childIndex = model->index(row++, column, m_index); while (childIndex.isValid()) { auto obj = new KJotsEntity(childIndex); list << QVariant::fromValue(obj); childIndex = model->index(row++, column, m_index); } return list; } QVariantList KJotsEntity::breadcrumbs() const { QVariantList list; QModelIndex parent = m_index.parent(); while (parent.isValid()) { QObject *obj = new KJotsEntity(parent); list << QVariant::fromValue(obj); parent = parent.parent(); } return list; } KJotsModel::KJotsModel(ChangeRecorder *monitor, QObject *parent) : EntityTreeModel(monitor, parent) { } KJotsModel::~KJotsModel() { qDeleteAll(m_documents); } bool KJotsModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (role == Qt::EditRole) { Item item = index.data(ItemRole).value(); if (!item.isValid()) { Collection col = index.data(CollectionRole).value(); col.setName(value.toString()); if (col.hasAttribute()) { EntityDisplayAttribute *eda = col.attribute(); eda->setDisplayName(value.toString()); } return EntityTreeModel::setData(index, QVariant::fromValue(col), CollectionRole); } NoteUtils::NoteMessageWrapper note(item.payload()); note.setTitle(value.toString()); note.setLastModifiedDate(QDateTime::currentDateTime()); item.setPayload(note.message()); if (item.hasAttribute()) { EntityDisplayAttribute *displayAttribute = item.attribute(); displayAttribute->setDisplayName(value.toString()); } return EntityTreeModel::setData(index, QVariant::fromValue(item), ItemRole); } if (role == KJotsModel::DocumentRole) { Item item = EntityTreeModel::data(index, ItemRole).value(); if (!item.hasPayload()) { return false; } QTextDocument *document = value.value(); NoteUtils::NoteMessageWrapper note(item.payload()); bool isRichText = KPIMTextEdit::TextUtils::containsFormatting(document); if (isRichText) { note.setText( document->toHtml(), Qt::RichText ); } else { note.setText( document->toPlainText(), Qt::PlainText ); } note.setLastModifiedDate(QDateTime::currentDateTime()); item.setPayload(note.message()); return EntityTreeModel::setData(index, QVariant::fromValue(item), ItemRole); } return EntityTreeModel::setData(index, value, role); } QVariant KJotsModel::data(const QModelIndex &index, int role) const { if (GrantleeObjectRole == role) { QObject *obj = new KJotsEntity(index); return QVariant::fromValue(obj); } if (role == KJotsModel::DocumentRole) { const Item item = index.data(ItemRole).value(); Item::Id itemId = item.id(); if (m_documents.contains(itemId)) { return QVariant::fromValue(m_documents.value(itemId)); } if (!item.hasPayload()) { return QVariant(); } NoteUtils::NoteMessageWrapper note(item.payload()); const QString doc = note.text(); auto document = new QTextDocument(); if (note.textFormat() == Qt::RichText || doc.startsWith(u"")) { document->setHtml(doc); } else { document->setPlainText(doc); } m_documents.insert(itemId, document); return QVariant::fromValue(document); } if (role == Qt::DecorationRole) { const Item item = index.data(ItemRole).value(); if (item.isValid() && item.hasAttribute()) { return QIcon::fromTheme(QLatin1String("emblem-locked")); } else { const Collection col = index.data(CollectionRole).value(); if (col.isValid() && col.hasAttribute()) { return QIcon::fromTheme(QLatin1String("emblem-locked")); } } } return EntityTreeModel::data(index, role); } QVariant KJotsModel::entityData(const Akonadi::Item &item, int column, int role) const { if ((role == Qt::EditRole || role == Qt::DisplayRole) && item.hasPayload()) { NoteUtils::NoteMessageWrapper note(item.payload()); return note.title(); } return EntityTreeModel::entityData(item, column, role); } QModelIndex KJotsModel::modelIndexForUrl(const QAbstractItemModel *model, const QUrl &url) { if (url.scheme() != QStringLiteral("akonadi")) { return QModelIndex(); } const auto item = Item::fromUrl(url); const auto col = Collection::fromUrl(url); if (item.isValid()) { const QModelIndexList idxs = EntityTreeModel::modelIndexesForItem(model, item); if (!idxs.isEmpty()) { return idxs.first(); } } else if (col.isValid()) { return EntityTreeModel::modelIndexForCollection(model, col); } return QModelIndex(); } diff --git a/src/kjotspart.cpp b/src/kjotspart.cpp index dc4c1fd..df133d9 100644 --- a/src/kjotspart.cpp +++ b/src/kjotspart.cpp @@ -1,114 +1,112 @@ /* This file is part of KJots. Copyright (c) 2008 Stephen Kelly This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. As a special exception, permission is given to link this program with any edition of Qt, and distribute the resulting executable, without including the source code for Qt in the source distribution. */ #include "kjotspart.h" #include "aboutdata.h" #include "kjotswidget.h" #include //#include //#include #include #include #include #include #include #include #include #include #include #include #include const KAboutData &createAboutData() { static AboutData aboutData; return aboutData; } K_PLUGIN_FACTORY(KJotsPartFactory, registerPlugin();) KJotsPart::KJotsPart(QWidget *parentWidget, QObject *parent, const QVariantList & /*args*/) : KParts::ReadOnlyPart(parent) { // we need an instance //QT5 setComponentData( KJotsPartFactory::componentData() ); // this should be your custom internal widget mComponent = new KJotsWidget(parentWidget, this); mStatusBar = new KParts::StatusBarExtension(this); // notify the part that this is our internal widget setWidget(mComponent); initAction(); // set our XML-UI resource file setComponentName(QStringLiteral("kjots"), QStringLiteral("kjots")); setXMLFile(QStringLiteral("kjotspartui.rc")); - QTimer::singleShot(0, this, SLOT(delayedInitialization())); + QTimer::singleShot(0, this, &KJotsPart::delayedInitialization); } KJotsPart::~KJotsPart() { mComponent->queryClose(); } void KJotsPart::initAction() { QAction *action = new QAction(QIcon::fromTheme(QLatin1String("configure")), i18n("&Configure KJots..."), this); actionCollection()->addAction(QLatin1String("kjots_configure"), action); - connect(action, SIGNAL(triggered(bool)), mComponent, - SLOT(configure())); + connect(action, &QAction::triggered, mComponent, &KJotsWidget::configure); } bool KJotsPart::openFile() { return false; } void KJotsPart::delayedInitialization() { - connect(mComponent, SIGNAL(activeAnchorChanged(QString,QString)), - SLOT(activeAnchorChanged(QString,QString))); + connect(mComponent, &KJotsWidget::activeAnchorChanged, this, &KJotsPart::activeAnchorChanged); } void KJotsPart::activeAnchorChanged(const QString &anchorTarget, const QString &anchorText) { if (!anchorTarget.isEmpty()) { mStatusBar->statusBar()->showMessage(i18nc("@info:status Link information; %1 is displayed text, %2 is link destination", "%1 -> %2", anchorText, anchorTarget)); } else { mStatusBar->statusBar()->clearMessage(); } } // // bool KJotsPart::saveFile() // { // return false; // } #include "kjotspart.moc" diff --git a/src/kjotsreplacenextdialog.cpp b/src/kjotsreplacenextdialog.cpp index 4e93162..8ba8a6f 100644 --- a/src/kjotsreplacenextdialog.cpp +++ b/src/kjotsreplacenextdialog.cpp @@ -1,80 +1,73 @@ // // kjots // // Copyright (C) 2008 Stephen Kelly // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // #include "kjotsreplacenextdialog.h" #include #include #include #include #include KJotsReplaceNextDialog::KJotsReplaceNextDialog(QWidget *parent) : QDialog(parent), m_answer(Close) { setModal(true); setWindowTitle(i18n("Replace")); QVBoxLayout *layout = new QVBoxLayout(this); m_mainLabel = new QLabel(this); layout->addWidget(m_mainLabel); QDialogButtonBox *buttonBox = new QDialogButtonBox; QPushButton *button = buttonBox->addButton(i18n("&All"), QDialogButtonBox::NoRole); - connect(button, SIGNAL(clicked(bool)), this, SLOT(onHandleAll())); + connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::onHandleAll); button = buttonBox->addButton(i18n("&Skip"), QDialogButtonBox::NoRole); - connect(button, SIGNAL(clicked(bool)), this, SLOT(onHandleSkip())); + connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::onHandleSkip); button = buttonBox->addButton(i18n("Replace"), QDialogButtonBox::NoRole); - connect(button, SIGNAL(clicked(bool)), this, SLOT(onHandleReplace())); + connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::onHandleReplace); button = buttonBox->addButton(QDialogButtonBox::Close); - connect(button, SIGNAL(clicked(bool)), this, SLOT(reject())); + connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::reject); layout->addWidget(buttonBox); - - QVBoxLayout - setMainWidget(m_mainLabel); - - connect(this, SIGNAL(user1Clicked()), SLOT(onHandleAll())); - connect(this, SIGNAL(user2Clicked()), SLOT(onHandleSkip())); - connect(this, SIGNAL(user3Clicked()), SLOT(onHandleReplace())); } void KJotsReplaceNextDialog::setLabel(const QString &pattern, const QString &replacement) { m_mainLabel->setText(i18n("Replace '%1' with '%2'?", pattern, replacement)); } void KJotsReplaceNextDialog::onHandleAll() { m_answer = All; accept(); } void KJotsReplaceNextDialog::onHandleSkip() { m_answer = Skip; accept(); } void KJotsReplaceNextDialog::onHandleReplace() { m_answer = Replace; accept(); } diff --git a/src/kjotswidget.cpp b/src/kjotswidget.cpp index a978f94..42d30f1 100644 --- a/src/kjotswidget.cpp +++ b/src/kjotswidget.cpp @@ -1,1735 +1,1734 @@ /* This file is part of KJots. Copyright (C) 1997 Christoph Neerfeld Copyright (C) 2002, 2003 Aaron J. Seigo Copyright (C) 2003 Stanislav Kljuhhin Copyright (C) 2005-2006 Jaison Lee Copyright (C) 2007-2009 Stephen Kelly This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kjotswidget.h" // Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include #include // Akonadi #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "akonadi_next/notecreatorandselector.h" // Grantlee #include #include #include // KDE #include #include #include #include #include #include #include #include #include #include #include #include #include #include // KMime #include // KJots #include "kjotsbookmarks.h" #include "kjotssortproxymodel.h" #include "kjotsmodel.h" #include "kjotsedit.h" #include "kjotstreeview.h" #include "kjotsconfigdlg.h" #include "kjotsreplacenextdialog.h" #include "KJotsSettings.h" #include "kjotslockjob.h" #include "kjotsbrowser.h" #include "noteshared/notelockattribute.h" #include "localresourcecreator.h" #include Q_DECLARE_METATYPE(QTextDocument *) Q_DECLARE_METATYPE(QTextCursor) using namespace Akonadi; using namespace Grantlee; KJotsWidget::KJotsWidget(QWidget *parent, KXMLGUIClient *xmlGuiClient, Qt::WindowFlags f) : QWidget(parent, f), m_xmlGuiClient(xmlGuiClient) { Akonadi::ControlGui::widgetNeedsAkonadi(this); KConfigGroup config(KSharedConfig::openConfig(), "General"); const bool autoCreate = config.readEntry("AutoCreateResourceOnStart", true); config.writeEntry("AutoCreateResourceOnStart", autoCreate); config.sync(); if (autoCreate) { LocalResourceCreator *creator = new LocalResourceCreator(this); creator->createIfMissing(); } m_splitter = new QSplitter(this); m_splitter->setStretchFactor(1, 1); // I think we can live without this //m_splitter->setOpaqueResize(KGlobalSettings::opaqueResize()); QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); m_templateEngine = new Engine(this); // We don't have custom plugins, so this should not be needed //m_templateEngine->setPluginPaths(KStd.findDirs("lib", QString())); m_loader = QSharedPointer(new FileSystemTemplateLoader()); m_loader->setTemplateDirs(QStandardPaths::locateAll(QStandardPaths::GenericDataLocation, QStringLiteral("kjots/themes"), QStandardPaths::LocateDirectory)); m_loader->setTheme(QLatin1String("default")); m_templateEngine->addTemplateLoader(m_loader); treeview = new KJotsTreeView(xmlGuiClient, m_splitter); ItemFetchScope scope; scope.fetchFullPayload(true); // Need to have full item when adding it to the internal data structure scope.fetchAttribute< EntityDisplayAttribute >(); scope.fetchAttribute< NoteShared::NoteLockAttribute >(); ChangeRecorder *monitor = new ChangeRecorder(this); monitor->fetchCollection(true); monitor->setItemFetchScope(scope); monitor->setCollectionMonitored(Collection::root()); monitor->setMimeTypeMonitored(Akonadi::NoteUtils::noteMimeType()); m_kjotsModel = new KJotsModel(monitor, this); m_sortProxyModel = new KJotsSortProxyModel(this); m_sortProxyModel->setSourceModel(m_kjotsModel); m_orderProxy = new EntityOrderProxyModel(this); m_orderProxy->setSourceModel(m_sortProxyModel); KConfigGroup cfg(KSharedConfig::openConfig(), "KJotsEntityOrder"); m_orderProxy->setOrderConfig(cfg); treeview->setModel(m_orderProxy); treeview->setSelectionMode(QAbstractItemView::ExtendedSelection); treeview->setEditTriggers(QAbstractItemView::DoubleClicked); selProxy = new KSelectionProxyModel(treeview->selectionModel(), this); selProxy->setSourceModel(treeview->model()); // TODO: Write a QAbstractItemView subclass to render kjots selection. // TODO: handle dataChanged properly, i.e. if item was changed from outside connect(selProxy, &KSelectionProxyModel::dataChanged, this, &KJotsWidget::renderSelection); connect(selProxy, &KSelectionProxyModel::rowsInserted, this, &KJotsWidget::renderSelection); connect(selProxy, &KSelectionProxyModel::rowsRemoved, this, &KJotsWidget::renderSelection); stackedWidget = new QStackedWidget(m_splitter); KActionCollection *actionCollection = xmlGuiClient->actionCollection(); editor = new KJotsEdit(stackedWidget); connect(editor, &KJotsEdit::linkClicked, this, &KJotsWidget::openLink); actionCollection->addActions(editor->createActions()); stackedWidget->addWidget(editor); layout->addWidget(m_splitter); browser = new KJotsBrowser(stackedWidget); connect(browser, &KJotsBrowser::linkClicked, this, &KJotsWidget::openLink); stackedWidget->addWidget(browser); stackedWidget->setCurrentWidget(browser); QAction *action; action = actionCollection->addAction(QLatin1String("go_next_book")); action->setText(i18n("Next Book")); action->setIcon(QIcon::fromTheme(QLatin1String("go-down"))); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_D)); connect(action, &QAction::triggered, this, &KJotsWidget::nextBook); connect(this, &KJotsWidget::canGoNextBookChanged, action, &QAction::setEnabled); action = actionCollection->addAction(QLatin1String("go_prev_book")); action->setText(i18n("Previous Book")); action->setIcon(QIcon::fromTheme(QLatin1String("go-up"))); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D)); connect(action, &QAction::triggered, this, &KJotsWidget::prevBook); connect(this, &KJotsWidget::canGoPreviousBookChanged, action, &QAction::setEnabled); action = actionCollection->addAction(QLatin1String("go_next_page")); action->setText(i18n("Next Page")); action->setIcon(QIcon::fromTheme(QLatin1String("go-next"))); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_PageDown)); connect(action, &QAction::triggered, this, &KJotsWidget::nextPage); connect(this, &KJotsWidget::canGoNextPageChanged, action, &QAction::setEnabled); action = actionCollection->addAction(QLatin1String("go_prev_page")); action->setText(i18n("Previous Page")); action->setIcon(QIcon::fromTheme(QLatin1String("go-previous"))); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_PageUp)); connect(action, &QAction::triggered, this, &KJotsWidget::prevPage); connect(this, &KJotsWidget::canGoPreviousPageChanged, action, &QAction::setEnabled); action = actionCollection->addAction(QLatin1String("new_page")); action->setText(i18n("&New Page")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_N)); action->setIcon(QIcon::fromTheme(QLatin1String("document-new"))); connect(action, &QAction::triggered, this, &KJotsWidget::newPage); action = actionCollection->addAction(QLatin1String("new_book")); action->setText(i18n("New &Book...")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_N)); action->setIcon(QIcon::fromTheme(QLatin1String("address-book-new"))); connect(action, &QAction::triggered, this, &KJotsWidget::newBook); action = actionCollection->addAction(QLatin1String("del_page")); action->setText(i18n("&Delete Page")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_Delete)); action->setIcon(QIcon::fromTheme(QLatin1String("edit-delete-page"))); connect(action, &QAction::triggered, this, &KJotsWidget::deletePage); action = actionCollection->addAction(QLatin1String("del_folder")); action->setText(i18n("Delete Boo&k")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Delete)); action->setIcon(QIcon::fromTheme(QLatin1String("edit-delete"))); connect(action, &QAction::triggered, this, &KJotsWidget::deleteBook); action = actionCollection->addAction(QLatin1String("del_mult")); action->setText(i18n("Delete Selected")); action->setIcon(QIcon::fromTheme(QLatin1String("edit-delete"))); connect(action, &QAction::triggered, this, &KJotsWidget::deleteMultiple); action = actionCollection->addAction(QLatin1String("manual_save")); action->setText(i18n("Manual Save")); action->setIcon(QIcon::fromTheme(QLatin1String("document-save"))); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_S)); action = actionCollection->addAction(QLatin1String("auto_bullet")); action->setText(i18n("Auto Bullets")); action->setIcon(QIcon::fromTheme(QLatin1String("format-list-unordered"))); action->setCheckable(true); action = actionCollection->addAction(QLatin1String("auto_decimal")); action->setText(i18n("Auto Decimal List")); action->setIcon(QIcon::fromTheme(QLatin1String("format-list-ordered"))); action->setCheckable(true); action = actionCollection->addAction(QLatin1String("manage_link")); action->setText(i18n("Link")); action->setIcon(QIcon::fromTheme(QLatin1String("insert-link"))); action = actionCollection->addAction(QLatin1String("insert_image")); action->setText(i18n("Insert Image")); action->setIcon(QIcon::fromTheme(QLatin1String("insert-image"))); action = actionCollection->addAction(QLatin1String("insert_checkmark")); action->setText(i18n("Insert Checkmark")); action->setIcon(QIcon::fromTheme(QLatin1String("checkmark"))); action->setEnabled(false); action = actionCollection->addAction(QLatin1String("rename_entry")); action->setText(i18n("Rename...")); action->setIcon(QIcon::fromTheme(QLatin1String("edit-rename"))); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_M)); action = actionCollection->addAction(QLatin1String("insert_date")); action->setText(i18n("Insert Date")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I)); action->setIcon(QIcon::fromTheme(QLatin1String("view-calendar-time-spent"))); action = actionCollection->addAction(QLatin1String("change_color")); action->setIcon(QIcon::fromTheme(QLatin1String("format-fill-color"))); action->setText(i18n("Change Color...")); action = actionCollection->addAction(QLatin1String("copy_link_address")); action->setText(i18n("Copy Link Address")); action = actionCollection->addAction(QLatin1String("lock")); action->setText(i18n("Lock Selected")); action->setIcon(QIcon::fromTheme(QLatin1String("emblem-locked"))); connect(action, &QAction::triggered, this, &KJotsWidget::actionLock); action = actionCollection->addAction(QLatin1String("unlock")); action->setText(i18n("Unlock Selected")); action->setIcon(QIcon::fromTheme(QLatin1String("emblem-unlocked"))); connect(action, &QAction::triggered, this, &KJotsWidget::actionUnlock); action = actionCollection->addAction(QLatin1String("sort_children_alpha")); action->setText(i18n("Sort children alphabetically")); connect(action, &QAction::triggered, this, &KJotsWidget::actionSortChildrenAlpha); action = actionCollection->addAction(QLatin1String("sort_children_by_date")); action->setText(i18n("Sort children by creation date")); connect(action, &QAction::triggered, this, &KJotsWidget::actionSortChildrenByDate); - action = KStandardAction::cut(editor, SLOT(cut()), actionCollection); + action = KStandardAction::cut(editor, &KJotsEdit::cut, actionCollection); connect(editor, &KJotsEdit::copyAvailable, action, &QAction::setEnabled); action->setEnabled(false); - action = KStandardAction::copy(this, SLOT(copy()), actionCollection); + action = KStandardAction::copy(this, &KJotsWidget::copy, actionCollection); connect(editor, &KJotsEdit::copyAvailable, action, &QAction::setEnabled); connect(browser, &KJotsBrowser::copyAvailable, action, &QAction::setEnabled); action->setEnabled(false); - KStandardAction::paste(editor, SLOT(paste()), actionCollection); + KStandardAction::paste(editor, &KJotsEdit::paste, actionCollection); - KStandardAction::undo(editor, SLOT(undo()), actionCollection); - KStandardAction::redo(editor, SLOT(redo()), actionCollection); - KStandardAction::selectAll(editor, SLOT(selectAll()), actionCollection); + KStandardAction::undo(editor, &KJotsEdit::undo, actionCollection); + KStandardAction::redo(editor, &KJotsEdit::redo, actionCollection); + KStandardAction::selectAll(editor, &KJotsEdit::selectAll, actionCollection); action = actionCollection->addAction(QLatin1String("copyIntoTitle")); action->setText(i18n("Copy &into Page Title")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_T)); action->setIcon(QIcon::fromTheme(QLatin1String("edit-copy"))); connect(action, &QAction::triggered, this, &KJotsWidget::copySelectionToTitle); connect(editor, &KJotsEdit::copyAvailable, action, &QAction::setEnabled); action->setEnabled(false); action = actionCollection->addAction(QLatin1String("paste_plain_text")); action->setText(i18nc("@action Paste the text in the clipboard without rich text formatting.", "Paste Plain Text")); connect(action, &QAction::triggered, editor, &KJotsEdit::pastePlainText); - KStandardAction::preferences(this, SLOT(configure()), actionCollection); + KStandardAction::preferences(this, &KJotsWidget::configure, actionCollection); bookmarkMenu = actionCollection->add(QLatin1String("bookmarks")); bookmarkMenu->setText(i18n("&Bookmarks")); KJotsBookmarks *bookmarks = new KJotsBookmarks(treeview); connect(bookmarks, &KJotsBookmarks::openLink, this, &KJotsWidget::openLink); KBookmarkMenu *bmm = new KBookmarkMenu( KBookmarkManager::managerForFile( - QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).first() + QStringLiteral("/kjots/bookmarks.xml"), + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + QStringLiteral("/kjots/bookmarks.xml"), QStringLiteral("kjots")), bookmarks, bookmarkMenu->menu()); // "Add bookmark" and "make text bold" actions have conflicting shortcuts (ctrl + b) // Make add_bookmark use ctrl+shift+b to resolve that. QAction *bm_action = bmm->addBookmarkAction(); actionCollection->addAction(QStringLiteral("add_bookmark"), bm_action); actionCollection->setDefaultShortcut(bm_action, Qt::CTRL | Qt::SHIFT | Qt::Key_B); actionCollection->addAction(QStringLiteral("edit_bookmark"), bmm->editBookmarksAction()); actionCollection->addAction(QStringLiteral("add_bookmarks_list"), bmm->bookmarkTabsAsFolderAction()); - KStandardAction::find(this, SLOT(onShowSearch()), actionCollection); - action = KStandardAction::findNext(this, SLOT(onRepeatSearch()), actionCollection); + KStandardAction::find(this, &KJotsWidget::onShowSearch, actionCollection); + action = KStandardAction::findNext(this, &KJotsWidget::onRepeatSearch, actionCollection); action->setEnabled(false); - KStandardAction::replace(this, SLOT(onShowReplace()), actionCollection); + KStandardAction::replace(this, &KJotsWidget::onShowReplace, actionCollection); action = actionCollection->addAction(QLatin1String("save_to")); action->setText(i18n("Rename...")); action->setIcon(QIcon::fromTheme(QLatin1String("edit-rename"))); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_M)); KActionMenu *exportMenu = actionCollection->add(QLatin1String("save_to")); exportMenu->setText(i18n("Export")); exportMenu->setIcon(QIcon::fromTheme(QLatin1String("document-export"))); action = actionCollection->addAction(QLatin1String("save_to_ascii")); action->setText(i18n("To Text File...")); action->setIcon(QIcon::fromTheme(QLatin1String("text-plain"))); connect(action, &QAction::triggered, this, &KJotsWidget::exportSelectionToPlainText); exportMenu->menu()->addAction(action); action = actionCollection->addAction(QLatin1String("save_to_html")); action->setText(i18n("To HTML File...")); action->setIcon(QIcon::fromTheme(QLatin1String("text-html"))); connect(action, &QAction::triggered, this, &KJotsWidget::exportSelectionToHtml); exportMenu->menu()->addAction(action); action = actionCollection->addAction(QLatin1String("save_to_book")); action->setText(i18n("To Book File...")); action->setIcon(QIcon::fromTheme(QLatin1String("x-office-address-book"))); connect(action, &QAction::triggered, this, &KJotsWidget::exportSelectionToXml); exportMenu->menu()->addAction(action); - KStandardAction::print(this, SLOT(printSelection()), actionCollection); - KStandardAction::printPreview(this, SLOT(printPreviewSelection()), actionCollection); + KStandardAction::print(this, &KJotsWidget::printSelection, actionCollection); + KStandardAction::printPreview(this, &KJotsWidget::printPreviewSelection, actionCollection); if (!KJotsSettings::splitterSizes().isEmpty()) { m_splitter->setSizes(KJotsSettings::splitterSizes()); } - QTimer::singleShot(0, this, SLOT(delayedInitialization())); + QTimer::singleShot(0, this, &KJotsWidget::delayedInitialization); - connect(treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(updateMenu())); - connect(treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(updateCaption())); + connect(treeview->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KJotsWidget::updateMenu); + connect(treeview->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KJotsWidget::updateCaption); connect(m_kjotsModel, &Akonadi::EntityTreeModel::modelAboutToBeReset, this, &KJotsWidget::saveState); connect(m_kjotsModel, &Akonadi::EntityTreeModel::modelReset, this, &KJotsWidget::restoreState); restoreState(); QDBusConnection::sessionBus().registerObject(QLatin1String("/KJotsWidget"), this, QDBusConnection::ExportScriptableContents); } KJotsWidget::~KJotsWidget() { saveState(); } void KJotsWidget::restoreState() { ETMViewStateSaver *saver = new ETMViewStateSaver; saver->setView(treeview); KConfigGroup cfg(KSharedConfig::openConfig(), "TreeState"); saver->restoreState(cfg); } void KJotsWidget::saveState() { ETMViewStateSaver saver; saver.setView(treeview); KConfigGroup cfg(KSharedConfig::openConfig(), "TreeState"); saver.saveState(cfg); cfg.sync(); } void KJotsWidget::delayedInitialization() { //TODO: Save previous searches in settings file? searchDialog = new KFindDialog(this, 0, QStringList(), false); QGridLayout *layout = new QGridLayout(searchDialog->findExtension()); layout->setMargin(0); searchAllPages = new QCheckBox(i18n("Search all pages"), searchDialog->findExtension()); layout->addWidget(searchAllPages, 0, 0); connect(searchDialog, &KFindDialog::okClicked, this, &KJotsWidget::onStartSearch); connect(searchDialog, &KFindDialog::cancelClicked, this, &KJotsWidget::onEndSearch); - connect(treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(onUpdateSearch())); + connect(treeview->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KJotsWidget::onUpdateSearch); connect(searchDialog, &KFindDialog::optionsChanged, this, &KJotsWidget::onUpdateSearch); connect(searchAllPages, &QCheckBox::stateChanged, this, &KJotsWidget::onUpdateSearch); replaceDialog = new KReplaceDialog(this, 0, searchHistory, replaceHistory, false); QGridLayout *layout2 = new QGridLayout(replaceDialog->findExtension()); layout2->setMargin(0); replaceAllPages = new QCheckBox(i18n("Search all pages"), replaceDialog->findExtension()); layout2->addWidget(replaceAllPages, 0, 0); connect(replaceDialog, &KReplaceDialog::okClicked, this, &KJotsWidget::onStartReplace); connect(replaceDialog, &KReplaceDialog::cancelClicked, this, &KJotsWidget::onEndReplace); connect(replaceDialog, &KReplaceDialog::optionsChanged, this, &KJotsWidget::onUpdateReplace); connect(replaceAllPages, &QCheckBox::stateChanged, this, &KJotsWidget::onUpdateReplace); // Actions are enabled or disabled based on whether the selection is a single page, a single book // multiple selections, or no selection. // // The entryActions are enabled for all single pages and single books, and the multiselectionActions // are enabled when the user has made multiple selections. // // Some actions are in neither (eg, new book) and are available even when there is no selection. // // Some actions are in both, so that they are available for valid selections, but not available // for invalid selections (eg, print/find are disabled when there is no selection) KActionCollection *actionCollection = m_xmlGuiClient->actionCollection(); // Actions for a single item selection. entryActions.insert(actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Find)))); entryActions.insert(actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Print)))); entryActions.insert(actionCollection->action(QLatin1String("rename_entry"))); entryActions.insert(actionCollection->action(QLatin1String("change_color"))); entryActions.insert(actionCollection->action(QLatin1String("save_to"))); entryActions.insert(actionCollection->action(QLatin1String("copy_link_address"))); // Actions that are used only when a page is selected. pageActions.insert(actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Cut)))); pageActions.insert(actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Paste)))); pageActions.insert(actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Replace)))); pageActions.insert(actionCollection->action(QLatin1String("del_page"))); pageActions.insert(actionCollection->action(QLatin1String("insert_date"))); pageActions.insert(actionCollection->action(QLatin1String("auto_bullet"))); pageActions.insert(actionCollection->action(QLatin1String("auto_decimal"))); pageActions.insert(actionCollection->action(QLatin1String("manage_link"))); pageActions.insert(actionCollection->action(QLatin1String("insert_checkmark"))); // Actions that are used only when a book is selected. bookActions.insert(actionCollection->action(QLatin1String("save_to_book"))); bookActions.insert(actionCollection->action(QLatin1String("del_folder"))); bookActions.insert(actionCollection->action(QLatin1String("sort_children_alpha"))); bookActions.insert(actionCollection->action(QLatin1String("sort_children_by_date"))); // Actions that are used when multiple items are selected. multiselectionActions.insert(actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Find)))); multiselectionActions.insert(actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Print)))); multiselectionActions.insert(actionCollection->action(QLatin1String("del_mult"))); multiselectionActions.insert(actionCollection->action(QLatin1String("save_to"))); multiselectionActions.insert(actionCollection->action(QLatin1String("change_color"))); m_autosaveTimer = new QTimer(this); updateConfiguration(); connect(m_autosaveTimer, &QTimer::timeout, editor, &KJotsEdit::savePage); - connect(treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), m_autosaveTimer, SLOT(start())); + connect(treeview->selectionModel(), &QItemSelectionModel::selectionChanged, m_autosaveTimer, qOverload<>(&QTimer::start)); treeview->delayedInitialization(); editor->delayedInitialization(m_xmlGuiClient->actionCollection()); browser->delayedInitialization(); - connect(treeview->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)), - SLOT(bookshelfEditItemFinished(QWidget*,QAbstractItemDelegate::EndEditHint))); + connect(treeview->itemDelegate(), &QItemDelegate::closeEditor, this, &KJotsWidget::bookshelfEditItemFinished); - connect(editor, SIGNAL(currentCharFormatChanged(QTextCharFormat)), - SLOT(currentCharFormatChanged(QTextCharFormat))); + connect(editor, &KJotsEdit::currentCharFormatChanged, this, &KJotsWidget::currentCharFormatChanged); updateMenu(); } void KJotsWidget::bookshelfEditItemFinished(QWidget *, QAbstractItemDelegate::EndEditHint) { // Make sure the editor gets focus again after naming a new book/page. activeEditor()->setFocus(); } void KJotsWidget::currentCharFormatChanged(const QTextCharFormat &fmt) { QString selectedAnchor = fmt.anchorHref(); if (selectedAnchor != activeAnchor) { activeAnchor = selectedAnchor; if (!selectedAnchor.isEmpty()) { QTextCursor c(editor->textCursor()); editor->selectLinkText(&c); QString selectedText = c.selectedText(); if (!selectedText.isEmpty()) { Q_EMIT activeAnchorChanged(selectedAnchor, selectedText); } } else { Q_EMIT activeAnchorChanged(QString(), QString()); } } } inline QTextEdit *KJotsWidget::activeEditor() { if (browser->isVisible()) { return browser; } else { return editor; } } void KJotsWidget::updateMenu() { QModelIndexList selection = treeview->selectionModel()->selectedRows(); int selectionSize = selection.size(); if (!selectionSize) { // no (meaningful?) selection for (QAction *action : qAsConst(multiselectionActions)) { action->setEnabled(false); } for (QAction *action : qAsConst(entryActions)) { action->setEnabled(false); } for (QAction *action : qAsConst(bookActions)) { action->setEnabled(false); } for (QAction *action : qAsConst(pageActions)) { action->setEnabled(false); } editor->setActionsEnabled(false); } else if (selectionSize > 1) { for (QAction *action : qAsConst(entryActions)) { action->setEnabled(false); } for (QAction *action : qAsConst(bookActions)) { action->setEnabled(false); } for (QAction *action : qAsConst(pageActions)) { action->setEnabled(false); } for (QAction *action : qAsConst(multiselectionActions)) { action->setEnabled(true); } editor->setActionsEnabled(false); } else { for (QAction *action : qAsConst(multiselectionActions)) { action->setEnabled(false); } for (QAction *action : qAsConst(entryActions)) { action->setEnabled(true); } QModelIndex idx = selection.at(0); Collection col = idx.data(KJotsModel::CollectionRole).value(); if (col.isValid()) { for (QAction *action : qAsConst(pageActions)) { action->setEnabled(false); } const bool colIsRootCollection = (col.parentCollection() == Collection::root()); for (QAction *action : qAsConst(bookActions)) { if (action->objectName() == QLatin1String("del_folder") && colIsRootCollection) { action->setEnabled(false); } else { action->setEnabled(true); } } editor->setActionsEnabled(false); } else { for (QAction *action : qAsConst(pageActions)) { if (action->objectName() == QLatin1String(name(KStandardAction::Cut))) { action->setEnabled(activeEditor()->textCursor().hasSelection()); } else { action->setEnabled(true); } } for (QAction *action : qAsConst(bookActions)) { action->setEnabled(false); } editor->setActionsEnabled(true); } } } void KJotsWidget::copy() { activeEditor()->copy(); } void KJotsWidget::configure() { // create a new preferences dialog... KJotsConfigDlg *dialog = new KJotsConfigDlg(i18n("Settings"), this); - connect(dialog, SIGNAL(configCommitted()), SLOT(updateConfiguration())); + connect(dialog, qOverload<>(&KJotsConfigDlg::configCommitted), this, &KJotsWidget::updateConfiguration); dialog->show(); } void KJotsWidget::updateConfiguration() { if (KJotsSettings::autoSave()) { m_autosaveTimer->setInterval(KJotsSettings::autoSaveInterval() * 1000 * 60); m_autosaveTimer->start(); } else { m_autosaveTimer->stop(); } } void KJotsWidget::copySelectionToTitle() { QString newTitle(editor->textCursor().selectedText()); if (!newTitle.isEmpty()) { QModelIndexList rows = treeview->selectionModel()->selectedRows(); if (rows.size() != 1) { return; } QModelIndex idx = rows.at(0); treeview->model()->setData(idx, newTitle); } } void KJotsWidget::deleteMultiple() { const QModelIndexList selectedRows = treeview->selectionModel()->selectedRows(); if (KMessageBox::questionYesNo(this, i18n("Do you really want to delete all selected books and pages?"), i18n("Delete?"), KStandardGuiItem::del(), KStandardGuiItem::cancel(), QString(), KMessageBox::Dangerous) != KMessageBox::Yes) { return; } for (const QModelIndex &index : selectedRows) { bool ok; qlonglong id = index.data(EntityTreeModel::ItemIdRole).toLongLong(&ok); Q_ASSERT(ok); if (id >= 0) { new ItemDeleteJob(Item(id), this); } else { id = index.data(EntityTreeModel::CollectionIdRole).toLongLong(&ok); Q_ASSERT(ok); if (id >= 0) { new CollectionDeleteJob(Collection(id), this); } } } } void KJotsWidget::deletePage() { QModelIndexList selectedRows = treeview->selectionModel()->selectedRows(); if (selectedRows.size() != 1) { return; } const QModelIndex idx = selectedRows.at(0); Item item = idx.data(EntityTreeModel::ItemRole).value(); if (!item.isValid()) { return; } if (item.hasAttribute()) { KMessageBox::information(topLevelWidget(), i18n("This page is locked. You can only delete it when you first unlock it."), i18n("Item is locked")); return; } if (KMessageBox::warningContinueCancel(topLevelWidget(), i18nc("remove the page, by title", "Are you sure you want to delete the page %1?", idx.data().toString()), i18n("Delete"), KStandardGuiItem::del(), KStandardGuiItem::cancel(), QLatin1String("DeletePageWarning")) == KMessageBox::Cancel) { return; } (void) new Akonadi::ItemDeleteJob(item, this); } void KJotsWidget::deleteBook() { QModelIndexList selectedRows = treeview->selectionModel()->selectedRows(); if (selectedRows.size() != 1) { return; } const QModelIndex idx = selectedRows.at(0); Collection col = idx.data(EntityTreeModel::CollectionRole).value(); if (!col.isValid()) { return; } if (col.parentCollection() == Collection::root()) { return; } if (col.hasAttribute()) { KMessageBox::information(topLevelWidget(), i18n("This book is locked. You can only delete it when you first unlock it."), i18n("Item is locked")); return; } if (KMessageBox::warningContinueCancel(topLevelWidget(), i18nc("remove the book, by title", "Are you sure you want to delete the book %1?", idx.data().toString()), i18n("Delete"), KStandardGuiItem::del(), KStandardGuiItem::cancel(), QLatin1String("DeleteBookWarning")) == KMessageBox::Cancel) { return; } (void) new Akonadi::CollectionDeleteJob(col, this); } void KJotsWidget::newBook() { QModelIndexList selectedRows = treeview->selectionModel()->selectedRows(); if (selectedRows.size() != 1) { return; } Collection col = selectedRows.at(0).data(EntityTreeModel::CollectionRole).value(); if (!col.isValid()) { return; } Collection newCollection; newCollection.setParentCollection(col); QString title = i18nc("The default name for new books.", "New Book"); newCollection.setName(KRandom::randomString(10)); newCollection.setContentMimeTypes({Akonadi::Collection::mimeType(), Akonadi::NoteUtils::noteMimeType()}); Akonadi::EntityDisplayAttribute *eda = new Akonadi::EntityDisplayAttribute(); eda->setIconName(QLatin1String("x-office-address-book")); eda->setDisplayName(title); newCollection.addAttribute(eda); Akonadi::CollectionCreateJob *job = new Akonadi::CollectionCreateJob(newCollection); connect(job, &Akonadi::CollectionCreateJob::result, this, &KJotsWidget::newBookResult); } void KJotsWidget::newPage() { QModelIndexList selectedRows = treeview->selectionModel()->selectedRows(); if (selectedRows.size() != 1) { return; } Item item = selectedRows.at(0).data(EntityTreeModel::ItemRole).value(); Collection col; if (item.isValid()) { col = selectedRows.at(0).data(EntityTreeModel::ParentCollectionRole).value(); } else { col = selectedRows.at(0).data(EntityTreeModel::CollectionRole).value(); } if (!col.isValid()) { return; } doCreateNewPage(col); } void KJotsWidget::doCreateNewPage(const Collection &collection) { Akonotes::NoteCreatorAndSelector *creatorAndSelector = new Akonotes::NoteCreatorAndSelector(treeview->selectionModel()); creatorAndSelector->createNote(collection); } void KJotsWidget::newPageResult(KJob *job) { if (job->error()) { qDebug() << job->errorString(); } } void KJotsWidget::newBookResult(KJob *job) { if (job->error()) { qDebug() << job->errorString(); return; } Akonadi::CollectionCreateJob *createJob = qobject_cast(job); if (!createJob) { return; } const Collection collection = createJob->collection(); if (!collection.isValid()) { return; } doCreateNewPage(collection); } QString KJotsWidget::renderSelectionToHtml() { QHash hash; QList objectList; const int rows = selProxy->rowCount(); const int column = 0; for (int row = 0; row < rows; ++row) { QModelIndex idx = selProxy->index(row, column, QModelIndex()); QObject *obj = idx.data(KJotsModel::GrantleeObjectRole).value(); KJotsEntity *kjotsEntity = qobject_cast(obj); kjotsEntity->setIndex(idx); objectList << QVariant::fromValue(static_cast(kjotsEntity)); } hash.insert(QLatin1String("entities"), objectList); hash.insert(QLatin1String("i18n_TABLE_OF_CONTENTS"), i18nc("Header for 'Table of contents' section of rendered output", "Table of contents")); Context c(hash); Template t = m_templateEngine->loadByName(QLatin1String("template.html")); QString result = t->render(&c); // TODO: handle errors. return result; } QString KJotsWidget::renderSelectionToPlainText() { QHash hash; QList objectList; const int rows = selProxy->rowCount(); const int column = 0; for (int row = 0; row < rows; ++row) { QModelIndex idx = selProxy->index(row, column, QModelIndex()); QObject *obj = idx.data(KJotsModel::GrantleeObjectRole).value(); KJotsEntity *kjotsEntity = qobject_cast(obj); kjotsEntity->setIndex(idx); objectList << QVariant::fromValue(static_cast(kjotsEntity)); } hash.insert(QLatin1String("entities"), objectList); hash.insert(QLatin1String("i18n_TABLE_OF_CONTENTS"), i18nc("Header for 'Table of contents' section of rendered output", "Table of contents")); Context c(hash); Template t = m_templateEngine->loadByName(QLatin1String("template.txt")); QString result = t->render(&c); // TODO: handle errors. return result; } QString KJotsWidget::renderSelectionToXml() { QHash hash; QList objectList; const int rows = selProxy->rowCount(); const int column = 0; for (int row = 0; row < rows; ++row) { QModelIndex idx = selProxy->index(row, column, QModelIndex()); QObject *obj = idx.data(KJotsModel::GrantleeObjectRole).value(); KJotsEntity *kjotsEntity = qobject_cast(obj); kjotsEntity->setIndex(idx); objectList << QVariant::fromValue(static_cast(kjotsEntity)); } hash.insert(QLatin1String("entities"), objectList); Context c(hash); QString currentTheme = m_loader->themeName(); m_loader->setTheme(QLatin1String("xml_output")); Template t = m_templateEngine->loadByName(QLatin1String("template.xml")); QString result = t->render(&c); m_loader->setTheme(currentTheme); return result; } QString KJotsWidget::getThemeFromUser() { return QString(); #if 0 bool ok; QString text = QInputDialog::getText(this, i18n("Change Theme"), tr("Theme name:"), QLineEdit::Normal, m_loader->themeName(), &ok); if (!ok || text.isEmpty()) { return QLatin1String("default"); } return text; #endif } void KJotsWidget::changeTheme() { #if 0 m_loader->setTheme(getThemeFromUser()); renderSelection(); #endif } void KJotsWidget::exportSelectionToHtml() { QString currentTheme = m_loader->themeName(); QString themeName = getThemeFromUser(); if (themeName.isEmpty()) { themeName = QLatin1String("default"); } m_loader->setTheme(themeName); QString filename = QFileDialog::getSaveFileName(); if (!filename.isEmpty()) { QFile exportFile(filename); if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) { m_loader->setTheme(currentTheme); KMessageBox::error(nullptr, i18n("Error opening internal file.")); return; } exportFile.write(renderSelectionToHtml().toUtf8()); exportFile.close(); } m_loader->setTheme(currentTheme); } void KJotsWidget::exportSelectionToPlainText() { QString currentTheme = m_loader->themeName(); m_loader->setTheme(QLatin1String("plain_text")); QString filename = QFileDialog::getSaveFileName(); if (!filename.isEmpty()) { QFile exportFile(filename); if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) { m_loader->setTheme(currentTheme); KMessageBox::error(nullptr, i18n("Error opening internal file.")); return; } exportFile.write(renderSelectionToPlainText().toUtf8()); exportFile.close(); } m_loader->setTheme(currentTheme); } void KJotsWidget::exportSelectionToXml() { QString currentTheme = m_loader->themeName(); m_loader->setTheme(QLatin1String("xml_output")); QString filename = QFileDialog::getSaveFileName(); if (!filename.isEmpty()) { QFile exportFile(filename); if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) { m_loader->setTheme(currentTheme); KMessageBox::error(nullptr, i18n("Error opening internal file.")); return; } exportFile.write(renderSelectionToXml().toUtf8()); exportFile.close(); } m_loader->setTheme(currentTheme); } std::unique_ptr KJotsWidget::setupPrinter(QPrinter::PrinterMode mode) { auto printer = std::make_unique(mode); printer->setDocName(QStringLiteral("KJots_Print")); printer->setCreator(QStringLiteral("KJots")); if (!activeEditor()->textCursor().selection().isEmpty()) { printer->setPrintRange(QPrinter::Selection); } return printer; } void KJotsWidget::printPreviewSelection() { auto printer = setupPrinter(QPrinter::ScreenResolution); QPrintPreviewDialog previewdlg(printer.get(), this); connect(&previewdlg, &QPrintPreviewDialog::paintRequested, this, &KJotsWidget::print); previewdlg.exec(); } void KJotsWidget::printSelection() { auto printer = setupPrinter(QPrinter::HighResolution); QPrintDialog printDialog(printer.get(), this); if (printDialog.exec() == QDialog::Accepted) { print(printer.get()); } } void KJotsWidget::print(QPrinter *printer) { QTextDocument printDocument; if (printer->printRange() == QPrinter::Selection) { printDocument.setHtml(activeEditor()->textCursor().selection().toHtml()); } else { QString currentTheme = m_loader->themeName(); m_loader->setTheme(QLatin1String("default")); printDocument.setHtml(renderSelectionToHtml()); m_loader->setTheme(currentTheme); } printDocument.print(printer); } void KJotsWidget::selectNext(int role, int step) { QModelIndexList list = treeview->selectionModel()->selectedRows(); Q_ASSERT(list.size() == 1); QModelIndex idx = list.at(0); const int column = idx.column(); QModelIndex sibling = idx.sibling(idx.row() + step, column); while (sibling.isValid()) { if (sibling.data(role).toInt() >= 0) { treeview->selectionModel()->select(sibling, QItemSelectionModel::SelectCurrent); return; } sibling = sibling.sibling(sibling.row() + step, column); } qWarning() << "No valid selection"; } void KJotsWidget::nextBook() { return selectNext(EntityTreeModel::CollectionIdRole, 1); } void KJotsWidget::nextPage() { return selectNext(EntityTreeModel::ItemIdRole, 1); } void KJotsWidget::prevBook() { return selectNext(EntityTreeModel::CollectionIdRole, -1); } void KJotsWidget::prevPage() { return selectNext(EntityTreeModel::ItemIdRole, -1); } bool KJotsWidget::canGo(int role, int step) const { QModelIndexList list = treeview->selectionModel()->selectedRows(); if (list.size() != 1) { return false; } QModelIndex currentIdx = list.at(0); const int column = currentIdx.column(); Q_ASSERT(currentIdx.isValid()); QModelIndex sibling = currentIdx.sibling(currentIdx.row() + step, column); while (sibling.isValid() && sibling != currentIdx) { if (sibling.data(role).toInt() >= 0) { return true; } sibling = sibling.sibling(sibling.row() + step, column); } return false; } bool KJotsWidget::canGoNextPage() const { return canGo(EntityTreeModel::ItemIdRole, 1); } bool KJotsWidget::canGoPreviousPage() const { return canGo(EntityTreeModel::ItemIdRole, -1); } bool KJotsWidget::canGoNextBook() const { return canGo(EntityTreeModel::CollectionIdRole, 1); } bool KJotsWidget::canGoPreviousBook() const { return canGo(EntityTreeModel::CollectionIdRole, -1); } void KJotsWidget::renderSelection() { Q_EMIT canGoNextBookChanged(canGoPreviousBook()); Q_EMIT canGoNextPageChanged(canGoNextPage()); Q_EMIT canGoPreviousBookChanged(canGoPreviousBook()); Q_EMIT canGoPreviousPageChanged(canGoPreviousPage()); const int rows = selProxy->rowCount(); // If the selection is a single page, present it for editing... if (rows == 1) { QModelIndex idx = selProxy->index(0, 0, QModelIndex()); if (editor->setModelIndex(selProxy->mapToSource(idx))) { stackedWidget->setCurrentWidget(editor); return; } // If something went wrong, we show user the browser } // ... Otherwise, render the selection read-only. browser->setHtml(renderSelectionToHtml()); stackedWidget->setCurrentWidget(browser); } /*! Shows the search dialog when "Find" is selected. */ void KJotsWidget::onShowSearch() { onUpdateSearch(); QTextEdit *browserOrEditor = activeEditor(); if (browserOrEditor->textCursor().hasSelection()) { searchDialog->setHasSelection(true); long dialogOptions = searchDialog->options(); dialogOptions |= KFind::SelectedText; searchDialog->setOptions(dialogOptions); } else { searchDialog->setHasSelection(false); } searchDialog->setFindHistory(searchHistory); searchDialog->show(); onUpdateSearch(); } /*! Updates the search dialog if the user is switching selections while it is open. */ void KJotsWidget::onUpdateSearch() { if (searchDialog->isVisible()) { long searchOptions = searchDialog->options(); if (searchOptions & KFind::SelectedText) { searchAllPages->setCheckState(Qt::Unchecked); searchAllPages->setEnabled(false); } else { searchAllPages->setEnabled(true); } if (searchAllPages->checkState() == Qt::Checked) { searchOptions &= ~KFind::SelectedText; searchDialog->setOptions(searchOptions); searchDialog->setHasSelection(false); } else { if (activeEditor()->textCursor().hasSelection()) { searchDialog->setHasSelection(true); } } if (activeEditor()->textCursor().hasSelection()) { if (searchAllPages->checkState() == Qt::Unchecked) { searchDialog->setHasSelection(true); } } else { searchOptions &= ~KFind::SelectedText; searchDialog->setOptions(searchOptions); searchDialog->setHasSelection(false); } } } /*! Called when the user presses OK in the search dialog. */ void KJotsWidget::onStartSearch() { QString searchPattern = searchDialog->pattern(); if (!searchHistory.contains(searchPattern)) { searchHistory.prepend(searchPattern); } QTextEdit *browserOrEditor = activeEditor(); QTextCursor cursor = browserOrEditor->textCursor(); long searchOptions = searchDialog->options(); if (searchOptions & KFind::FromCursor) { searchPos = cursor.position(); searchBeginPos = 0; cursor.movePosition(QTextCursor::End); searchEndPos = cursor.position(); } else { if (searchOptions & KFind::SelectedText) { searchBeginPos = cursor.selectionStart(); searchEndPos = cursor.selectionEnd(); } else { searchBeginPos = 0; cursor.movePosition(QTextCursor::End); searchEndPos = cursor.position(); } if (searchOptions & KFind::FindBackwards) { searchPos = searchEndPos; } else { searchPos = searchBeginPos; } } m_xmlGuiClient->actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::FindNext)))->setEnabled(true); onRepeatSearch(); } /*! Called when user chooses "Find Next" */ void KJotsWidget::onRepeatSearch() { if (search(false) == 0) { KMessageBox::sorry(nullptr, i18n("No matches found.")); m_xmlGuiClient->actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::FindNext)))->setEnabled(false); } } /*! Called when user presses Cancel in find dialog. */ void KJotsWidget::onEndSearch() { m_xmlGuiClient->actionCollection()->action(QLatin1String(KStandardAction::name(KStandardAction::FindNext)))->setEnabled(false); } /*! Shows the replace dialog when "Replace" is selected. */ void KJotsWidget::onShowReplace() { Q_ASSERT(editor->isVisible()); if (editor->textCursor().hasSelection()) { replaceDialog->setHasSelection(true); long dialogOptions = replaceDialog->options(); dialogOptions |= KFind::SelectedText; replaceDialog->setOptions(dialogOptions); } else { replaceDialog->setHasSelection(false); } replaceDialog->setFindHistory(searchHistory); replaceDialog->setReplacementHistory(replaceHistory); replaceDialog->show(); onUpdateReplace(); } /*! Updates the replace dialog if the user is switching selections while it is open. */ void KJotsWidget::onUpdateReplace() { if (replaceDialog->isVisible()) { long replaceOptions = replaceDialog->options(); if (replaceOptions & KFind::SelectedText) { replaceAllPages->setCheckState(Qt::Unchecked); replaceAllPages->setEnabled(false); } else { replaceAllPages->setEnabled(true); } if (replaceAllPages->checkState() == Qt::Checked) { replaceOptions &= ~KFind::SelectedText; replaceDialog->setOptions(replaceOptions); replaceDialog->setHasSelection(false); } else { if (activeEditor()->textCursor().hasSelection()) { replaceDialog->setHasSelection(true); } } } } /*! Called when the user presses OK in the replace dialog. */ void KJotsWidget::onStartReplace() { QString searchPattern = replaceDialog->pattern(); if (!searchHistory.contains(searchPattern)) { searchHistory.prepend(searchPattern); } QString replacePattern = replaceDialog->replacement(); if (!replaceHistory.contains(replacePattern)) { replaceHistory.prepend(replacePattern); } QTextCursor cursor = editor->textCursor(); long replaceOptions = replaceDialog->options(); if (replaceOptions & KFind::FromCursor) { replacePos = cursor.position(); replaceBeginPos = 0; cursor.movePosition(QTextCursor::End); replaceEndPos = cursor.position(); } else { if (replaceOptions & KFind::SelectedText) { replaceBeginPos = cursor.selectionStart(); replaceEndPos = cursor.selectionEnd(); } else { replaceBeginPos = 0; cursor.movePosition(QTextCursor::End); replaceEndPos = cursor.position(); } if (replaceOptions & KFind::FindBackwards) { replacePos = replaceEndPos; } else { replacePos = replaceBeginPos; } } replaceStartPage = treeview->selectionModel()->selectedRows().first(); //allow KReplaceDialog to exit so the user can see. - QTimer::singleShot(0, this, SLOT(onRepeatReplace())); + QTimer::singleShot(0, this, &KJotsWidget::onRepeatReplace); } /*! Only called after onStartReplace. Kept the name scheme for consistancy. */ void KJotsWidget::onRepeatReplace() { KJotsReplaceNextDialog *dlg = nullptr; QString searchPattern = replaceDialog->pattern(); QString replacePattern = replaceDialog->replacement(); int found = 0; int replaced = 0; long replaceOptions = replaceDialog->options(); if (replaceOptions & KReplaceDialog::PromptOnReplace) { dlg = new KJotsReplaceNextDialog(this); } while (true) { if (!search(true)) { break; } QTextCursor cursor = editor->textCursor(); if (!cursor.hasSelection()) { break; } else { ++found; } QString replacementText = replacePattern; if (replaceOptions & KReplaceDialog::BackReference) { QRegExp regExp(searchPattern, (replaceOptions & Qt::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::RegExp2); regExp.indexIn(cursor.selectedText()); int capCount = regExp.captureCount(); for (int i = 0; i <= capCount; ++i) { QString c = QString::fromLatin1("\\%1").arg(i); replacementText.replace(c, regExp.cap(i)); } } if (replaceOptions & KReplaceDialog::PromptOnReplace) { dlg->setLabel(cursor.selectedText(), replacementText); if (!dlg->exec()) { break; } if (dlg->answer() != KJotsReplaceNextDialog::Skip) { cursor.insertText(replacementText); editor->setTextCursor(cursor); ++replaced; } if (dlg->answer() == KJotsReplaceNextDialog::All) { replaceOptions |= ~KReplaceDialog::PromptOnReplace; } } else { cursor.insertText(replacementText); editor->setTextCursor(cursor); ++replaced; } } if (replaced == found) { KMessageBox::information(nullptr, i18np("Replaced 1 occurrence.", "Replaced %1 occurrences.", replaced)); } else if (replaced < found) { KMessageBox::information(nullptr, i18np("Replaced %2 of 1 occurrence.", "Replaced %2 of %1 occurrences.", found, replaced)); } if (dlg) { delete dlg; } } /*! Called when user presses Cancel in replace dialog. Just a placeholder for now. */ void KJotsWidget::onEndReplace() { } /*! Searches for the given pattern, with the given options. This is huge and unwieldly function, but the operation we're performing is huge and unwieldly. */ int KJotsWidget::search(bool replacing) { int rc = 0; int *beginPos = replacing ? &replaceBeginPos : &searchBeginPos; int *endPos = replacing ? &replaceEndPos : &searchEndPos; long options = replacing ? replaceDialog->options() : searchDialog->options(); QString pattern = replacing ? replaceDialog->pattern() : searchDialog->pattern(); int *curPos = replacing ? &replacePos : &searchPos; QModelIndex startPage = replacing ? replaceStartPage : treeview->selectionModel()->selectedRows().first(); bool allPages = false; QCheckBox *box = replacing ? replaceAllPages : searchAllPages; if (box->isEnabled() && box->checkState() == Qt::Checked) { allPages = true; } QTextDocument::FindFlags findFlags; if (options & Qt::CaseSensitive) { findFlags |= QTextDocument::FindCaseSensitively; } if (options & KFind::WholeWordsOnly) { findFlags |= QTextDocument::FindWholeWords; } if (options & KFind::FindBackwards) { findFlags |= QTextDocument::FindBackward; } // We will find a match or return 0 int attempts = 0; while (true) { ++attempts; QTextEdit *browserOrEditor = activeEditor(); QTextDocument *theDoc = browserOrEditor->document(); QTextCursor cursor; if (options & KFind::RegularExpression) { QRegExp regExp(pattern, (options & Qt::CaseSensitive) ? Qt::CaseSensitive : Qt::CaseInsensitive, QRegExp::RegExp2); cursor = theDoc->find(regExp, *curPos, findFlags); } else { cursor = theDoc->find(pattern, *curPos, findFlags); } if (cursor.hasSelection()) { if (cursor.selectionStart() >= *beginPos && cursor.selectionEnd() <= *endPos) { browserOrEditor->setTextCursor(cursor); browserOrEditor->ensureCursorVisible(); *curPos = (options & KFind::FindBackwards) ? cursor.selectionStart() : cursor.selectionEnd(); rc = 1; break; } } //No match. Determine what to do next. if (replacing && !(options & KFind::FromCursor) && !allPages) { break; } if ((options & KFind::FromCursor) && !allPages) { if (KMessageBox::questionYesNo(this, i18n("End of search area reached. Do you want to wrap around and continue?")) == KMessageBox::No) { rc = 3; break; } } if (allPages) { if (options & KFind::FindBackwards) { if (canGoPreviousPage()) { prevPage(); } } else { if (canGoNextPage()) { nextPage(); } } if (startPage == treeview->selectionModel()->selectedRows().first()) { rc = 0; break; } *beginPos = 0; cursor = editor->textCursor(); cursor.movePosition(QTextCursor::End); *endPos = cursor.position(); *curPos = (options & KFind::FindBackwards) ? *endPos : *beginPos; continue; } // By now, we should have figured out what to do. In all remaining cases we // will automatically loop and try to "find next" from the top/bottom, because // I like this behavior the best. if (attempts <= 1) { *curPos = (options & KFind::FindBackwards) ? *endPos : *beginPos; } else { // We've already tried the loop and failed to find anything. Bail. rc = 0; break; } } return rc; } void KJotsWidget::updateCaption() { Q_EMIT captionChanged(treeview->captionForSelection(QLatin1String(" / "))); } void KJotsWidget::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight) { QModelIndexList rows = treeview->selectionModel()->selectedRows(); if (rows.size() != 1) { return; } QItemSelection changed(topLeft, bottomRight); if (changed.contains(rows.first())) { Q_EMIT captionChanged(treeview->captionForSelection(QLatin1String(" / "))); } } bool KJotsWidget::queryClose() { KJotsSettings::setSplitterSizes(m_splitter->sizes()); KJotsSettings::self()->save(); m_orderProxy->saveOrder(); return true; } void KJotsWidget::actionLock() { const QModelIndexList selection = treeview->selectionModel()->selectedRows(); if (selection.isEmpty()) { return; } Collection::List collections; Item::List items; for (const QModelIndex &idx : selection) { Collection col = idx.data(EntityTreeModel::CollectionRole).value(); if (col.isValid()) { collections << col; } else { Item item = idx.data(EntityTreeModel::ItemRole).value(); if (item.isValid()) { items << item; } } } if (collections.isEmpty() && items.isEmpty()) { return; } new KJotsLockJob(collections, items, this); } void KJotsWidget::actionUnlock() { const QModelIndexList selection = treeview->selectionModel()->selectedRows(); if (selection.isEmpty()) { return; } Collection::List collections; Item::List items; for (const QModelIndex &idx : selection) { Collection col = idx.data(EntityTreeModel::CollectionRole).value(); if (col.isValid()) { collections << col; } else { Item item = idx.data(EntityTreeModel::ItemRole).value(); if (item.isValid()) { items << item; } } } if (collections.isEmpty() && items.isEmpty()) { return; } new KJotsLockJob(collections, items, KJotsLockJob::UnlockJob, this); } void KJotsWidget::actionSortChildrenAlpha() { const QModelIndexList selection = treeview->selectionModel()->selectedRows(); for (const QModelIndex &index : selection) { const QPersistentModelIndex persistent(index); m_sortProxyModel->sortChildrenAlphabetically(m_orderProxy->mapToSource(index)); m_orderProxy->clearOrder(persistent); } } void KJotsWidget::actionSortChildrenByDate() { const QModelIndexList selection = treeview->selectionModel()->selectedRows(); for (const QModelIndex &index : selection) { const QPersistentModelIndex persistent(index); m_sortProxyModel->sortChildrenByCreationTime(m_orderProxy->mapToSource(index)); m_orderProxy->clearOrder(persistent); } } void KJotsWidget::openLink(const QUrl &url) { if (url.scheme() == QStringLiteral("akonadi")) { treeview->selectionModel()->select(KJotsModel::modelIndexForUrl(treeview->model(), url), QItemSelectionModel::ClearAndSelect); } else { new KRun(url, this); } } diff --git a/src/kjotswidget.h b/src/kjotswidget.h index ff09fbd..dde2464 100644 --- a/src/kjotswidget.h +++ b/src/kjotswidget.h @@ -1,212 +1,213 @@ /* This file is part of KJots. Copyright (C) 1997 Christoph Neerfeld Copyright (C) 2002, 2003 Aaron J. Seigo Copyright (C) 2003 Stanislav Kljuhhin Copyright (C) 2005-2006 Jaison Lee Copyright (C) 2007-2009 Stephen Kelly This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KJOTSWIDGET_H #define KJOTSWIDGET_H #include #include #include #include #include #include class QCheckBox; class QTextEdit; class QTextCharFormat; class QSplitter; class QStackedWidget; class QModelIndex; class KActionMenu; class KFindDialog; class KJob; class KReplaceDialog; class KSelectionProxyModel; class KJotsBrowser; class KXMLGUIClient; namespace Akonadi { class EntityTreeModel; class EntityOrderProxyModel; } namespace Grantlee { class Engine; } class KJotsEdit; class KJotsTreeView; class KJotsSortProxyModel; class KJotsWidget : public QWidget { Q_OBJECT Q_CLASSINFO("D-Bus Interface", "org.kde.KJotsWidget") public: explicit KJotsWidget(QWidget *parent, KXMLGUIClient *xmlGuiclient, Qt::WindowFlags f = 0); ~KJotsWidget(); QTextEdit *activeEditor(); public Q_SLOTS: + void configure(); void prevPage(); void nextPage(); void prevBook(); void nextBook(); - bool canGoNextPage() const; - bool canGoPreviousPage() const; - bool canGoNextBook() const; - bool canGoPreviousBook() const; void updateCaption(); void updateMenu(); void doCreateNewPage(const Akonadi::Collection &collection); Q_SCRIPTABLE void newPage(); Q_SCRIPTABLE void newBook(); Q_SCRIPTABLE bool queryClose(); Q_SIGNALS: void canGoNextPageChanged(bool); void canGoPreviousPageChanged(bool); void canGoNextBookChanged(bool); void canGoPreviousBookChanged(bool); void captionChanged(const QString &newCaption); /** Signals that the text cursor in the editor is now on a different anchor, or not on an anchor anymore. @param anchorTarget The href of the focused anchor. @param anchorText The display text of the focused anchor. */ void activeAnchorChanged(const QString &anchorTarget, const QString &anchorText); protected: + bool canGo(int role, int step) const; + bool canGoNextPage() const; + bool canGoPreviousPage() const; + bool canGoNextBook() const; + bool canGoPreviousBook() const; + QString renderSelectionToHtml(); QString renderSelectionToXml(); QString renderSelectionToPlainText(); QString getThemeFromUser(); void selectNext(int role, int step); int search(bool); std::unique_ptr setupPrinter(QPrinter::PrinterMode mode = QPrinter::ScreenResolution); protected Q_SLOTS: /** * Renders contents on either KJotsEdit or KJotsBrowser based on KJotsTreeView selection */ void renderSelection(); void changeTheme(); void exportSelectionToHtml(); void exportSelectionToPlainText(); void exportSelectionToXml(); void printSelection(); void printPreviewSelection(); void deletePage(); void deleteBook(); void deleteMultiple(); void openLink(const QUrl &url); private Q_SLOTS: void delayedInitialization(); void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); void bookshelfEditItemFinished(QWidget *, QAbstractItemDelegate::EndEditHint); - bool canGo(int role, int step) const; void newPageResult(KJob *job); void newBookResult(KJob *job); void copySelectionToTitle(); void copy(); - void configure(); void onShowSearch(); void onUpdateSearch(); void onStartSearch(); void onRepeatSearch(); void onEndSearch(); void onShowReplace(); void onUpdateReplace(); void onStartReplace(); void onRepeatReplace(); void onEndReplace(); void actionLock(); void actionUnlock(); void actionSortChildrenAlpha(); void actionSortChildrenByDate(); void saveState(); void restoreState(); void currentCharFormatChanged(const QTextCharFormat &); void updateConfiguration(); void print(QPrinter *printer); private: KXMLGUIClient *m_xmlGuiClient; KJotsEdit *editor; KJotsBrowser *browser; QStackedWidget *stackedWidget; KActionMenu *bookmarkMenu; Akonadi::EntityTreeModel *m_kjotsModel; KSelectionProxyModel *selProxy; KJotsSortProxyModel *m_sortProxyModel; Akonadi::EntityOrderProxyModel *m_orderProxy; KJotsTreeView *treeview; QSplitter *m_splitter; QTimer *m_autosaveTimer; QString activeAnchor; Grantlee::Engine *m_templateEngine; QSharedPointer m_loader; KFindDialog *searchDialog; QStringList searchHistory; int searchBeginPos, searchEndPos, searchPos; QCheckBox *searchAllPages; KReplaceDialog *replaceDialog; QStringList replaceHistory; int replaceBeginPos, replaceEndPos, replacePos; QCheckBox *replaceAllPages; QModelIndex replaceStartPage; QSet entryActions, pageActions, bookActions, multiselectionActions; }; #endif diff --git a/src/noteshared/localresourcecreator.cpp b/src/noteshared/localresourcecreator.cpp index a5314d4..51acfc1 100644 --- a/src/noteshared/localresourcecreator.cpp +++ b/src/noteshared/localresourcecreator.cpp @@ -1,121 +1,116 @@ /* Copyright (c) 2013-2015 Montel Laurent based on localresourcecreator from kjots This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "localresourcecreator.h" #include #include -#pragma message("port QT5") #include "maildirsettings.h" #include #include "noteshared_debug.h" #include #include using namespace NoteShared; LocalResourceCreator::LocalResourceCreator(QObject *parent) : QObject(parent) { } QString LocalResourceCreator::akonadiNotesInstanceName() { return QStringLiteral("akonadi_akonotes_resource"); } void LocalResourceCreator::createIfMissing() { const Akonadi::AgentInstance::List instances = Akonadi::AgentManager::self()->instances(); - bool found = false; - for (const Akonadi::AgentInstance &instance : instances) { - if (instance.type().identifier() == akonadiNotesInstanceName()) { - found = true; - break; - } - } + const bool found = std::any_of(instances.cbegin(), instances.cend(), [](const Akonadi::AgentInstance &instance) { + return instance.type().identifier() == akonadiNotesInstanceName(); + }); if (found) { deleteLater(); return; } createInstance(); } void LocalResourceCreator::createInstance() { Akonadi::AgentType notesType = Akonadi::AgentManager::self()->type(akonadiNotesInstanceName()); Akonadi::AgentInstanceCreateJob *job = new Akonadi::AgentInstanceCreateJob(notesType); connect(job, &Akonadi::AgentInstanceCreateJob::result, this, &LocalResourceCreator::slotInstanceCreated); job->start(); } void LocalResourceCreator::slotInstanceCreated(KJob *job) { if (job->error()) { qCWarning(NOTESHARED_LOG) << job->errorString(); deleteLater(); return; } Akonadi::AgentInstanceCreateJob *createJob = qobject_cast(job); Akonadi::AgentInstance instance = createJob->instance(); instance.setName(i18nc("Default name for resource holding notes", "Local Notes")); org::kde::Akonadi::Maildir::Settings *iface = new org::kde::Akonadi::Maildir::Settings( QLatin1String("org.freedesktop.Akonadi.Resource.") + instance.identifier(), QStringLiteral("/Settings"), QDBusConnection::sessionBus(), this); // TODO: Make errors user-visible. if (!iface->isValid()) { qCWarning(NOTESHARED_LOG) << "Failed to obtain D-Bus interface for remote configuration."; delete iface; deleteLater(); return; } delete iface; instance.reconfigure(); Akonadi::ResourceSynchronizationJob *syncJob = new Akonadi::ResourceSynchronizationJob(instance, this); connect(syncJob, &Akonadi::ResourceSynchronizationJob::result, this, &LocalResourceCreator::slotSyncDone); syncJob->start(); } void LocalResourceCreator::slotSyncDone(KJob *job) { if (job->error()) { qCWarning(NOTESHARED_LOG) << "Synchronizing the resource failed:" << job->errorString(); deleteLater(); return; } qCWarning(NOTESHARED_LOG) << "Instance synchronized"; } void LocalResourceCreator::finishCreateResource() { deleteLater(); } diff --git a/src/noteshared/noteeditorutils.cpp b/src/noteshared/noteeditorutils.cpp index 661bfa5..20e1e80 100644 --- a/src/noteshared/noteeditorutils.cpp +++ b/src/noteshared/noteeditorutils.cpp @@ -1,74 +1,74 @@ /* Copyright (c) 2013-2015 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "noteeditorutils.h" #include #include #include #include #include #include #include #include #include #include using namespace NoteShared; NoteEditorUtils::NoteEditorUtils() { } void NoteEditorUtils::addCheckmark(QTextCursor &cursor) { static const QChar unicode[] = {0x2713}; const int size = sizeof(unicode) / sizeof(QChar); const int position = cursor.position(); cursor.movePosition(QTextCursor::StartOfLine); const QString checkMark = QString::fromRawData(unicode, size); cursor.insertText(checkMark); cursor.setPosition(position + checkMark.size()); } void NoteEditorUtils::insertDate(QTextEdit *editor) { editor->insertPlainText(QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat) + QLatin1Char(' ')); } -void NoteEditorUtils::insertImage(QTextDocument *doc, QTextCursor &cursor, QTextEdit *par) +void NoteEditorUtils::insertImage(QTextDocument * /*doc*/, QTextCursor &/*cursor*/, QTextEdit *par) { QString imageFileName = QFileDialog::getOpenFileName(par, i18n("Select image file"), QLatin1String("."), QLatin1String("Images (*.png *.bmp *.jpg *.jpeg *.jpe)")); if (!imageFileName.isEmpty()) { QFileInfo qfio = QFileInfo(imageFileName); QImage imgRes(imageFileName); if (!imgRes.isNull()) { QMimeDatabase mimedb; QByteArray imageData; QBuffer buffer(&imageData); QMimeType filemime = mimedb.mimeTypeForFile(qfio); QString filetype = filemime.name(); QByteArray formatChars = filemime.preferredSuffix().toUpper().toLatin1(); buffer.open(QIODevice::WriteOnly); imgRes.save(&buffer, formatChars.data()); QString Base64Image = QString::fromLatin1(imageData.toBase64().data());//is null par->insertHtml(QLatin1String("")); } } }