diff options
-rw-r--r-- | src/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/bookmarks/bookmarksmanager.cpp | 4 | ||||
-rw-r--r-- | src/bookmarks/bookmarksmanager.h | 4 | ||||
-rw-r--r-- | src/bookmarks/bookmarkspanel.cpp | 441 | ||||
-rw-r--r-- | src/bookmarks/bookmarkspanel.h | 36 | ||||
-rw-r--r-- | src/bookmarks/bookmarkstreemodel.cpp | 265 | ||||
-rw-r--r-- | src/bookmarks/bookmarkstreemodel.h | 51 | ||||
-rw-r--r-- | src/history/historymodels.cpp | 8 | ||||
-rw-r--r-- | src/history/historypanel.cpp | 89 | ||||
-rw-r--r-- | src/history/historypanel.h | 10 | ||||
-rw-r--r-- | src/mainwindow.cpp | 6 |
11 files changed, 774 insertions, 141 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc4e91c8..0cab993c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,6 +19,7 @@ SET( rekonq_KDEINIT_SRCS protocolhandler.cpp sessionmanager.cpp tabbar.cpp + urltreeview.cpp walletbar.cpp webinspectorpanel.cpp webpage.cpp diff --git a/src/bookmarks/bookmarksmanager.cpp b/src/bookmarks/bookmarksmanager.cpp index cfe26a55..9feed63a 100644 --- a/src/bookmarks/bookmarksmanager.cpp +++ b/src/bookmarks/bookmarksmanager.cpp @@ -178,7 +178,9 @@ BookmarkProvider::BookmarkProvider(QObject *parent) bookfile = KUrl(bookmarksPath); } } - m_manager = KBookmarkManager::managerForExternalFile(bookfile.path()); + // A workaround to avoid a long delay between the two changed signals of the bookmark manager + m_manager = KBookmarkManager::managerForFile(bookfile.path(), "rekonq"); + connect(m_manager, SIGNAL(changed(const QString &, const QString &)), this, SLOT(slotBookmarksChanged(const QString &, const QString &))); diff --git a/src/bookmarks/bookmarksmanager.h b/src/bookmarks/bookmarksmanager.h index d4afb997..e50148e4 100644 --- a/src/bookmarks/bookmarksmanager.h +++ b/src/bookmarks/bookmarksmanager.h @@ -210,7 +210,9 @@ public: */ KBookmarkGroup rootGroup(); - KBookmarkManager *bookmarkManager() { return m_manager; } + KBookmarkManager *bookmarkManager() { return m_manager; } + BookmarkOwner *bookmarkOwner() { return m_owner; } + signals: /** * @short This signal is emitted when an url has to be loaded diff --git a/src/bookmarks/bookmarkspanel.cpp b/src/bookmarks/bookmarkspanel.cpp index 48ca6537..c50ebcdb 100644 --- a/src/bookmarks/bookmarkspanel.cpp +++ b/src/bookmarks/bookmarkspanel.cpp @@ -29,6 +29,7 @@ #include "bookmarkspanel.moc" // Local Includes +#include "bookmarksmanager.h" #include "bookmarkstreemodel.h" #include "bookmarksproxy.h" @@ -44,12 +45,21 @@ // KDE includes #include <KLineEdit> #include <KLocalizedString> +#include <KAction> +#include <KMenu> +#include <KBookmarkDialog> +#include <KMessageBox> BookmarksPanel::BookmarksPanel(const QString &title, QWidget *parent, Qt::WindowFlags flags) - : QDockWidget(title, parent, flags) + : QDockWidget(title, parent, flags), + m_treeView(new UrlTreeView(this)), + m_ac(new KActionCollection(this)), + menu(new KMenu(this)), + expandLock(false) { setup(); + setupActions(); setShown(ReKonfig::showBookmarksPanel()); } @@ -60,13 +70,6 @@ BookmarksPanel::~BookmarksPanel() } -void BookmarksPanel::bookmarkActivated( const QModelIndex &index ) -{ - if( index.isValid() ) - emit openUrl( qVariantValue< KUrl >( index.data( Qt::UserRole ) ) ); -} - - void BookmarksPanel::setup() { setObjectName("bookmarksPanel"); @@ -85,19 +88,20 @@ void BookmarksPanel::setup() searchLabel->setBuddy( search ); // setup tree view - QTreeView *treeView = new QTreeView(ui); - treeView->setUniformRowHeights(true); - treeView->setSelectionBehavior(QAbstractItemView::SelectRows); - treeView->setTextElideMode(Qt::ElideMiddle); - treeView->setAlternatingRowColors(true); - treeView->header()->hide(); - treeView->setRootIsDecorated( false ); + m_treeView->setUniformRowHeights(true); + m_treeView->setTextElideMode(Qt::ElideMiddle); + m_treeView->setAlternatingRowColors(true); + m_treeView->header()->hide(); + m_treeView->setDragEnabled(true); + m_treeView->setAutoExpandDelay(750); + m_treeView->setDefaultDropAction(Qt::MoveAction); + m_treeView->viewport()->setAcceptDrops(true); // put everything together QVBoxLayout *vBoxLayout = new QVBoxLayout; vBoxLayout->setContentsMargins(0, 0, 0, 0); vBoxLayout->addLayout(searchLayout); - vBoxLayout->addWidget(treeView); + vBoxLayout->addWidget(m_treeView); // add it to the UI ui->setLayout(vBoxLayout); @@ -106,8 +110,407 @@ void BookmarksPanel::setup() BookmarksTreeModel *model = new BookmarksTreeModel( this ); BookmarksProxy *proxy = new BookmarksProxy(ui); proxy->setSourceModel( model ); - treeView->setModel( proxy ); + m_treeView->setModel( proxy ); + + connect(m_treeView, SIGNAL(contextMenuItemRequested(const QPoint &)), this, SLOT(contextMenuBk(const QPoint &))); + connect(m_treeView, SIGNAL(contextMenuGroupRequested(const QPoint &)), this, SLOT(contextMenuBkGroup(const QPoint &))); + connect(m_treeView, SIGNAL(contextMenuEmptyRequested(const QPoint &)), this, SLOT(contextMenuBlank(const QPoint &))); + connect(m_treeView, SIGNAL(delKeyPressed()), this, SLOT(deleteBookmark())); + connect(m_treeView, SIGNAL(collapsed(const QModelIndex &)), this, SLOT(onCollapse(const QModelIndex &))); + connect(m_treeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(onExpand(const QModelIndex &))); + connect(search, SIGNAL(textChanged(const QString &)), proxy, SLOT(setFilterFixedString(const QString &))); + callAutoExpand(); +} + + +void BookmarksPanel::onCollapse(const QModelIndex &index) +{ + if(expandLock) + return; + + KBookmark bookmark = bookmarkForIndex(index); + bookmark.internalElement().setAttribute("folded", "yes"); + Application::bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksPanel::onExpand(const QModelIndex &index) +{ + if(expandLock) + return; + + KBookmark bookmark = bookmarkForIndex(index); + bookmark.internalElement().setAttribute("folded", "no"); + Application::bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksPanel::callAutoExpand() +{ + expandLock = true; + autoExpand(); + expandLock = false; +} + + +void BookmarksPanel::autoExpand(const QModelIndex &root) +{ + + int count = m_treeView->model()->rowCount(root); + QModelIndex temp; + + for(int i = 0; i < count; i++) + { + temp = m_treeView->model()->index(i,0,root); + m_treeView->setExpanded(temp, bookmarkForIndex(temp).toGroup().isOpen()); + autoExpand(temp); + } +} + + +void BookmarksPanel::setupActions() +{ + KAction* action; + + action = new KAction(KIcon("tab-new"), i18n("Open"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInCurrentTab())); + m_ac.addAction("open", action); + + action = new KAction(KIcon("tab-new"), i18n("Open in New Tab"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewTab())); + m_ac.addAction("open_tab", action); + + action = new KAction(KIcon("window-new"), i18n("Open in New Window"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewWindow())); + m_ac.addAction("open_window", action); + + action = new KAction(KIcon("rating"), i18n("Bookmark Page"), this); + connect(action, SIGNAL(triggered()), this, SLOT(bookmarkPage())); + m_ac.addAction("bookmark_page", action); + + action = new KAction(KIcon("bookmark-new"), i18n("New Bookmark"), this); + connect(action, SIGNAL(triggered()), this, SLOT(newBookmark())); + m_ac.addAction("bookmark_new", action); + + action = new KAction(KIcon("folder-new"), i18n("New Bookmark Folder"), this); + connect(action, SIGNAL(triggered()), this, SLOT(newBookmarkGroup())); + m_ac.addAction("folder_new", action); + + action = new KAction(KIcon("edit-clear"), i18n("New Separator"), this); + connect(action, SIGNAL(triggered()), this, SLOT(newSeparator())); + m_ac.addAction("separator_new", action); + + action = new KAction(KIcon("edit-copy"), i18n("Copy Link"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(copyToClipboard())); + m_ac.addAction("copy", action); + + action = new KAction(KIcon("edit-delete"), i18n("Delete"), this); + connect(action, SIGNAL(triggered()), this, SLOT(deleteBookmark())); + m_ac.addAction("delete", action); + + action = new KAction(KIcon("configure"), i18n("Properties"), this); + connect(action, SIGNAL(triggered()), this, SLOT(editBookmark())); + m_ac.addAction("properties", action); + + action = new KAction(KIcon("tab-new"), i18n("Open all Bookmarks"), this); + connect(action, SIGNAL(triggered()), this, SLOT(openAll())); + m_ac.addAction("open_all", action); +} + + +KBookmark BookmarksPanel::bookmarkForIndex(const QModelIndex &index) +{ + if(!index.isValid()) + return KBookmark(); + + const QAbstractProxyModel* proxyModel = dynamic_cast< const QAbstractProxyModel* >(index.model()); + QModelIndex originalIndex = proxyModel->mapToSource(index); + + BtmItem *node = static_cast< BtmItem* >( originalIndex.internalPointer() ); + return node->getBkm(); +} + + +void BookmarksPanel::contextMenuBk(const QPoint &pos) +{ + QPoint position = m_treeView->mapToGlobal(pos); + QModelIndex index = m_treeView->indexAt(pos); + if(!index.isValid() || expandLock) + return; + + KBookmark selected = bookmarkForIndex(index); + + if(selected.isGroup()) + { + contextMenuBkGroup(pos, true); + return; + } + + if(selected.isSeparator()) + { + contextMenuSeparator(pos); + return; + } + + menu = new KMenu(this); + + menu->addAction(m_ac.action("open")); + menu->addAction(m_ac.action("open_tab")); + menu->addAction(m_ac.action("open_window")); + + menu->addSeparator(); + + menu->addAction(m_ac.action("bookmark_page")); + menu->addAction(m_ac.action("bookmark_new")); + menu->addAction(m_ac.action("folder_new")); + menu->addAction(m_ac.action("separator_new")); + + menu->addSeparator(); + + menu->addAction(m_ac.action("copy")); + + menu->addSeparator(); + + menu->addAction(m_ac.action("delete")); + menu->addAction(m_ac.action("properties")); + + menu->popup(position); +} + + +void BookmarksPanel::contextMenuBkGroup(const QPoint &pos, bool emptyGroup) +{ + if(expandLock) + return; + + QPoint position = m_treeView->mapToGlobal(pos); + menu = new KMenu(this); + + if(!emptyGroup) + { + menu->addAction(m_ac.action("open_all")); + menu->addSeparator(); + } + + menu->addAction(m_ac.action("bookmark_page")); + menu->addAction(m_ac.action("bookmark_new")); + menu->addAction(m_ac.action("folder_new")); + menu->addAction(m_ac.action("separator_new")); + + menu->addSeparator(); + + menu->addAction(m_ac.action("delete")); + menu->addAction(m_ac.action("properties")); + + menu->popup(position); +} + + +void BookmarksPanel::contextMenuSeparator(const QPoint &pos) +{ + QPoint position = m_treeView->mapToGlobal(pos); + menu = new KMenu(this); + + menu->addAction(m_ac.action("bookmark_page")); + menu->addAction(m_ac.action("bookmark_new")); + menu->addAction(m_ac.action("folder_new")); + menu->addAction(m_ac.action("separator_new")); + + menu->addSeparator(); + + menu->addAction(m_ac.action("delete")); + + menu->popup(position); +} + + +void BookmarksPanel::contextMenuBlank(const QPoint &pos) +{ + QPoint position = m_treeView->mapToGlobal(pos); + menu = new KMenu(this); + + menu->addAction(m_ac.action("bookmark_page")); + menu->addAction(m_ac.action("bookmark_new")); + menu->addAction(m_ac.action("folder_new")); + menu->addAction(m_ac.action("separator_new")); + + menu->popup(position); +} + + +void BookmarksPanel::deleteBookmark() +{ + QModelIndex index = m_treeView->currentIndex(); + if(!index.isValid()) + return; + + KBookmark selected = bookmarkForIndex(index); + KBookmarkGroup parent = selected.parentGroup(); + + parent.deleteBookmark(selected); + Application::instance()->bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksPanel::editBookmark() +{ + QModelIndex index = m_treeView->currentIndex(); + if(!index.isValid()) + return; + + KBookmark selected = bookmarkForIndex(index); + + KBookmarkDialog *dialog = Application::bookmarkProvider()->bookmarkOwner()->bookmarkDialog(Application::bookmarkProvider()->bookmarkManager(), QApplication::activeWindow()); + dialog->editBookmark(selected); + delete dialog; +} + + +void BookmarksPanel::openAll() +{ + QModelIndex index = m_treeView->currentIndex(); + if(!index.isValid()) + return; + + QList<KUrl> allChild = bookmarkForIndex(index).toGroup().groupUrlList(); + + if(allChild.length() > 8) // 8, a good choice ? + { + if(!(KMessageBox::warningContinueCancel(this, i18n("You are about to open a lot of tabs : %1\nAre you sure ?", QString::number(allChild.length()))) == KMessageBox::Continue)) + return; + } + + for(int i = 0; i < allChild.length(); i++) + emit openUrl(allChild.at(i).url(), Rekonq::SettingOpenTab); +} + + +void BookmarksPanel::newBookmark() +{ + QModelIndex index = m_treeView->currentIndex(); + + KBookmark selected; + KBookmark newBk; + + KBookmarkDialog *dialog = Application::bookmarkProvider()->bookmarkOwner()->bookmarkDialog(Application::bookmarkProvider()->bookmarkManager(), QApplication::activeWindow()); + + if(index.isValid()) + { + selected = bookmarkForIndex(index); + + if(selected.isGroup()) + newBk = dialog->addBookmark("New bookmark", KUrl("www.kde.org"), selected); + else + newBk = dialog->addBookmark("New bookmark", KUrl("www.kde.org"), selected.parentGroup()); + } + + else + { + newBk = dialog->addBookmark("New bookmark", KUrl("www.kde.org")); + } + + delete dialog; + + // addBookmark already added the bookmark, but without the default favicon + KBookmarkGroup parent = newBk.parentGroup(); + parent.deleteBookmark(newBk); + newBk.setIcon(("text-html")); + parent.addBookmark(newBk); + + if(index.isValid()) + parent.moveBookmark(newBk, selected); + + Application::bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksPanel::newBookmarkGroup() +{ + QModelIndex index = m_treeView->currentIndex(); + KBookmark newBk; + + KBookmarkDialog *dialog = Application::bookmarkProvider()->bookmarkOwner()->bookmarkDialog(Application::bookmarkProvider()->bookmarkManager(), QApplication::activeWindow()); + + if(index.isValid()) + { + KBookmark selected = bookmarkForIndex(index); + + if(selected.isGroup()) + { + newBk = dialog->createNewFolder("New folder", selected); + } + + else + { + newBk = dialog->createNewFolder("New folder", selected.parentGroup()); + selected.parentGroup().moveBookmark(newBk, selected); + Application::bookmarkProvider()->bookmarkManager()->emitChanged(); + } + } + + else + { + dialog->createNewFolder("New folder"); + } + + delete dialog; +} + + +void BookmarksPanel::newSeparator() +{ + QModelIndex index = m_treeView->currentIndex(); + + KBookmark selected; + KBookmark newBk; + + if(index.isValid()) + { + selected = bookmarkForIndex(index); + + if(selected.isGroup()) + newBk = selected.toGroup().createNewSeparator(); + else + newBk = selected.parentGroup().createNewSeparator(); + } + + else + { + newBk = Application::bookmarkProvider()->rootGroup().createNewSeparator(); + } + + KBookmarkGroup parent = newBk.parentGroup(); + newBk.setIcon(("edit-clear")); + parent.addBookmark(newBk); + + if(index.isValid()) + parent.moveBookmark(newBk, selected); + + Application::bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksPanel::bookmarkPage() +{ + QModelIndex index = m_treeView->currentIndex(); + KBookmarkGroup parent = Application::bookmarkProvider()->rootGroup(); + + if(index.isValid()) + { + KBookmark selected = bookmarkForIndex(index); + parent = selected.parentGroup(); + + if(selected.isGroup()) + parent = selected.toGroup(); + + KBookmark newBk = parent.addBookmark(Application::bookmarkProvider()->bookmarkOwner()->currentTitle(), KUrl(Application::bookmarkProvider()->bookmarkOwner()->currentUrl()), "text-html"); + parent.moveBookmark(newBk, selected); + } + + else + { + parent.addBookmark(Application::bookmarkProvider()->bookmarkOwner()->currentTitle(), KUrl(Application::bookmarkProvider()->bookmarkOwner()->currentUrl()), "text-html"); + } - connect(search, SIGNAL(textChanged(QString)), proxy, SLOT(setFilterFixedString(QString))); - connect(treeView, SIGNAL( activated(QModelIndex) ), this, SLOT( bookmarkActivated(QModelIndex) ) ); + Application::bookmarkProvider()->bookmarkManager()->emitChanged(); } diff --git a/src/bookmarks/bookmarkspanel.h b/src/bookmarks/bookmarkspanel.h index f5376d98..ea33e265 100644 --- a/src/bookmarks/bookmarkspanel.h +++ b/src/bookmarks/bookmarkspanel.h @@ -31,10 +31,17 @@ // Local Includes #include "rekonqprivate_export.h" +#include "application.h" +#include "urltreeview.h" // Qt Includes #include <QDockWidget> +// KDE Includes +#include <KBookmark> +#include <KActionCollection> +#include <KMenu> + // Forward Declarations class KUrl; class QModelIndex; @@ -49,13 +56,38 @@ public: ~BookmarksPanel(); signals: - void openUrl(const KUrl &); + void openUrl(const KUrl &, const Rekonq::OpenType &); + void itemHovered(const QString &); + void saveExpFinished(const QString &); + void saveRequested(); private slots: - void bookmarkActivated( const QModelIndex &index ); + void contextMenuBk(const QPoint &pos); + void contextMenuBkGroup(const QPoint &pos, const bool emptyGroup = false); + void contextMenuBlank(const QPoint &pos); + void deleteBookmark(); + void openAll(); + void editBookmark(); + void newBookmark(); + void newBookmarkGroup(); + void newSeparator(); + void bookmarkPage(); + void autoExpand(const QModelIndex &root = QModelIndex()); + void onCollapse(const QModelIndex &index); + void onExpand(const QModelIndex &index); + void callAutoExpand(); private: void setup(); + void setupActions(); + void contextMenuSeparator(const QPoint &pos); + KBookmark bookmarkForIndex(const QModelIndex &index); + + UrlTreeView *m_treeView; + QStringList m_expList; + KActionCollection m_ac; + KMenu *menu; + bool expandLock; }; #endif // BOOKMARKSPANEL_H diff --git a/src/bookmarks/bookmarkstreemodel.cpp b/src/bookmarks/bookmarkstreemodel.cpp index 95e5ad41..d63c92d3 100644 --- a/src/bookmarks/bookmarkstreemodel.cpp +++ b/src/bookmarks/bookmarkstreemodel.cpp @@ -33,94 +33,112 @@ #include "application.h" #include "bookmarksmanager.h" +// Qt Includes +#include <QMimeData> + // KDE includes #include <KBookmarkGroup> #include <KLocalizedString> -class BookmarksTreeModel::BtmItem +BtmItem::BtmItem(const KBookmark &bm) + : m_parent(0) + , m_kbm(bm) { -public: - BtmItem(const KBookmark &bm) - : m_parent(0) - , m_kbm(bm) - { - } - - - ~BtmItem() - { - qDeleteAll(m_children); - } +} - QVariant data( int role = Qt::DisplayRole ) const - { - if( m_kbm.isNull() ) - return QVariant(); // should only happen for root item +BtmItem::~BtmItem() +{ + qDeleteAll(m_children); +} - if( role == Qt::DisplayRole ) - return m_kbm.text(); - if( role == Qt::DecorationRole ) - return KIcon( m_kbm.icon() ); - if( role == Qt::UserRole ) - return m_kbm.url(); - return QVariant(); +QVariant BtmItem::data( int role ) const +{ + if( m_kbm.isNull() ) + return QVariant(); // should only happen for root item + + if( role == Qt::DisplayRole ) + return m_kbm.text(); + if( role == Qt::DecorationRole ) + return KIcon( m_kbm.icon() ); + if( role == Qt::UserRole ) + return m_kbm.url(); + if( role == Qt::ToolTipRole) + { + QString tooltip = ""; + + if(!m_kbm.text().isEmpty()) + { + tooltip += m_kbm.text(); + } + if(m_kbm.isGroup()) + { + tooltip += " [" + QString::number(childCount()) + " " + i18n("Items") + "]"; + } + if(!m_kbm.url().url().isEmpty()) + { + if(!tooltip.isEmpty()) + tooltip += "\n"; + tooltip += m_kbm.url().url(); + } + return tooltip; } + return QVariant(); +} - int row() const - { - if(m_parent) - return m_parent->m_children.indexOf( const_cast< BtmItem* >( this ) ); - return 0; - } +int BtmItem::row() const +{ + if(m_parent) + return m_parent->m_children.indexOf( const_cast< BtmItem* >( this ) ); + return 0; +} - int childCount() const - { - return m_children.count(); - } +int BtmItem::childCount() const +{ + return m_children.count(); +} - BtmItem* child( int n ) - { - Q_ASSERT(n>=0); - Q_ASSERT(n<childCount()); - return m_children.at(n); - } +BtmItem* BtmItem::child( int n ) +{ + Q_ASSERT(n>=0); + Q_ASSERT(n<childCount()); + return m_children.at(n); +} - BtmItem* parent() const - { - return m_parent; - } +BtmItem* BtmItem::parent() const +{ + return m_parent; +} - void appendChild(BtmItem *child) - { - if( !child ) - return; - child->m_parent = this; - m_children << child; - } +void BtmItem::appendChild(BtmItem *child) +{ + if( !child ) + return; + child->m_parent = this; + m_children << child; +} - void clear() - { - qDeleteAll(m_children); - m_children.clear(); - } -private: - BtmItem *m_parent; - QList< BtmItem* > m_children; - KBookmark m_kbm; -}; +void BtmItem::clear() +{ + qDeleteAll(m_children); + m_children.clear(); +} +KBookmark BtmItem::getBkm() const +{ + return m_kbm; +} // ------------------------------------------------------------------------------------- @@ -130,8 +148,8 @@ BookmarksTreeModel::BookmarksTreeModel(QObject *parent) , m_root(0) { resetModel(); + connect( this, SIGNAL(bookmarkChangedFinished()), parent, SLOT(callAutoExpand())); connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( changed(QString,QString) ), this, SLOT( bookmarksChanged(QString) ) ); - connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( bookmarksChanged(QString) ), this, SLOT( bookmarksChanged(QString) ) ); } @@ -179,8 +197,17 @@ QVariant BookmarksTreeModel::headerData(int section, Qt::Orientation orientation Qt::ItemFlags BookmarksTreeModel::flags(const QModelIndex &index) const { - Q_UNUSED(index) - return Qt::ItemIsEnabled | Qt::ItemIsSelectable; + Qt::ItemFlags flags = QAbstractItemModel::flags(index); + + if(!index.isValid()) + return flags | Qt::ItemIsDropEnabled; + + flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; + + if(bookmarkForIndex(index).isGroup()) + flags |= Qt::ItemIsDropEnabled; + + return flags; } @@ -258,30 +285,9 @@ QVariant BookmarksTreeModel::data(const QModelIndex &index, int role) const void BookmarksTreeModel::bookmarksChanged( const QString &groupAddress ) { - if( groupAddress.isEmpty() ) - { - resetModel(); - return; - } - - BtmItem *node = m_root; - QModelIndex nodeIndex; - - QStringList indexChain( groupAddress.split( '/', QString::SkipEmptyParts) ); - foreach( const QString &sIndex, indexChain ) - { - bool ok; - int i = sIndex.toInt( &ok ); - if( !ok ) - break; - - if( i < 0 || i >= node->childCount() ) - break; - - node = node->child( i ); - nodeIndex = index( i, 0, nodeIndex ); - } - emit dataChanged( index( 0, 0, nodeIndex ), index( node->childCount(), 0, nodeIndex ) ); + Q_UNUSED(groupAddress); + resetModel(); + emit bookmarkChangedFinished(); } @@ -322,3 +328,86 @@ void BookmarksTreeModel::populate( BtmItem *node, KBookmarkGroup bmg) bm = bmg.next( bm ); } } + + +KBookmark BookmarksTreeModel::bookmarkForIndex(const QModelIndex index) const +{ + return static_cast<BtmItem*>(index.internalPointer())->getBkm(); +} + + +Qt::DropActions BookmarksTreeModel::supportedDropActions () const +{ + return Qt::MoveAction; +} + + +QStringList BookmarksTreeModel::mimeTypes () const +{ + return KBookmark::List::mimeDataTypes(); +} + + +QMimeData* BookmarksTreeModel::mimeData( const QModelIndexList & indexes ) const +{ + QMimeData *mimeData = new QMimeData; + + QByteArray addresse = bookmarkForIndex(indexes.first()).address().toLatin1(); + mimeData->setData( "application/rekonq-bookmark", addresse); + bookmarkForIndex(indexes.first()).populateMimeData(mimeData); + + return mimeData; +} + + +bool BookmarksTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex & parent) +{ + if(action == Qt::MoveAction) + { + if(data->hasFormat("application/rekonq-bookmark")) + { + QByteArray addresses = data->data("application/rekonq-bookmark"); + KBookmark bookmark = Application::bookmarkProvider()->bookmarkManager()->findByAddress(QString::fromLatin1(addresses.data())); + + QModelIndex destIndex = index(row, column, parent); + + KBookmark dropDestBookmark; + if(destIndex.isValid()) + dropDestBookmark = bookmarkForIndex(destIndex); + + KBookmarkGroup root = Application::bookmarkProvider()->rootGroup(); + if(parent.isValid()) + root = bookmarkForIndex(parent).toGroup(); + + if(!destIndex.isValid()) + { + if(!parent.isValid()) // Drop into a blank area + { + Application::bookmarkProvider()->rootGroup().deleteBookmark(bookmark); + Application::bookmarkProvider()->rootGroup().addBookmark(bookmark); + } + else // Drop at the last item of the group or directly on the main item of the group + { + root.deleteBookmark(bookmark); + root.addBookmark(bookmark); + } + } + + else + { + if(row == -1) + { + root.deleteBookmark(bookmark); + root.addBookmark(bookmark); + } + else // A classic drop + { + root.moveBookmark(bookmark, root.previous(dropDestBookmark)); + } + } + + Application::bookmarkProvider()->bookmarkManager()->emitChanged(root); + } + } + return true; +} diff --git a/src/bookmarks/bookmarkstreemodel.h b/src/bookmarks/bookmarkstreemodel.h index dfad52ba..4ff19e5f 100644 --- a/src/bookmarks/bookmarkstreemodel.h +++ b/src/bookmarks/bookmarkstreemodel.h @@ -38,6 +38,26 @@ // Qt Includes #include <QAbstractItemModel> +class BtmItem +{ +public: + BtmItem(const KBookmark &bm); + ~BtmItem(); + QVariant data( int role = Qt::DisplayRole ) const; + int row() const; + int childCount() const; + BtmItem* child( int n ); + BtmItem* parent() const; + void appendChild(BtmItem *child); + void clear(); + KBookmark getBkm() const; + +private: + BtmItem *m_parent; + QList< BtmItem* > m_children; + KBookmark m_kbm; +}; + class REKONQ_TESTS_EXPORT BookmarksTreeModel : public QAbstractItemModel { @@ -48,28 +68,33 @@ public: explicit BookmarksTreeModel(QObject *parent = 0); ~BookmarksTreeModel(); - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; - virtual Qt::ItemFlags flags(const QModelIndex &index) const; + virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + virtual Qt::ItemFlags flags(const QModelIndex &index) const; - virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; virtual QModelIndex parent(const QModelIndex &index) const; - virtual QVariant data(const QModelIndex &index, int role) const; -// virtual bool setData(const QModelIndex &index, const QVariant &value, int role); + virtual QVariant data(const QModelIndex &index, int role) const; -private slots: - void bookmarksChanged( const QString &groupAddress ); + virtual QStringList mimeTypes () const; + virtual bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent); + virtual Qt::DropActions supportedDropActions () const; + virtual QMimeData *mimeData( const QModelIndexList & indexes ) const; -private: - class BtmItem; - BtmItem *m_root; +private slots: + void bookmarksChanged( const QString &groupAddress ); - void resetModel(); +signals: + void bookmarkChangedFinished(); +private: + BtmItem *m_root; + void resetModel(); void setRoot(KBookmarkGroup bmg); - void populate( BtmItem *node, KBookmarkGroup bmg); + void populate( BtmItem *node, KBookmarkGroup bmg); + KBookmark bookmarkForIndex(const QModelIndex index) const; }; #endif // BOOKMARKSTREEMODEL_H diff --git a/src/history/historymodels.cpp b/src/history/historymodels.cpp index 709d0523..736dbcd7 100644 --- a/src/history/historymodels.cpp +++ b/src/history/historymodels.cpp @@ -118,6 +118,8 @@ QVariant HistoryModel::data(const QModelIndex &index, int role) const return item.dateTime.date(); case UrlRole: return QUrl(item.url); + case Qt::UserRole: + return KUrl(item.url); case UrlStringRole: return item.url; case Qt::DisplayRole: @@ -144,6 +146,12 @@ QVariant HistoryModel::data(const QModelIndex &index, int role) const { return Application::icon(item.url); } + case Qt::ToolTipRole: + QString tooltip = ""; + if(!item.title.isEmpty()) + tooltip = item.title + "\n"; + tooltip += item.dateTime.toString(Qt::SystemLocaleShortDate) + "\n" + item.url; + return tooltip; } return QVariant(); } diff --git a/src/history/historypanel.cpp b/src/history/historypanel.cpp index 8c8eae75..c67594ff 100644 --- a/src/history/historypanel.cpp +++ b/src/history/historypanel.cpp @@ -46,6 +46,9 @@ // KDE Includes #include <KLineEdit> #include <KLocalizedString> +#include <KMenu> +#include <KAction> +#include <KMessageBox> HistoryPanel::HistoryPanel(const QString &title, QWidget *parent, Qt::WindowFlags flags) @@ -70,11 +73,12 @@ void HistoryPanel::setup() QWidget *ui = new QWidget(this); - QTreeView *historyTreeView = new QTreeView(this); - historyTreeView->setUniformRowHeights(true); - historyTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); - historyTreeView->setTextElideMode(Qt::ElideMiddle); - historyTreeView->setAlternatingRowColors(true); + m_treeView = new UrlTreeView(this); + m_treeView->setUniformRowHeights(true); + m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_treeView->setTextElideMode(Qt::ElideMiddle); + m_treeView->setAlternatingRowColors(true); + m_treeView->header()->hide(); // add search bar QHBoxLayout *hBoxLayout = new QHBoxLayout; @@ -91,7 +95,7 @@ void HistoryPanel::setup() QVBoxLayout *vBoxLayout = new QVBoxLayout; vBoxLayout->setContentsMargins(0, 0, 0, 0); vBoxLayout->addWidget(searchBar); - vBoxLayout->addWidget(historyTreeView); + vBoxLayout->addWidget(m_treeView); // add it to the UI ui->setLayout(vBoxLayout); @@ -103,19 +107,78 @@ void HistoryPanel::setup() TreeProxyModel *treeProxyModel = new TreeProxyModel(this); treeProxyModel->setSourceModel(model); - historyTreeView->setModel(treeProxyModel); - historyTreeView->setExpanded(treeProxyModel->index(0, 0), true); - historyTreeView->header()->hideSection(1); + m_treeView->setModel(treeProxyModel); + m_treeView->setExpanded(treeProxyModel->index(0, 0), true); + m_treeView->header()->hideSection(1); QFontMetrics fm(font()); int header = fm.width(QLatin1Char('m')) * 40; - historyTreeView->header()->resizeSection(0, header); + m_treeView->header()->resizeSection(0, header); connect(search, SIGNAL(textChanged(QString)), treeProxyModel, SLOT(setFilterFixedString(QString))); - connect(historyTreeView, SIGNAL(activated(const QModelIndex &)), this, SLOT(itemActivated(const QModelIndex &))); + connect(m_treeView, SIGNAL(contextMenuItemRequested(const QPoint &)), this, SLOT(contextMenuItem(const QPoint &))); + connect(m_treeView, SIGNAL(contextMenuGroupRequested(const QPoint &)), this, SLOT(contextMenuGroup(const QPoint &))); } +void HistoryPanel::contextMenuItem(const QPoint &pos) +{ + QPoint position = m_treeView->mapToGlobal(pos); + KMenu *menu = new KMenu(this); + KAction* action; + + action = new KAction(KIcon("tab-new"), i18n("Open"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInCurrentTab())); + menu->addAction(action); + + action = new KAction(KIcon("tab-new"), i18n("Open in new tab"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewTab())); + menu->addAction(action); + + action = new KAction(KIcon("window-new"), i18n("Open in new window"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewWindow())); + menu->addAction(action); + + action = new KAction(KIcon("edit-copy"), i18n("Copy link"), this); + connect(action, SIGNAL(triggered()), m_treeView, SLOT(copyToClipboard())); + menu->addAction(action); -void HistoryPanel::itemActivated(const QModelIndex &item) + if (!menu) + return; + menu->popup(position); +} + +void HistoryPanel::contextMenuGroup(const QPoint &pos) { - emit openUrl( item.data(HistoryModel::UrlRole).toUrl() ); + QPoint position = m_treeView->mapToGlobal(pos); + KMenu *menu = new KMenu(this); + KAction* action; + + action = new KAction(KIcon("tab-new"), i18n("Open all Bookmarks"), this); + connect(action, SIGNAL(triggered()), this, SLOT(openAll())); + + menu->addAction(action); + + if (!menu) + return; + menu->popup(position); +} + +void HistoryPanel::openAll() +{ + QModelIndex index = m_treeView->currentIndex(); + if(!index.isValid()) + return; + + QList<KUrl> allChild; + + for(int i = 0; i < index.model()->rowCount(index); i++) + allChild << qVariantValue<KUrl>(index.child(i, 0).data(Qt::UserRole)); + + if(allChild.length() > 8) // 8, a good choice ? + { + if(!(KMessageBox::warningContinueCancel(this, i18n("You are about to open a lot of tabs : %1\nAre you sure ?", QString::number(allChild.length()))) == KMessageBox::Continue)) + return; + } + + for(int i = 0; i < allChild.length(); i++) + emit openUrl(allChild.at(i).url(), Rekonq::SettingOpenTab); } diff --git a/src/history/historypanel.h b/src/history/historypanel.h index 6e6a9162..0c01189c 100644 --- a/src/history/historypanel.h +++ b/src/history/historypanel.h @@ -31,6 +31,8 @@ // Local Includes #include "rekonqprivate_export.h" +#include "application.h" +#include "urltreeview.h" // Qt Includes #include <QDockWidget> @@ -50,13 +52,17 @@ public: ~HistoryPanel(); signals: - void openUrl(const KUrl &); + void openUrl(const KUrl &, const Rekonq::OpenType &); + void itemHovered(const QString &); private slots: - void itemActivated(const QModelIndex &); + void contextMenuItem(const QPoint &pos); + void contextMenuGroup(const QPoint &pos); + void openAll(); private: void setup(); + UrlTreeView *m_treeView; }; #endif // HISTORYPANEL_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index d15ce0c4..93273dc9 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -500,7 +500,8 @@ void MainWindow::setupPanels() // STEP 1 // Setup history panel m_historyPanel = new HistoryPanel(i18n("History Panel"), this); - connect(m_historyPanel, SIGNAL(openUrl(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); + connect(m_historyPanel, SIGNAL(openUrl(const KUrl&, const Rekonq::OpenType &)), Application::instance(), SLOT(loadUrl(const KUrl&, const Rekonq::OpenType &))); + connect(m_historyPanel, SIGNAL(itemHovered(QString)), this, SLOT(notifyMessage(QString))); connect(m_historyPanel, SIGNAL(destroyed()), Application::instance(), SLOT(saveConfiguration())); addDockWidget(Qt::LeftDockWidgetArea, m_historyPanel); @@ -514,7 +515,8 @@ void MainWindow::setupPanels() // STEP 2 // Setup bookmarks panel m_bookmarksPanel = new BookmarksPanel(i18n("Bookmarks Panel"), this); - connect(m_bookmarksPanel, SIGNAL(openUrl(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); + connect(m_bookmarksPanel, SIGNAL(openUrl(const KUrl&, const Rekonq::OpenType &)), Application::instance(), SLOT(loadUrl(const KUrl&, const Rekonq::OpenType &))); + connect(m_bookmarksPanel, SIGNAL(itemHovered(QString)), this, SLOT(notifyMessage(QString))); connect(m_bookmarksPanel, SIGNAL(destroyed()), Application::instance(), SLOT(saveConfiguration())); addDockWidget(Qt::LeftDockWidgetArea, m_bookmarksPanel); |