diff --git a/src/KJotsMain.cpp b/src/KJotsMain.cpp index bd4d411..7f92007 100644 --- a/src/KJotsMain.cpp +++ b/src/KJotsMain.cpp @@ -1,70 +1,66 @@ /* 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 #include "KJotsSettings.h" #include "kjotsbookmarks.h" -#include "kjotsedit.h" #include "kjotsbrowser.h" +#include "kjotsedit.h" #include "kjotswidget.h" //---------------------------------------------------------------------- // KJOTSMAIN //---------------------------------------------------------------------- -KJotsMain::KJotsMain() +KJotsMain::KJotsMain(QWidget *parent) + : KXmlGuiWindow(parent) + , component(new KJotsWidget(this, this)) { - - // Main widget - // - KStandardAction::quit(this, &KJotsMain::onQuit, actionCollection()); - component = new KJotsWidget(this, this); - setCentralWidget(component); setupGUI(); connect(component, &KJotsWidget::captionChanged, this, qOverload(&KJotsMain::setCaption)); } bool KJotsMain::queryClose() { return component->queryClose(); } void KJotsMain::onQuit() { component->queryClose(); deleteLater(); qApp->quit(); } diff --git a/src/KJotsMain.h b/src/KJotsMain.h index 0e03b15..5c6f79c 100644 --- a/src/KJotsMain.h +++ b/src/KJotsMain.h @@ -1,51 +1,50 @@ /* 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. */ #ifndef KJOTSMAIN_H #define KJOTSMAIN_H #include class KJotsWidget; class KJotsMain : public KXmlGuiWindow { Q_OBJECT public: - explicit KJotsMain(); + explicit KJotsMain(QWidget *parent = nullptr); public Q_SLOTS: void onQuit(); protected: bool queryClose() override; private: KJotsWidget *component; - }; #endif // KJotsMainNew_included /* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/kjotsbookmarks.cpp b/src/kjotsbookmarks.cpp index 966ae3f..98c2a6a 100644 --- a/src/kjotsbookmarks.cpp +++ b/src/kjotsbookmarks.cpp @@ -1,79 +1,80 @@ /* kjotsbookmarks 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. */ #include "kjotsbookmarks.h" #include "kjotsmodel.h" #include -KJotsBookmarks::KJotsBookmarks(QItemSelectionModel *model) - : m_model(model) +KJotsBookmarks::KJotsBookmarks(QItemSelectionModel *model, QObject *parent) + : QObject(parent) + , m_model(model) { } -void KJotsBookmarks::openBookmark(const KBookmark &bookmark, Qt::MouseButtons, Qt::KeyboardModifiers) +void KJotsBookmarks::openBookmark(const KBookmark &bm, Qt::MouseButtons /*mb*/, Qt::KeyboardModifiers /*km*/) { - if (bookmark.url().scheme() != QLatin1String("akonadi")) { + if (bm.url().scheme() != QLatin1String("akonadi")) { return; } - Q_EMIT openLink(bookmark.url()); + Q_EMIT openLink(bm.url()); } QString KJotsBookmarks::currentIcon() const { const QModelIndexList rows = m_model->selectedRows(); if (rows.size() != 1) { return QString(); } const QModelIndex idx = rows.first(); const auto collection = idx.data(EntityTreeModel::CollectionRole).value(); if (collection.isValid()) { return QStringLiteral("x-office-address-book"); } const auto item = idx.data(EntityTreeModel::ItemRole).value(); if (item.isValid()) { return QStringLiteral("x-office-document"); } return QString(); } QUrl KJotsBookmarks::currentUrl() const { const QModelIndexList rows = m_model->selectedRows(); if (rows.size() != 1) { return QUrl(); } else { return rows.first().data(KJotsModel::EntityUrlRole).toUrl(); } } QString KJotsBookmarks::currentTitle() const { const QModelIndexList rows = m_model->selectedRows(); if (rows.size() != 1) { return QString(); } else { return KJotsModel::itemPath(rows.first(), QStringLiteral(": ")); } } diff --git a/src/kjotsbookmarks.h b/src/kjotsbookmarks.h index a1ea282..643b6b1 100644 --- a/src/kjotsbookmarks.h +++ b/src/kjotsbookmarks.h @@ -1,51 +1,51 @@ /* kjotsbookmarks 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 KJOTSBOOKMARKS #define KJOTSBOOKMARKS #include class QItemSelectionModel; class KJotsBookmarks : public QObject, public KBookmarkOwner { Q_OBJECT public: - explicit KJotsBookmarks(QItemSelectionModel *model); + explicit KJotsBookmarks(QItemSelectionModel *model, QObject *parent = nullptr); QUrl currentUrl() const override; QString currentIcon() const override; QString currentTitle() const override; void openBookmark(const KBookmark &bm, Qt::MouseButtons mb, Qt::KeyboardModifiers km) override; Q_SIGNALS: void openLink(const QUrl &url); private: QItemSelectionModel *m_model = nullptr; }; #endif /* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/kjotsbookshelfentryvalidator.cpp b/src/kjotsbookshelfentryvalidator.cpp index f0449f6..f62fb84 100644 --- a/src/kjotsbookshelfentryvalidator.cpp +++ b/src/kjotsbookshelfentryvalidator.cpp @@ -1,60 +1,60 @@ /* This file is part of KJots. Copyright (c) 2008 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 "kjotsbookshelfentryvalidator.h" #include KJotsBookshelfEntryValidator::KJotsBookshelfEntryValidator(QAbstractItemModel *model, QObject *parent) : QValidator(parent) { m_model = model; } QValidator::State KJotsBookshelfEntryValidator::validate(QString &input, int &pos) const { Q_UNUSED(pos) if (!m_model) { return Invalid; } if (input.isEmpty()) { return Intermediate; } const QModelIndexList list = m_model->match( m_model->index(0, 0), Qt::DisplayRole, input, Qt::MatchStartsWith | Qt::MatchFixedString | Qt::MatchWrap); if (list.empty()) { return Invalid; + } + + if (std::any_of(list.cbegin(), list.cend(), [&input](const QModelIndex &index) { + return QString::compare(index.data().toString(), input, Qt::CaseInsensitive); + })) { + return Acceptable; } else { - for (const QModelIndex &index : list) { - if (0 == QString::compare(m_model->data(index).toString(), input, Qt::CaseInsensitive)) { - return Acceptable; - } - return Intermediate; - } + return Intermediate; } - return Invalid; } diff --git a/src/kjotsconfigdlg.cpp b/src/kjotsconfigdlg.cpp index fb642dd..d44d4e5 100644 --- a/src/kjotsconfigdlg.cpp +++ b/src/kjotsconfigdlg.cpp @@ -1,76 +1,76 @@ /* 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 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(QStringLiteral("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); + auto *lay = new QHBoxLayout(this); miscPage = new confPageMisc(nullptr); lay->addWidget(miscPage); 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(QStringLiteral("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(QStringLiteral("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 95f2df2..9e77bb2 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 #include #include #include #include -#include "kjotsmodel.h" #include "kjotslinkdialog.h" -#include "noteshared/notelockattribute.h" +#include "kjotsmodel.h" #include "noteshared/noteeditorutils.h" +#include "noteshared/notelockattribute.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 | SupportHeading); setFocusPolicy(Qt::StrongFocus); } void KJotsEdit::contextMenuEvent(QContextMenuEvent *event) { QMenu *popup = mousePopupMenu(); if (popup) { popup->addSeparator(); QAction *act = actionCollection->action(QStringLiteral("copyIntoTitle")); popup->addAction(act); act = actionCollection->action(QStringLiteral("insert_checkmark")); act->setEnabled(!isReadOnly()); popup->addAction(act); if (!qApp->clipboard()->text().isEmpty()) { act = actionCollection->action(QStringLiteral("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(QStringLiteral("auto_bullet")), &QAction::triggered, this, &KJotsEdit::onAutoBullet); connect(actionCollection->action(QStringLiteral("auto_decimal")), &QAction::triggered, this, &KJotsEdit::onAutoDecimal); connect(actionCollection->action(QStringLiteral("manage_link")), &QAction::triggered, this, &KJotsEdit::onLinkify); connect(actionCollection->action(QStringLiteral("insert_checkmark")), &QAction::triggered, this, &KJotsEdit::addCheckmark); connect(actionCollection->action(QStringLiteral("insert_date")), &QAction::triggered, this, &KJotsEdit::insertDate); connect(actionCollection->action(QStringLiteral("insert_image")), &QAction::triggered, this, &KJotsEdit::insertImage); } bool KJotsEdit::modified() { return document()->isModified(); } void KJotsEdit::insertDate() { - NoteShared::NoteEditorUtils().insertDate(this); + NoteShared::NoteEditorUtils::insertDate(this); } void KJotsEdit::insertImage() { QTextCursor cursor = textCursor(); - NoteShared::NoteEditorUtils().insertImage(document(), cursor, this); + 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 doc = m_index->data(KJotsModel::DocumentRole).value(); + auto *doc = m_index->data(KJotsModel::DocumentRole).value(); if (!doc) { setReadOnly(true); return false; } disconnect(document(), &QTextDocument::modificationChanged, this, &KJotsEdit::documentModified); setDocument(doc); connect(doc, &QTextDocument::modificationChanged, this, &KJotsEdit::documentModified); // Setting cursor auto cursor = doc->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 inaccessible) 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) +void KJotsEdit::onAutoBullet() { KTextEdit::AutoFormatting currentFormatting = autoFormatting(); //TODO: set line spacing properly. if (currentFormatting == KTextEdit::AutoBulletList) { setAutoFormatting(KTextEdit::AutoNone); actionCollection->action(QStringLiteral("auto_bullet"))->setChecked(false); } else { setAutoFormatting(KTextEdit::AutoBulletList); actionCollection->action(QStringLiteral("auto_bullet"))->setChecked(true); } } -void KJotsEdit::createAutoDecimalList(void) +void KJotsEdit::createAutoDecimalList() { //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) +void KJotsEdit::DecimalList() { 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) +void KJotsEdit::onAutoDecimal() { - if (allowAutoDecimal == true) { + if (allowAutoDecimal) { allowAutoDecimal = false; disconnect(this, &KJotsEdit::textChanged, this, &KJotsEdit::DecimalList); actionCollection->action(QStringLiteral("auto_decimal"))->setChecked(false); } else { allowAutoDecimal = true; connect(this, &KJotsEdit::textChanged, this, &KJotsEdit::DecimalList); actionCollection->action(QStringLiteral("auto_decimal"))->setChecked(true); } } -void KJotsEdit::onLinkify(void) +void KJotsEdit::onLinkify() { // Nothing is yet opened, ignoring if (!m_index) { return; } selectLinkText(); auto linkDialog = std::make_unique(const_cast(m_index->model()), this); linkDialog->setLinkText(currentLinkText()); linkDialog->setLinkUrl(currentLinkUrl()); if (linkDialog->exec()) { updateLink(linkDialog->linkUrl(), linkDialog->linkText()); } } -void KJotsEdit::addCheckmark(void) +void KJotsEdit::addCheckmark() { QTextCursor cursor = textCursor(); - NoteShared::NoteEditorUtils().addCheckmark(cursor); + 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()); + 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/kjotsedit.h b/src/kjotsedit.h index 8d0fd82..ca1cd3d 100644 --- a/src/kjotsedit.h +++ b/src/kjotsedit.h @@ -1,96 +1,96 @@ /* 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. */ #ifndef KJOTSEDIT_H #define KJOTSEDIT_H #include class QItemSelection; class QItemSelectionModel; class KActionCollection; class KJotsEdit : public KRichTextWidget { Q_OBJECT public: explicit KJotsEdit(QWidget *); void delayedInitialization(KActionCollection *); bool canInsertFromMimeData(const QMimeData *) const override; void insertFromMimeData(const QMimeData *) override; /** * Load document based on KJotsModel index * * @returns true if loaded successfully */ bool setModelIndex(const QModelIndex &index); /** * Returns the current modified state of the document */ bool modified(); protected: /* To be able to change cursor when hovering over links */ void mouseMoveEvent(QMouseEvent *event) override; void leaveEvent(QEvent *event) override; /** Override to make ctrl+click follow links */ void mousePressEvent(QMouseEvent *) override; void contextMenuEvent(QContextMenuEvent *event) override; void focusOutEvent(QFocusEvent *) override; bool event(QEvent *event) override; void tooltipEvent(QHelpEvent *event); public Q_SLOTS: - void onAutoBullet(void); + void onAutoBullet(); void onLinkify(void); void addCheckmark(void); void onAutoDecimal(void); void DecimalList(void); void pastePlainText(void); void savePage(); void insertDate(); void insertImage(); Q_SIGNALS: void linkClicked(const QUrl &url); void documentModified(bool modified); private: void createAutoDecimalList(); KActionCollection *actionCollection; bool allowAutoDecimal; std::unique_ptr m_index; bool m_cursorChanged = false; }; #endif // __KJOTSEDIT_H /* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/kjotslinkdialog.cpp b/src/kjotslinkdialog.cpp index cecd658..6b4b06d 100644 --- a/src/kjotslinkdialog.cpp +++ b/src/kjotslinkdialog.cpp @@ -1,164 +1,164 @@ /* 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 +#include #include -#include #include +#include #include "KJotsSettings.h" #include "kjotsbookshelfentryvalidator.h" #include "kjotsmodel.h" KJotsLinkDialog::KJotsLinkDialog(QAbstractItemModel *kjotsModel, QWidget *parent) : QDialog(parent), m_kjotsModel(kjotsModel) { setWindowTitle(i18n("Manage Link")); - QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); - QVBoxLayout *mainLayout = new QVBoxLayout(this); + auto *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + auto *mainLayout = new QVBoxLayout(this); setLayout(mainLayout); QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); - okButton->setShortcut(Qt::CTRL | Qt::Key_Return); + okButton->setShortcut(QKeySequence(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); + auto *proxyModel = new KDescendantsProxyModel(this); proxyModel->setSourceModel(kjotsModel); proxyModel->setAncestorSeparator(QStringLiteral(" / ")); m_descendantsProxyModel = proxyModel; - QWidget *entries = new QWidget(this); + auto *entries = new QWidget(this); - QGridLayout *layout = new QGridLayout(entries); + auto *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(this); tree->setModel(proxyModel); tree->expandAll(); tree->setColumnHidden(1, true); hrefCombo->setModel(proxyModel); hrefCombo->setView(tree); hrefCombo->setEditable(true); - QCompleter *completer = new QCompleter(proxyModel, this); + auto *completer = new QCompleter(proxyModel, this); completer->setCaseSensitivity(Qt::CaseInsensitive); hrefCombo->setCompleter(completer); - KJotsBookshelfEntryValidator *validator = new KJotsBookshelfEntryValidator(proxyModel, this); + auto *validator = new KJotsBookshelfEntryValidator(proxyModel, this); hrefCombo->setValidator(validator); - QGridLayout *linkLayout = new QGridLayout(this); + auto *linkLayout = new QGridLayout(this); 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, &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 ff29e20..6f9929d 100644 --- a/src/kjotsmodel.cpp +++ b/src/kjotsmodel.cpp @@ -1,304 +1,303 @@ /* 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 #include #include #include #include "noteshared/notelockattribute.h" Q_DECLARE_METATYPE(QTextDocument *) KJotsEntity::KJotsEntity(const QModelIndex &index, QObject *parent) : QObject(parent) , m_index(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(); + auto *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(); + auto *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); + 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(); + auto *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(); + auto *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(); + auto *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) { auto *obj = new KJotsEntity(index); obj->setIndex(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(); + auto *document = new QTextDocument(); if (note.textFormat() == Qt::RichText || doc.startsWith(u"")) { document->setHtml(doc); } else { document->setPlainText(doc); } document->setModified(false); 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(QStringLiteral("emblem-locked")); - } else { - const Collection col = index.data(CollectionRole).value(); - if (col.isValid() && col.hasAttribute()) { - return QIcon::fromTheme(QStringLiteral("emblem-locked")); - } + } + const Collection col = index.data(CollectionRole).value(); + if (col.isValid() && col.hasAttribute()) { + return QIcon::fromTheme(QStringLiteral("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(); + return {}; } 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(); + return {}; } QString KJotsModel::itemPath(const QModelIndex &index, const QString &sep) { QString caption; QModelIndex curIndex = index; while (curIndex.isValid()) { QModelIndex parentBook = curIndex.parent(); if (parentBook.isValid()) { caption = sep + curIndex.data().toString() + caption; } else { caption = curIndex.data().toString() + caption; } curIndex = parentBook; } return caption; } diff --git a/src/kjotspart.cpp b/src/kjotspart.cpp index 0e757bb..13f721f 100644 --- a/src/kjotspart.cpp +++ b/src/kjotspart.cpp @@ -1,88 +1,88 @@ /* 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 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")); connect(mComponent, &KJotsWidget::captionChanged, this, &KJotsPart::setWindowCaption); } KJotsPart::~KJotsPart() { mComponent->queryClose(); } void KJotsPart::initAction() { - QAction *action = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Configure KJots..."), this); + auto *action = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("&Configure KJots..."), this); actionCollection()->addAction(QStringLiteral("kjots_configure"), action); connect(action, &QAction::triggered, mComponent, &KJotsWidget::configure); } bool KJotsPart::openFile() { return false; } // // bool KJotsPart::saveFile() // { // return false; // } #include "kjotspart.moc" diff --git a/src/kjotsreplacenextdialog.cpp b/src/kjotsreplacenextdialog.cpp index ab32ea9..ff383a1 100644 --- a/src/kjotsreplacenextdialog.cpp +++ b/src/kjotsreplacenextdialog.cpp @@ -1,73 +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); + auto *layout = new QVBoxLayout(this); m_mainLabel = new QLabel(this); layout->addWidget(m_mainLabel); - QDialogButtonBox *buttonBox = new QDialogButtonBox(this); + auto *buttonBox = new QDialogButtonBox(this); QPushButton *button = buttonBox->addButton(i18n("&All"), QDialogButtonBox::NoRole); connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::onHandleAll); button = buttonBox->addButton(i18n("&Skip"), QDialogButtonBox::NoRole); connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::onHandleSkip); button = buttonBox->addButton(i18n("Replace"), QDialogButtonBox::NoRole); connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::onHandleReplace); button = buttonBox->addButton(QDialogButtonBox::Close); connect(button, &QPushButton::clicked, this, &KJotsReplaceNextDialog::reject); layout->addWidget(buttonBox); } 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/kjotstreeview.cpp b/src/kjotstreeview.cpp index f2c410c..78c09f0 100644 --- a/src/kjotstreeview.cpp +++ b/src/kjotstreeview.cpp @@ -1,101 +1,101 @@ /* 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 "kjotstreeview.h" #include "kjotsmodel.h" #include #include #include #include #include #include #include #include #include #include using namespace Akonadi; KJotsTreeView::KJotsTreeView(KXMLGUIClient *xmlGuiClient, QWidget *parent) : EntityTreeView(xmlGuiClient, parent) , m_xmlGuiClient(xmlGuiClient) { } void KJotsTreeView::contextMenuEvent(QContextMenuEvent *event) { - QMenu *popup = new QMenu(this); + auto *popup = new QMenu(this); const QModelIndexList rows = selectionModel()->selectedRows(); const bool noselection = rows.isEmpty(); const bool singleselection = rows.size() == 1; const bool itemSelected = singleselection && rows.first().data(EntityTreeModel::ItemRole).value().isValid(); if (singleselection) { popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_note_create"))); popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_collection_create"))); popup->addAction(m_xmlGuiClient->actionCollection()->action(QString::fromLatin1(KStandardAction::name(KStandardAction::RenameFile)))); if (itemSelected) { popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_item_copy"))); } else { popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_collection_copy"))); } popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_change_color"))); popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("sort_children_alpha"))); popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("sort_children_by_date"))); } else if (!noselection) { popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_collection_create"))); popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_change_color"))); } if (!noselection) { popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("save_to"))); } popup->addSeparator(); popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_note_lock"))); popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_note_unlock"))); if (singleselection) { if (itemSelected) { popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_item_delete"))); } else { popup->addAction(m_xmlGuiClient->actionCollection()->action(QStringLiteral("akonadi_collection_delete"))); } } popup->exec(event->globalPos()); delete popup; } void KJotsTreeView::renameEntry() { const QModelIndexList rows = selectionModel()->selectedRows(); if (rows.size() != 1) { return; } edit(rows.first()); } diff --git a/src/kjotswidget.cpp b/src/kjotswidget.cpp index 19ce4c7..71b1d84 100644 --- a/src/kjotswidget.cpp +++ b/src/kjotswidget.cpp @@ -1,1264 +1,1262 @@ /* 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 // Akonadi #include #include #include #include #include #include #include #include #include #include #include #include // Grantlee #include #include #include // KDE #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 "kjotsbrowser.h" #include "noteshared/notelockattribute.h" #include "noteshared/standardnoteactionmanager.h" #include "localresourcecreator.h" #include using namespace Akonadi; using namespace Grantlee; KJotsWidget::KJotsWidget(QWidget *parent, KXMLGUIClient *xmlGuiClient, Qt::WindowFlags f) : QWidget(parent, f) , m_xmlGuiClient(xmlGuiClient) { 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); + auto *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); + auto *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(QStringLiteral("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); + auto *monitor = new ChangeRecorder(this); monitor->fetchCollection(true); monitor->setItemFetchScope(scope); monitor->setCollectionMonitored(Collection::root()); monitor->setMimeTypeMonitored(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()); m_actionManager = new StandardNoteActionManager(xmlGuiClient->actionCollection(), this); m_actionManager->setCollectionSelectionModel(treeview->selectionModel()); m_actionManager->setItemSelectionModel(treeview->selectionModel()); m_actionManager->createAllActions(); // 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(m_kjotsModel, stackedWidget); connect(browser, &KJotsBrowser::linkClicked, this, &KJotsWidget::openLink); stackedWidget->addWidget(browser); stackedWidget->setCurrentWidget(browser); QAction *action; action = actionCollection->addAction(QStringLiteral("go_next_book")); action->setText(i18n("Next Book")); action->setIcon(QIcon::fromTheme(QStringLiteral("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(QStringLiteral("go_prev_book")); action->setText(i18n("Previous Book")); action->setIcon(QIcon::fromTheme(QStringLiteral("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 = KStandardAction::next(this, &KJotsWidget::nextPage, actionCollection); - actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_PageDown)); + actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_PageDown)); connect(this, &KJotsWidget::canGoNextPageChanged, action, &QAction::setEnabled); action = KStandardAction::prior(this, &KJotsWidget::prevPage, actionCollection); - actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL | Qt::Key_PageUp)); + actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_PageUp)); connect(this, &KJotsWidget::canGoPreviousPageChanged, action, &QAction::setEnabled); actionCollection->setDefaultShortcut(m_actionManager->action(StandardActionManager::CreateCollection), QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_N)); actionCollection->setDefaultShortcut(m_actionManager->action(StandardActionManager::DeleteCollections), QKeySequence(Qt::CTRL + Qt::Key_Delete)); actionCollection->setDefaultShortcut(m_actionManager->action(StandardActionManager::DeleteItems), QKeySequence(Qt::CTRL + Qt::Key_Delete)); KStandardAction::save( editor, &KJotsEdit::savePage, actionCollection); action = actionCollection->addAction(QStringLiteral("auto_bullet")); action->setText(i18n("Auto Bullets")); action->setIcon(QIcon::fromTheme(QStringLiteral("format-list-unordered"))); action->setCheckable(true); action = actionCollection->addAction(QStringLiteral("auto_decimal")); action->setText(i18n("Auto Decimal List")); action->setIcon(QIcon::fromTheme(QStringLiteral("format-list-ordered"))); action->setCheckable(true); action = actionCollection->addAction(QStringLiteral("manage_link")); action->setText(i18n("Link")); action->setIcon(QIcon::fromTheme(QStringLiteral("insert-link"))); action = actionCollection->addAction(QStringLiteral("insert_image")); action->setText(i18n("Insert Image")); action->setIcon(QIcon::fromTheme(QStringLiteral("insert-image"))); action = actionCollection->addAction(QStringLiteral("insert_checkmark")); action->setText(i18n("Insert Checkmark")); action->setIcon(QIcon::fromTheme(QStringLiteral("checkmark"))); action->setEnabled(false); KStandardAction::renameFile(treeview, &KJotsTreeView::renameEntry, actionCollection); action = actionCollection->addAction(QStringLiteral("insert_date")); action->setText(i18n("Insert Date")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I)); action->setIcon(QIcon::fromTheme(QStringLiteral("view-calendar-time-spent"))); action = actionCollection->addAction(QStringLiteral("sort_children_alpha")); action->setText(i18n("Sort children alphabetically")); connect(action, &QAction::triggered, this, &KJotsWidget::actionSortChildrenAlpha); action = actionCollection->addAction(QStringLiteral("sort_children_by_date")); action->setText(i18n("Sort children by creation date")); connect(action, &QAction::triggered, this, &KJotsWidget::actionSortChildrenByDate); action = KStandardAction::cut(editor, &KJotsEdit::cut, actionCollection); connect(editor, &KJotsEdit::copyAvailable, action, &QAction::setEnabled); action->setEnabled(false); action = KStandardAction::copy(this, [this](){ activeEditor()->copy(); }, actionCollection); connect(editor, &KJotsEdit::copyAvailable, action, &QAction::setEnabled); connect(browser, &KJotsBrowser::copyAvailable, action, &QAction::setEnabled); action->setEnabled(false); KStandardAction::paste(editor, &KJotsEdit::paste, actionCollection); KStandardAction::undo(editor, &KJotsEdit::undo, actionCollection); KStandardAction::redo(editor, &KJotsEdit::redo, actionCollection); KStandardAction::selectAll(editor, &KJotsEdit::selectAll, actionCollection); action = actionCollection->addAction(QStringLiteral("copyIntoTitle")); action->setText(i18n("Copy &into Page Title")); actionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_T)); action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy"))); connect(action, &QAction::triggered, this, &KJotsWidget::copySelectionToTitle); connect(editor, &KJotsEdit::copyAvailable, action, &QAction::setEnabled); action->setEnabled(false); action = actionCollection->addAction(QStringLiteral("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, &KJotsWidget::configure, actionCollection); bookmarkMenu = actionCollection->add(QStringLiteral("bookmarks")); bookmarkMenu->setText(i18n("&Bookmarks")); - KJotsBookmarks *bookmarks = new KJotsBookmarks(treeview->selectionModel()); + auto *bookmarks = new KJotsBookmarks(treeview->selectionModel(), this); connect(bookmarks, &KJotsBookmarks::openLink, this, &KJotsWidget::openLink); - KBookmarkMenu *bmm = new KBookmarkMenu( + auto *bmm = new KBookmarkMenu( KBookmarkManager::managerForFile( 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, &KJotsWidget::onShowSearch, actionCollection); action = KStandardAction::findNext(this, &KJotsWidget::onRepeatSearch, actionCollection); action->setEnabled(false); KStandardAction::replace(this, &KJotsWidget::onShowReplace, actionCollection); - KActionMenu *exportMenu = actionCollection->add(QStringLiteral("save_to")); + auto *exportMenu = actionCollection->add(QStringLiteral("save_to")); exportMenu->setText(i18n("Export")); exportMenu->setIcon(QIcon::fromTheme(QStringLiteral("document-export"))); action = actionCollection->addAction(QStringLiteral("save_to_ascii")); action->setText(i18n("To Text File...")); action->setIcon(QIcon::fromTheme(QStringLiteral("text-plain"))); connect(action, &QAction::triggered, this, [this](){ exportSelection(QStringLiteral("plain_text"), QStringLiteral("template.txt")); }); exportMenu->menu()->addAction(action); action = actionCollection->addAction(QStringLiteral("save_to_html")); action->setText(i18n("To HTML File...")); action->setIcon(QIcon::fromTheme(QStringLiteral("text-html"))); connect(action, &QAction::triggered, this, [this](){ exportSelection(QStringLiteral("default"), QStringLiteral("template.html")); }); exportMenu->menu()->addAction(action); 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, &KJotsWidget::delayedInitialization); connect(treeview->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KJotsWidget::updateMenu); connect(treeview->selectionModel(), &QItemSelectionModel::selectionChanged, this, &KJotsWidget::updateCaption); connect(treeview->model(), &QAbstractItemModel::dataChanged, this, &KJotsWidget::updateCaption); connect(editor, &KJotsEdit::documentModified, this, &KJotsWidget::updateCaption); connect(m_kjotsModel, &EntityTreeModel::modelAboutToBeReset, this, &KJotsWidget::saveState); connect(m_kjotsModel, &EntityTreeModel::modelReset, this, &KJotsWidget::restoreState); restoreState(); QDBusConnection::sessionBus().registerObject(QStringLiteral("/KJotsWidget"), this, QDBusConnection::ExportScriptableContents); } KJotsWidget::~KJotsWidget() { saveState(); } void KJotsWidget::restoreState() { - ETMViewStateSaver *saver = new ETMViewStateSaver; + auto *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()); + auto *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(), &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()); + auto *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(QString::fromLatin1(KStandardAction::name(KStandardAction::Find)))); entryActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Print)))); entryActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::RenameFile)))); entryActions.insert(m_actionManager->action(StandardNoteActionManager::ChangeColor)); entryActions.insert(actionCollection->action(QStringLiteral("save_to"))); entryActions.insert(m_actionManager->action(StandardActionManager::CopyItems)); entryActions.insert(m_actionManager->action(StandardActionManager::CopyCollections)); // Actions that are used only when a page is selected. pageActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Cut)))); pageActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Paste)))); pageActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Replace)))); pageActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Save)))); pageActions.insert(m_actionManager->action(StandardActionManager::DeleteItems)); pageActions.insert(actionCollection->action(QStringLiteral("insert_date"))); pageActions.insert(actionCollection->action(QStringLiteral("auto_bullet"))); pageActions.insert(actionCollection->action(QStringLiteral("auto_decimal"))); pageActions.insert(actionCollection->action(QStringLiteral("manage_link"))); pageActions.insert(actionCollection->action(QStringLiteral("insert_checkmark"))); // Actions that are used only when a book is selected. bookActions.insert(m_actionManager->action(StandardActionManager::DeleteCollections)); bookActions.insert(actionCollection->action(QStringLiteral("sort_children_alpha"))); bookActions.insert(actionCollection->action(QStringLiteral("sort_children_by_date"))); // Actions that are used when multiple items are selected. multiselectionActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Find)))); multiselectionActions.insert(actionCollection->action(QString::fromLatin1(KStandardAction::name(KStandardAction::Print)))); multiselectionActions.insert(actionCollection->action(QStringLiteral("save_to"))); multiselectionActions.insert(m_actionManager->action(StandardNoteActionManager::ChangeColor)); m_autosaveTimer = new QTimer(this); updateConfiguration(); connect(m_autosaveTimer, &QTimer::timeout, editor, &KJotsEdit::savePage); connect(treeview->selectionModel(), &QItemSelectionModel::selectionChanged, m_autosaveTimer, qOverload<>(&QTimer::start)); editor->delayedInitialization(m_xmlGuiClient->actionCollection()); browser->delayedInitialization(); // Make sure the editor gets focus again after naming a new book/page. connect(treeview->itemDelegate(), &QItemDelegate::closeEditor, this, [this](){ activeEditor()->setFocus(); }); updateMenu(); } 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); } for (QAction *action : qAsConst(bookActions)) { action->setEnabled(true); } editor->setActionsEnabled(false); } else { for (QAction *action : qAsConst(pageActions)) { if (action->objectName() == QString::fromLatin1(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::configure() { // create a new preferences dialog... - KJotsConfigDlg *dialog = new KJotsConfigDlg(i18n("Settings"), this); + auto *dialog = new KJotsConfigDlg(i18n("Settings"), this); 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); } } QString KJotsWidget::renderSelectionTo(const QString &theme, const QString &templ) { 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()); objectList << idx.data(KJotsModel::GrantleeObjectRole); } QHash hash = {{QStringLiteral("entities"), objectList}, {QStringLiteral("i18n_TABLE_OF_CONTENTS"), i18nc("Header for 'Table of contents' section of rendered output", "Table of contents")}}; Context c(hash); const QString currentTheme = m_loader->themeName(); m_loader->setTheme(theme); Template t = m_templateEngine->loadByName(templ); const QString result = t->render(&c); m_loader->setTheme(currentTheme); return result; } QString KJotsWidget::renderSelectionToHtml() { return renderSelectionTo(QStringLiteral("default"), QStringLiteral("template.html")); } void KJotsWidget::exportSelection(const QString &theme, const QString &templ) { // TODO: dialog captions & etc QString filename = QFileDialog::getSaveFileName(); if (filename.isEmpty()) { return; } QFile exportFile(filename); if (!exportFile.open(QIODevice::WriteOnly | QIODevice::Text)) { KMessageBox::error(this, i18n("Could not open \"%1\" for writing", filename)); return; } exportFile.write(renderSelectionTo(theme, templ).toUtf8()); exportFile.close(); } 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(QStringLiteral("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(QString::fromLatin1(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(QString::fromLatin1(KStandardAction::name(KStandardAction::FindNext)))->setEnabled(false); } } /*! Called when user presses Cancel in find dialog. */ void KJotsWidget::onEndSearch() { m_xmlGuiClient->actionCollection()->action(QString::fromLatin1(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, &KJotsWidget::onRepeatReplace); } /*! Only called after onStartReplace. Kept the name scheme for consistency. */ 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; - } + 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() { const QModelIndexList selection = treeview->selectionModel()->selectedRows(); QString caption; if (selection.size() == 1) { caption = KJotsModel::itemPath(selection.first()); if (editor->modified()) { caption.append(QStringLiteral(" *")); } } else if (selection.size() > 1) { caption = i18nc("@title:window", "Multiple selection"); } Q_EMIT captionChanged(caption); } bool KJotsWidget::queryClose() { KJotsSettings::setSplitterSizes(m_splitter->sizes()); KJotsSettings::self()->save(); m_orderProxy->saveOrder(); // TODO: we better wait for a result here! editor->savePage(); return true; } 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/kontact_plugin/kjots_plugin.cpp b/src/kontact_plugin/kjots_plugin.cpp index ec55a26..105b07e 100644 --- a/src/kontact_plugin/kjots_plugin.cpp +++ b/src/kontact_plugin/kjots_plugin.cpp @@ -1,118 +1,110 @@ /* Copyright (C) 2016 Daniel Vrátil 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 "kjots_plugin.h" #include "kjotspart.h" //#include "akregator_options.h" //#include "partinterface.h" #include #include -#include -#include #include #include +#include +#include + #if KONTACTINTERFACE_VERSION < QT_VERSION_CHECK(5, 14, 42) /** Exports Kontact plugin. @param pluginclass the class to instantiate (must derive from KontactInterface::Plugin @param jsonFile filename of the JSON file, generated from a .desktop file */ #define EXPORT_KONTACT_PLUGIN_WITH_JSON( pluginclass, jsonFile ) \ class Instance \ { \ public: \ static QObject *createInstance( QWidget *, QObject *parent, const QVariantList &list ) \ { return new pluginclass( static_cast( parent ), list ); } \ }; \ K_PLUGIN_FACTORY_WITH_JSON( KontactPluginFactory, jsonFile, registerPlugin< pluginclass > \ ( QString(), Instance::createInstance ); ) \ K_EXPORT_PLUGIN_VERSION(KONTACT_PLUGIN_VERSION) #endif EXPORT_KONTACT_PLUGIN_WITH_JSON(KJotsPlugin, "kjotsplugin.json") -KJotsPlugin::KJotsPlugin(KontactInterface::Core *core, const QVariantList &) +KJotsPlugin::KJotsPlugin(KontactInterface::Core *core, const QVariantList &/*args*/) : KontactInterface::Plugin(core, core, "kjots") { setComponentName(QStringLiteral("kjots"), QStringLiteral("kjots")); mUniqueAppWatcher = new KontactInterface::UniqueAppWatcher( new KontactInterface::UniqueAppHandlerFactory(), this); } -void KJotsPlugin::setHelpText(QAction *action, const QString &text) -{ - action->setStatusTip(text); - action->setToolTip(text); - if (action->whatsThis().isEmpty()) { - action->setWhatsThis(text); - } -} - bool KJotsPlugin::isRunningStandalone() const { return mUniqueAppWatcher->isRunningStandalone(); } QStringList KJotsPlugin::invisibleToolbarActions() const { return { QStringLiteral("akonadi_note_create"), QStringLiteral("akonadi_collection_create") }; } #if KONTACTINTERFACE_VERSION >= QT_VERSION_CHECK(5, 14, 42) KParts::Part *KJotsPlugin::createPart() { return loadPart(); } #else KParts::ReadOnlyPart *KJotsPlugin::createPart() { return loadPart(); } #endif QStringList KJotsPlugin::configModules() const { QStringList modules; modules << QStringLiteral("PIM/kjots.desktop"); return modules; } void KJotsUniqueAppHandler::loadCommandLineOptions(QCommandLineParser *parser) { Q_UNUSED(parser) } int KJotsUniqueAppHandler::activate(const QStringList &args, const QString &workingDir) { // Ensure part is loaded (void)plugin()->part(); return KontactInterface::UniqueAppHandler::activate(args, workingDir); } #include "kjots_plugin.moc" diff --git a/src/kontact_plugin/kjots_plugin.h b/src/kontact_plugin/kjots_plugin.h index c52de00..a73f374 100644 --- a/src/kontact_plugin/kjots_plugin.h +++ b/src/kontact_plugin/kjots_plugin.h @@ -1,78 +1,75 @@ /* Copyright (C) 2016 Daniel Vrátil 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. */ #ifndef KJOTS_PLUGIN_H #define KJOTS_PLUGIN_H #include #include namespace KontactInterface { class Plugin; } class KJotsUniqueAppHandler : public KontactInterface::UniqueAppHandler { Q_OBJECT public: explicit KJotsUniqueAppHandler(KontactInterface::Plugin *plugin) : KontactInterface::UniqueAppHandler(plugin) { } int activate(const QStringList &args, const QString &workingDir) Q_DECL_OVERRIDE; void loadCommandLineOptions(QCommandLineParser *parser) Q_DECL_OVERRIDE; }; class KJotsPlugin : public KontactInterface::Plugin { Q_OBJECT public: KJotsPlugin(KontactInterface::Core *core, const QVariantList &); int weight() const Q_DECL_OVERRIDE { return 475; } virtual QStringList configModules() const; bool isRunningStandalone() const Q_DECL_OVERRIDE; QStringList invisibleToolbarActions() const Q_DECL_OVERRIDE; protected: #if KONTACTINTERFACE_VERSION >= QT_VERSION_CHECK(5, 14, 42) KParts::Part *createPart() override; #else KParts::ReadOnlyPart *createPart() Q_DECL_OVERRIDE; #endif KontactInterface::UniqueAppWatcher *mUniqueAppWatcher; - -private: - void setHelpText(QAction *action, const QString &text); }; #endif diff --git a/src/localresourcecreator.cpp b/src/localresourcecreator.cpp index d06ea3d..d7ab1f5 100644 --- a/src/localresourcecreator.cpp +++ b/src/localresourcecreator.cpp @@ -1,163 +1,163 @@ /* Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net, author 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 "localresourcecreator.h" #include #include #include #include #include #include #include #include #include #include #include #include LocalResourceCreator::LocalResourceCreator(QObject *parent) : NoteShared::LocalResourceCreator(parent) { } void LocalResourceCreator::finishCreateResource() { - Akonadi::CollectionFetchJob *collectionFetchJob = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(), Akonadi::CollectionFetchJob::FirstLevel, this); + auto *collectionFetchJob = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(), Akonadi::CollectionFetchJob::FirstLevel, this); connect(collectionFetchJob, &Akonadi::CollectionFetchJob::result, this, &LocalResourceCreator::rootFetchFinished); } void LocalResourceCreator::rootFetchFinished(KJob *job) { if (job->error()) { qWarning() << job->errorString(); deleteLater(); return; } - Akonadi::CollectionFetchJob *lastCollectionFetchJob = qobject_cast(job); + auto *lastCollectionFetchJob = qobject_cast(job); if (!lastCollectionFetchJob) { deleteLater(); return; } Akonadi::Collection::List list = lastCollectionFetchJob->collections(); if (list.isEmpty()) { qWarning() << "Couldn't find new collection in resource"; deleteLater(); return; } for (const Akonadi::Collection &col : qAsConst(list)) { Akonadi::AgentInstance instance = Akonadi::AgentManager::self()->instance(col.resource()); if (instance.type().identifier() == akonadiNotesInstanceName()) { Akonadi::CollectionFetchJob *collectionFetchJob = new Akonadi::CollectionFetchJob(col, Akonadi::CollectionFetchJob::FirstLevel, this); collectionFetchJob->setProperty("FetchedCollection", col.id()); connect(collectionFetchJob, &Akonadi::CollectionFetchJob::result, this, &LocalResourceCreator::topLevelFetchFinished); return; } } Q_ASSERT(!"Couldn't find new collection"); deleteLater(); } void LocalResourceCreator::topLevelFetchFinished(KJob *job) { if (job->error()) { qWarning() << job->errorString(); deleteLater(); return; } Akonadi::CollectionFetchJob *lastCollectionFetchJob = qobject_cast(job); if (!lastCollectionFetchJob) { deleteLater(); return; } Akonadi::Collection::List list = lastCollectionFetchJob->collections(); if (!list.isEmpty()) { deleteLater(); return; } Akonadi::Collection::Id id = lastCollectionFetchJob->property("FetchedCollection").toLongLong(); Akonadi::Collection collection; collection.setParentCollection(Akonadi::Collection(id)); QString title = i18nc("The default name for new books.", "New Book"); collection.setName(KRandom::randomString(10)); collection.setContentMimeTypes({Akonadi::Collection::mimeType(), Akonadi::NoteUtils::noteMimeType()}); Akonadi::EntityDisplayAttribute *eda = new Akonadi::EntityDisplayAttribute(); eda->setIconName(QStringLiteral("x-office-address-book")); eda->setDisplayName(title); collection.addAttribute(eda); Akonadi::CollectionCreateJob *createJob = new Akonadi::CollectionCreateJob(collection, this); connect(createJob, &Akonadi::CollectionCreateJob::result, this, &LocalResourceCreator::createFinished); } void LocalResourceCreator::createFinished(KJob *job) { if (job->error()) { qWarning() << job->errorString(); deleteLater(); return; } Akonadi::CollectionCreateJob *collectionCreateJob = qobject_cast(job); if (!collectionCreateJob) { deleteLater(); return; } Akonadi::Item item; item.setParentCollection(collectionCreateJob->collection()); item.setMimeType(Akonadi::NoteUtils::noteMimeType()); Akonadi::NoteUtils::NoteMessageWrapper note(KMime::Message::Ptr(new KMime::Message)); note.setFrom(QStringLiteral("KJots@KDE5")); note.setTitle(i18nc("The default name for new pages.", "New Page")); note.setCreationDate(QDateTime::currentDateTime()); note.setLastModifiedDate(QDateTime::currentDateTime()); // Need a non-empty body part so that the serializer regards this as a valid message. note.setText(QStringLiteral(" ")); item.setPayload(note.message()); item.attribute(Akonadi::Item::AddIfMissing)->setIconName(QStringLiteral("text-plain")); auto itemJob = new Akonadi::ItemCreateJob(item, collectionCreateJob->collection(), this); connect(itemJob, &Akonadi::ItemCreateJob::result, this, [this, itemJob](KJob*){ if (itemJob->error()) { qWarning() << "Failed to create a note:" << itemJob->errorString(); } deleteLater(); }); } diff --git a/src/main.cpp b/src/main.cpp index 75105a2..fd7923b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,65 +1,65 @@ /* 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. */ #include "KJotsMain.h" #include "aboutdata.h" #include #include #include #include #include int main(int argc, char **argv) { AboutData aboutData; KontactInterface::PimUniqueApplication app(argc, &argv); KLocalizedString::setApplicationDomain("kjots"); app.setAboutData(aboutData); QCommandLineParser *cmdArgs = app.cmdArgs(); const QStringList args = QApplication::arguments(); cmdArgs->process(args); aboutData.processCommandLine(cmdArgs); if (!KontactInterface::PimUniqueApplication::start(args)) { qWarning() << "kjots is already running!"; exit(0); } - KJotsMain *jots = new KJotsMain; + auto *jots = new KJotsMain; if (app.isSessionRestored()) { if (KJotsMain::canBeRestored(1)) { jots->restore(1); } } jots->show(); jots->resize(jots->size()); return app.exec(); } /* ex: set tabstop=4 softtabstop=4 shiftwidth=4 expandtab: */ diff --git a/src/noteshared/localresourcecreator.cpp b/src/noteshared/localresourcecreator.cpp index c775761..8f6d0c6 100644 --- a/src/noteshared/localresourcecreator.cpp +++ b/src/noteshared/localresourcecreator.cpp @@ -1,115 +1,115 @@ /* 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 #include #include +#include #include #include "maildirsettings.h" #include "noteshared_debug.h" 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(); 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); + auto *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); + auto *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( + auto *iface = new org::kde::Akonadi::Maildir::Settings( QStringLiteral("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); + auto *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/notecreatorandselector.cpp b/src/noteshared/notecreatorandselector.cpp index 1bc8f6c..1f973f3 100644 --- a/src/noteshared/notecreatorandselector.cpp +++ b/src/noteshared/notecreatorandselector.cpp @@ -1,129 +1,127 @@ /* Copyright (C) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net, author 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 "notecreatorandselector.h" #include #include #include -#include #include +#include #include #include "noteshared_debug.h" using namespace Akonadi; using namespace NoteShared; NoteCreatorAndSelector::NoteCreatorAndSelector(QItemSelectionModel *primaryModel, QItemSelectionModel *secondaryModel, QObject *parent) : QObject(parent), m_primarySelectionModel(primaryModel), m_secondarySelectionModel(secondaryModel == nullptr ? primaryModel : secondaryModel), m_containerCollectionId(-1), m_newNoteId(-1), m_giveupTimer(new QTimer(this)) { // If the note doesn't exist after 5 seconds, give up waiting for it. m_giveupTimer->setInterval(5000); connect(m_giveupTimer, &QTimer::timeout, this, &NoteCreatorAndSelector::deleteLater); } -NoteCreatorAndSelector::~NoteCreatorAndSelector() -{ -} +NoteCreatorAndSelector::~NoteCreatorAndSelector() = default; void NoteCreatorAndSelector::createNote(const Akonadi::Collection &containerCollection) { m_containerCollectionId = containerCollection.id(); if (m_primarySelectionModel == m_secondarySelectionModel) { doCreateNote(); } else { m_giveupTimer->start(); connect(m_primarySelectionModel->model(), &QAbstractItemModel::rowsInserted, this, &NoteCreatorAndSelector::trySelectCollection); trySelectCollection(); } } void NoteCreatorAndSelector::trySelectCollection() { QModelIndex idx = EntityTreeModel::modelIndexForCollection(m_primarySelectionModel->model(), Collection(m_containerCollectionId)); if (!idx.isValid()) { return; } m_giveupTimer->stop(); m_primarySelectionModel->select(QItemSelection(idx, idx), QItemSelectionModel::Select); disconnect(m_primarySelectionModel->model(), &QAbstractItemModel::rowsInserted, this, &NoteCreatorAndSelector::trySelectCollection); doCreateNote(); } void NoteCreatorAndSelector::doCreateNote() { Item newItem; newItem.setMimeType(Akonadi::NoteUtils::noteMimeType()); Akonadi::NoteUtils::NoteMessageWrapper note(KMime::Message::Ptr(new KMime::Message)); note.setFrom(QStringLiteral("KJots@KDE5")); note.setTitle(i18nc("The default name for new pages.", "New Page")); note.setCreationDate(QDateTime::currentDateTime()); note.setLastModifiedDate(QDateTime::currentDateTime()); // Need a non-empty body part so that the serializer regards this as a valid message. note.setText(QStringLiteral(" ")); newItem.setPayload(note.message()); newItem.attribute(Akonadi::Item::AddIfMissing)->setIconName(QStringLiteral("text-plain")); - Akonadi::ItemCreateJob *job = new Akonadi::ItemCreateJob(newItem, Collection(m_containerCollectionId), this); + auto *job = new Akonadi::ItemCreateJob(newItem, Collection(m_containerCollectionId), this); connect(job, &Akonadi::ItemCreateJob::result, this, &NoteCreatorAndSelector::noteCreationFinished); } void NoteCreatorAndSelector::noteCreationFinished(KJob *job) { if (job->error()) { qCWarning(NOTESHARED_LOG) << job->errorString(); return; } - Akonadi::ItemCreateJob *createJob = qobject_cast(job); + auto *createJob = qobject_cast(job); Q_ASSERT(createJob); Item newItem = createJob->item(); m_newNoteId = newItem.id(); m_giveupTimer->start(); connect(m_primarySelectionModel->model(), &QAbstractItemModel::rowsInserted, this, &NoteCreatorAndSelector::trySelectNote); trySelectNote(); } void NoteCreatorAndSelector::trySelectNote() { QModelIndexList list = EntityTreeModel::modelIndexesForItem(m_secondarySelectionModel->model(), Item(m_newNoteId)); if (list.isEmpty()) { return; } const QModelIndex idx = list.first(); m_secondarySelectionModel->select(QItemSelection(idx, idx), QItemSelectionModel::ClearAndSelect); } diff --git a/src/noteshared/noteeditorutils.cpp b/src/noteshared/noteeditorutils.cpp index 0cb7233..59533cc 100644 --- a/src/noteshared/noteeditorutils.cpp +++ b/src/noteshared/noteeditorutils.cpp @@ -1,73 +1,66 @@ /* 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() -{ - -} +using namespace NoteShared::NoteEditorUtils; -void NoteEditorUtils::addCheckmark(QTextCursor &cursor) +void NoteShared::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()); + cursor.insertText(QString::fromUtf16(u"\U00002713")); + cursor.setPosition(position + 1); } -void NoteEditorUtils::insertDate(QTextEdit *editor) +void NoteShared::NoteEditorUtils::insertDate(QTextEdit *editor) { editor->insertPlainText(QLocale().toString(QDateTime::currentDateTime(), QLocale::ShortFormat) + QLatin1Char(' ')); } -void NoteEditorUtils::insertImage(QTextDocument * /*doc*/, QTextCursor &/*cursor*/, QTextEdit *par) +void NoteShared::NoteEditorUtils::insertImage(QTextDocument * /*doc*/, QTextCursor &/*cursor*/, QTextEdit *par) { QString imageFileName = QFileDialog::getOpenFileName(par, i18n("Select image file"), QStringLiteral("."), QStringLiteral("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(QStringLiteral("").arg(filetype, Base64Image)); } } } diff --git a/src/noteshared/noteeditorutils.h b/src/noteshared/noteeditorutils.h index 5be91fd..0780c00 100644 --- a/src/noteshared/noteeditorutils.h +++ b/src/noteshared/noteeditorutils.h @@ -1,37 +1,35 @@ /* 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 */ #ifndef NOTEEDITORUTILS_H #define NOTEEDITORUTILS_H class QTextCursor; class QTextEdit; class QTextDocument; class QWidget; namespace NoteShared { -class NoteEditorUtils +namespace NoteEditorUtils { -public: - NoteEditorUtils(); - void addCheckmark(QTextCursor &cursor); - void insertDate(QTextEdit *editor); - void insertImage(QTextDocument *doc, QTextCursor &cursor, QTextEdit *par); +void addCheckmark(QTextCursor &cursor); +void insertDate(QTextEdit *editor); +void insertImage(QTextDocument *doc, QTextCursor &cursor, QTextEdit *par); }; } #endif // NOTEEDITORUTILS_H diff --git a/src/noteshared/standardnoteactionmanager.cpp b/src/noteshared/standardnoteactionmanager.cpp index 878ff12..5f8c091 100644 --- a/src/noteshared/standardnoteactionmanager.cpp +++ b/src/noteshared/standardnoteactionmanager.cpp @@ -1,589 +1,586 @@ /* This file is part of KJots. Copyright (c) 2020 Igor Poboiko 2009 - 2010 Tobias Koenig 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 "standardnoteactionmanager.h" #include #include #include -#include #include #include #include #include +#include #include #include -#include "notelockattribute.h" #include "notecreatorandselector.h" +#include "notelockattribute.h" using namespace Akonadi; class Q_DECL_HIDDEN StandardNoteActionManager::Private { public: Private(KActionCollection *actionCollection, QWidget *parentWidget, StandardNoteActionManager *parent) : mActionCollection(actionCollection) , mParentWidget(parentWidget) , mGenericManager(std::make_unique(actionCollection, parentWidget)) - , mCollectionSelectionModel(nullptr) - , mItemSelectionModel(nullptr) , mParent(parent) { - mParent->connect(mGenericManager.get(), &StandardActionManager::actionStateUpdated, + QObject::connect(mGenericManager.get(), &StandardActionManager::actionStateUpdated, mParent, &StandardNoteActionManager::actionStateUpdated); mGenericManager->setMimeTypeFilter({ NoteUtils::noteMimeType() }); mGenericManager->setCapabilityFilter({ QStringLiteral("Resource") }); } ~Private() = default; void updateGenericAllActions() { updateGenericAction(StandardActionManager::CreateCollection); updateGenericAction(StandardActionManager::CopyCollections); updateGenericAction(StandardActionManager::DeleteCollections); updateGenericAction(StandardActionManager::SynchronizeCollections); updateGenericAction(StandardActionManager::CollectionProperties); updateGenericAction(StandardActionManager::CopyItems); updateGenericAction(StandardActionManager::Paste); updateGenericAction(StandardActionManager::DeleteItems); updateGenericAction(StandardActionManager::ManageLocalSubscriptions); updateGenericAction(StandardActionManager::AddToFavoriteCollections); updateGenericAction(StandardActionManager::RemoveFromFavoriteCollections); updateGenericAction(StandardActionManager::RenameFavoriteCollection); updateGenericAction(StandardActionManager::CopyCollectionToMenu); updateGenericAction(StandardActionManager::CopyItemToMenu); updateGenericAction(StandardActionManager::MoveItemToMenu); updateGenericAction(StandardActionManager::MoveCollectionToMenu); updateGenericAction(StandardActionManager::CutItems); updateGenericAction(StandardActionManager::CutCollections); updateGenericAction(StandardActionManager::CreateResource); updateGenericAction(StandardActionManager::DeleteResources); updateGenericAction(StandardActionManager::ResourceProperties); updateGenericAction(StandardActionManager::SynchronizeResources); updateGenericAction(StandardActionManager::ToggleWorkOffline); updateGenericAction(StandardActionManager::CopyCollectionToDialog); updateGenericAction(StandardActionManager::MoveCollectionToDialog); updateGenericAction(StandardActionManager::CopyItemToDialog); updateGenericAction(StandardActionManager::MoveItemToDialog); updateGenericAction(StandardActionManager::SynchronizeCollectionsRecursive); updateGenericAction(StandardActionManager::MoveCollectionsToTrash); updateGenericAction(StandardActionManager::MoveItemsToTrash); updateGenericAction(StandardActionManager::RestoreCollectionsFromTrash); updateGenericAction(StandardActionManager::RestoreItemsFromTrash); updateGenericAction(StandardActionManager::MoveToTrashRestoreCollection); updateGenericAction(StandardActionManager::MoveToTrashRestoreCollectionAlternative); updateGenericAction(StandardActionManager::MoveToTrashRestoreItem); updateGenericAction(StandardActionManager::MoveToTrashRestoreItemAlternative); updateGenericAction(StandardActionManager::SynchronizeFavoriteCollections); } void updateGenericAction(StandardActionManager::Type type) { switch (type) { case StandardActionManager::CreateCollection: mGenericManager->action(StandardActionManager::CreateCollection)->setText( i18n("New Note Book...")); mGenericManager->action(StandardActionManager::CreateCollection)->setIcon( QIcon::fromTheme(QStringLiteral("address-book-new"))); mGenericManager->action(StandardActionManager::CreateCollection)->setWhatsThis( i18n("Add a new note book to the currently selected bookshelf.")); mGenericManager->setContextText( StandardActionManager::CreateCollection, StandardActionManager::DialogTitle, i18nc("@title:window", "New Note Book")); mGenericManager->setContextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageText, ki18n("Could not create note book: %1")); mGenericManager->setContextText( StandardActionManager::CreateCollection, StandardActionManager::ErrorMessageTitle, i18n("Note book creation failed")); mGenericManager->action(StandardActionManager::CreateCollection)->setProperty("ContentMimeTypes", { NoteUtils::noteMimeType() }); break; case StandardActionManager::CopyCollections: mGenericManager->setActionText(StandardActionManager::CopyCollections, ki18np("Copy Note Book", "Copy %1 Note Books")); mGenericManager->action(StandardActionManager::CopyCollections)->setWhatsThis( i18n("Copy the selected note books to the clipboard.")); break; case StandardActionManager::DeleteCollections: mGenericManager->setActionText(StandardActionManager::DeleteCollections, ki18np("Delete Note Book", "Delete %1 Note Books")); mGenericManager->action(StandardActionManager::DeleteCollections)->setWhatsThis( i18n("Delete the selected note books from the bookshelf.")); mGenericManager->setContextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxText, ki18np("Do you really want to delete this note book and all its contents?", "Do you really want to delete %1 note books and all their contents?")); mGenericManager->setContextText( StandardActionManager::DeleteCollections, StandardActionManager::MessageBoxTitle, ki18ncp("@title:window", "Delete note book?", "Delete note books?")); mGenericManager->setContextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageText, ki18n("Could not delete note book: %1")); mGenericManager->setContextText( StandardActionManager::DeleteCollections, StandardActionManager::ErrorMessageTitle, i18n("Note book deletion failed")); break; case StandardActionManager::SynchronizeCollections: mGenericManager->setActionText(StandardActionManager::SynchronizeCollections, ki18np("Update Note Book", "Update %1 Note Books")); mGenericManager->action(StandardActionManager::SynchronizeCollections)->setWhatsThis( i18n("Update the content of the selected note books.")); break; case StandardActionManager::CutCollections: mGenericManager->setActionText(StandardActionManager::CutCollections, ki18np("Cut Note Book", "Cut %1 Note Books")); mGenericManager->action(StandardActionManager::CutCollections)->setWhatsThis( i18n("Cut the selected note books from the bookshelf.")); break; case StandardActionManager::CollectionProperties: mGenericManager->action(StandardActionManager::CollectionProperties)->setText( i18n("Note Book Properties...")); mGenericManager->action(StandardActionManager::CollectionProperties)->setWhatsThis( i18n("Open a dialog to edit the properties of the selected note book.")); mGenericManager->setContextText( StandardActionManager::CollectionProperties, StandardActionManager::DialogTitle, ki18nc("@title:window", "Properties of Note Book %1")); break; case StandardActionManager::CopyItems: mGenericManager->setActionText(StandardActionManager::CopyItems, ki18np("Copy Note", "Copy %1 Notes")); mGenericManager->action(StandardActionManager::CopyItems)->setWhatsThis( i18n("Copy the selected notes to the clipboard.")); break; case StandardActionManager::DeleteItems: mGenericManager->setActionText(StandardActionManager::DeleteItems, ki18np("Delete Note", "Delete %1 Notes")); mGenericManager->action(StandardActionManager::DeleteItems)->setWhatsThis( i18n("Delete the selected notes from the note book.")); mGenericManager->setContextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxText, ki18np("Do you really want to delete the selected note?", "Do you really want to delete %1 notes?")); mGenericManager->setContextText( StandardActionManager::DeleteItems, StandardActionManager::MessageBoxTitle, ki18ncp("@title:window", "Delete Note?", "Delete Notes?")); mGenericManager->setContextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageText, ki18n("Could not delete note: %1")); mGenericManager->setContextText( StandardActionManager::DeleteItems, StandardActionManager::ErrorMessageTitle, i18n("Note deletion failed")); break; case StandardActionManager::CutItems: mGenericManager->setActionText(StandardActionManager::CutItems, ki18np("Cut Note", "Cut %1 Notes")); mGenericManager->action(StandardActionManager::CutItems)->setWhatsThis( i18n("Cut the selected notes from the note book.")); break; case StandardActionManager::CreateResource: mGenericManager->action(StandardActionManager::CreateResource)->setText( i18n("Add &Bookshelf...")); mGenericManager->action(StandardActionManager::CreateResource)->setWhatsThis( i18n("Add a new bookshelf

" "You will be presented with a dialog where you can select " "the type of the bookshelf that shall be added.

")); mGenericManager->setContextText( StandardActionManager::CreateResource, StandardActionManager::DialogTitle, i18nc("@title:window", "Add Bookshelf")); mGenericManager->setContextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageText, ki18n("Could not create bookshelf: %1")); mGenericManager->setContextText( StandardActionManager::CreateResource, StandardActionManager::ErrorMessageTitle, i18n("Bookshelf creation failed")); break; case StandardActionManager::DeleteResources: mGenericManager->setActionText(StandardActionManager::DeleteResources, ki18np("&Delete Bookshelf", "&Delete %1 Bookshelfs")); mGenericManager->action(StandardActionManager::DeleteResources)->setWhatsThis( i18n("Delete the selected bookshelfs

" "The currently selected bookshelfs will be deleted, " "along with all the notes they contain.

")); mGenericManager->setContextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxText, ki18np("Do you really want to delete this bookshelf?", "Do you really want to delete %1 bookshelfs?")); mGenericManager->setContextText( StandardActionManager::DeleteResources, StandardActionManager::MessageBoxTitle, ki18ncp("@title:window", "Delete Bookshelf?", "Delete Bookshelfs?")); break; case StandardActionManager::ResourceProperties: mGenericManager->action(StandardActionManager::ResourceProperties)->setText( i18n("Bookshelf Properties...")); mGenericManager->action(StandardActionManager::ResourceProperties)->setWhatsThis( i18n("Open a dialog to edit properties of the selected bookshelf.")); break; case StandardActionManager::SynchronizeResources: mGenericManager->setActionText(StandardActionManager::SynchronizeResources, ki18np("Update Bookshelf", "Update %1 Bookshelfs")); mGenericManager->action(StandardActionManager::SynchronizeResources)->setWhatsThis (i18n("Updates the content of all note books of the selected bookshelfs.")); break; case StandardActionManager::Paste: mGenericManager->setContextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageText, ki18n("Could not paste note: %1")); mGenericManager->setContextText( StandardActionManager::Paste, StandardActionManager::ErrorMessageTitle, i18n("Paste failed")); break; default: break; } } void updateActions() { if (mItemSelectionModel && mCollectionSelectionModel) { const Collection::List collections = mParent->selectedCollections(); const Item::List items = mParent->selectedItems(); QAction *action = mActions.value(StandardNoteActionManager::Lock); if (action) { bool canLock = std::any_of(collections.cbegin(), collections.cend(), [](const Collection &collection){ return collection.isValid() && !collection.hasAttribute(); }); canLock = canLock || std::any_of(items.cbegin(), items.cend(), [](const Item &item){ return item.isValid() && !item.hasAttribute(); }); action->setEnabled(canLock); } action = mActions.value(StandardNoteActionManager::Unlock); if (action) { const bool hasLockedCollection = std::any_of(collections.cbegin(), collections.cend(), [](const Collection &collection){ return collection.isValid() && collection.hasAttribute(); }); if (hasLockedCollection) { mGenericManager->action(StandardActionManager::DeleteCollections)->setEnabled(false); } const bool hasLockedItems = std::any_of(items.cbegin(), items.cend(), [](const Item &item){ return item.isValid() && item.hasAttribute(); }); if (hasLockedItems) { mGenericManager->action(StandardActionManager::DeleteItems)->setEnabled(false); } action->setEnabled(hasLockedItems || hasLockedCollection); } } else { if (mActions.contains(StandardNoteActionManager::Lock)) { mActions[StandardNoteActionManager::Lock]->setEnabled(false); } if (mActions.contains(StandardNoteActionManager::Unlock)) { mActions[StandardNoteActionManager::Unlock]->setEnabled(false); } } Q_EMIT mParent->actionStateUpdated(); } void slotLockUnlock(bool lock) { if (!mItemSelectionModel || !mCollectionSelectionModel) { return; } if ((lock && mInterceptedActions.contains(Lock)) || (!lock && mInterceptedActions.contains(Unlock))) { return; } const Item::List items = mParent->selectedItems(); for (auto item : items) { if (item.isValid()) { if (lock) { item.addAttribute(new NoteShared::NoteLockAttribute); } else { item.removeAttribute(); } new ItemModifyJob(item, mParent); } } const Collection::List collections = mParent->selectedCollections(); for (auto collection : collections) { if (collection.isValid()) { if (lock) { collection.addAttribute(new NoteShared::NoteLockAttribute); } else { collection.removeAttribute(); } new CollectionModifyJob(collection, mParent); } } } void slotCreateNote() { if (mInterceptedActions.contains(CreateNote)) { return; } const Collection::List collections = mParent->selectedCollections(); if (collections.count() != 1) { return; } - Collection collection = collections.first(); - auto creatorAndSelector = new NoteShared::NoteCreatorAndSelector(mCollectionSelectionModel, mItemSelectionModel, mParent); - creatorAndSelector->createNote(collection); + auto *creatorAndSelector = new NoteShared::NoteCreatorAndSelector(mCollectionSelectionModel, mItemSelectionModel, mParent); + creatorAndSelector->createNote(collections.constFirst()); } void slotChangeColor() { if (mInterceptedActions.contains(ChangeColor)) { return; } QColor color = Qt::white; const Collection::List collections = mParent->selectedCollections(); const Item::List items = mParent->selectedItems(); if (collections.size() + items.size() == 1) { const EntityDisplayAttribute *attr = (collections.size() == 1) ? collections.first().attribute() : items.first().attribute();; if (attr) { color = attr->backgroundColor(); } } color = QColorDialog::getColor(color, mParentWidget); if (!color.isValid()) { return; } for (auto item : items) { item.attribute(Item::AddIfMissing)->setBackgroundColor(color); new ItemModifyJob(item, mParent); } for (auto collection : collections) { collection.attribute(Collection::AddIfMissing)->setBackgroundColor(color); new CollectionModifyJob(collection, mParent); } } KActionCollection *mActionCollection = nullptr; QWidget *mParentWidget = nullptr; std::unique_ptr mGenericManager; QItemSelectionModel *mCollectionSelectionModel = nullptr; QItemSelectionModel *mItemSelectionModel = nullptr; QHash mActions; QSet mInterceptedActions; StandardNoteActionManager *mParent = nullptr; }; StandardNoteActionManager::StandardNoteActionManager(KActionCollection *actionCollection, QWidget *parent) : QObject(parent) , d(std::make_unique(actionCollection, parent, this)) { } StandardNoteActionManager::~StandardNoteActionManager() = default; void StandardNoteActionManager::setCollectionSelectionModel(QItemSelectionModel *selectionModel) { d->mCollectionSelectionModel = selectionModel; d->mGenericManager->setCollectionSelectionModel(selectionModel); connect(selectionModel->model(), &QAbstractItemModel::dataChanged, this, [this]() { d->updateActions(); }); connect(selectionModel->model(), &QAbstractItemModel::rowsInserted, this, [this]() { d->updateActions(); }); connect(selectionModel->model(), &QAbstractItemModel::rowsRemoved, this, [this]() { d->updateActions(); }); connect(selectionModel, &QItemSelectionModel::selectionChanged, this, [this]() { d->updateActions(); }); d->updateActions(); } void StandardNoteActionManager::setItemSelectionModel(QItemSelectionModel *selectionModel) { d->mItemSelectionModel = selectionModel; d->mGenericManager->setItemSelectionModel(selectionModel); connect(selectionModel->model(), &QAbstractItemModel::dataChanged, this, [this]() { d->updateActions(); }); connect(selectionModel, &QItemSelectionModel::selectionChanged, this, [this]() { d->updateActions(); }); d->updateActions(); } QAction *StandardNoteActionManager::createAction(Type type) { QAction *action = d->mActions.value(type); if (action) { return action; } switch (type) { case CreateNote: action = new QAction(d->mParentWidget); action->setIcon(QIcon::fromTheme(QStringLiteral("document-new"))); action->setText(i18n("&New Note")); action->setWhatsThis(i18n("Add a new note to a selected note book")); d->mActions.insert(CreateNote, action); d->mActionCollection->addAction(QStringLiteral("akonadi_note_create"), action); d->mActionCollection->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_N)); connect(action, &QAction::triggered, this, [this](){ d->slotCreateNote(); }); break; case Lock: action = new QAction(d->mParentWidget); action->setIcon(QIcon::fromTheme(QStringLiteral("emblem-locked"))); action->setText(i18n("Lock Selected")); action->setWhatsThis(i18n("Lock selected note book or notes")); d->mActions.insert(Lock, action); d->mActionCollection->addAction(QStringLiteral("akonadi_note_lock"), action); connect(action, &QAction::triggered, this, [this]() { d->slotLockUnlock(true); }); break; case Unlock: action = new QAction(d->mParentWidget); action->setIcon(QIcon::fromTheme(QStringLiteral("emblem-unlocked"))); action->setText(i18n("Unlock Selected")); action->setWhatsThis(i18n("Unlock selected note books or notes")); d->mActions.insert(Unlock, action); d->mActionCollection->addAction(QStringLiteral("akonadi_note_unlock"), action); connect(action, &QAction::triggered, this, [this]() { d->slotLockUnlock(false); }); break; case ChangeColor: action = new QAction(d->mParentWidget); action->setIcon(QIcon::fromTheme(QStringLiteral("format-fill-color"))); action->setText(i18n("Change Color...")); action->setWhatsThis(i18n("Changes the color of a selected note books or notes")); d->mActions.insert(ChangeColor, action); d->mActionCollection->addAction(QStringLiteral("akonadi_change_color"), action); connect(action, &QAction::triggered, this, [this](){ d->slotChangeColor(); }); break; default: Q_ASSERT(false); // should never happen break; } return action; } QAction *StandardNoteActionManager::createAction(StandardActionManager::Type type) { QAction *act = d->mGenericManager->action(type); if (!act) { act = d->mGenericManager->createAction(type); } d->updateGenericAction(type); return act; } void StandardNoteActionManager::createAllActions() { (void)createAction(CreateNote); (void)createAction(Lock); (void)createAction(Unlock); (void)createAction(ChangeColor); d->mGenericManager->createAllActions(); d->updateGenericAllActions(); d->updateActions(); } QAction *StandardNoteActionManager::action(Type type) const { if (d->mActions.contains(type)) { return d->mActions.value(type); } return nullptr; } QAction *StandardNoteActionManager::action(StandardActionManager::Type type) const { return d->mGenericManager->action(type); } void StandardNoteActionManager::setActionText(StandardActionManager::Type type, const KLocalizedString &text) { d->mGenericManager->setActionText(type, text); } void StandardNoteActionManager::interceptAction(Type type, bool intercept) { if (intercept) { d->mInterceptedActions.insert(type); } else { d->mInterceptedActions.remove(type); } } void StandardNoteActionManager::interceptAction(StandardActionManager::Type type, bool intercept) { d->mGenericManager->interceptAction(type, intercept); } Collection::List StandardNoteActionManager::selectedCollections() const { return d->mGenericManager->selectedCollections(); } Item::List StandardNoteActionManager::selectedItems() const { return d->mGenericManager->selectedItems(); } void StandardNoteActionManager::setCollectionPropertiesPageNames(const QStringList &names) { d->mGenericManager->setCollectionPropertiesPageNames(names); }