summaryrefslogtreecommitdiffstats
path: root/src/assistant/tools/assistant/bookmarkmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/assistant/tools/assistant/bookmarkmanager.cpp')
-rw-r--r--src/assistant/tools/assistant/bookmarkmanager.cpp559
1 files changed, 559 insertions, 0 deletions
diff --git a/src/assistant/tools/assistant/bookmarkmanager.cpp b/src/assistant/tools/assistant/bookmarkmanager.cpp
new file mode 100644
index 000000000..87331463b
--- /dev/null
+++ b/src/assistant/tools/assistant/bookmarkmanager.cpp
@@ -0,0 +1,559 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "tracer.h"
+
+#include "bookmarkmanager.h"
+#include "bookmarkmanagerwidget.h"
+#include "bookmarkdialog.h"
+#include "bookmarkfiltermodel.h"
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+#include "centralwidget.h"
+#include "helpenginewrapper.h"
+
+#include <QtGui/QMenu>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QMessageBox>
+#include <QtGui/QSortFilterProxyModel>
+#include <QtGui/QToolBar>
+
+QT_BEGIN_NAMESPACE
+
+// -- BookmarkManager::BookmarkWidget
+
+void BookmarkManager::BookmarkWidget::focusInEvent(QFocusEvent *event)
+{
+ TRACE_OBJ
+ if (event->reason() != Qt::MouseFocusReason) {
+ ui.lineEdit->selectAll();
+ ui.lineEdit->setFocus();
+
+ // force the focus in event on bookmark manager
+ emit focusInEvent();
+ }
+}
+
+// -- BookmarkManager::BookmarkTreeView
+
+BookmarkManager::BookmarkTreeView::BookmarkTreeView(QWidget *parent)
+ : QTreeView(parent)
+{
+ TRACE_OBJ
+ setAcceptDrops(true);
+ setDragEnabled(true);
+ setAutoExpandDelay(1000);
+ setUniformRowHeights(true);
+ setDropIndicatorShown(true);
+ setExpandsOnDoubleClick(true);
+
+ connect(this, SIGNAL(expanded(QModelIndex)), this,
+ SLOT(setExpandedData(QModelIndex)));
+ connect(this, SIGNAL(collapsed(QModelIndex)), this,
+ SLOT(setExpandedData(QModelIndex)));
+
+}
+
+void BookmarkManager::BookmarkTreeView::subclassKeyPressEvent(QKeyEvent *event)
+{
+ TRACE_OBJ
+ QTreeView::keyPressEvent(event);
+}
+
+void BookmarkManager::BookmarkTreeView::setExpandedData(const QModelIndex &index)
+{
+ TRACE_OBJ
+ if (BookmarkModel *treeModel = qobject_cast<BookmarkModel*> (model()))
+ treeModel->setData(index, isExpanded(index), UserRoleExpanded);
+}
+
+// -- BookmarkManager
+
+QMutex BookmarkManager::mutex;
+BookmarkManager* BookmarkManager::bookmarkManager = 0;
+
+// -- public
+
+BookmarkManager* BookmarkManager::instance()
+{
+ TRACE_OBJ
+ if (!bookmarkManager) {
+ QMutexLocker _(&mutex);
+ if (!bookmarkManager)
+ bookmarkManager = new BookmarkManager();
+ }
+ return bookmarkManager;
+}
+
+void BookmarkManager::destroy()
+{
+ TRACE_OBJ
+ delete bookmarkManager;
+ bookmarkManager = 0;
+}
+
+QWidget* BookmarkManager::bookmarkDockWidget() const
+{
+ TRACE_OBJ
+ if (bookmarkWidget)
+ return bookmarkWidget;
+ return 0;
+}
+
+void BookmarkManager::setBookmarksMenu(QMenu* menu)
+{
+ TRACE_OBJ
+ bookmarkMenu = menu;
+ refreshBookmarkMenu();
+}
+
+void BookmarkManager::setBookmarksToolbar(QToolBar *toolBar)
+{
+ TRACE_OBJ
+ m_toolBar = toolBar;
+ refreshBookmarkToolBar();
+}
+
+// -- public slots
+
+void BookmarkManager::addBookmark(const QString &title, const QString &url)
+{
+ TRACE_OBJ
+ showBookmarkDialog(title.isEmpty() ? tr("Untitled") : title,
+ url.isEmpty() ? QLatin1String("about:blank") : url);
+}
+
+// -- private
+
+BookmarkManager::BookmarkManager()
+ : typeAndSearch(false)
+ , bookmarkMenu(0)
+ , m_toolBar(0)
+ , bookmarkModel(new BookmarkModel)
+ , bookmarkFilterModel(0)
+ , typeAndSearchModel(0)
+ , bookmarkWidget(new BookmarkWidget)
+ , bookmarkTreeView(new BookmarkTreeView)
+ , bookmarkManagerWidget(0)
+{
+ TRACE_OBJ
+ bookmarkWidget->installEventFilter(this);
+ connect(bookmarkWidget->ui.add, SIGNAL(clicked()), this,
+ SLOT(addBookmark()));
+ connect(bookmarkWidget->ui.remove, SIGNAL(clicked()), this,
+ SLOT(removeBookmark()));
+ connect(bookmarkWidget->ui.lineEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(textChanged(QString)));
+ connect(bookmarkWidget, SIGNAL(focusInEvent()), this, SLOT(focusInEvent()));
+
+ bookmarkTreeView->setModel(bookmarkModel);
+ bookmarkTreeView->installEventFilter(this);
+ bookmarkTreeView->viewport()->installEventFilter(this);
+ bookmarkTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
+ bookmarkWidget->ui.stackedWidget->addWidget(bookmarkTreeView);
+
+ connect(bookmarkTreeView, SIGNAL(activated(QModelIndex)), this,
+ SLOT(setSourceFromIndex(QModelIndex)));
+ connect(bookmarkTreeView, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(customContextMenuRequested(QPoint)));
+
+ connect(&HelpEngineWrapper::instance(), SIGNAL(setupFinished()), this,
+ SLOT(setupFinished()));
+ connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkMenu()));
+ connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkMenu()));
+ connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(refreshBookmarkMenu()));
+
+ connect(bookmarkModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkToolBar()));
+ connect(bookmarkModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this,
+ SLOT(refreshBookmarkToolBar()));
+ connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(refreshBookmarkToolBar()));
+}
+
+BookmarkManager::~BookmarkManager()
+{
+ TRACE_OBJ
+ delete bookmarkManagerWidget;
+ HelpEngineWrapper::instance().setBookmarks(bookmarkModel->bookmarks());
+ delete bookmarkModel;
+}
+
+void BookmarkManager::removeItem(const QModelIndex &index)
+{
+ TRACE_OBJ
+ QModelIndex current = index;
+ if (typeAndSearch) { // need to map because of proxy
+ current = typeAndSearchModel->mapToSource(current);
+ current = bookmarkFilterModel->mapToSource(current);
+ } else if (!bookmarkModel->parent(index).isValid()) {
+ return; // check if we should delete the "Bookmarks Menu", bail
+ }
+
+ if (bookmarkModel->hasChildren(current)) {
+ int value = QMessageBox::question(bookmarkTreeView, tr("Remove"),
+ tr("You are going to delete a Folder, this will also<br>"
+ "remove it's content. Are you sure to continue?"),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
+ if (value == QMessageBox::Cancel)
+ return;
+ }
+ bookmarkModel->removeItem(current);
+}
+
+bool BookmarkManager::eventFilter(QObject *object, QEvent *event)
+{
+ if (object != bookmarkTreeView && object != bookmarkTreeView->viewport()
+ && object != bookmarkWidget)
+ return QObject::eventFilter(object, event);
+
+ TRACE_OBJ
+ const bool isWidget = object == bookmarkWidget;
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ switch (ke->key()) {
+ case Qt::Key_F2: {
+ renameBookmark(bookmarkTreeView->currentIndex());
+ } break;
+
+ case Qt::Key_Delete: {
+ removeItem(bookmarkTreeView->currentIndex());
+ return true;
+ } break;
+
+ case Qt::Key_Up: { // needs event filter on widget
+ case Qt::Key_Down:
+ if (isWidget)
+ bookmarkTreeView->subclassKeyPressEvent(ke);
+ } break;
+
+ case Qt::Key_Escape: {
+ emit escapePressed();
+ } break;
+
+ default: break;
+ }
+ }
+
+ if (event->type() == QEvent::MouseButtonRelease && !isWidget) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ switch (me->button()) {
+ case Qt::LeftButton: {
+ if (me->modifiers() & Qt::ControlModifier)
+ setSourceFromIndex(bookmarkTreeView->currentIndex(), true);
+ } break;
+
+ case Qt::MidButton: {
+ setSourceFromIndex(bookmarkTreeView->currentIndex(), true);
+ } break;
+
+ default: break;
+ }
+ }
+
+ return QObject::eventFilter(object, event);
+}
+
+void BookmarkManager::buildBookmarksMenu(const QModelIndex &index, QMenu* menu)
+{
+ TRACE_OBJ
+ if (!index.isValid())
+ return;
+
+ const QString &text = index.data().toString();
+ const QIcon &icon = qvariant_cast<QIcon>(index.data(Qt::DecorationRole));
+ if (index.data(UserRoleFolder).toBool()) {
+ if (QMenu* subMenu = menu->addMenu(icon, text)) {
+ for (int i = 0; i < bookmarkModel->rowCount(index); ++i)
+ buildBookmarksMenu(bookmarkModel->index(i, 0, index), subMenu);
+ }
+ } else {
+ QAction *action = menu->addAction(icon, text);
+ action->setData(index.data(UserRoleUrl).toString());
+ }
+}
+
+void BookmarkManager::showBookmarkDialog(const QString &name, const QString &url)
+{
+ TRACE_OBJ
+ BookmarkDialog dialog(bookmarkModel, name, url, bookmarkTreeView);
+ dialog.exec();
+}
+
+// -- private slots
+
+void BookmarkManager::setupFinished()
+{
+ TRACE_OBJ
+ bookmarkModel->setBookmarks(HelpEngineWrapper::instance().bookmarks());
+ bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView);
+
+ refreshBookmarkMenu();
+ refreshBookmarkToolBar();
+
+ bookmarkTreeView->hideColumn(1);
+ bookmarkTreeView->header()->setVisible(false);
+ bookmarkTreeView->header()->setStretchLastSection(true);
+
+ if (!bookmarkFilterModel)
+ bookmarkFilterModel = new BookmarkFilterModel(this);
+ bookmarkFilterModel->setSourceModel(bookmarkModel);
+ bookmarkFilterModel->filterBookmarkFolders();
+
+ if (!typeAndSearchModel)
+ typeAndSearchModel = new QSortFilterProxyModel(this);
+ typeAndSearchModel->setDynamicSortFilter(true);
+ typeAndSearchModel->setSourceModel(bookmarkFilterModel);
+}
+
+void BookmarkManager::addBookmark()
+{
+ TRACE_OBJ
+ if (CentralWidget *widget = CentralWidget::instance())
+ addBookmark(widget->currentTitle(), widget->currentSource().toString());
+}
+
+void BookmarkManager::removeBookmark()
+{
+ TRACE_OBJ
+ removeItem(bookmarkTreeView->currentIndex());
+}
+
+void BookmarkManager::manageBookmarks()
+{
+ TRACE_OBJ
+ if (bookmarkManagerWidget == 0) {
+ bookmarkManagerWidget = new BookmarkManagerWidget(bookmarkModel);
+ connect(bookmarkManagerWidget, SIGNAL(setSource(QUrl)), this,
+ SIGNAL(setSource(QUrl)));
+ connect(bookmarkManagerWidget, SIGNAL(setSourceInNewTab(QUrl))
+ , this, SIGNAL(setSourceInNewTab(QUrl)));
+ connect(bookmarkManagerWidget, SIGNAL(managerWidgetAboutToClose())
+ , this, SLOT(managerWidgetAboutToClose()));
+ }
+ bookmarkManagerWidget->show();
+ bookmarkManagerWidget->raise();
+}
+
+void BookmarkManager::refreshBookmarkMenu()
+{
+ TRACE_OBJ
+ if (!bookmarkMenu)
+ return;
+
+ bookmarkMenu->clear();
+
+ bookmarkMenu->addAction(tr("Manage Bookmarks..."), this,
+ SLOT(manageBookmarks()));
+ bookmarkMenu->addAction(QIcon::fromTheme("bookmark-new"),
+ tr("Add Bookmark..."), this, SLOT(addBookmark()), QKeySequence(tr("Ctrl+D")));
+
+ bookmarkMenu->addSeparator();
+
+ QModelIndex root = bookmarkModel->index(0, 0, QModelIndex()).parent();
+ buildBookmarksMenu(bookmarkModel->index(0, 0, root), bookmarkMenu);
+
+ bookmarkMenu->addSeparator();
+
+ root = bookmarkModel->index(1, 0, QModelIndex());
+ for (int i = 0; i < bookmarkModel->rowCount(root); ++i)
+ buildBookmarksMenu(bookmarkModel->index(i, 0, root), bookmarkMenu);
+
+ connect(bookmarkMenu, SIGNAL(triggered(QAction*)), this,
+ SLOT(setSourceFromAction(QAction*)));
+}
+
+void BookmarkManager::refreshBookmarkToolBar()
+{
+ TRACE_OBJ
+ if (!m_toolBar)
+ return;
+
+ m_toolBar->clear();
+ m_toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+
+ const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex());
+ for (int i = 0; i < bookmarkModel->rowCount(root); ++i) {
+ const QModelIndex &index = bookmarkModel->index(i, 0, root);
+ if (index.data(UserRoleFolder).toBool()) {
+ QToolButton *button = new QToolButton(m_toolBar);
+ button->setPopupMode(QToolButton::InstantPopup);
+ button->setText(index.data().toString());
+ QMenu *menu = new QMenu(button);
+ for (int j = 0; j < bookmarkModel->rowCount(index); ++j)
+ buildBookmarksMenu(bookmarkModel->index(j, 0, index), menu);
+ connect(menu, SIGNAL(triggered(QAction*)), this,
+ SLOT(setSourceFromAction(QAction*)));
+ button->setMenu(menu);
+ button->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
+ button->setIcon(qvariant_cast<QIcon>(index.data(Qt::DecorationRole)));
+ QAction *a = m_toolBar->addWidget(button);
+ a->setText(index.data().toString());
+ } else {
+ QAction *action = m_toolBar->addAction(
+ qvariant_cast<QIcon>(index.data(Qt::DecorationRole)),
+ index.data().toString(), this, SLOT(setSourceFromAction()));
+ action->setData(index.data(UserRoleUrl).toString());
+ }
+ }
+}
+
+void BookmarkManager::renameBookmark(const QModelIndex &index)
+{
+ // check if we should rename the "Bookmarks Menu", bail
+ if (!typeAndSearch && !bookmarkModel->parent(index).isValid())
+ return;
+
+ bookmarkModel->setItemsEditable(true);
+ bookmarkTreeView->edit(index);
+ bookmarkModel->setItemsEditable(false);
+}
+
+
+void BookmarkManager::setSourceFromAction()
+{
+ TRACE_OBJ
+ setSourceFromAction(qobject_cast<QAction*> (sender()));
+}
+
+void BookmarkManager::setSourceFromAction(QAction *action)
+{
+ TRACE_OBJ
+ if (action) {
+ const QVariant &data = action->data();
+ if (data.canConvert<QUrl>())
+ emit setSource(data.toUrl());
+ }
+}
+
+void BookmarkManager::setSourceFromIndex(const QModelIndex &index, bool newTab)
+{
+ TRACE_OBJ
+ QAbstractItemModel *base = bookmarkModel;
+ if (typeAndSearch)
+ base = typeAndSearchModel;
+
+ if (base->data(index, UserRoleFolder).toBool())
+ return;
+
+ const QVariant &data = base->data(index, UserRoleUrl);
+ if (data.canConvert<QUrl>()) {
+ if (newTab)
+ emit setSourceInNewTab(data.toUrl());
+ else
+ emit setSource(data.toUrl());
+ }
+}
+
+void BookmarkManager::customContextMenuRequested(const QPoint &point)
+{
+ TRACE_OBJ
+ QModelIndex index = bookmarkTreeView->indexAt(point);
+ if (!index.isValid())
+ return;
+
+ // check if we should open the menu on "Bookmarks Menu", bail
+ if (!typeAndSearch && !bookmarkModel->parent(index).isValid())
+ return;
+
+ QAction *remove = 0;
+ QAction *rename = 0;
+ QAction *showItem = 0;
+ QAction *showItemInNewTab = 0;
+
+ QMenu menu(QLatin1String(""));
+ if (!typeAndSearch && bookmarkModel->data(index, UserRoleFolder).toBool()) {
+ remove = menu.addAction(tr("Delete Folder"));
+ rename = menu.addAction(tr("Rename Folder"));
+ } else {
+ showItem = menu.addAction(tr("Show Bookmark"));
+ showItemInNewTab = menu.addAction(tr("Show Bookmark in New Tab"));
+ menu.addSeparator();
+ remove = menu.addAction(tr("Delete Bookmark"));
+ rename = menu.addAction(tr("Rename Bookmark"));
+ }
+
+ QAction *pickedAction = menu.exec(bookmarkTreeView->mapToGlobal(point));
+ if (pickedAction == rename)
+ renameBookmark(index);
+ else if (pickedAction == remove)
+ removeItem(index);
+ else if (pickedAction == showItem || pickedAction == showItemInNewTab)
+ setSourceFromIndex(index, pickedAction == showItemInNewTab);
+}
+
+void BookmarkManager::focusInEvent()
+{
+ TRACE_OBJ
+ const QModelIndex &index = bookmarkTreeView->indexAt(QPoint(2, 2));
+ if (index.isValid())
+ bookmarkTreeView->setCurrentIndex(index);
+}
+
+void BookmarkManager::managerWidgetAboutToClose()
+{
+ delete bookmarkManagerWidget;
+ bookmarkManagerWidget = 0;
+}
+
+void BookmarkManager::textChanged(const QString &text)
+{
+ TRACE_OBJ
+ if (!bookmarkWidget->ui.lineEdit->text().isEmpty()) {
+ if (!typeAndSearch) {
+ typeAndSearch = true;
+ bookmarkTreeView->setItemsExpandable(false);
+ bookmarkTreeView->setRootIsDecorated(false);
+ bookmarkTreeView->setModel(typeAndSearchModel);
+ }
+ typeAndSearchModel->setFilterRegExp(QRegExp(text));
+ } else {
+ typeAndSearch = false;
+ bookmarkTreeView->setModel(bookmarkModel);
+ bookmarkTreeView->setItemsExpandable(true);
+ bookmarkTreeView->setRootIsDecorated(true);
+ bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView);
+ }
+}
+
+QT_END_NAMESPACE