mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 10:22:50 +00:00
1851 lines
60 KiB
C++
1851 lines
60 KiB
C++
/*
|
|
This file is part of KJots.
|
|
|
|
Copyright (C) 1997 Christoph Neerfeld <Christoph.Neerfeld@home.ivm.de>
|
|
Copyright (C) 2002, 2003 Aaron J. Seigo <aseigo@kde.org>
|
|
Copyright (C) 2003 Stanislav Kljuhhin <crz@hot.ee>
|
|
Copyright (C) 2005-2006 Jaison Lee <lee.jaison@gmail.com>
|
|
Copyright (C) 2007-2009 Stephen Kelly <steveire@gmail.com>
|
|
|
|
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 <QHBoxLayout>
|
|
#include <QInputDialog>
|
|
#include <QSplitter>
|
|
#include <QStackedWidget>
|
|
#include <QTextCursor>
|
|
#include <QTextDocument>
|
|
#include <QTextDocumentFragment>
|
|
#include <QTimer>
|
|
#include <QPrintDialog>
|
|
#include <QPainter>
|
|
#include <QPointer>
|
|
#include <QPrinter>
|
|
#include <QAbstractTextDocumentLayout>
|
|
#include <QDBusConnection>
|
|
|
|
// Akonadi
|
|
#include <akonadi/control.h>
|
|
#include <akonadi/collectiondeletejob.h>
|
|
#include <akonadi/collectioncreatejob.h>
|
|
#include <akonadi/changerecorder.h>
|
|
#include <akonadi/entitydisplayattribute.h>
|
|
#include <akonadi/entitytreeview.h>
|
|
#include <akonadi/etmviewstatesaver.h>
|
|
#include <akonadi/item.h>
|
|
#include <Akonadi/ItemCreateJob>
|
|
#include <Akonadi/ItemDeleteJob>
|
|
#include <akonadi/itemfetchjob.h>
|
|
#include <akonadi/itemfetchscope.h>
|
|
|
|
#include "akonadi/entityorderproxymodel.h"
|
|
#include "akonadi_next/note.h"
|
|
#include "akonadi_next/notecreatorandselector.h"
|
|
|
|
// Grantlee
|
|
#include <grantlee/template.h>
|
|
#include <grantlee/engine.h>
|
|
#include <grantlee/context.h>
|
|
|
|
// KDE
|
|
#include <KAction>
|
|
#include <KActionCollection>
|
|
#include <KBookmarkMenu>
|
|
#include <KFileDialog>
|
|
#include <KFind>
|
|
#include <KFindDialog>
|
|
#include <KLocalizedString>
|
|
#include <KMessageBox>
|
|
#include <KReplaceDialog>
|
|
#include <kselectionproxymodel.h>
|
|
#include <KStandardDirs>
|
|
#include <KGlobalSettings>
|
|
#include <KXMLGUIClient>
|
|
#include <KProcess>
|
|
#include <KPrintPreview>
|
|
|
|
// KMime
|
|
#include <KMime/KMimeMessage>
|
|
|
|
// KJots
|
|
#include "kjotsbookmarks.h"
|
|
#include "kjotssortproxymodel.h"
|
|
#include "kjotsmodel.h"
|
|
#include "kjotsedit.h"
|
|
#include "kjotstreeview.h"
|
|
#include "kjotsconfigdlg.h"
|
|
#include "kjotsreplacenextdialog.h"
|
|
#include "KJotsSettings.h"
|
|
#include "kjotslockjob.h"
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <memory>
|
|
#include "noteshared/attributes/notelockattribute.h"
|
|
#include "localresourcecreator.h"
|
|
#include <krandom.h>
|
|
#include "kjotsbrowser.h"
|
|
|
|
#ifndef KDE_USE_FINAL
|
|
Q_DECLARE_METATYPE(QTextDocument*)
|
|
Q_DECLARE_METATYPE(QTextCursor)
|
|
#endif
|
|
using namespace Akonadi;
|
|
using namespace Grantlee;
|
|
|
|
KJotsWidget::KJotsWidget( QWidget * parent, KXMLGUIClient *xmlGuiClient, Qt::WindowFlags f )
|
|
: QWidget( parent, f ), m_xmlGuiClient( xmlGuiClient )
|
|
{
|
|
Akonadi::Control::widgetNeedsAkonadi( this );
|
|
|
|
KConfigGroup migrationCfg( KGlobal::config(), "General" );
|
|
const bool autoCreate = migrationCfg.readEntry( "AutoCreateResourceOnStart", true );
|
|
migrationCfg.writeEntry("AutoCreateResourceOnStart", autoCreate);
|
|
migrationCfg.sync();
|
|
if (autoCreate) {
|
|
LocalResourceCreator *creator = new LocalResourceCreator( this );
|
|
creator->createIfMissing();
|
|
}
|
|
|
|
m_splitter = new QSplitter( this );
|
|
|
|
m_splitter->setStretchFactor(1, 1);
|
|
m_splitter->setOpaqueResize( KGlobalSettings::opaqueResize() );
|
|
|
|
QHBoxLayout *layout = new QHBoxLayout( this );
|
|
layout->setMargin( 0 );
|
|
|
|
KStandardDirs KStd;
|
|
m_templateEngine = new Engine(this);
|
|
m_templateEngine->setPluginPaths( KStd.findDirs( "lib", QString() ) );
|
|
|
|
m_loader = FileSystemTemplateLoader::Ptr( new FileSystemTemplateLoader() );
|
|
m_loader->setTemplateDirs( KStd.findDirs( "data", QLatin1String( "kjots/themes" ) ) );
|
|
m_loader->setTheme( QLatin1String( "default" ) );
|
|
|
|
m_templateEngine->addTemplateLoader( m_loader );
|
|
|
|
treeview = new KJotsTreeView( xmlGuiClient, m_splitter );
|
|
|
|
ItemFetchScope scope;
|
|
scope.fetchFullPayload( true ); // Need to have full item when adding it to the internal data structure
|
|
scope.fetchAttribute< EntityDisplayAttribute >();
|
|
scope.fetchAttribute< NoteShared::NoteLockAttribute >();
|
|
|
|
ChangeRecorder *monitor = new ChangeRecorder( this );
|
|
monitor->fetchCollection( true );
|
|
monitor->setItemFetchScope( scope );
|
|
monitor->setCollectionMonitored( Collection::root() );
|
|
monitor->setMimeTypeMonitored( Akonotes::Note::mimeType() );
|
|
|
|
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( KGlobal::config(), "KJotsEntityOrder" );
|
|
|
|
m_orderProxy->setOrderConfig( cfg );
|
|
|
|
treeview->setModel( m_orderProxy );
|
|
treeview->setSelectionMode( QAbstractItemView::ExtendedSelection );
|
|
treeview->setEditTriggers( QAbstractItemView::DoubleClicked );
|
|
|
|
connect( treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(selectionChanged(QItemSelection,QItemSelection)) );
|
|
|
|
selProxy = new KSelectionProxyModel( treeview->selectionModel(), this );
|
|
selProxy->setSourceModel( treeview->model() );
|
|
|
|
// TODO: Write a QAbstractItemView subclass to render kjots selection.
|
|
connect( selProxy, SIGNAL(dataChanged(QModelIndex,QModelIndex)), SLOT(renderSelection()) );
|
|
connect( selProxy, SIGNAL(rowsInserted(QModelIndex,int,int)), SLOT(renderSelection()) );
|
|
connect( selProxy, SIGNAL(rowsRemoved(QModelIndex,int,int)), SLOT(renderSelection()) );
|
|
|
|
|
|
stackedWidget = new QStackedWidget( m_splitter );
|
|
|
|
KActionCollection *actionCollection = xmlGuiClient->actionCollection();
|
|
|
|
editor = new KJotsEdit( treeview->selectionModel(), stackedWidget );
|
|
editor->createActions( actionCollection );
|
|
stackedWidget->addWidget( editor );
|
|
|
|
layout->addWidget( m_splitter );
|
|
|
|
browser = new KJotsBrowser( treeview->selectionModel(), stackedWidget );
|
|
stackedWidget->addWidget( browser );
|
|
stackedWidget->setCurrentWidget( browser );
|
|
|
|
|
|
KAction *action;
|
|
|
|
action = actionCollection->addAction( QLatin1String("go_next_book") );
|
|
action->setText( i18n( "Next Book" ) );
|
|
action->setIcon( KIcon( QLatin1String("go-down") ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_D ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(nextBook()) );
|
|
connect( this, SIGNAL(canGoNextBookChanged(bool)), action, SLOT(setEnabled(bool)) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("go_prev_book") );
|
|
action->setText( i18n( "Previous Book" ) );
|
|
action->setIcon( KIcon( QLatin1String("go-up") ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_D ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(prevBook()) );
|
|
connect( this, SIGNAL(canGoPreviousBookChanged(bool)), action, SLOT(setEnabled(bool)) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("go_next_page") );
|
|
action->setText( i18n( "Next Page" ) );
|
|
action->setIcon( KIcon( QLatin1String("go-next") ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_PageDown ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(nextPage()));
|
|
connect( this, SIGNAL(canGoNextPageChanged(bool)), action, SLOT(setEnabled(bool)) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("go_prev_page") );
|
|
action->setText( i18n( "Previous Page" ) );
|
|
action->setIcon( KIcon( QLatin1String("go-previous") ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_PageUp ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(prevPage()) );
|
|
connect( this, SIGNAL(canGoPreviousPageChanged(bool)), action, SLOT(setEnabled(bool)) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("new_page") );
|
|
action->setText( i18n( "&New Page" ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_N ) );
|
|
action->setIcon( KIcon( QLatin1String("document-new") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(newPage()) );
|
|
|
|
action = actionCollection->addAction(QLatin1String("new_book"));
|
|
action->setText( i18n( "New &Book..." ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_N ) );
|
|
action->setIcon( KIcon( QLatin1String("address-book-new") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(newBook()) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("del_page") );
|
|
action->setText( i18n( "&Delete Page" ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_Delete ) );
|
|
action->setIcon( KIcon( QLatin1String("edit-delete-page") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(deletePage()) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("del_folder") );
|
|
action->setText( i18n( "Delete Boo&k" ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_Delete ) );
|
|
action->setIcon( KIcon( QLatin1String("edit-delete") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(deleteBook()) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("del_mult") );
|
|
action->setText( i18n( "Delete Selected" ) );
|
|
action->setIcon( KIcon( QLatin1String("edit-delete") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(deleteMultiple()) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("manual_save") );
|
|
action->setText( i18n( "Manual Save" ) );
|
|
action->setIcon( KIcon( QLatin1String("document-save") ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_S ) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("auto_bullet") );
|
|
action->setText( i18n( "Auto Bullets" ) );
|
|
action->setIcon( KIcon( QLatin1String("format-list-unordered") ) );
|
|
action->setCheckable( true );
|
|
|
|
action = actionCollection->addAction( QLatin1String("auto_decimal") );
|
|
action->setText( i18n( "Auto Decimal List" ) );
|
|
action->setIcon( KIcon( QLatin1String("format-list-ordered") ) );
|
|
action->setCheckable( true );
|
|
|
|
action = actionCollection->addAction( QLatin1String("manage_link") );
|
|
action->setText( i18n( "Link" ) );
|
|
action->setIcon( KIcon( QLatin1String("insert-link") ) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("insert_checkmark") );
|
|
action->setText( i18n( "Insert Checkmark" ) );
|
|
action->setIcon( KIcon( QLatin1String("checkmark") ) );
|
|
action->setEnabled( false );
|
|
|
|
action = actionCollection->addAction( QLatin1String("rename_entry") );
|
|
action->setText( i18n( "Rename..." ) );
|
|
action->setIcon( KIcon( QLatin1String("edit-rename") ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_M ) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("insert_date") );
|
|
action->setText( i18n( "Insert Date" ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_I ) );
|
|
action->setIcon( KIcon( QLatin1String("view-calendar-time-spent") ) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("change_color") );
|
|
action->setIcon( KIcon( QLatin1String("format-fill-color") ) );
|
|
action->setText( i18n( "Change Color..." ) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("copy_link_address") );
|
|
action->setText( i18n( "Copy Link Address" ) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("lock") );
|
|
action->setText(i18n( "Lock Selected" ) );
|
|
action->setIcon( KIcon( QLatin1String("emblem-locked") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(actionLock()) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("unlock") );
|
|
action->setText( i18n( "Unlock Selected" ) );
|
|
action->setIcon( KIcon( QLatin1String("emblem-unlocked") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(actionUnlock()) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("sort_children_alpha") );
|
|
action->setText( i18n( "Sort children alphabetically" ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(actionSortChildrenAlpha()) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("sort_children_by_date") );
|
|
action->setText( i18n( "Sort children by creation date" ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(actionSortChildrenByDate()) );
|
|
|
|
action = KStandardAction::cut( editor, SLOT(cut()), actionCollection );
|
|
connect( editor, SIGNAL(copyAvailable(bool)), action, SLOT(setEnabled(bool)) );
|
|
action->setEnabled( false );
|
|
|
|
action = KStandardAction::copy( this, SLOT(copy()), actionCollection );
|
|
connect( editor, SIGNAL(copyAvailable(bool)), action, SLOT(setEnabled(bool)) );
|
|
connect( browser, SIGNAL(copyAvailable(bool)), action, SLOT(setEnabled(bool)) );
|
|
action->setEnabled( false );
|
|
|
|
KStandardAction::pasteText( editor, SLOT(paste()), actionCollection );
|
|
|
|
KStandardAction::undo( editor, SLOT(undo()), actionCollection );
|
|
KStandardAction::redo( editor, SLOT(redo()), actionCollection );
|
|
KStandardAction::selectAll( editor, SLOT(selectAll()), actionCollection );
|
|
|
|
action = actionCollection->addAction( QLatin1String("copyIntoTitle") );
|
|
action->setText( i18n( "Copy &into Page Title" ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_T ) );
|
|
action->setIcon( KIcon( QLatin1String("edit-copy") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(copySelectionToTitle()) );
|
|
connect( editor, SIGNAL(copyAvailable(bool)), action, SLOT(setEnabled(bool)) );
|
|
action->setEnabled( false );
|
|
|
|
action = actionCollection->addAction( QLatin1String("paste_plain_text") );
|
|
action->setText( i18nc( "@action Paste the text in the clipboard without rich text formatting.", "Paste Plain Text" ) );
|
|
connect( action, SIGNAL(triggered()), editor, SLOT(pastePlainText()) );
|
|
|
|
KStandardAction::preferences( this, SLOT(configure()), actionCollection );
|
|
|
|
bookmarkMenu = actionCollection->add<KActionMenu>( QLatin1String("bookmarks") );
|
|
bookmarkMenu->setText( i18n( "&Bookmarks" ) );
|
|
KJotsBookmarks* bookmarks = new KJotsBookmarks( treeview );
|
|
/*KBookmarkMenu *bmm =*/ new KBookmarkMenu(
|
|
KBookmarkManager::managerForFile( KStandardDirs::locateLocal( "data",QLatin1String("kjots/bookmarks.xml") ), QLatin1String("kjots") ),
|
|
bookmarks, bookmarkMenu->menu(), actionCollection );
|
|
|
|
// "Add bookmark" and "make text bold" actions have conflicting shortcuts (ctrl + b)
|
|
// Make add_bookmark use ctrl+shift+b to resolve that.
|
|
KAction *bm_action = qobject_cast<KAction *>(actionCollection->action(QLatin1String("add_bookmark")));
|
|
Q_ASSERT(bm_action);
|
|
bm_action->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_B );
|
|
|
|
KStandardAction::find( this, SLOT(onShowSearch()), actionCollection );
|
|
action = KStandardAction::findNext( this, SLOT(onRepeatSearch()), actionCollection );
|
|
action->setEnabled(false);
|
|
KStandardAction::replace( this, SLOT(onShowReplace()), actionCollection );
|
|
|
|
action = actionCollection->addAction( QLatin1String("save_to") );
|
|
action->setText( i18n( "Rename..." ) );
|
|
action->setIcon( KIcon( QLatin1String("edit-rename") ) );
|
|
action->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_M ) );
|
|
|
|
KActionMenu *exportMenu = actionCollection->add<KActionMenu>( QLatin1String("save_to") );
|
|
exportMenu->setText( i18n( "Export" ) );
|
|
exportMenu->setIcon( KIcon( QLatin1String("document-export") ) );
|
|
|
|
action = actionCollection->addAction( QLatin1String("save_to_ascii") );
|
|
action->setText( i18n( "To Text File..." ) );
|
|
action->setIcon( KIcon( QLatin1String("text-plain") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(exportSelectionToPlainText()) );
|
|
exportMenu->menu()->addAction( action );
|
|
|
|
action = actionCollection->addAction( QLatin1String("save_to_html") );
|
|
action->setText( i18n( "To HTML File..." ) );
|
|
action->setIcon( KIcon( QLatin1String("text-html") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(exportSelectionToHtml()) );
|
|
exportMenu->menu()->addAction( action );
|
|
|
|
action = actionCollection->addAction( QLatin1String("save_to_book") );
|
|
action->setText( i18n( "To Book File..." ) );
|
|
action->setIcon( KIcon( QLatin1String("x-office-address-book") ) );
|
|
connect( action, SIGNAL(triggered()), SLOT(exportSelectionToXml()) );
|
|
exportMenu->menu()->addAction( action );
|
|
|
|
KStandardAction::print(this, SLOT(printSelection()), actionCollection);
|
|
KStandardAction::printPreview(this, SLOT(printPreviewSelection()), actionCollection);
|
|
|
|
if ( !KJotsSettings::splitterSizes().isEmpty() )
|
|
{
|
|
m_splitter->setSizes( KJotsSettings::splitterSizes() );
|
|
}
|
|
|
|
QTimer::singleShot( 0, this, SLOT(delayedInitialization()) );
|
|
|
|
connect( treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(updateMenu()) );
|
|
connect( treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(updateCaption()) );
|
|
|
|
connect( m_kjotsModel, SIGNAL(modelAboutToBeReset()), SLOT(saveState()));
|
|
connect( m_kjotsModel, SIGNAL(modelReset()), SLOT(restoreState()));
|
|
|
|
restoreState();
|
|
|
|
QDBusConnection::sessionBus().registerObject( QLatin1String("/KJotsWidget"), this, QDBusConnection::ExportScriptableContents );
|
|
}
|
|
|
|
KJotsWidget::~KJotsWidget()
|
|
{
|
|
saveState();
|
|
}
|
|
|
|
void KJotsWidget::restoreState()
|
|
{
|
|
ETMViewStateSaver *saver = new ETMViewStateSaver;
|
|
saver->setView( treeview );
|
|
KConfigGroup cfg( KGlobal::config(), "TreeState" );
|
|
saver->restoreState( cfg );
|
|
}
|
|
|
|
void KJotsWidget::saveState()
|
|
{
|
|
ETMViewStateSaver saver;
|
|
saver.setView( treeview );
|
|
KConfigGroup cfg( KGlobal::config(), "TreeState" );
|
|
saver.saveState( cfg );
|
|
cfg.sync();
|
|
}
|
|
|
|
void KJotsWidget::delayedInitialization()
|
|
{
|
|
migrateNoteData( QLatin1String("kjotsmigrator") );
|
|
// Disable nigration of data from KNotes as that app still exists in 4.5.
|
|
// migrateNoteData( "kres-migrator", "notes" );
|
|
|
|
//TODO: Save previous searches in settings file?
|
|
searchDialog = new KFindDialog ( this, 0, QStringList(), false );
|
|
QGridLayout *layout = new QGridLayout(searchDialog->findExtension());
|
|
layout->setMargin(0);
|
|
searchAllPages = new QCheckBox(i18n("Search all pages"), searchDialog->findExtension());
|
|
layout->addWidget(searchAllPages, 0, 0);
|
|
|
|
connect(searchDialog, SIGNAL(okClicked()), this, SLOT(onStartSearch()) );
|
|
connect(searchDialog, SIGNAL(cancelClicked()), this, SLOT(onEndSearch()) );
|
|
connect(treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(onUpdateSearch()) );
|
|
connect(searchDialog, SIGNAL(optionsChanged()), SLOT(onUpdateSearch()) );
|
|
connect(searchAllPages, SIGNAL(stateChanged(int)), SLOT(onUpdateSearch()) );
|
|
|
|
replaceDialog = new KReplaceDialog ( this, 0, searchHistory, replaceHistory, false );
|
|
QGridLayout *layout2 = new QGridLayout(replaceDialog->findExtension());
|
|
layout2->setMargin(0);
|
|
replaceAllPages = new QCheckBox(i18n("Search all pages"), replaceDialog->findExtension());
|
|
layout2->addWidget(replaceAllPages, 0, 0);
|
|
|
|
connect(replaceDialog, SIGNAL(okClicked()), this, SLOT(onStartReplace()) );
|
|
connect(replaceDialog, SIGNAL(cancelClicked()), this, SLOT(onEndReplace()) );
|
|
connect(replaceDialog, SIGNAL(optionsChanged()), SLOT(onUpdateReplace()) );
|
|
connect(replaceAllPages, SIGNAL(stateChanged(int)), SLOT(onUpdateReplace()) );
|
|
|
|
// Actions are enabled or disabled based on whether the selection is a single page, a single book
|
|
// multiple selections, or no selection.
|
|
//
|
|
// The entryActions are enabled for all single pages and single books, and the multiselectionActions
|
|
// are enabled when the user has made multiple selections.
|
|
//
|
|
// Some actions are in neither (eg, new book) and are available even when there is no selection.
|
|
//
|
|
// Some actions are in both, so that they are available for valid selections, but not available
|
|
// for invalid selections (eg, print/find are disabled when there is no selection)
|
|
|
|
KActionCollection *actionCollection = m_xmlGuiClient->actionCollection();
|
|
|
|
// Actions for a single item selection.
|
|
entryActions.insert( actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Find))) );
|
|
entryActions.insert( actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Print))) );
|
|
entryActions.insert( actionCollection->action(QLatin1String("rename_entry")) );
|
|
entryActions.insert( actionCollection->action(QLatin1String("change_color")) );
|
|
entryActions.insert( actionCollection->action(QLatin1String("save_to")) );
|
|
entryActions.insert( actionCollection->action(QLatin1String("copy_link_address")) );
|
|
|
|
// Actions that are used only when a page is selected.
|
|
pageActions.insert( actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Cut))) );
|
|
pageActions.insert( actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Paste))) );
|
|
pageActions.insert( actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Replace))) );
|
|
pageActions.insert( actionCollection->action(QLatin1String("del_page")) );
|
|
pageActions.insert( actionCollection->action(QLatin1String("insert_date")) );
|
|
pageActions.insert( actionCollection->action(QLatin1String("auto_bullet")) );
|
|
pageActions.insert( actionCollection->action(QLatin1String("auto_decimal")) );
|
|
pageActions.insert( actionCollection->action(QLatin1String("manage_link")) );
|
|
pageActions.insert( actionCollection->action(QLatin1String("insert_checkmark")) );
|
|
|
|
// Actions that are used only when a book is selected.
|
|
bookActions.insert( actionCollection->action(QLatin1String("save_to_book")) );
|
|
bookActions.insert( actionCollection->action(QLatin1String("del_folder")) );
|
|
bookActions.insert( actionCollection->action(QLatin1String("sort_children_alpha")) );
|
|
bookActions.insert( actionCollection->action(QLatin1String("sort_children_by_date")) );
|
|
|
|
// Actions that are used when multiple items are selected.
|
|
multiselectionActions.insert( actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Find))) );
|
|
multiselectionActions.insert( actionCollection->action(QLatin1String(KStandardAction::name(KStandardAction::Print))));
|
|
multiselectionActions.insert( actionCollection->action(QLatin1String("del_mult")) );
|
|
multiselectionActions.insert( actionCollection->action(QLatin1String("save_to")) );
|
|
multiselectionActions.insert( actionCollection->action(QLatin1String("change_color")) );
|
|
|
|
m_autosaveTimer = new QTimer(this);
|
|
updateConfiguration();
|
|
|
|
connect(m_autosaveTimer, SIGNAL(timeout()), editor, SLOT(savePage()));
|
|
connect(treeview->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), m_autosaveTimer, SLOT(start()) );
|
|
|
|
treeview->delayedInitialization();
|
|
editor->delayedInitialization( m_xmlGuiClient->actionCollection() );
|
|
browser->delayedInitialization();
|
|
|
|
|
|
connect( treeview->itemDelegate(), SIGNAL(closeEditor(QWidget*,QAbstractItemDelegate::EndEditHint)),
|
|
SLOT(bookshelfEditItemFinished(QWidget*,QAbstractItemDelegate::EndEditHint)) );
|
|
|
|
connect( editor, SIGNAL(currentCharFormatChanged(QTextCharFormat)),
|
|
SLOT(currentCharFormatChanged(QTextCharFormat)) );
|
|
updateMenu();
|
|
}
|
|
|
|
void KJotsWidget::bookshelfEditItemFinished( QWidget *, QAbstractItemDelegate::EndEditHint )
|
|
{
|
|
// Make sure the editor gets focus again after naming a new book/page.
|
|
activeEditor()->setFocus();
|
|
}
|
|
|
|
void KJotsWidget::currentCharFormatChanged(const QTextCharFormat & fmt)
|
|
{
|
|
QString selectedAnchor = fmt.anchorHref();
|
|
if (selectedAnchor != activeAnchor)
|
|
{
|
|
activeAnchor = selectedAnchor;
|
|
if (!selectedAnchor.isEmpty())
|
|
{
|
|
QTextCursor c(editor->textCursor());
|
|
editor->selectLinkText(&c);
|
|
QString selectedText = c.selectedText();
|
|
if (!selectedText.isEmpty())
|
|
{
|
|
emit activeAnchorChanged(selectedAnchor, selectedText);
|
|
}
|
|
} else {
|
|
emit activeAnchorChanged(QString(), QString());
|
|
}
|
|
}
|
|
}
|
|
|
|
void KJotsWidget::migrateNoteData( const QString &migrator, const QString &type )
|
|
{
|
|
// Akonadi migration
|
|
KConfig config( migrator + QLatin1String("rc") );
|
|
KConfigGroup migrationCfg( &config, "Migration" );
|
|
const bool enabled = migrationCfg.readEntry( "Enabled", true );
|
|
const bool completed = migrationCfg.readEntry( "Completed", false );
|
|
const int currentVersion = migrationCfg.readEntry( "Version", 0 );
|
|
const int targetVersion = migrationCfg.readEntry( "TargetVersion", 1 );
|
|
if ( enabled && !completed && currentVersion < targetVersion ) {
|
|
kDebug() << "Performing Akonadi migration. Good luck!";
|
|
KProcess proc;
|
|
QStringList args = QStringList() << QLatin1String("--interactive-on-change");
|
|
if ( !type.isEmpty() )
|
|
args << QLatin1String("--type") << type;
|
|
|
|
const QString path = KStandardDirs::findExe( migrator );
|
|
proc.setProgram( path, args );
|
|
proc.start();
|
|
bool result = proc.waitForStarted();
|
|
if ( result ) {
|
|
result = proc.waitForFinished();
|
|
}
|
|
if ( result && proc.exitCode() == 0 ) {
|
|
kDebug() << "Akonadi migration has been successful";
|
|
} else {
|
|
// exit code 1 means it is already running, so we are probably called by a migrator instance
|
|
kError() << "Akonadi migration failed!";
|
|
kError() << "command was: " << proc.program();
|
|
kError() << "exit code: " << proc.exitCode();
|
|
kError() << "stdout: " << proc.readAllStandardOutput();
|
|
kError() << "stderr: " << proc.readAllStandardError();
|
|
}
|
|
migrationCfg.writeEntry( "Version", targetVersion );
|
|
migrationCfg.writeEntry( "Completed", true );
|
|
migrationCfg.sync();
|
|
}
|
|
}
|
|
|
|
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
|
|
foreach ( QAction* action, multiselectionActions )
|
|
action->setEnabled(false);
|
|
foreach ( QAction* action, entryActions )
|
|
action->setEnabled(false);
|
|
foreach ( QAction* action, bookActions )
|
|
action->setEnabled(false);
|
|
foreach ( QAction* action, pageActions )
|
|
action->setEnabled(false);
|
|
editor->setActionsEnabled( false );
|
|
} else if ( selectionSize > 1 ) {
|
|
foreach ( QAction* action, entryActions )
|
|
action->setEnabled(false);
|
|
foreach ( QAction* action, bookActions )
|
|
action->setEnabled(false);
|
|
foreach ( QAction* action, pageActions )
|
|
action->setEnabled(false);
|
|
foreach ( QAction* action, multiselectionActions )
|
|
action->setEnabled(true);
|
|
|
|
editor->setActionsEnabled( false );
|
|
} else {
|
|
|
|
foreach ( QAction* action, multiselectionActions )
|
|
action->setEnabled(false);
|
|
foreach ( QAction* action, entryActions )
|
|
action->setEnabled(true);
|
|
|
|
QModelIndex idx = selection.at( 0 );
|
|
|
|
Collection col = idx.data( KJotsModel::CollectionRole ).value<Collection>();
|
|
if ( col.isValid() ) {
|
|
foreach ( QAction* action, pageActions )
|
|
action->setEnabled(false);
|
|
const bool colIsRootCollection = ( col.parentCollection() == Collection::root() );
|
|
foreach ( QAction* action, bookActions ) {
|
|
if (action->objectName() == QLatin1String("del_folder") && colIsRootCollection ) {
|
|
action->setEnabled( false );
|
|
} else {
|
|
action->setEnabled( true );
|
|
}
|
|
|
|
}
|
|
|
|
editor->setActionsEnabled( false );
|
|
} else {
|
|
foreach ( QAction* action, pageActions ) {
|
|
if (action->objectName() == QLatin1String(name( KStandardAction::Cut )) ) {
|
|
action->setEnabled( activeEditor()->textCursor().hasSelection() );
|
|
} else {
|
|
action->setEnabled( true );
|
|
}
|
|
}
|
|
foreach ( QAction* action, bookActions )
|
|
action->setEnabled( false );
|
|
editor->setActionsEnabled( true );
|
|
}
|
|
}
|
|
}
|
|
|
|
void KJotsWidget::copy() {
|
|
activeEditor()->copy();
|
|
}
|
|
|
|
void KJotsWidget::configure()
|
|
{
|
|
// create a new preferences dialog...
|
|
KJotsConfigDlg *dialog = new KJotsConfigDlg( i18n( "Settings" ), this );
|
|
connect( dialog, SIGNAL(configCommitted()), SLOT(updateConfiguration()) );
|
|
dialog->show();
|
|
}
|
|
|
|
void KJotsWidget::updateConfiguration()
|
|
{
|
|
if (KJotsSettings::autoSave())
|
|
{
|
|
m_autosaveTimer->setInterval(KJotsSettings::autoSaveInterval()*1000*60);
|
|
m_autosaveTimer->start();
|
|
} else
|
|
m_autosaveTimer->stop();
|
|
}
|
|
|
|
void KJotsWidget::copySelectionToTitle()
|
|
{
|
|
QString newTitle( editor->textCursor().selectedText() );
|
|
|
|
if ( !newTitle.isEmpty() ) {
|
|
|
|
QModelIndexList rows = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( rows.size() != 1 )
|
|
return;
|
|
|
|
QModelIndex idx = rows.at( 0 );
|
|
|
|
treeview->model()->setData( idx, newTitle );
|
|
}
|
|
}
|
|
|
|
void KJotsWidget::deleteMultiple()
|
|
{
|
|
QModelIndexList selectedRows = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( KMessageBox::questionYesNo( this,
|
|
i18n( "Do you really want to delete all selected books and pages?" ),
|
|
i18n("Delete?"), KStandardGuiItem::del(), KStandardGuiItem::cancel(),
|
|
QString(), KMessageBox::Dangerous ) != KMessageBox::Yes )
|
|
return;
|
|
|
|
foreach ( const QModelIndex &index, selectedRows ) {
|
|
bool ok;
|
|
qlonglong id = index.data( EntityTreeModel::ItemIdRole ).toLongLong(&ok);
|
|
Q_ASSERT(ok);
|
|
if ( id >= 0 )
|
|
{
|
|
new ItemDeleteJob( Item( id ), this );
|
|
}
|
|
else {
|
|
id = index.data( EntityTreeModel::CollectionIdRole ).toLongLong(&ok);
|
|
Q_ASSERT(ok);
|
|
if ( id >= 0 )
|
|
new CollectionDeleteJob( Collection( id ), this );
|
|
}
|
|
}
|
|
}
|
|
|
|
void KJotsWidget::deletePage()
|
|
{
|
|
QModelIndexList selectedRows = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( selectedRows.size() != 1 )
|
|
return;
|
|
|
|
const QModelIndex idx = selectedRows.at( 0 );
|
|
Item item = idx.data( EntityTreeModel::ItemRole ).value<Item>();
|
|
|
|
if ( !item.isValid() )
|
|
return;
|
|
|
|
if( item.hasAttribute<NoteShared::NoteLockAttribute>() ) {
|
|
|
|
KMessageBox::information(topLevelWidget(),
|
|
i18n("This page is locked. You can only delete it when you first unlock it."),
|
|
i18n("Item is locked"));
|
|
return;
|
|
}
|
|
|
|
if ( KMessageBox::warningContinueCancel(topLevelWidget(),
|
|
i18nc("remove the page, by title", "<qt>Are you sure you want to delete the page <strong>%1</strong>?</qt>", idx.data().toString()),
|
|
i18n("Delete"), KStandardGuiItem::del(), KStandardGuiItem::cancel(), QLatin1String("DeletePageWarning")) == KMessageBox::Cancel) {
|
|
return;
|
|
}
|
|
|
|
(void) new Akonadi::ItemDeleteJob( item, this );
|
|
}
|
|
|
|
void KJotsWidget::deleteBook()
|
|
{
|
|
QModelIndexList selectedRows = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( selectedRows.size() != 1 )
|
|
return;
|
|
|
|
const QModelIndex idx = selectedRows.at( 0 );
|
|
Collection col = idx.data( EntityTreeModel::CollectionRole ).value<Collection>();
|
|
|
|
if ( !col.isValid() )
|
|
return;
|
|
|
|
if ( col.parentCollection() == Collection::root() )
|
|
return;
|
|
|
|
if( col.hasAttribute<NoteShared::NoteLockAttribute>() ) {
|
|
|
|
KMessageBox::information(topLevelWidget(),
|
|
i18n("This book is locked. You can only delete it when you first unlock it."),
|
|
i18n("Item is locked"));
|
|
return;
|
|
}
|
|
if ( KMessageBox::warningContinueCancel(topLevelWidget(),
|
|
i18nc("remove the book, by title", "<qt>Are you sure you want to delete the book <strong>%1</strong>?</qt>", idx.data().toString()),
|
|
i18n("Delete"), KStandardGuiItem::del(), KStandardGuiItem::cancel(), QLatin1String("DeleteBookWarning")) == KMessageBox::Cancel) {
|
|
return;
|
|
}
|
|
|
|
(void) new Akonadi::CollectionDeleteJob( col, this );
|
|
}
|
|
|
|
void KJotsWidget::newBook()
|
|
{
|
|
QModelIndexList selectedRows = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( selectedRows.size() != 1 )
|
|
return;
|
|
|
|
Collection col = selectedRows.at( 0 ).data( EntityTreeModel::CollectionRole ).value<Collection>();
|
|
|
|
if ( !col.isValid() )
|
|
return;
|
|
|
|
Collection newCollection;
|
|
newCollection.setParentCollection( col );
|
|
|
|
QString title = i18nc( "The default name for new books.", "New Book" );
|
|
newCollection.setName( KRandom::randomString( 10 ) );
|
|
newCollection.setContentMimeTypes( QStringList() << Akonadi::Collection::mimeType() << Akonotes::Note::mimeType() );
|
|
|
|
Akonadi::EntityDisplayAttribute *eda = new Akonadi::EntityDisplayAttribute();
|
|
eda->setIconName( QLatin1String("x-office-address-book") );
|
|
eda->setDisplayName( title );
|
|
newCollection.addAttribute( eda );
|
|
|
|
Akonadi::CollectionCreateJob *job = new Akonadi::CollectionCreateJob( newCollection );
|
|
connect( job, SIGNAL(result(KJob*)), this, SLOT(newBookResult(KJob*)) );
|
|
}
|
|
|
|
void KJotsWidget::newPage()
|
|
{
|
|
QModelIndexList selectedRows = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( selectedRows.size() != 1 )
|
|
return;
|
|
|
|
Item item = selectedRows.at( 0 ).data( EntityTreeModel::ItemRole ).value<Item>();
|
|
|
|
Collection col;
|
|
if ( item.isValid() )
|
|
{
|
|
col = selectedRows.at( 0 ).data( EntityTreeModel::ParentCollectionRole ).value<Collection>();
|
|
} else {
|
|
col = selectedRows.at( 0 ).data( EntityTreeModel::CollectionRole ).value<Collection>();
|
|
}
|
|
|
|
if ( !col.isValid() )
|
|
return;
|
|
doCreateNewPage(col);
|
|
}
|
|
|
|
void KJotsWidget::doCreateNewPage(const Collection &collection)
|
|
{
|
|
Akonotes::NoteCreatorAndSelector *creatorAndSelector = new Akonotes::NoteCreatorAndSelector(treeview->selectionModel());
|
|
creatorAndSelector->createNote(collection);
|
|
}
|
|
|
|
void KJotsWidget::newPageResult( KJob* job )
|
|
{
|
|
if ( job->error() )
|
|
kDebug() << job->errorString();
|
|
}
|
|
|
|
void KJotsWidget::newBookResult( KJob* job )
|
|
{
|
|
if ( job->error() ) {
|
|
kDebug() << job->errorString();
|
|
return;
|
|
}
|
|
Akonadi::CollectionCreateJob *createJob = qobject_cast<Akonadi::CollectionCreateJob*>(job);
|
|
if ( !createJob )
|
|
return;
|
|
const Collection collection = createJob->collection();
|
|
if ( !collection.isValid() )
|
|
return;
|
|
|
|
doCreateNewPage(collection);
|
|
}
|
|
|
|
QString KJotsWidget::renderSelectionToHtml()
|
|
{
|
|
QHash<QString, QVariant> hash;
|
|
|
|
QList<QVariant> objectList;
|
|
|
|
const int rows = selProxy->rowCount();
|
|
const int column = 0;
|
|
for ( int row = 0; row < rows; ++row )
|
|
{
|
|
QModelIndex idx = selProxy->index( row, column, QModelIndex() );
|
|
|
|
QObject *obj = idx.data(KJotsModel::GrantleeObjectRole).value<QObject*>();
|
|
KJotsEntity *kjotsEntity = qobject_cast<KJotsEntity*>(obj);
|
|
kjotsEntity->setIndex(idx);
|
|
objectList << QVariant::fromValue(static_cast<QObject *>(kjotsEntity));
|
|
}
|
|
|
|
hash.insert( QLatin1String( "entities" ), objectList);
|
|
hash.insert( QLatin1String( "i18n_TABLE_OF_CONTENTS" ),
|
|
i18nc("Header for 'Table of contents' section of rendered output", "Table of contents") );
|
|
Context c(hash);
|
|
|
|
Template t = m_templateEngine->loadByName( QLatin1String( "template.html" ) );
|
|
|
|
QString result = t->render(&c);
|
|
|
|
// TODO: handle errors.
|
|
return result;
|
|
}
|
|
|
|
QString KJotsWidget::renderSelectionToPlainText()
|
|
{
|
|
QHash<QString, QVariant> hash;
|
|
|
|
QList<QVariant> objectList;
|
|
|
|
const int rows = selProxy->rowCount();
|
|
const int column = 0;
|
|
for ( int row = 0; row < rows; ++row )
|
|
{
|
|
QModelIndex idx = selProxy->index( row, column, QModelIndex() );
|
|
|
|
QObject *obj = idx.data(KJotsModel::GrantleeObjectRole).value<QObject*>();
|
|
KJotsEntity *kjotsEntity = qobject_cast<KJotsEntity*>(obj);
|
|
kjotsEntity->setIndex(idx);
|
|
objectList << QVariant::fromValue(static_cast<QObject *>(kjotsEntity));
|
|
}
|
|
|
|
hash.insert( QLatin1String( "entities" ), objectList);
|
|
hash.insert( QLatin1String( "i18n_TABLE_OF_CONTENTS" ),
|
|
i18nc("Header for 'Table of contents' section of rendered output", "Table of contents") );
|
|
Context c(hash);
|
|
|
|
Template t = m_templateEngine->loadByName( QLatin1String( "template.txt" ) );
|
|
|
|
QString result = t->render(&c);
|
|
|
|
// TODO: handle errors.
|
|
return result;
|
|
}
|
|
|
|
|
|
QString KJotsWidget::renderSelectionToXml()
|
|
{
|
|
QHash<QString, QVariant> hash;
|
|
|
|
QList<QVariant> objectList;
|
|
|
|
const int rows = selProxy->rowCount();
|
|
const int column = 0;
|
|
for ( int row = 0; row < rows; ++row )
|
|
{
|
|
QModelIndex idx = selProxy->index( row, column, QModelIndex() );
|
|
|
|
QObject *obj = idx.data(KJotsModel::GrantleeObjectRole).value<QObject*>();
|
|
KJotsEntity *kjotsEntity = qobject_cast<KJotsEntity*>(obj);
|
|
kjotsEntity->setIndex(idx);
|
|
objectList << QVariant::fromValue(static_cast<QObject *>(kjotsEntity));
|
|
}
|
|
|
|
hash.insert( QLatin1String( "entities" ), objectList);
|
|
Context c(hash);
|
|
|
|
QString currentTheme = m_loader->themeName();
|
|
m_loader->setTheme( QLatin1String("xml_output") );
|
|
Template t = m_templateEngine->loadByName( QLatin1String( "template.xml" ) );
|
|
|
|
QString result = t->render(&c);
|
|
|
|
m_loader->setTheme(currentTheme);
|
|
return result;
|
|
}
|
|
|
|
void KJotsWidget::renderSelection()
|
|
{
|
|
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());
|
|
|
|
QTextDocument *document = idx.data( KJotsModel::DocumentRole ).value<QTextDocument*>();
|
|
|
|
if ( document )
|
|
{
|
|
editor->setDocument( document );
|
|
QTextCursor textCursor = document->property( "textCursor" ).value<QTextCursor>();
|
|
if ( !textCursor.isNull() )
|
|
editor->setTextCursor( textCursor );
|
|
stackedWidget->setCurrentWidget( editor );
|
|
editor->setFocus();
|
|
return;
|
|
} // else fallthrough
|
|
}
|
|
|
|
// ... Otherwise, render the selection read-only.
|
|
|
|
QTextDocument doc;
|
|
QTextCursor cursor(&doc);
|
|
|
|
browser->setHtml( renderSelectionToHtml() );
|
|
stackedWidget->setCurrentWidget( browser );
|
|
}
|
|
|
|
QString KJotsWidget::getThemeFromUser()
|
|
{
|
|
return QString();
|
|
#if 0
|
|
bool ok;
|
|
QString text = QInputDialog::getText(this, i18n("Change Theme"),
|
|
tr("Theme name:"), QLineEdit::Normal,
|
|
m_loader->themeName(), &ok);
|
|
if (!ok || text.isEmpty())
|
|
{
|
|
return QLatin1String("default");
|
|
}
|
|
|
|
return text;
|
|
#endif
|
|
}
|
|
|
|
|
|
void KJotsWidget::changeTheme()
|
|
{
|
|
#if 0
|
|
m_loader->setTheme(getThemeFromUser());
|
|
renderSelection();
|
|
#endif
|
|
}
|
|
|
|
void KJotsWidget::exportSelectionToHtml()
|
|
{
|
|
QString currentTheme = m_loader->themeName();
|
|
QString themeName = getThemeFromUser();
|
|
if (themeName.isEmpty())
|
|
{
|
|
themeName = QLatin1String( "default" );
|
|
}
|
|
m_loader->setTheme(themeName);
|
|
|
|
QString filename = KFileDialog::getSaveFileName();
|
|
if (!filename.isEmpty())
|
|
{
|
|
QFile exportFile ( filename );
|
|
if ( !exportFile.open(QIODevice::WriteOnly | QIODevice::Text) ) {
|
|
m_loader->setTheme(currentTheme);
|
|
KMessageBox::error(0, i18n("<qt>Error opening internal file.</qt>"));
|
|
return;
|
|
}
|
|
exportFile.write(renderSelectionToHtml().toUtf8());
|
|
|
|
exportFile.close();
|
|
}
|
|
m_loader->setTheme(currentTheme);
|
|
}
|
|
|
|
void KJotsWidget::exportSelectionToPlainText()
|
|
{
|
|
QString currentTheme = m_loader->themeName();
|
|
|
|
m_loader->setTheme( QLatin1String("plain_text") );
|
|
|
|
QString filename = KFileDialog::getSaveFileName();
|
|
if (!filename.isEmpty())
|
|
{
|
|
QFile exportFile ( filename );
|
|
if ( !exportFile.open(QIODevice::WriteOnly | QIODevice::Text) ) {
|
|
m_loader->setTheme(currentTheme);
|
|
KMessageBox::error(0, i18n("<qt>Error opening internal file.</qt>"));
|
|
return;
|
|
}
|
|
exportFile.write(renderSelectionToPlainText().toUtf8());
|
|
|
|
exportFile.close();
|
|
}
|
|
m_loader->setTheme(currentTheme);
|
|
}
|
|
|
|
void KJotsWidget::exportSelectionToXml()
|
|
{
|
|
QString currentTheme = m_loader->themeName();
|
|
|
|
m_loader->setTheme( QLatin1String("xml_output") );
|
|
|
|
QString filename = KFileDialog::getSaveFileName();
|
|
if (!filename.isEmpty())
|
|
{
|
|
QFile exportFile ( filename );
|
|
if ( !exportFile.open(QIODevice::WriteOnly | QIODevice::Text) ) {
|
|
m_loader->setTheme(currentTheme);
|
|
KMessageBox::error(0, i18n("<qt>Error opening internal file.</qt>"));
|
|
return;
|
|
}
|
|
exportFile.write(renderSelectionToXml().toUtf8());
|
|
|
|
exportFile.close();
|
|
}
|
|
m_loader->setTheme(currentTheme);
|
|
}
|
|
|
|
void KJotsWidget::printPreviewSelection()
|
|
{
|
|
QPrinter printer(QPrinter::HighResolution);
|
|
printer.setDocName(QLatin1String("KJots_Print"));
|
|
printer.setFullPage(false);
|
|
printer.setCreator(QLatin1String("KJots"));
|
|
KPrintPreview previewdlg( &printer, 0 );
|
|
print(printer);
|
|
previewdlg.exec();
|
|
}
|
|
|
|
void KJotsWidget::printSelection()
|
|
{
|
|
|
|
QPrinter printer(QPrinter::HighResolution);
|
|
printer.setDocName(QLatin1String("KJots_Print"));
|
|
printer.setFullPage(false);
|
|
printer.setCreator(QLatin1String("KJots"));
|
|
//Not supported in Qt?
|
|
//printer->setPageSelection(QPrinter::ApplicationSide);
|
|
|
|
//KPrinter::pageList() only works with ApplicationSide. ApplicationSide
|
|
//requires min/max pages. How am I supposed to tell how many pages there
|
|
//are before I setup the printer?
|
|
|
|
|
|
QPointer<QPrintDialog> printDialog = new QPrintDialog(&printer, this);
|
|
|
|
QAbstractPrintDialog::PrintDialogOptions options = printDialog->enabledOptions();
|
|
options &= ~QAbstractPrintDialog::PrintPageRange;
|
|
if (activeEditor()->textCursor().hasSelection())
|
|
options |= QAbstractPrintDialog::PrintSelection;
|
|
printDialog->setEnabledOptions(options);
|
|
|
|
printDialog->setWindowTitle(i18n("Send To Printer"));
|
|
if (printDialog->exec() == QDialog::Accepted) {
|
|
print(printer);
|
|
}
|
|
delete printDialog;
|
|
}
|
|
|
|
void KJotsWidget::print(QPrinter &printer)
|
|
{
|
|
QTextDocument printDocument;
|
|
if ( printer.printRange() == QPrinter::Selection )
|
|
{
|
|
printDocument.setHtml( activeEditor()->textCursor().selection().toHtml() );
|
|
} else {
|
|
//QTextCursor printCursor ( &printDocument );
|
|
QString currentTheme = m_loader->themeName();
|
|
m_loader->setTheme( QLatin1String("default") );
|
|
printDocument.setHtml( renderSelectionToHtml() );
|
|
m_loader->setTheme( currentTheme );
|
|
}
|
|
|
|
QPainter p(&printer);
|
|
|
|
// Check that there is a valid device to print to.
|
|
if (p.isActive()) {
|
|
QTextDocument *doc = &printDocument;
|
|
|
|
QRectF body = QRectF(QPointF(0, 0), doc->pageSize());
|
|
QPointF pageNumberPos;
|
|
|
|
QAbstractTextDocumentLayout *layout = doc->documentLayout();
|
|
layout->setPaintDevice(p.device());
|
|
|
|
const int dpiy = p.device()->logicalDpiY();
|
|
|
|
const int margin = (int) ((2/2.54)*dpiy); // 2 cm margins
|
|
QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
|
|
fmt.setMargin(margin);
|
|
doc->rootFrame()->setFrameFormat(fmt);
|
|
|
|
body = QRectF(0, 0, p.device()->width(), p.device()->height());
|
|
pageNumberPos = QPointF(body.width() - margin,
|
|
body.height() - margin
|
|
+ QFontMetrics(doc->defaultFont(), p.device()).ascent()
|
|
+ 5 * p.device()->logicalDpiY() / 72);
|
|
|
|
doc->setPageSize(body.size());
|
|
|
|
int docCopies = printer.numCopies();
|
|
for (int copy = 0; copy < docCopies; ++copy) {
|
|
|
|
int lastPage = layout->pageCount();
|
|
for ( int page = 1; page <= lastPage ; ++page ) {
|
|
p.save();
|
|
p.translate(body.left(), body.top() - (page - 1) * body.height());
|
|
QRectF view(0, (page - 1) * body.height(), body.width(), body.height());
|
|
|
|
QAbstractTextDocumentLayout *layout = doc->documentLayout();
|
|
QAbstractTextDocumentLayout::PaintContext ctx;
|
|
|
|
p.setClipRect(view);
|
|
ctx.clip = view;
|
|
|
|
// don't use the system palette text as default text color, on HP/UX
|
|
// for example that's white, and white text on white paper doesn't
|
|
// look that nice
|
|
ctx.palette.setColor(QPalette::Text, Qt::black);
|
|
|
|
layout->draw(&p, ctx);
|
|
|
|
if (!pageNumberPos.isNull()) {
|
|
p.setClipping(false);
|
|
p.setFont(QFont(doc->defaultFont()));
|
|
const QString pageString = QString::number(page);
|
|
|
|
p.drawText(qRound(pageNumberPos.x() - p.fontMetrics().width(pageString)),
|
|
qRound(pageNumberPos.y() + view.top()),
|
|
pageString);
|
|
}
|
|
|
|
p.restore();
|
|
|
|
if ( (page+1) <= lastPage ) {
|
|
printer.newPage();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
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 );
|
|
}
|
|
kWarning() << "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::selectionChanged( const QItemSelection &selected, const QItemSelection &deselected )
|
|
{
|
|
Q_UNUSED( selected );
|
|
|
|
emit canGoNextBookChanged( canGoPreviousBook() );
|
|
emit canGoNextPageChanged( canGoNextPage() );
|
|
emit canGoPreviousBookChanged( canGoPreviousBook() );
|
|
emit canGoPreviousPageChanged( canGoPreviousPage() );
|
|
|
|
if ( deselected.size() == 1 )
|
|
{
|
|
editor->document()->setProperty( "textCursor", QVariant::fromValue( editor->textCursor() ) );
|
|
if ( editor->document()->isModified() )
|
|
{
|
|
treeview->model()->setData( deselected.indexes().first(), QVariant::fromValue( editor->document() ), KJotsModel::DocumentRole );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Shows the search dialog when "Find" is selected.
|
|
*/
|
|
void KJotsWidget::onShowSearch()
|
|
{
|
|
onUpdateSearch();
|
|
|
|
QTextEdit *browserOrEditor = activeEditor();
|
|
|
|
if ( browserOrEditor->textCursor().hasSelection() ) {
|
|
searchDialog->setHasSelection(true);
|
|
long dialogOptions = searchDialog->options();
|
|
dialogOptions |= KFind::SelectedText;
|
|
searchDialog->setOptions(dialogOptions);
|
|
} else {
|
|
searchDialog->setHasSelection(false);
|
|
}
|
|
|
|
searchDialog->setFindHistory(searchHistory);
|
|
searchDialog->show();
|
|
onUpdateSearch();
|
|
}
|
|
|
|
|
|
/*!
|
|
Updates the search dialog if the user is switching selections while it is open.
|
|
*/
|
|
void KJotsWidget::onUpdateSearch()
|
|
{
|
|
if ( searchDialog->isVisible() ) {
|
|
long searchOptions = searchDialog->options();
|
|
if ( searchOptions & KFind::SelectedText ) {
|
|
searchAllPages->setCheckState( Qt::Unchecked );
|
|
searchAllPages->setEnabled( false );
|
|
} else {
|
|
searchAllPages->setEnabled( true );
|
|
}
|
|
|
|
if ( searchAllPages->checkState() == Qt::Checked ) {
|
|
searchOptions &= ~KFind::SelectedText;
|
|
searchDialog->setOptions( searchOptions );
|
|
searchDialog->setHasSelection( false );
|
|
} else {
|
|
if ( activeEditor()->textCursor().hasSelection() ) {
|
|
searchDialog->setHasSelection( true );
|
|
}
|
|
}
|
|
|
|
if ( activeEditor()->textCursor().hasSelection() ) {
|
|
if ( searchAllPages->checkState() == Qt::Unchecked ) {
|
|
searchDialog->setHasSelection( true );
|
|
}
|
|
} else {
|
|
searchOptions &= ~KFind::SelectedText;
|
|
searchDialog->setOptions( searchOptions );
|
|
searchDialog->setHasSelection( false );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Called when the user presses OK in the search dialog.
|
|
*/
|
|
void KJotsWidget::onStartSearch()
|
|
{
|
|
QString searchPattern = searchDialog->pattern();
|
|
if ( !searchHistory.contains ( searchPattern ) ) {
|
|
searchHistory.prepend( searchPattern );
|
|
}
|
|
|
|
QTextEdit *browserOrEditor = activeEditor();
|
|
QTextCursor cursor = browserOrEditor->textCursor();
|
|
|
|
long searchOptions = searchDialog->options();
|
|
if ( searchOptions & KFind::FromCursor ) {
|
|
searchPos = cursor.position();
|
|
searchBeginPos = 0;
|
|
cursor.movePosition( QTextCursor::End );
|
|
searchEndPos = cursor.position();
|
|
} else {
|
|
if ( searchOptions & KFind::SelectedText ) {
|
|
searchBeginPos = cursor.selectionStart();
|
|
searchEndPos = cursor.selectionEnd();
|
|
} else {
|
|
searchBeginPos = 0;
|
|
cursor.movePosition( QTextCursor::End );
|
|
searchEndPos = cursor.position();
|
|
}
|
|
|
|
if ( searchOptions & KFind::FindBackwards ) {
|
|
searchPos = searchEndPos;
|
|
} else {
|
|
searchPos = searchBeginPos;
|
|
}
|
|
}
|
|
|
|
m_xmlGuiClient->actionCollection()->action( QLatin1String(KStandardAction::name( KStandardAction::FindNext )) )->setEnabled( true );
|
|
|
|
onRepeatSearch();
|
|
}
|
|
|
|
/*!
|
|
Called when user chooses "Find Next"
|
|
*/
|
|
void KJotsWidget::onRepeatSearch()
|
|
{
|
|
if ( search( false ) == 0 ) {
|
|
KMessageBox::sorry( 0, i18n( "<qt>No matches found.</qt>" ) );
|
|
m_xmlGuiClient->actionCollection()->action( QLatin1String(KStandardAction::name( KStandardAction::FindNext )) )->setEnabled( false );
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Called when user presses Cancel in find dialog.
|
|
*/
|
|
void KJotsWidget::onEndSearch()
|
|
{
|
|
m_xmlGuiClient->actionCollection()->action( QLatin1String(KStandardAction::name( KStandardAction::FindNext )) )->setEnabled( false );
|
|
}
|
|
|
|
/*!
|
|
Shows the replace dialog when "Replace" is selected.
|
|
*/
|
|
void KJotsWidget::onShowReplace()
|
|
{
|
|
Q_ASSERT( editor->isVisible() );
|
|
|
|
if ( editor->textCursor().hasSelection() ) {
|
|
replaceDialog->setHasSelection( true );
|
|
long dialogOptions = replaceDialog->options();
|
|
dialogOptions |= KFind::SelectedText;
|
|
replaceDialog->setOptions( dialogOptions );
|
|
} else {
|
|
replaceDialog->setHasSelection( false );
|
|
}
|
|
|
|
replaceDialog->setFindHistory( searchHistory );
|
|
replaceDialog->setReplacementHistory( replaceHistory );
|
|
replaceDialog->show();
|
|
onUpdateReplace();
|
|
}
|
|
|
|
/*!
|
|
Updates the replace dialog if the user is switching selections while it is open.
|
|
*/
|
|
void KJotsWidget::onUpdateReplace()
|
|
{
|
|
if ( replaceDialog->isVisible() ) {
|
|
long replaceOptions = replaceDialog->options();
|
|
if ( replaceOptions & KFind::SelectedText ) {
|
|
replaceAllPages->setCheckState( Qt::Unchecked );
|
|
replaceAllPages->setEnabled( false );
|
|
} else {
|
|
replaceAllPages->setEnabled( true );
|
|
}
|
|
|
|
if ( replaceAllPages->checkState() == Qt::Checked ) {
|
|
replaceOptions &= ~KFind::SelectedText;
|
|
replaceDialog->setOptions( replaceOptions );
|
|
replaceDialog->setHasSelection( false );
|
|
} else {
|
|
if ( activeEditor()->textCursor().hasSelection() ) {
|
|
replaceDialog->setHasSelection( true );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Called when the user presses OK in the replace dialog.
|
|
*/
|
|
void KJotsWidget::onStartReplace()
|
|
{
|
|
QString searchPattern = replaceDialog->pattern();
|
|
if ( !searchHistory.contains ( searchPattern ) ) {
|
|
searchHistory.prepend( searchPattern );
|
|
}
|
|
|
|
QString replacePattern = replaceDialog->replacement();
|
|
if ( !replaceHistory.contains ( replacePattern ) ) {
|
|
replaceHistory.prepend( replacePattern );
|
|
}
|
|
|
|
QTextCursor cursor = editor->textCursor();
|
|
|
|
long replaceOptions = replaceDialog->options();
|
|
if ( replaceOptions & KFind::FromCursor ) {
|
|
replacePos = cursor.position();
|
|
replaceBeginPos = 0;
|
|
cursor.movePosition( QTextCursor::End );
|
|
replaceEndPos = cursor.position();
|
|
} else {
|
|
if ( replaceOptions & KFind::SelectedText ) {
|
|
replaceBeginPos = cursor.selectionStart();
|
|
replaceEndPos = cursor.selectionEnd();
|
|
} else {
|
|
replaceBeginPos = 0;
|
|
cursor.movePosition( QTextCursor::End );
|
|
replaceEndPos = cursor.position();
|
|
}
|
|
|
|
if ( replaceOptions & KFind::FindBackwards ) {
|
|
replacePos = replaceEndPos;
|
|
} else {
|
|
replacePos = replaceBeginPos;
|
|
}
|
|
}
|
|
|
|
replaceStartPage = treeview->selectionModel()->selectedRows().first();
|
|
|
|
//allow KReplaceDialog to exit so the user can see.
|
|
QTimer::singleShot( 0, this, SLOT(onRepeatReplace()) );
|
|
}
|
|
|
|
/*!
|
|
Only called after onStartReplace. Kept the name scheme for consistancy.
|
|
*/
|
|
void KJotsWidget::onRepeatReplace()
|
|
{
|
|
KJotsReplaceNextDialog *dlg = 0;
|
|
|
|
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 );
|
|
}
|
|
|
|
forever {
|
|
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.numCaptures();
|
|
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() != KDialog::User2 ) {
|
|
cursor.insertText( replacementText );
|
|
editor->setTextCursor( cursor );
|
|
++replaced;
|
|
}
|
|
|
|
if ( dlg->answer() == KDialog::User1 ) {
|
|
replaceOptions |= ~KReplaceDialog::PromptOnReplace;
|
|
}
|
|
} else {
|
|
cursor.insertText( replacementText );
|
|
editor->setTextCursor( cursor );
|
|
++replaced;
|
|
}
|
|
}
|
|
|
|
if ( replaced == found )
|
|
{
|
|
KMessageBox::information( 0, i18np( "<qt>Replaced 1 occurrence.</qt>", "<qt>Replaced %1 occurrences.</qt>", replaced ) );
|
|
}
|
|
else if ( replaced < found )
|
|
{
|
|
KMessageBox::information( 0,
|
|
i18np( "<qt>Replaced %2 of 1 occurrence.</qt>", "<qt>Replaced %2 of %1 occurrences.</qt>", found, replaced ) );
|
|
}
|
|
|
|
if ( dlg ) {
|
|
delete dlg;
|
|
}
|
|
}
|
|
|
|
/*!
|
|
Called when user presses Cancel in replace dialog. Just a placeholder for now.
|
|
*/
|
|
void KJotsWidget::onEndReplace()
|
|
{
|
|
}
|
|
|
|
/*!
|
|
Searches for the given pattern, with the given options. This is huge and
|
|
unwieldly function, but the operation we're performing is huge and unwieldly.
|
|
*/
|
|
int KJotsWidget::search( bool replacing )
|
|
{
|
|
int rc = 0;
|
|
int *beginPos = replacing ? &replaceBeginPos : &searchBeginPos;
|
|
int *endPos = replacing ? &replaceEndPos : &searchEndPos;
|
|
long options = replacing ? replaceDialog->options() : searchDialog->options();
|
|
QString pattern = replacing ? replaceDialog->pattern() : searchDialog->pattern();
|
|
int *curPos = replacing ? &replacePos : &searchPos;
|
|
|
|
QModelIndex startPage = replacing ? replaceStartPage : treeview->selectionModel()->selectedRows().first();
|
|
|
|
bool allPages = false;
|
|
QCheckBox *box = replacing ? replaceAllPages : searchAllPages;
|
|
if ( box->isEnabled() && box->checkState() == Qt::Checked ) {
|
|
allPages = true;
|
|
}
|
|
|
|
QTextDocument::FindFlags findFlags = 0;
|
|
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;
|
|
forever {
|
|
++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("<qt>End of search area reached. Do you want to wrap around and continue?</qt>")) ==
|
|
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()
|
|
{
|
|
emit captionChanged( treeview->captionForSelection( QLatin1String(" / ") ) );
|
|
}
|
|
|
|
void KJotsWidget::dataChanged( const QModelIndex &topLeft, const QModelIndex &bottomRight )
|
|
{
|
|
QModelIndexList rows = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( rows.size() != 1 )
|
|
return;
|
|
|
|
QItemSelection changed( topLeft, bottomRight );
|
|
if ( changed.contains( rows.first() ) )
|
|
{
|
|
emit captionChanged( treeview->captionForSelection( QLatin1String(" / ") ) );
|
|
}
|
|
}
|
|
|
|
bool KJotsWidget::queryClose()
|
|
{
|
|
KJotsSettings::setSplitterSizes(m_splitter->sizes());
|
|
|
|
KJotsSettings::self()->writeConfig();
|
|
m_orderProxy->saveOrder();
|
|
|
|
return true;
|
|
}
|
|
|
|
void KJotsWidget::actionLock()
|
|
{
|
|
QModelIndexList selection = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( selection.isEmpty() )
|
|
return;
|
|
|
|
Collection::List collections;
|
|
Item::List items;
|
|
foreach ( const QModelIndex &idx, selection )
|
|
{
|
|
Collection col = idx.data( EntityTreeModel::CollectionRole ).value<Collection>();
|
|
if ( col.isValid() )
|
|
{
|
|
collections << col;
|
|
} else {
|
|
Item item = idx.data( EntityTreeModel::ItemRole ).value<Item>();
|
|
if ( item.isValid() )
|
|
items << item;
|
|
}
|
|
}
|
|
if ( collections.isEmpty() && items.isEmpty() )
|
|
return;
|
|
|
|
KJotsLockJob *job = new KJotsLockJob(collections, items, this);
|
|
}
|
|
|
|
void KJotsWidget::actionUnlock()
|
|
{
|
|
QModelIndexList selection = treeview->selectionModel()->selectedRows();
|
|
|
|
if ( selection.isEmpty() )
|
|
return;
|
|
|
|
Collection::List collections;
|
|
Item::List items;
|
|
foreach ( const QModelIndex &idx, selection )
|
|
{
|
|
Collection col = idx.data( EntityTreeModel::CollectionRole ).value<Collection>();
|
|
if ( col.isValid() )
|
|
{
|
|
collections << col;
|
|
} else {
|
|
Item item = idx.data( EntityTreeModel::ItemRole ).value<Item>();
|
|
if ( item.isValid() )
|
|
items << item;
|
|
}
|
|
}
|
|
if ( collections.isEmpty() && items.isEmpty() )
|
|
return;
|
|
|
|
KJotsLockJob *job = new KJotsLockJob(collections, items, KJotsLockJob::UnlockJob, this);
|
|
}
|
|
|
|
void KJotsWidget::actionSortChildrenAlpha()
|
|
{
|
|
QModelIndexList selection = treeview->selectionModel()->selectedRows();
|
|
|
|
foreach( const QModelIndex &index, selection )
|
|
{
|
|
const QPersistentModelIndex persistent( index );
|
|
m_sortProxyModel->sortChildrenAlphabetically( m_orderProxy->mapToSource( index ) );
|
|
m_orderProxy->clearOrder( persistent );
|
|
}
|
|
}
|
|
|
|
void KJotsWidget::actionSortChildrenByDate()
|
|
{
|
|
QModelIndexList selection = treeview->selectionModel()->selectedRows();
|
|
|
|
foreach( const QModelIndex &index, selection )
|
|
{
|
|
const QPersistentModelIndex persistent( index );
|
|
m_sortProxyModel->sortChildrenByCreationTime( m_orderProxy->mapToSource( index ) );
|
|
m_orderProxy->clearOrder( persistent );
|
|
}
|
|
}
|
|
|