summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt2
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/bookmarks/bookmarksmanager.cpp18
-rw-r--r--src/bookmarks/bookmarksmanager.h11
-rw-r--r--src/bookmarks/bookmarkspanel.cpp408
-rw-r--r--src/bookmarks/bookmarkspanel.h32
-rw-r--r--src/bookmarks/bookmarkstreemodel.cpp283
-rw-r--r--src/bookmarks/bookmarkstreemodel.h52
-rw-r--r--src/history/historymodels.cpp8
-rw-r--r--src/history/historypanel.cpp91
-rw-r--r--src/history/historypanel.h10
-rw-r--r--src/mainview.cpp3
-rw-r--r--src/mainwindow.cpp6
-rw-r--r--src/urlbar/completionwidget.cpp242
-rw-r--r--src/urlbar/completionwidget.h77
-rw-r--r--src/urlbar/lineedit.cpp4
-rw-r--r--src/urlbar/lineedit.h12
-rw-r--r--src/urlbar/listitem.cpp173
-rw-r--r--src/urlbar/listitem.h59
-rw-r--r--src/urlbar/urlbar.cpp208
-rw-r--r--src/urlbar/urlbar.h28
-rw-r--r--src/urlbar/urlresolver.cpp177
-rw-r--r--src/urlbar/urlresolver.h72
-rw-r--r--src/urltreeview.cpp195
-rw-r--r--src/urltreeview.h69
25 files changed, 1964 insertions, 280 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d41552a4..5fa7cf4e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,7 +7,7 @@ PROJECT( rekonq )
# Informations to update before to release this package.
# rekonq info
-SET(REKONQ_VERSION "0.4.55" )
+SET(REKONQ_VERSION "0.4.57" )
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h )
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index bc4e91c8..a68faa59 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
@@ -48,6 +49,9 @@ SET( rekonq_KDEINIT_SRCS
#----------------------------------------
urlbar/urlbar.cpp
urlbar/lineedit.cpp
+ urlbar/completionwidget.cpp
+ urlbar/urlresolver.cpp
+ urlbar/listitem.cpp
)
diff --git a/src/bookmarks/bookmarksmanager.cpp b/src/bookmarks/bookmarksmanager.cpp
index cfe26a55..89e39ef8 100644
--- a/src/bookmarks/bookmarksmanager.cpp
+++ b/src/bookmarks/bookmarksmanager.cpp
@@ -161,7 +161,12 @@ BookmarkProvider::BookmarkProvider(QObject *parent)
, m_actionCollection(new KActionCollection(this))
, m_bookmarkMenu(0)
, m_bookmarkToolBar(0)
+ , m_completion(0)
{
+ // take care of the completion object
+ m_completion = new KCompletion;
+ m_completion->setOrder( KCompletion::Weighted );
+
KUrl bookfile = KUrl("~/.kde/share/apps/konqueror/bookmarks.xml"); // share konqueror bookmarks
if (!QFile::exists(bookfile.path()))
@@ -178,7 +183,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 &)));
@@ -220,6 +227,7 @@ void BookmarkProvider::slotBookmarksChanged(const QString &group, const QString
return;
m_bookmarkToolBar->clear(); // FIXME CRASH
+ m_completion->clear();
KBookmark bookmark = toolBarGroup.first();
while (!bookmark.isNull())
@@ -285,7 +293,8 @@ KAction *BookmarkProvider::fillBookmarkBar(const KBookmark &bookmark)
return a;
}
else
- {
+ {
+ m_completion->addItem(bookmark.url().path());
return new KBookmarkAction(bookmark, m_owner, this);
}
}
@@ -295,3 +304,8 @@ KBookmarkGroup BookmarkProvider::rootGroup()
{
return m_manager->root();
}
+
+KCompletion *BookmarkProvider::completionObject() const
+{
+ return m_completion;
+}
diff --git a/src/bookmarks/bookmarksmanager.h b/src/bookmarks/bookmarksmanager.h
index d4afb997..18ff3ef0 100644
--- a/src/bookmarks/bookmarksmanager.h
+++ b/src/bookmarks/bookmarksmanager.h
@@ -39,6 +39,7 @@
// KDE Includes
#include <KBookmarkOwner>
+#include <KCompletion>
// Forward Declarations
class BookmarkProvider;
@@ -210,7 +211,14 @@ public:
*/
KBookmarkGroup rootGroup();
- KBookmarkManager *bookmarkManager() { return m_manager; }
+ KBookmarkManager *bookmarkManager() { return m_manager; }
+ BookmarkOwner *bookmarkOwner() { return m_owner; }
+
+ /**
+ * @returns the KCompletion object.
+ */
+ KCompletion *completionObject() const;
+
signals:
/**
* @short This signal is emitted when an url has to be loaded
@@ -245,6 +253,7 @@ private:
KActionCollection *m_actionCollection;
BookmarkMenu *m_bookmarkMenu;
KToolBar *m_bookmarkToolBar;
+ KCompletion *m_completion;
};
#endif
diff --git a/src/bookmarks/bookmarkspanel.cpp b/src/bookmarks/bookmarkspanel.cpp
index 48ca6537..2f530c6c 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,20 @@
// 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)),
+ m_loadingState(false)
{
setup();
+ setupActions();
setShown(ReKonfig::showBookmarksPanel());
}
@@ -60,13 +69,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 +87,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 +109,375 @@ 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 &)));
+ loadFoldedState();
+}
+
+
+void BookmarksPanel::onCollapse(const QModelIndex &index)
+{
+ if(m_loadingState)
+ return;
+
+ KBookmark bookmark = bookmarkForIndex(index);
+ bookmark.internalElement().setAttribute("folded", "yes");
+ emit saveOnlyRequested();
+}
+
+
+void BookmarksPanel::onExpand(const QModelIndex &index)
+{
+ if(m_loadingState)
+ return;
+
+ KBookmark bookmark = bookmarkForIndex(index);
+ bookmark.internalElement().setAttribute("folded", "no");
+ emit saveOnlyRequested();
+}
+
+
+void BookmarksPanel::loadFoldedState()
+{
+ m_loadingState = true;
+ loadFoldedState(QModelIndex());
+ m_loadingState = false;
+}
+
+
+void BookmarksPanel::loadFoldedState(const QModelIndex &root)
+{
+
+ int count = m_treeView->model()->rowCount(root);
+ QModelIndex index;
+
+ for(int i = 0; i < count; i++)
+ {
+ index = m_treeView->model()->index(i, 0, root);
+ if(index.isValid() && bookmarkForIndex(index).isGroup())
+ {
+ m_treeView->setExpanded(index, bookmarkForIndex(index).toGroup().isOpen());
+ loadFoldedState(index);
+ }
+ }
+}
+
+
+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("bookmark-new"), i18n("Add Bookmark Here"), this);
+ connect(action, SIGNAL(triggered()), this, SLOT(bookmarkCurrentPage()));
+ m_ac->addAction("bookmark_page", 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 Address"), this);
+ connect(action, SIGNAL(triggered()), m_treeView, SLOT(copyToClipboard()));
+ m_ac->addAction("copy", action);
+
+ action = new KAction(KIcon("edit-delete"), i18n("Delete Bookmark"), 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 Folder in Tabs"), this);
+ connect(action, SIGNAL(triggered()), this, SLOT(openFolderInTabs()));
+ 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() || m_loadingState)
+ return;
+
+ KBookmark selected = bookmarkForIndex(index);
+
+ if(selected.isGroup())
+ {
+ contextMenuBkGroup(pos, true);
+ return;
+ }
+
+ if(selected.isSeparator())
+ {
+ contextMenuSeparator(pos);
+ return;
+ }
+
+ KMenu *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("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(m_loadingState)
+ return;
+
+ QPoint position = m_treeView->mapToGlobal(pos);
+ KMenu *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("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);
+ KMenu *menu = new KMenu(this);
+
+ menu->addAction(m_ac->action("bookmark_page"));
+ 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);
+ KMenu *menu = new KMenu(this);
+
+ menu->addAction(m_ac->action("bookmark_page"));
+ 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 bm = bookmarkForIndex(index);
+ bool folder = bm.isGroup();
+
+ if (KMessageBox::warningContinueCancel(
+ QApplication::activeWindow(),
+ folder ? i18n("Are you sure you wish to remove the bookmark folder\n\"%1\"?", bm.text())
+ : i18n("Are you sure you wish to remove the bookmark\n\"%1\"?", bm.text()),
+ folder ? i18n("Bookmark Folder Deletion")
+ : i18n("Bookmark Deletion"),
+ KStandardGuiItem::del())
+ != KMessageBox::Continue
+ )
+ return;
+
+
+ bm.parentGroup().deleteBookmark(bm);
+ 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::openFolderInTabs()
+{
+ QModelIndex index = m_treeView->currentIndex();
+ if(!index.isValid() || !bookmarkForIndex(index).isGroup())
+ 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::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::bookmarkCurrentPage()
+{
+ 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.parentGroup().previous(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..f8528b71 100644
--- a/src/bookmarks/bookmarkspanel.h
+++ b/src/bookmarks/bookmarkspanel.h
@@ -31,10 +31,16 @@
// Local Includes
#include "rekonqprivate_export.h"
+#include "application.h"
+#include "urltreeview.h"
// Qt Includes
#include <QDockWidget>
+// KDE Includes
+#include <KBookmark>
+#include <KActionCollection>
+
// Forward Declarations
class KUrl;
class QModelIndex;
@@ -49,13 +55,35 @@ public:
~BookmarksPanel();
signals:
- void openUrl(const KUrl &);
+ void openUrl(const KUrl &, const Rekonq::OpenType &);
+ void itemHovered(const QString &);
+ void saveOnlyRequested();
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 openFolderInTabs();
+ void editBookmark();
+ void newBookmarkGroup();
+ void newSeparator();
+ void onCollapse(const QModelIndex &index);
+ void onExpand(const QModelIndex &index);
+ void bookmarkCurrentPage();
+ void loadFoldedState(const QModelIndex &root);
+ void loadFoldedState();
+
private:
void setup();
+ void setupActions();
+ void contextMenuSeparator(const QPoint &pos);
+ KBookmark bookmarkForIndex(const QModelIndex &index);
+
+ UrlTreeView *m_treeView;
+ KActionCollection *m_ac;
+ bool m_loadingState;
};
#endif // BOOKMARKSPANEL_H
diff --git a/src/bookmarks/bookmarkstreemodel.cpp b/src/bookmarks/bookmarkstreemodel.cpp
index 95e5ad41..836401a6 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,9 @@ BookmarksTreeModel::BookmarksTreeModel(QObject *parent)
, m_root(0)
{
resetModel();
- connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( changed(QString,QString) ), this, SLOT( bookmarksChanged(QString) ) );
- connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( bookmarksChanged(QString) ), this, SLOT( bookmarksChanged(QString) ) );
+ connect( this, SIGNAL(bookmarksUpdated()), parent, SLOT(loadFoldedState()));
+ connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( changed(QString,QString) ), this, SLOT( bookmarksChanged() ) );
+ connect( parent, SIGNAL(saveOnlyRequested()), this, SLOT(saveOnly()) );
}
@@ -179,8 +198,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;
}
@@ -256,32 +284,10 @@ QVariant BookmarksTreeModel::data(const QModelIndex &index, int role) const
}
-void BookmarksTreeModel::bookmarksChanged( const QString &groupAddress )
+void BookmarksTreeModel::bookmarksChanged()
{
- 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 ) );
+ resetModel();
+ emit bookmarksUpdated();
}
@@ -322,3 +328,100 @@ 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();
+}
+
+
+void BookmarksTreeModel::saveOnly()
+{
+ disconnect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL(changed(QString,QString)), this, SLOT(bookmarksChanged()));
+ connect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL(changed(QString,QString)), this, SLOT(reconnectManager()));
+ Application::bookmarkProvider()->bookmarkManager()->emitChanged();
+}
+
+
+void BookmarksTreeModel::reconnectManager()
+{
+ connect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL( changed(QString,QString) ), this, SLOT(bookmarksChanged()));
+}
+
+
+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..b312ab2d 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,36 @@ 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;
+
+ 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 slots:
- void bookmarksChanged( const QString &groupAddress );
+ void bookmarksChanged();
+ void saveOnly();
+ void reconnectManager();
-private:
- class BtmItem;
- BtmItem *m_root;
+signals:
+ void bookmarksUpdated();
- void resetModel();
+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..03f2b880 100644
--- a/src/history/historypanel.cpp
+++ b/src/history/historypanel.cpp
@@ -46,10 +46,14 @@
// KDE Includes
#include <KLineEdit>
#include <KLocalizedString>
+#include <KMenu>
+#include <KAction>
+#include <KMessageBox>
HistoryPanel::HistoryPanel(const QString &title, QWidget *parent, Qt::WindowFlags flags)
- : QDockWidget(title, parent, flags)
+ : QDockWidget(title, parent, flags),
+ m_treeView(new UrlTreeView(this))
{
setup();
setShown(ReKonfig::showHistoryPanel());
@@ -70,11 +74,11 @@ 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->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 Address"), 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 Folder in Tabs"), 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/mainview.cpp b/src/mainview.cpp
index f2152364..6643becb 100644
--- a/src/mainview.cpp
+++ b/src/mainview.cpp
@@ -242,8 +242,7 @@ void MainView::clear()
{
// FIXME (the programmer, not the code)
// What exactly do we need to clear here?
- m_urlBar->clearHistory();
- m_urlBar->clear();
+ m_urlBar->clear();
m_recentlyClosedTabs.clear();
}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 6a17d1b8..6efd58ed 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);
diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp
new file mode 100644
index 00000000..42abcb73
--- /dev/null
+++ b/src/urlbar/completionwidget.cpp
@@ -0,0 +1,242 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "completionwidget.h"
+#include "completionwidget.moc"
+
+// KDE Includes
+#include <KGlobalSettings>
+#include <KDebug>
+#include <KUrl>
+
+// Qt Includes
+#include <QPoint>
+#include <QSize>
+#include <QVBoxLayout>
+#include <QString>
+#include <QEvent>
+#include <QKeyEvent>
+
+#define MAX_ELEMENTS 9
+#include "application.h"
+
+CompletionWidget::CompletionWidget( QWidget *parent)
+:QFrame( parent, Qt::ToolTip)
+ , _parent(parent)
+ , _currentIndex(-1)
+{
+ QPalette p(palette());
+ p.setColor(QPalette::Background, Qt::white); //todo: choose the correct color
+ setPalette(p);
+ setFrameStyle(QFrame::Panel);
+ setLayoutDirection(Qt::LeftToRight);
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+ setLayout(layout);
+
+}
+
+
+void CompletionWidget::insertSearchList(const UrlSearchList &list)
+{
+ _list = list;
+ int min = MAX_ELEMENTS;
+ if(list.count() < min)
+ min = list.count();
+
+ for(int i = 0; i<min ; ++i)
+ {
+ UrlSearchItem item = list.at(i);
+ ListItem *suggestion = new ListItem(item);
+ connect(suggestion, SIGNAL(itemClicked(ListItem *)), this, SLOT(itemChosen(ListItem *)));
+ suggestion->setObjectName( QString::number(i) );
+ layout()->addWidget( suggestion );
+ }
+}
+
+
+void CompletionWidget::sizeAndPosition()
+{
+ // size
+ setFixedHeight(layout()->count() * 44 );
+ setFixedWidth( _parent->width() );
+
+ // position
+ QPoint p = _parent->mapToGlobal( QPoint(0,0) );
+ move(p.x(), p.y() + _parent->height());
+}
+
+
+void CompletionWidget::popup()
+{
+ down();
+ sizeAndPosition();
+ if (!isVisible())
+ show();
+}
+
+
+void CompletionWidget::up()
+{
+ // deactivate previous
+ if(_currentIndex != -1)
+ {
+ ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) );
+ widget->deactivate();
+ }
+
+ if(_currentIndex > 0)
+ _currentIndex--;
+ else
+ _currentIndex=layout()->count()-1;
+
+ // activate "new" current
+ ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) );
+ widget->activate();
+}
+
+KUrl CompletionWidget::currentUrl()
+{
+ return _list.at(_currentIndex).url;
+}
+
+void CompletionWidget::down()
+{
+ // deactivate previous
+ if(_currentIndex != -1)
+ {
+ ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) );
+ widget->deactivate();
+ }
+
+ if(_currentIndex < _list.count() -1)
+ _currentIndex++;
+ else
+ _currentIndex=0;
+
+ // activate "new" current
+ ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) );
+ widget->activate();
+}
+
+void CompletionWidget::clear()
+{
+ QLayoutItem *child;
+ while ((child = layout()->takeAt(0)) != 0)
+ {
+ delete child->widget();
+ delete child;
+ }
+ _currentIndex = -1;
+}
+
+
+bool CompletionWidget::eventFilter( QObject *o, QEvent *e )
+{
+ int type = e->type();
+ QWidget *wid = qobject_cast<QWidget*>(o);
+
+ if (o == this)
+ {
+ return false;
+ }
+
+ //hide conditions of the CompletionWidget
+ if (wid
+ && ((wid == _parent && (type == QEvent::Move || type == QEvent::Resize))
+ || ((wid->windowFlags() & Qt::Window)
+ && (type == QEvent::Move || type == QEvent::Hide || type == QEvent::WindowDeactivate)
+ && wid == _parent->window())
+ || (type == QEvent::MouseButtonPress && !isAncestorOf(wid)))
+ )
+ {
+ hide();
+ return false;
+ }
+
+ //actions on the CompletionWidget
+ if (wid && wid->isAncestorOf(_parent) && isVisible())
+ {
+ if ( type == QEvent::KeyPress )
+ {
+ QKeyEvent *ev = static_cast<QKeyEvent *>( e );
+ switch ( ev->key() )
+ {
+ case Qt::Key_Up:
+ case Qt::Key_Backtab:
+ if (ev->modifiers() == Qt::NoButton || (ev->modifiers() & Qt::ShiftModifier))
+ {
+ up();
+ ev->accept();
+ return true;
+ }
+ break;
+
+ case Qt::Key_Down:
+ case Qt::Key_Tab:
+ if (ev->modifiers() == Qt::NoButton)
+ {
+ down();
+ ev->accept();
+ return true;
+ }
+ break;
+
+ case Qt::Key_Return:
+ hide();
+ emit chosenUrl(currentUrl().url());
+ ev->accept();
+ return true;
+ break;
+ }
+ }
+ }
+
+ return QFrame::eventFilter(o,e);
+}
+
+
+void CompletionWidget::setVisible( bool visible )
+{
+ if (visible)
+ {
+ Application::instance()->installEventFilter(this);
+ }
+ else
+ {
+ Application::instance()->removeEventFilter(this);
+ }
+
+ QFrame::setVisible(visible);
+}
+
+
+void CompletionWidget::itemChosen(ListItem *item)
+{
+ emit chosenUrl(_list.at(layout()->indexOf(item)).url);
+ hide();
+} \ No newline at end of file
diff --git a/src/urlbar/completionwidget.h b/src/urlbar/completionwidget.h
new file mode 100644
index 00000000..7b474bd8
--- /dev/null
+++ b/src/urlbar/completionwidget.h
@@ -0,0 +1,77 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef COMPLETION_WIDGET_H
+#define COMPLETION_WIDGET_H
+
+
+// Local Includes
+#include "urlresolver.h"
+#include "listitem.h"
+
+// Qt Includes
+#include <QFrame>
+
+// KDE Includes
+#include <KLineEdit>
+
+// Forward Declarations
+class KUrl;
+
+
+class CompletionWidget : public QFrame
+{
+Q_OBJECT
+
+public:
+ CompletionWidget(QWidget *parent);
+
+ void insertSearchList(const UrlSearchList &list);
+ void popup();
+
+ void up();
+ void down();
+ void clear();
+ virtual bool eventFilter(QObject *obj, QEvent *ev);
+ void setVisible(bool visible);
+ KUrl currentUrl();
+
+private slots:
+ void itemChosen(ListItem *item);
+
+signals:
+ void chosenUrl(const QString&);
+
+private:
+ void sizeAndPosition();
+
+ QWidget *_parent;
+
+ UrlSearchList _list;
+ int _currentIndex;
+};
+
+#endif // COMPLETION_WIDGET_H
diff --git a/src/urlbar/lineedit.cpp b/src/urlbar/lineedit.cpp
index db36bd0c..f3c93e8e 100644
--- a/src/urlbar/lineedit.cpp
+++ b/src/urlbar/lineedit.cpp
@@ -2,9 +2,9 @@
*
* This file is a part of the rekonq project
*
-* Copyright (C) 2009-2010 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
-* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
+* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>
*
*
* This program is free software; you can redistribute it and/or
diff --git a/src/urlbar/lineedit.h b/src/urlbar/lineedit.h
index 1ac3af2e..d76a5fcb 100644
--- a/src/urlbar/lineedit.h
+++ b/src/urlbar/lineedit.h
@@ -2,9 +2,9 @@
*
* This file is a part of the rekonq project
*
-* Copyright (C) 2009-2010 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
-* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
+* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>
*
*
* This program is free software; you can redistribute it and/or
@@ -30,9 +30,6 @@
#define LINEEDIT_H
-// Local Includes
-#include "rekonqprivate_export.h"
-
// KDE Includes
#include <KLineEdit>
@@ -42,7 +39,7 @@ class QFocusEvent;
class QKeyEvent;
-class REKONQ_TESTS_EXPORT LineEdit : public KLineEdit
+class LineEdit : public KLineEdit
{
Q_OBJECT
@@ -50,9 +47,12 @@ public:
explicit LineEdit(QWidget *parent = 0);
virtual ~LineEdit();
+
protected:
virtual void keyPressEvent(QKeyEvent*);
virtual void mouseDoubleClickEvent(QMouseEvent *);
+
+
};
#endif // LINEEDIT_H
diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp
new file mode 100644
index 00000000..92951cb7
--- /dev/null
+++ b/src/urlbar/listitem.cpp
@@ -0,0 +1,173 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "listitem.h"
+
+// Local Includes
+#include "urlresolver.h"
+#include "application.h"
+
+// KDE Includes
+#include <KIcon>
+#include <KStandardDirs>
+#include <KDebug>
+
+// Qt Includes
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QLabel>
+#include <QSizePolicy>
+#include <QPixmap>
+#include <QStylePainter>
+#include <QFile>
+
+ListItem::ListItem(const UrlSearchItem &item, QWidget *parent)
+ : QWidget(parent),
+ m_option()
+{
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ QVBoxLayout *vLayout = new QVBoxLayout;
+
+ QLabel *previewLabel = new QLabel;
+ previewLabel->setFixedSize(40,30);
+ QPixmap preview;
+ QString path = KStandardDirs::locateLocal("cache", QString("thumbs/") + guessNameFromUrl(item.url) + ".png", true);
+ if(QFile::exists(path))
+ {
+ preview.load(path);
+ previewLabel->setPixmap(preview.scaled(40,30));
+ }
+ else
+ {
+ if(item.icon.startsWith( QLatin1String("http://") ) )
+ preview = Application::icon( item.icon ).pixmap(22);
+ }
+ previewLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
+
+ hLayout->addWidget(previewLabel);
+ hLayout->addLayout(vLayout);
+
+ QLabel *titleLabel = new QLabel("<b>" + item.title + "</b>");
+ titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ QLabel *urlLabel = new QLabel("<i>" + item.url + "</i>");
+ urlLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+
+ vLayout->addWidget(titleLabel);
+ vLayout->addWidget(urlLabel);
+
+
+ QLabel *iconLabel = new QLabel;
+ QPixmap pixmap;
+ if(item.icon.startsWith( QLatin1String("http://") ) )
+ pixmap = Application::icon( item.icon ).pixmap(18);
+ else
+ pixmap = KIcon(item.icon).pixmap(18);
+
+ iconLabel->setPixmap(pixmap);
+ iconLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum);
+ hLayout->addWidget(iconLabel);
+
+ setLayout(hLayout);
+
+ m_option.initFrom(this);
+ m_option.direction = Qt::LeftToRight;
+
+ deactivate();
+}
+
+ListItem::~ListItem()
+{
+ disconnect();
+}
+
+
+//TODO: REMOVE DUPLICATE CODE WITH PREVIEWIMAGE
+QString ListItem::guessNameFromUrl(QUrl url)
+{
+ QString name = url.toString( QUrl::RemoveScheme | QUrl::RemoveUserInfo | QUrl::StripTrailingSlash );
+
+ // TODO learn Regular Expressions :)
+ // and implement something better here..
+ name.remove('/');
+ name.remove('&');
+ name.remove('.');
+ name.remove('-');
+ name.remove('_');
+ name.remove('?');
+ name.remove('=');
+ name.remove('+');
+
+ return name;
+}
+
+
+void ListItem::activate()
+{
+ m_option.state |= QStyle::State_Selected;
+ repaint();
+}
+
+
+void ListItem::deactivate()
+{
+ m_option.state &= ~QStyle::State_Selected;
+ repaint();
+}
+
+void ListItem::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+
+ if( m_option.state.testFlag(QStyle::State_Selected) || m_option.state.testFlag(QStyle::State_MouseOver))
+ {
+ QPainter painter(this);
+ m_option.rect=QRect(QPoint(),size());
+ style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &m_option, &painter, this);
+ }
+}
+
+void ListItem::enterEvent(QEvent *e)
+{
+ m_option.state |= QStyle::State_MouseOver;
+ repaint();
+ QWidget::enterEvent(e);
+}
+
+void ListItem::leaveEvent(QEvent *e)
+{
+ m_option.state &= ~QStyle::State_MouseOver;
+ repaint();
+ QWidget::enterEvent(e);
+}
+
+void ListItem::mousePressEvent(QMouseEvent *e)
+{
+ emit itemClicked(this);
+ QWidget::mousePressEvent(e);
+}
+
diff --git a/src/urlbar/listitem.h b/src/urlbar/listitem.h
new file mode 100644
index 00000000..6aa3f1e9
--- /dev/null
+++ b/src/urlbar/listitem.h
@@ -0,0 +1,59 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Qt Includes
+#include <QWidget>
+#include <QStyleOptionViewItemV4>
+
+// Forward Declarations
+class UrlSearchItem;
+
+
+class ListItem : public QWidget
+{
+Q_OBJECT
+
+public:
+ ListItem(const UrlSearchItem &item, QWidget *parent = 0);
+ ~ListItem();
+
+ void activate();
+ void deactivate();
+
+signals:
+ void itemClicked(ListItem *item);
+
+protected:
+ virtual void paintEvent(QPaintEvent *event);
+ virtual void enterEvent(QEvent *);
+ virtual void leaveEvent(QEvent *);
+ virtual void mousePressEvent(QMouseEvent *e);
+
+private:
+ QStyleOptionViewItemV4 m_option;
+ QString guessNameFromUrl(QUrl url);
+
+};
diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp
index 718d9f67..54a0a02d 100644
--- a/src/urlbar/urlbar.cpp
+++ b/src/urlbar/urlbar.cpp
@@ -2,10 +2,10 @@
*
* This file is a part of the rekonq project
*
-* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@gmail.com>
* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
-* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
+* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>
*
*
* This program is free software; you can redistribute it and/or
@@ -36,8 +36,7 @@
#include "lineedit.h"
#include "mainwindow.h"
#include "webview.h"
-#include "historymanager.h"
-#include "webtab.h"
+#include "urlresolver.h"
// KDE Includes
#include <KDebug>
@@ -49,43 +48,44 @@
#include <QPaintEvent>
#include <QPalette>
#include <QTimer>
-
+#include <QVBoxLayout>
QColor UrlBar::s_defaultBaseColor;
UrlBar::UrlBar(QWidget *parent)
- : KHistoryComboBox(true, parent)
- , m_lineEdit(new LineEdit)
- , m_progress(0)
+ : KComboBox(true, parent)
+ , m_lineEdit(new LineEdit)
+ , m_progress(0)
+ , m_box(new CompletionWidget(this))
{
- setUrlDropsEnabled(true);
- setAutoDeleteCompletionObject(true);
-
//cosmetic
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
setMinimumWidth(180);
-
- setTrapReturnKey(true);
-
- setupLineEdit();
- // add every item to history
- connect(this, SIGNAL(returnPressed(const QString&)), SLOT(activated(const QString&)));
- connect(completionBox(), SIGNAL(activated(const QString&)), SLOT(activated(const QString&)));
+ // signal handlings
+ setTrapReturnKey(true);
+ setUrlDropsEnabled(true);
+
+ // Make m_lineEdit background transparent
+ QPalette p = m_lineEdit->palette();
+ p.setColor(QPalette::Base, Qt::transparent);
+ m_lineEdit->setPalette(p);
- connect(this, SIGNAL(cleared()), SLOT(cleared()));
+ if (!s_defaultBaseColor.isValid())
+ {
+ s_defaultBaseColor = palette().color(QPalette::Base);
+ }
- // setup completion box
- setCompletionObject( Application::historyManager()->completionObject() );
-
- // set dropdown list background
- QPalette p = view()->palette();
- p.setColor(QPalette::Base, palette().color(QPalette::Base));
- view()->setPalette(p);
+ setLineEdit(m_lineEdit);
+ // clear the URL bar
+ m_lineEdit->clear();
// load urls on activated urlbar signal
- connect(this, SIGNAL(activated(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&)));
+ connect(this, SIGNAL(returnPressed(const QString&)), SLOT(activated(const QString&)));
+
+ installEventFilter(m_box);
+ connect(m_box, SIGNAL(chosenUrl(const QString&)), SLOT(activated(const QString&)));
}
@@ -96,7 +96,7 @@ UrlBar::~UrlBar()
void UrlBar::selectAll() const
{
- lineEdit()->selectAll();
+ m_lineEdit->selectAll();
}
@@ -106,42 +106,12 @@ KUrl UrlBar::url() const
}
-KLineEdit *UrlBar::lineEdit() const
-{
- return m_lineEdit;
-}
-
-
-void UrlBar::setupLineEdit()
-{
- // Make m_lineEdit background transparent
- QPalette p = m_lineEdit->palette();
- p.setColor(QPalette::Base, Qt::transparent);
- m_lineEdit->setPalette(p);
-
- if (!s_defaultBaseColor.isValid())
- {
- s_defaultBaseColor = palette().color(QPalette::Base);
- }
-
- setLineEdit(m_lineEdit);
-
- // Make the lineedit consume the Qt::Key_Enter event...
- lineEdit()->setTrapReturnKey(true);
-
- lineEdit()->setHandleSignals(true);
-
- // clear the URL bar
- lineEdit()->clear();
-}
-
-
void UrlBar::setUrl(const QUrl& url)
{
if(url.scheme() == "about")
{
m_currentUrl = KUrl();
- updateUrl(); // updateUrl before setFocus
+ updateUrl();
setFocus();
}
else
@@ -149,13 +119,14 @@ void UrlBar::setUrl(const QUrl& url)
m_currentUrl = KUrl(url);
updateUrl();
}
+
}
void UrlBar::setProgress(int progress)
{
m_progress = progress;
- repaint();
+ update();
}
@@ -195,29 +166,21 @@ void UrlBar::updateUrl()
// Must be AFTER setCurrentIndex
if (!hasFocus())
{
- lineEdit()->setCursorPosition(0);
+ m_lineEdit->setCursorPosition(0);
}
}
void UrlBar::activated(const QString& urlString)
{
+ disconnect(this, SIGNAL(editTextChanged(const QString &)), this, SLOT(suggestUrls(const QString &)));
+
if (urlString.isEmpty())
return;
- // this fix urlbar behaviour, removing focus from there and enabling
- // loading animation. Temporary fix??
- Application::instance()->mainWindow()->currentTab()->setFocus();
-
- setUrl( KUrl(urlString) );
- emit activated( KUrl(urlString) );
-}
-
-
-void UrlBar::cleared()
-{
- // clear the history on user's request from context menu
- clear();
+ clearFocus();
+ setUrl(urlString);
+ Application::instance()->loadUrl(m_currentUrl);
}
@@ -225,14 +188,14 @@ void UrlBar::loadFinished(bool)
{
// reset progress bar after small delay
m_progress = 0;
- QTimer::singleShot(200, this, SLOT(repaint()));
+ QTimer::singleShot(200, this, SLOT(update()));
}
void UrlBar::updateProgress(int progress)
{
m_progress = progress;
- repaint();
+ update();
}
@@ -243,7 +206,7 @@ void UrlBar::paintEvent(QPaintEvent *event)
p.setColor(QPalette::Base, s_defaultBaseColor);
setPalette(p);
- KHistoryComboBox::paintEvent(event);
+ KComboBox::paintEvent(event);
if (!hasFocus())
{
@@ -261,7 +224,7 @@ void UrlBar::paintEvent(QPaintEvent *event)
painter.setBrush(generateGradient(loadingColor, height()));
painter.setPen(Qt::transparent);
- QRect backgroundRect = lineEdit()->frameGeometry();
+ QRect backgroundRect = m_lineEdit->frameGeometry();
int mid = backgroundRect.width() * m_progress / 100;
QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height());
painter.drawRect(progressRect);
@@ -272,7 +235,7 @@ void UrlBar::paintEvent(QPaintEvent *event)
QSize UrlBar::sizeHint() const
{
- return lineEdit()->sizeHint();
+ return m_lineEdit->sizeHint();
}
@@ -295,7 +258,7 @@ QLinearGradient UrlBar::generateGradient(const QColor &color, int height)
void UrlBar::setBackgroundColor(QColor c)
{
s_defaultBaseColor = c;
- repaint();
+ update();
}
@@ -308,43 +271,70 @@ bool UrlBar::isLoading()
return true;
}
-
void UrlBar::keyPressEvent(QKeyEvent *event)
{
+
+ // this handles the Modifiers + Return key combinations
QString currentText = m_lineEdit->text().trimmed();
- if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
+ if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return)
+ && !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive))
{
- if( !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive) )
+ QString append;
+ if (event->modifiers() == Qt::ControlModifier)
{
- QString append;
- if (event->modifiers() == Qt::ControlModifier)
- {
- append = QLatin1String(".com");
- }
- else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier))
- {
- append = QLatin1String(".org");
- }
- else if (event->modifiers() == Qt::ShiftModifier)
- {
- append = QLatin1String(".net");
- }
-
- QUrl url(QLatin1String("http://www.") + currentText);
- QString host = url.host();
- if (!host.endsWith(append, Qt::CaseInsensitive))
- {
- host += append;
- url.setHost(host);
- m_lineEdit->setText(url.toString());
- }
+ append = QLatin1String(".com");
}
- else
+ else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier))
+ {
+ append = QLatin1String(".org");
+ }
+ else if (event->modifiers() == Qt::ShiftModifier)
+ {
+ append = QLatin1String(".net");
+ }
+
+ QUrl url(QLatin1String("http://www.") + currentText);
+ QString host = url.host();
+ if (!host.endsWith(append, Qt::CaseInsensitive))
{
- // fill lineEdit with its stripped contents to remove trailing spaces
- m_lineEdit->setText(currentText);
+ host += append;
+ url.setHost(host);
+ m_lineEdit->setText(url.toString());
}
}
+
+ KComboBox::keyPressEvent(event);
+}
+
+
+void UrlBar::suggestUrls(const QString &text)
+{
+ if (!hasFocus())
+ {
+ return;
+ }
+
+ if(text.isEmpty())
+ {
+ m_box->hide();
+ return;
+ }
+
+ UrlResolver res(text);
+ UrlSearchList list = res.orderedSearchItems();
+
+ if(list.count() > 0)
+ {
+ m_box->clear();
+ m_box->insertSearchList(list);
+ m_box->popup();
+ }
+}
- KHistoryComboBox::keyPressEvent(event);
+void UrlBar::focusInEvent(QFocusEvent *event)
+{
+ // activate suggestions on edit text
+ connect(this, SIGNAL(editTextChanged(const QString &)), this, SLOT(suggestUrls(const QString &)));
+
+ KComboBox::focusInEvent(event);
}
diff --git a/src/urlbar/urlbar.h b/src/urlbar/urlbar.h
index 39911bb2..ef53d63a 100644
--- a/src/urlbar/urlbar.h
+++ b/src/urlbar/urlbar.h
@@ -2,10 +2,10 @@
*
* This file is a part of the rekonq project
*
-* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>
* Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@gmail.com>
* Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com>
-* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr>
+* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>
*
*
* This program is free software; you can redistribute it and/or
@@ -32,23 +32,23 @@
// Local Includes
-#include "rekonqprivate_export.h"
#include "lineedit.h"
+#include "completionwidget.h"
// KDE Includes
#include <KUrl>
-#include <KHistoryComboBox>
+#include <KComboBox>
// Qt Includes
#include <QUrl>
+#include <QPointer>
// Forward Declarations
class QLinearGradient;
class QWidget;
-class KCompletion;
-class REKONQ_TESTS_EXPORT UrlBar : public KHistoryComboBox
+class UrlBar : public KComboBox
{
Q_OBJECT
@@ -61,31 +61,24 @@ public:
QSize sizeHint() const;
void setBackgroundColor(QColor);
bool isLoading();
-
void setProgress(int progress);
-signals:
- void activated(const KUrl&);
-
public slots:
void setUrl(const QUrl &url);
void updateProgress(int progress);
void updateUrl();
-
+
private slots:
void activated(const QString& url);
void loadFinished(bool);
- void cleared();
+ void suggestUrls(const QString &editedText);
protected:
virtual void paintEvent(QPaintEvent *event);
virtual void keyPressEvent(QKeyEvent *event);
+ virtual void focusInEvent(QFocusEvent *event);
private:
- void setupLineEdit();
-
- KLineEdit *lineEdit() const;
-
static QLinearGradient generateGradient(const QColor &color, int height);
static QColor s_defaultBaseColor;
@@ -94,6 +87,9 @@ private:
KUrl m_currentUrl;
int m_progress;
+
+ CompletionWidget *m_box;
+ KUrl m_suggestedUrl;
};
#endif
diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp
new file mode 100644
index 00000000..b2bf50af
--- /dev/null
+++ b/src/urlbar/urlresolver.cpp
@@ -0,0 +1,177 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "urlresolver.h"
+
+// Local Includes
+#include "application.h"
+#include "historymanager.h"
+#include "bookmarksmanager.h"
+
+// KDE Includes
+#include <KUriFilter>
+#include <KCompletion>
+#include <KDebug>
+#include <KService>
+#include <KConfig>
+#include <KConfigGroup>
+
+// Qt Includes
+#include <QString>
+#include <QByteArray>
+#include <QUrl>
+
+
+// NOTE default kurifilter plugin list (at least in my box)
+// 1. "kshorturifilter"
+// 2. "kurisearchfilter"
+// 3. "localdomainurifilter"
+// 4 ."kuriikwsfilter"
+// 5. "fixhosturifilter"
+
+
+UrlResolver::UrlResolver(const QString &typedUrl)
+ : _urlString(typedUrl)
+{
+}
+
+
+UrlSearchList UrlResolver::orderedSearchItems()
+{
+ // NOTE: the logic here is : "we wanna suggest (at least) 9 elements"
+ // so we have (more or less) 3 from first results (1 from QUrl Resolutions, 2 from
+ // default search engines).
+ // There are 6 remaining: if bookmarkResults + historyResults <= 6, catch all, else
+ // catch first 3 results from the two resulting lists :)
+
+ UrlSearchList list;
+
+ list << qurlFromUserInputResolution();
+ list << webSearchesResolution();
+ int firstResults = list.count();
+ int checkPoint = 9 - firstResults;
+
+ UrlSearchList historyList = historyResolution();
+ int historyResults = historyList.count();
+
+ UrlSearchList bookmarksList = bookmarksResolution();
+ int bookmarkResults = bookmarksList.count();
+
+ if(historyResults + bookmarkResults > checkPoint)
+ {
+ historyList = historyList.mid(0,3);
+ bookmarksList = bookmarksList.mid(0,3);
+ }
+ list << historyList;
+ list << bookmarksList;
+
+ return list;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE ENGINES
+
+
+// STEP 1 = QUrl from User Input (easily the best solution... )
+UrlSearchList UrlResolver::qurlFromUserInputResolution()
+{
+ UrlSearchList list;
+
+ QString url2 = _urlString;
+ QUrl urlFromUserInput = QUrl::fromUserInput(url2);
+ if(urlFromUserInput.isValid())
+ {
+ QByteArray ba = urlFromUserInput.toEncoded();
+ if(!ba.isEmpty())
+ {
+ QString str(ba);
+ UrlSearchItem it(str);
+ list << it;
+ }
+ }
+
+ return list;
+}
+
+
+// STEP 2 = Web Searches
+UrlSearchList UrlResolver::webSearchesResolution()
+{
+ UrlSearchList list;
+
+ QString url1 = _urlString;
+ if(KUrl(url1).isRelative() && !url1.contains('.'))
+ {
+ // KUriFilter has the worst performance possible here and let this trick unusable
+ QString gUrl = QString("http://www.google.com/search?q=%1&ie=UTF-8&oe=UTF-8").arg(url1);
+ QString gTitle = i18n("Search Google for ") + url1;
+ UrlSearchItem gItem(gUrl, gTitle, QString("http://www.google.com") );
+ list << gItem;
+
+ QString wUrl = QString("http://en.wikipedia.org/wiki/Special:Search?search=%1&go=Go").arg(url1);
+ QString wTitle = i18n("Search Wikipedia for ") + url1;
+ UrlSearchItem wItem(wUrl, wTitle, QString("http://wikipedia.org") );
+ list << wItem;
+ }
+
+ return list;
+}
+
+
+// STEP 3 = history completion
+UrlSearchList UrlResolver::historyResolution()
+{
+ UrlSearchList list;
+
+ KCompletion *historyCompletion = Application::historyManager()->completionObject();
+ QStringList historyResults = historyCompletion->substringCompletion(_urlString);
+ Q_FOREACH(const QString &s, historyResults)
+ {
+ UrlSearchItem it(s, s, QString("view-history"));
+ list << it;
+ }
+
+ return list;
+}
+
+
+// STEP 4 = bookmarks completion
+UrlSearchList UrlResolver::bookmarksResolution()
+{
+ UrlSearchList list;
+
+ KCompletion *bookmarkCompletion = Application::bookmarkProvider()->completionObject();
+ QStringList bookmarkResults = bookmarkCompletion->substringCompletion(_urlString);
+ Q_FOREACH(const QString &s, bookmarkResults)
+ {
+ UrlSearchItem it( s, QString(), QString("rating") );
+ list << it;
+ }
+
+ return list;
+}
diff --git a/src/urlbar/urlresolver.h b/src/urlbar/urlresolver.h
new file mode 100644
index 00000000..0a880150
--- /dev/null
+++ b/src/urlbar/urlresolver.h
@@ -0,0 +1,72 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef URL_RESOLVER_H
+#define URL_RESOLVER_H
+
+
+// Qt Includes
+#include <QString>
+#include <QList>
+
+// Forward Declarations
+class KUrl;
+
+class UrlSearchItem
+{
+public:
+ QString url;
+ QString title;
+ QString icon;
+
+ UrlSearchItem(const QString &_url, const QString &_title = QString(), const QString &_icon = QString())
+ : url(_url), title(_title), icon(_icon)
+ {};
+};
+
+typedef QList <UrlSearchItem> UrlSearchList;
+
+
+// ----------------------------------------------------------------------
+
+
+class UrlResolver
+{
+public:
+ UrlResolver(const QString &typedUrl);
+
+ UrlSearchList orderedSearchItems();
+
+private:
+ QString _urlString;
+
+ UrlSearchList webSearchesResolution();
+ UrlSearchList historyResolution();
+ UrlSearchList qurlFromUserInputResolution();
+ UrlSearchList bookmarksResolution();
+};
+
+#endif // URL_RESOLVER_H
diff --git a/src/urltreeview.cpp b/src/urltreeview.cpp
new file mode 100644
index 00000000..507a7973
--- /dev/null
+++ b/src/urltreeview.cpp
@@ -0,0 +1,195 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010 by Yoann Laissus <yoann dot laissus at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+// Self Includes
+#include "urltreeview.h"
+
+// Local Includes
+#include "application.h"
+
+// Qt Includes
+#include <QMouseEvent>
+#include <QClipboard>
+
+
+UrlTreeView::UrlTreeView(QWidget *parent)
+ : QTreeView(parent)
+{
+ connect(this, SIGNAL(itemHovered(const QString &)), parent, SIGNAL(itemHovered(const QString &)));
+ connect(this, SIGNAL(openUrl(const KUrl &, Rekonq::OpenType)), parent, SIGNAL(openUrl(const KUrl &, Rekonq::OpenType)));
+ setMouseTracking(true);
+ setExpandsOnDoubleClick(false);
+}
+
+
+UrlTreeView::~UrlTreeView()
+{
+}
+
+
+void UrlTreeView::mousePressEvent(QMouseEvent *event)
+{
+ const QModelIndex index = indexAt(event->pos());
+ bool expanded = isExpanded(index);
+
+ QTreeView::mousePressEvent(event);
+
+ // A change of an item expansion is handle by mouseReleaseEvent()
+ // So toggle again the item
+ if(expanded != isExpanded(index))
+ setExpanded(index, !isExpanded(index));
+
+ if(!index.isValid())
+ {
+ clearSelection();
+ setCurrentIndex(QModelIndex());
+
+ if(event->button() == Qt::RightButton)
+ emit contextMenuEmptyRequested(event->pos());
+ return;
+ }
+
+ if(event->button() == Qt::RightButton)
+ {
+ if(model()->rowCount(index) == 0)
+ {
+ // An empty group needs to be handle by the panels
+ emit contextMenuItemRequested(event->pos());
+ }
+ else
+ {
+ emit contextMenuGroupRequested(event->pos());
+ }
+ }
+}
+
+
+void UrlTreeView::mouseReleaseEvent(QMouseEvent *event)
+{
+ QTreeView::mouseReleaseEvent(event);
+
+ const QModelIndex index = indexAt(event->pos());
+ if(!index.isValid())
+ return;
+
+ if(event->button() == Qt::MidButton)
+ validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole)), Rekonq::NewCurrentTab);
+
+ else if(event->button() == Qt::LeftButton)
+ {
+ if(model()->rowCount(index) == 0)
+ validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole)));
+ else
+ setExpanded(index, !isExpanded(index));
+ }
+}
+
+
+void UrlTreeView::keyPressEvent(QKeyEvent *event)
+{
+ QTreeView::keyPressEvent(event);
+ QModelIndex index = currentIndex();
+
+ if(!index.isValid())
+ return;
+
+ if(event->key() == Qt::Key_Return)
+ {
+ if(model()->rowCount(index) == 0)
+ validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole)));
+ else
+ setExpanded(index, !isExpanded(index));
+ }
+
+ else if(event->key() == Qt::Key_Delete)
+ {
+ emit delKeyPressed();
+ }
+}
+
+
+void UrlTreeView::validOpenUrl(const KUrl &url, Rekonq::OpenType openType)
+{
+ // To workaround a crash when the url is about:blank
+ if(url.url() == "about:blank")
+ emit openUrl(KUrl("about:home"), openType);
+ else
+ emit openUrl(url, openType);
+}
+
+
+void UrlTreeView::mouseMoveEvent(QMouseEvent *event)
+{
+ QTreeView::mouseMoveEvent(event);
+ const QModelIndex index = indexAt(event->pos());
+ if(!index.isValid())
+ {
+ emit itemHovered("");
+ return;
+ }
+ emit itemHovered(qVariantValue< KUrl >(index.data(Qt::UserRole)).url());
+}
+
+
+void UrlTreeView::openInCurrentTab()
+{
+ QModelIndex index = currentIndex();
+ if(!index.isValid())
+ return;
+
+ validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole)));
+}
+
+
+void UrlTreeView::copyToClipboard()
+{
+ QModelIndex index = currentIndex();
+ if(!index.isValid())
+ return;
+
+ QClipboard *cb = QApplication::clipboard();
+ cb->setText(qVariantValue< KUrl >(index.data(Qt::UserRole)).url());
+}
+
+
+void UrlTreeView::openInNewTab()
+{
+ QModelIndex index = currentIndex();
+ if(!index.isValid())
+ return;
+
+ validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole)), Rekonq::SettingOpenTab);
+}
+
+
+void UrlTreeView::openInNewWindow()
+{
+ QModelIndex index = currentIndex();
+ if(!index.isValid())
+ return;
+
+ validOpenUrl( qVariantValue< KUrl >(index.data(Qt::UserRole)), Rekonq::NewWindow);
+}
diff --git a/src/urltreeview.h b/src/urltreeview.h
new file mode 100644
index 00000000..cce7a257
--- /dev/null
+++ b/src/urltreeview.h
@@ -0,0 +1,69 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010 by Yoann Laissus <yoann dot laissus at gmail dot com>
+*
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License as
+* published by the Free Software Foundation; either version 2 of
+* the License or (at your option) version 3 or any later version
+* accepted by the membership of KDE e.V. (or its successor approved
+* by the membership of KDE e.V.), which shall act as a proxy
+* defined in Section 14 of version 3 of the license.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program. If not, see <http://www.gnu.org/licenses/>.
+*
+* ============================================================ */
+
+
+#ifndef URLTREEVIEW_H
+#define URLTREEVIEW_H
+
+// Local Includes
+#include "application.h"
+
+// Qt Includes
+#include <QTreeView>
+
+
+class UrlTreeView : public QTreeView
+{
+ Q_OBJECT
+
+public:
+ UrlTreeView(QWidget *parent = 0);
+ ~UrlTreeView();
+
+signals:
+ void openUrl(const KUrl &, const Rekonq::OpenType &);
+ void itemHovered(const QString &);
+ void delKeyPressed();
+ void contextMenuItemRequested(const QPoint &pos);
+ void contextMenuGroupRequested(const QPoint &pos);
+ void contextMenuEmptyRequested(const QPoint &pos);
+
+public slots:
+ void copyToClipboard();
+ void openInCurrentTab();
+ void openInNewTab();
+ void openInNewWindow();
+
+protected:
+ void mouseReleaseEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+
+private:
+ void validOpenUrl(const KUrl &url, Rekonq::OpenType openType = Rekonq::CurrentTab);
+};
+
+#endif // URLTREEVIEW_H