summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrea Diamantini <adjam7@gmail.com>2012-08-01 17:46:50 +0200
committerAndrea Diamantini <adjam7@gmail.com>2012-12-10 02:48:04 +0100
commitd2fdce46263a6cee66c4adee9ea7366d085a1729 (patch)
treec50747e1d05bc43dddd1fef2b651a6f1a37cd81a
parentRemove a lot of application calls by refactoring code (diff)
downloadrekonq-d2fdce46263a6cee66c4adee9ea7366d085a1729.tar.xz
Urlbar, first code ported to the new API
-rw-r--r--src/CMakeLists.txt10
-rw-r--r--src/urlbar/bookmarkwidget.cpp363
-rw-r--r--src/urlbar/bookmarkwidget.h101
-rw-r--r--src/urlbar/completionwidget.cpp402
-rw-r--r--src/urlbar/completionwidget.h93
-rw-r--r--src/urlbar/favoritewidget.cpp115
-rw-r--r--src/urlbar/favoritewidget.h58
-rw-r--r--src/urlbar/listitem.cpp664
-rw-r--r--src/urlbar/listitem.h291
-rw-r--r--src/urlbar/rsswidget.cpp165
-rw-r--r--src/urlbar/rsswidget.h61
-rw-r--r--src/urlbar/sslwidget.cpp251
-rw-r--r--src/urlbar/sslwidget.h58
-rw-r--r--src/urlbar/urlbar.cpp776
-rw-r--r--src/urlbar/urlbar.h156
-rw-r--r--src/urlbar/urlsuggester.cpp397
-rw-r--r--src/urlbar/urlsuggester.h155
-rw-r--r--src/urlbar/webshortcutwidget.cpp163
-rw-r--r--src/urlbar/webshortcutwidget.h76
-rw-r--r--src/webtab/webtab.cpp18
-rw-r--r--src/webtab/webtab.h3
21 files changed, 4376 insertions, 0 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 35bbe67e..0a2fa6ef 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -67,6 +67,16 @@ set(rekonq_KDEINIT_SRCS
tabwindow/tabpreviewpopup.cpp
tabwindow/tabwindow.cpp
#----------------------------------------
+ urlbar/urlbar.cpp
+ urlbar/completionwidget.cpp
+ urlbar/listitem.cpp
+ urlbar/rsswidget.cpp
+ urlbar/sslwidget.cpp
+ urlbar/bookmarkwidget.cpp
+ urlbar/webshortcutwidget.cpp
+ urlbar/favoritewidget.cpp
+ urlbar/urlsuggester.cpp
+ #----------------------------------------
useragent/useragentinfo.cpp
useragent/useragentmanager.cpp
useragent/useragentwidget.cpp
diff --git a/src/urlbar/bookmarkwidget.cpp b/src/urlbar/bookmarkwidget.cpp
new file mode 100644
index 00000000..1a69c052
--- /dev/null
+++ b/src/urlbar/bookmarkwidget.cpp
@@ -0,0 +1,363 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2011 by Yoann Laissus <yoann dot laissus at gmail dot com>
+* Copyright (C) 2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (c) 2011-2012 by Phaneendra Hegde <pnh.pes@gmail.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/>.
+*
+* ============================================================ */
+
+
+// Auto Includes
+#include "bookmarkwidget.h"
+#include "bookmarkwidget.moc"
+
+// Local includes
+#include "bookmarkmanager.h"
+#include "bookmarkowner.h"
+
+// KDE Includes
+#include <KComboBox>
+#include <KLocalizedString>
+#include <KIcon>
+#include <KLineEdit>
+#include <KRatingWidget>
+
+// Qt Includes
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QPushButton>
+#include <QCompleter>
+#include <QTextCursor>
+#include <QDBusConnection>
+#include <QDBusConnectionInterface>
+
+// Nepomuk config include
+#include "config-nepomuk.h"
+
+#ifdef HAVE_NEPOMUK
+// Local Nepomuk Includes
+#include "resourcelinkdialog.h"
+
+//Nepomuk Includes
+#include <Soprano/Vocabulary/NAO>
+#endif
+
+
+
+BookmarkWidget::BookmarkWidget(const KBookmark &bookmark, QWidget *parent)
+ : QMenu(parent)
+ , m_bookmark(new KBookmark(bookmark))
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ setFixedWidth(320);
+
+#ifdef HAVE_NEPOMUK
+ m_nfoResource = (QUrl)m_bookmark->url();
+ m_isNepomukEnabled = QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.NepomukServer");
+ kDebug() << "IS NEPOMUK ACTUALLY RUNNING? " << m_isNepomukEnabled;
+#endif
+
+ QFormLayout *layout = new QFormLayout(this);
+ layout->setHorizontalSpacing(20);
+
+ // Title
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ QLabel *bookmarkInfo = new QLabel(this);
+ bookmarkInfo->setText(i18n(" Bookmark"));
+ QFont f = bookmarkInfo->font();
+ f.setBold(true);
+ bookmarkInfo->setFont(f);
+
+ // Remove button
+ QLabel *removeLabel = new QLabel(this);
+ removeLabel->setText(i18n("<a href='Remove'>Remove</a>"));
+ removeLabel->setAlignment(Qt::AlignRight);
+ hLayout->addWidget(bookmarkInfo);
+ hLayout->addWidget(removeLabel);
+ layout->addRow(hLayout);
+
+ connect(removeLabel, SIGNAL(linkActivated(QString)), this, SLOT(removeBookmark()));
+
+ //Bookmark Folder
+ QLabel *folderLabel = new QLabel(this);
+ folderLabel->setText(i18n("Folder:"));
+
+ m_folder = new KComboBox(this);
+ layout->addRow(folderLabel, m_folder);
+ setupFolderComboBox();
+
+ // Bookmark name
+ QLabel *nameLabel = new QLabel(this);
+ nameLabel->setText(i18n("Name:"));
+ m_name = new KLineEdit(this);
+ if (m_bookmark->isNull())
+ {
+ m_name->setEnabled(false);
+ }
+ else
+ {
+ m_name->setText(m_bookmark->text());
+ m_name->setFocus();
+ }
+ layout->addRow(nameLabel, m_name);
+
+#ifdef HAVE_NEPOMUK
+
+ if (m_isNepomukEnabled)
+ {
+ QLabel* rateLabel = new QLabel(this);
+ rateLabel->setText(i18n("Rate:"));
+ KRatingWidget *ratingWidget = new KRatingWidget(this);
+ if (m_nfoResource.rating() != 0)
+ {
+ ratingWidget->setRating(m_nfoResource.rating());
+ }
+ connect(ratingWidget, SIGNAL(ratingChanged(int)), this, SLOT(setRatingSlot(int)));
+ ratingWidget->setToolTip(i18n("Rate this page"));
+ layout->addRow(rateLabel, ratingWidget);
+
+ //Add comments
+ QLabel *commentLabel = new QLabel(this);
+ commentLabel->setText(i18n("Describe:"));
+ commentLabel->setAlignment(Qt::AlignCenter);
+ m_commentEdit = new QPlainTextEdit(this);
+ if (!m_nfoResource.description().isEmpty())
+ {
+ m_commentEdit->setPlainText(m_nfoResource.description());
+ }
+ connect(m_commentEdit, SIGNAL(textChanged()), this, SLOT(addCommentSlot()));
+ layout->addRow(commentLabel, m_commentEdit);
+
+ // Create tags
+ QLabel *tagLabel = new QLabel(this);
+ tagLabel->setText(i18n("Tags:"));
+ tagLabel->setAlignment(Qt::AlignLeft);
+ m_tagLine = new KLineEdit(this);
+ m_tagLine->setPlaceholderText(i18n("add tags(comma separated)"));
+
+
+ QList<Nepomuk::Tag> tagList = Nepomuk::Tag::allTags();
+ Q_FOREACH(Nepomuk::Tag t, tagList)
+ {
+ m_tList.append(t.label());
+ }
+ QCompleter *completeTag = new QCompleter(m_tList);
+ completeTag->setCompletionMode(QCompleter::PopupCompletion);
+ m_tagLine->setCompleter(completeTag);
+ loadTags();
+
+ layout->addRow(tagLabel, m_tagLine);
+
+ QPushButton *linkToResource = new QPushButton(this);
+ linkToResource->setText(i18n("Link Resources"));
+ connect(linkToResource, SIGNAL(clicked()), this, SLOT(linkToResourceSlot()));
+ layout->addWidget(linkToResource);
+ }
+ else
+ {
+ QLabel *nepomukLabel = new QLabel(this);
+ QPalette p = nepomukLabel->palette();
+ p.setColor(QPalette::WindowText, Qt::red);
+ nepomukLabel->setPalette(p);
+ nepomukLabel->setText(i18n("Nepomuk is actually disabled."));
+ layout->addWidget(nepomukLabel);
+ }
+#endif
+
+ // Ok & Cancel buttons
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
+ layout->addWidget(buttonBox);
+}
+
+
+BookmarkWidget::~BookmarkWidget()
+{
+ delete m_bookmark;
+}
+
+
+void BookmarkWidget::showAt(const QPoint &pos)
+{
+ adjustSize();
+
+ QPoint p(pos.x() - width(), pos.y() + 10);
+ move(p);
+ show();
+}
+
+
+void BookmarkWidget::accept()
+{
+ if (!m_bookmark->isNull() && m_name->text() != m_bookmark->fullText())
+ {
+ m_bookmark->setFullText(m_name->text());
+ BookmarkManager::self()->emitChanged();
+ }
+ QString folderAddress = m_folder->itemData(m_folder->currentIndex()).toString();
+ KBookmarkGroup a = BookmarkManager::self()->manager()->findByAddress(folderAddress).toGroup();
+
+ KBookmarkGroup parent = m_bookmark->parentGroup();
+ parent.deleteBookmark(*m_bookmark);
+ a.addBookmark(*m_bookmark);
+ BookmarkManager::self()->manager()->emitChanged(a);
+
+#ifdef HAVE_NEPOMUK
+ if (m_isNepomukEnabled)
+ {
+ parseTags();
+ }
+#endif
+
+ close();
+}
+
+
+void BookmarkWidget::setupFolderComboBox()
+{
+ KBookmarkGroup root = BookmarkManager::self()->manager()->toolbar();
+
+ if (BookmarkManager::self()->manager()->toolbar().address() == BookmarkManager::self()->manager()->root().address())
+ {
+ m_folder->addItem(i18n("Bookmark Toolbar"),
+ BookmarkManager::self()->manager()->toolbar().address());
+ }
+ else
+ {
+ m_folder->addItem(BookmarkManager::self()->manager()->toolbar().text(),
+ BookmarkManager::self()->manager()->toolbar().address());
+ }
+ m_folder->insertSeparator(1);
+
+ if (m_bookmark->parentGroup().address() != BookmarkManager::self()->manager()->toolbar().address())
+ {
+ m_folder->addItem(m_bookmark->parentGroup().text(),
+ m_bookmark->parentGroup().address());
+ m_folder->insertSeparator(3);
+ }
+
+ for (KBookmark bookmark = root.first(); !bookmark.isNull(); bookmark = root.next(bookmark))
+ {
+ if (bookmark.isGroup())
+ {
+ m_folder->addItem(bookmark.text(), bookmark.address());
+ }
+ }
+
+ if (m_bookmark->parentGroup().address() == root.address())
+ {
+ m_folder->setCurrentIndex(0);
+ }
+ else
+ {
+ int index = m_folder->findText(m_bookmark->parentGroup().text());
+ m_folder->setCurrentIndex(index);
+ }
+}
+
+
+void BookmarkWidget::removeBookmark()
+{
+ BookmarkManager::self()->owner()->deleteBookmark(*m_bookmark);
+ close();
+
+ emit updateIcon();
+}
+
+
+#ifdef HAVE_NEPOMUK
+void BookmarkWidget::addTags(QList<Nepomuk::Tag> tagList)
+{
+ Q_FOREACH(const Nepomuk::Tag & tag, tagList)
+ {
+ if (!m_nfoResource.tags().contains(tag))
+ {
+ m_nfoResource.addTag(tag);
+ }
+ }
+ Q_FOREACH(Nepomuk::Tag tag, m_nfoResource.tags())
+ {
+ if (!tagList.contains(tag))
+ {
+ tag.remove();
+ }
+ }
+}
+
+void BookmarkWidget::parseTags()
+{
+ QList<Nepomuk::Tag> tagList;
+ if (m_tagLine->text().contains(','))
+ {
+ QString text = m_tagLine->text();
+ QStringList tagStringList = text.split(QChar::fromAscii(','));
+
+ Q_FOREACH(const QString & tag, tagStringList)
+ {
+ QString trimmedTag = tag.trimmed();
+ if (!trimmedTag.isEmpty())
+ tagList << trimmedTag;
+ }
+ }
+ else
+ {
+ tagList << m_tagLine->text().trimmed();
+ }
+ addTags(tagList);
+}
+
+
+void BookmarkWidget::loadTags()
+{
+ QString list;
+ if (!m_nfoResource.tags().isEmpty())
+ {
+ Q_FOREACH(const Nepomuk::Tag & tag, m_nfoResource.tags())
+ {
+ list.append(tag.genericLabel());
+ list.append(",");
+ }
+ m_tagLine->setText(list);
+ }
+}
+
+
+void BookmarkWidget::setRatingSlot(int rate)
+{
+ m_nfoResource.setRating(rate);
+}
+
+
+void BookmarkWidget::addCommentSlot()
+{
+ m_nfoResource.setDescription(m_commentEdit->toPlainText());
+}
+
+
+void BookmarkWidget::linkToResourceSlot()
+{
+ Nepomuk::ResourceLinkDialog r(m_nfoResource);
+ r.exec();
+}
+#endif
diff --git a/src/urlbar/bookmarkwidget.h b/src/urlbar/bookmarkwidget.h
new file mode 100644
index 00000000..e5f25d37
--- /dev/null
+++ b/src/urlbar/bookmarkwidget.h
@@ -0,0 +1,101 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2011 by Yoann Laissus <yoann dot laissus at gmail dot com>
+* Copyright (C) 2012 by Andrea Diamantini <adjam7 at gmail dot com>
+* Copyright (c) 2011-2012 by Phaneendra Hegde <pnh.pes@gmail.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 BOOKMARKWIDGET_H
+#define BOOKMARKWIDGET_H
+
+// Qt Includes
+#include <QMenu>
+#include <QGridLayout>
+#include <QPlainTextEdit>
+
+// Nepomuk config include
+#include "config-nepomuk.h"
+
+#ifdef HAVE_NEPOMUK
+
+// Nepomuk Includes
+#include <Nepomuk/Resource>
+#include <Nepomuk/Tag>
+#include <Nepomuk/Vocabulary/NFO>
+
+#endif
+
+// Forward Declarations
+class KBookmark;
+class KLineEdit;
+class KComboBox;
+
+
+class BookmarkWidget : public QMenu
+{
+ Q_OBJECT
+
+public:
+ explicit BookmarkWidget(const KBookmark &bookmark, QWidget *parent = 0);
+ virtual ~BookmarkWidget();
+
+ void showAt(const QPoint &pos);
+
+#ifdef HAVE_NEPOMUK
+ void addTags(QList<Nepomuk::Tag>);
+ void parseTags();
+ void loadTags();
+#endif
+
+Q_SIGNALS:
+ void updateIcon();
+
+private:
+ void setupFolderComboBox();
+
+private Q_SLOTS:
+ void accept();
+ void removeBookmark();
+
+#ifdef HAVE_NEPOMUK
+ void setRatingSlot(int rate);
+ void addCommentSlot();
+ void linkToResourceSlot();
+#endif
+
+private:
+ KBookmark *m_bookmark;
+ KLineEdit *m_name;
+ KComboBox *m_folder;
+ KLineEdit *m_tagLine;
+ QPlainTextEdit *m_commentEdit;
+ QStringList m_tList;
+
+#ifdef HAVE_NEPOMUK
+ Nepomuk::Resource m_nfoResource;
+ bool m_isNepomukEnabled;
+#endif
+};
+
+#endif
diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp
new file mode 100644
index 00000000..5ef65fd9
--- /dev/null
+++ b/src/urlbar/completionwidget.cpp
@@ -0,0 +1,402 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 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"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "searchengine.h"
+
+#include "listitem.h"
+#include "urlbar.h"
+
+// KDE Includes
+#include <KGlobalSettings>
+#include <KUrl>
+
+// Qt Includes
+#include <QApplication>
+#include <QPoint>
+#include <QSize>
+#include <QEvent>
+
+#include <QVBoxLayout>
+#include <QKeyEvent>
+
+
+
+CompletionWidget::CompletionWidget(QWidget *parent)
+ : QFrame(parent, Qt::ToolTip)
+ , _parent(parent)
+ , _currentIndex(0)
+ , _hasSuggestions(false)
+{
+ setFrameStyle(QFrame::Panel);
+ setLayoutDirection(Qt::LeftToRight);
+ QVBoxLayout *layout = new QVBoxLayout;
+ layout->setMargin(0);
+ layout->setSpacing(0);
+ setLayout(layout);
+}
+
+
+void CompletionWidget::insertItems(const UrlSuggestionList &list, const QString& text, int offset)
+{
+ Q_FOREACH(const UrlSuggestionItem & item, list)
+ {
+ ListItem *suggestion = ListItemFactory::create(item, text, this);
+ suggestion->setBackgroundRole(offset % 2 ? QPalette::AlternateBase : QPalette::Base);
+ connect(suggestion,
+ SIGNAL(itemClicked(ListItem*, Qt::MouseButton, Qt::KeyboardModifiers)),
+ this,
+ SLOT(itemChosen(ListItem*, Qt::MouseButton, Qt::KeyboardModifiers)));
+ connect(suggestion, SIGNAL(updateList()), this, SLOT(updateList()));
+ connect(this, SIGNAL(nextItemSubChoice()), suggestion, SLOT(nextItemSubChoice()));
+
+ suggestion->setObjectName(QString::number(offset++));
+ layout()->addWidget(suggestion);
+ }
+}
+
+
+void CompletionWidget::updateSuggestionList(const UrlSuggestionList &list, const QString& text)
+{
+ if (_hasSuggestions || _typedString != text)
+ return;
+ _hasSuggestions = true;
+
+ if (_resList.count() > 0)
+ {
+ clear();
+
+ insertItems(_resList, text);
+ _list = _resList;
+
+ UrlSuggestionList sugList = list.mid(0, 4);
+ insertItems(sugList, text, _list.count());
+ _list.append(sugList);
+ popup();
+ }
+}
+
+
+void CompletionWidget::sizeAndPosition()
+{
+ setFixedWidth(_parent->width());
+
+ int h = 0;
+ for (int i = 0; i < layout()->count(); i++)
+ {
+ QWidget *widget = layout()->itemAt(i)->widget();
+ h += widget->sizeHint().height();
+ }
+ setFixedSize(_parent->width(), h + 5);
+
+ // position
+ QPoint p = _parent->mapToGlobal(QPoint(0, 0));
+ move(p.x(), p.y() + _parent->height());
+}
+
+
+void CompletionWidget::popup()
+{
+ findChild<ListItem *>(QString::number(0))->activate(); //activate first listitem
+ sizeAndPosition();
+ if (!isVisible())
+ show();
+}
+
+
+void CompletionWidget::up()
+{
+ if (_currentIndex >= 0)
+ findChild<ListItem *>(QString::number(_currentIndex))->deactivate(); // deactivate previous
+
+ --_currentIndex;
+ if (_currentIndex < -1)
+ {
+ _currentIndex = _list.count() - 1;
+ }
+
+ activateCurrentListItem();
+}
+
+
+void CompletionWidget::down()
+{
+ if (_currentIndex >= 0)
+ findChild<ListItem *>(QString::number(_currentIndex))->deactivate(); // deactivate previous
+
+ ++_currentIndex;
+ if (_currentIndex == _list.count())
+ _currentIndex = -1;
+
+ activateCurrentListItem();
+}
+
+
+void CompletionWidget::activateCurrentListItem()
+{
+ UrlBar *bar = qobject_cast<UrlBar *>(_parent);
+
+ // activate "new" current
+ ListItem *widget = findChild<ListItem *>(QString::number(_currentIndex));
+
+ // update text of the url bar
+ bar->blockSignals(true); // without compute suggestions
+ if (widget)
+ {
+ widget->activate();
+ bar->setQUrl(widget->text());
+ }
+ else
+ {
+ bar->setText(_typedString);
+ }
+ bar->blockSignals(false);
+ bar->setFocus();
+ bar->setCursorPosition(bar->text().length());
+}
+
+
+void CompletionWidget::clear()
+{
+ QLayoutItem *child;
+ while ((child = layout()->takeAt(0)) != 0)
+ {
+ delete child->widget();
+ delete child;
+ }
+ _currentIndex = 0;
+ _hasSuggestions = false;
+}
+
+
+bool CompletionWidget::eventFilter(QObject *obj, QEvent *ev)
+{
+ int type = ev->type();
+ QWidget *wid = qobject_cast<QWidget*>(obj);
+
+ if (obj == 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())
+ {
+ ListItem *child;
+ UrlBar *w;
+
+ if (type == QEvent::KeyPress)
+ {
+ QKeyEvent *kev = static_cast<QKeyEvent *>(ev);
+ switch (kev->key())
+ {
+ case Qt::Key_Up:
+ case Qt::Key_Backtab:
+ if (kev->modifiers() == Qt::NoButton || (kev->modifiers() & Qt::ShiftModifier))
+ {
+ up();
+ kev->accept();
+ return true;
+ }
+ break;
+
+ case Qt::Key_Down:
+ case Qt::Key_Tab:
+ if (kev->modifiers() == Qt::NoButton)
+ {
+ down();
+ kev->accept();
+ return true;
+ }
+ if (kev->modifiers() & Qt::ControlModifier)
+ {
+ emit nextItemSubChoice();
+ kev->accept();
+ return true;
+ }
+ break;
+
+ case Qt::Key_Enter:
+ case Qt::Key_Return:
+ w = qobject_cast<UrlBar *>(parent());
+ if (kev->modifiers() == Qt::AltModifier)
+ {
+ if (kev->key() == Qt::Key_Return || kev->key() == Qt::Key_Enter)
+ {
+ emit chosenUrl(w->text(), Rekonq::NewFocusedTab);
+ }
+ }
+
+ if (!w->text().startsWith(QL1S("http://"), Qt::CaseInsensitive))
+ {
+ QString append;
+ if (kev->modifiers() == Qt::ControlModifier)
+ {
+ append = QL1S(".com");
+ }
+ else if (kev->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier))
+ {
+ append = QL1S(".org");
+ }
+ else if (kev->modifiers() == Qt::ShiftModifier)
+ {
+ append = QL1S(".net");
+ }
+
+ if (!append.isEmpty())
+ {
+ QUrl url(QL1S("http://") + w->text());
+ QString host = url.host();
+ if (!host.endsWith(append, Qt::CaseInsensitive))
+ {
+ host += append;
+ url.setHost(host);
+ }
+
+ emit chosenUrl(url, Rekonq::CurrentTab);
+ }
+ }
+
+ kDebug() << "Suggestion INDEX chosen: " << _currentIndex;
+ if (_currentIndex == -1)
+ _currentIndex = 0;
+ child = findChild<ListItem *>(QString::number(_currentIndex));
+
+ if (child) //the completionwidget is visible and the user had press down
+ {
+ //we can use the url of the listitem
+ emit chosenUrl(child->url(), Rekonq::CurrentTab);
+ }
+ else //the user type too fast (completionwidget not visible or suggestion not downloaded)
+ {
+ UrlSuggester res(w->text());
+ UrlSuggestionList list = res.orderedSearchItems();
+ if (list.isEmpty())
+ {
+ emit chosenUrl(KUrl(_typedString), Rekonq::CurrentTab);
+ }
+ else
+ {
+ emit chosenUrl(list.first().url, Rekonq::CurrentTab);
+ }
+ }
+ kev->accept();
+ hide();
+ return true;
+
+ case Qt::Key_Escape:
+ hide();
+ return true;
+ }
+ }
+ }
+
+ return QFrame::eventFilter(obj, ev);
+}
+
+
+void CompletionWidget::setVisible(bool visible)
+{
+ if (visible)
+ {
+ qApp->installEventFilter(this);
+ }
+ else
+ {
+ qApp->removeEventFilter(this);
+ }
+
+ QFrame::setVisible(visible);
+}
+
+
+void CompletionWidget::itemChosen(ListItem *item, Qt::MouseButton button, Qt::KeyboardModifiers modifier)
+{
+ if (button == Qt::MidButton
+ || modifier == Qt::ControlModifier)
+ {
+ emit chosenUrl(item->url(), Rekonq::NewFocusedTab);
+ }
+ else
+ {
+ emit chosenUrl(item->url(), Rekonq::CurrentTab);
+ }
+ hide();
+}
+
+
+void CompletionWidget::updateList()
+{
+ suggestUrls(_typedString);
+}
+
+
+void CompletionWidget::suggestUrls(const QString &text)
+{
+ _typedString = text;
+
+ QWidget *w = qobject_cast<QWidget *>(parent());
+ if (!w->hasFocus())
+ return;
+
+ if (text.isEmpty())
+ {
+ hide();
+ return;
+ }
+
+ if (!isVisible())
+ {
+// FIXME UrlResolver::setSearchEngine(SearchEngine::defaultEngine());
+ }
+
+ UrlSuggester *res = new UrlSuggester(text);
+ connect(res, SIGNAL(suggestionsReady(UrlSuggestionList, QString)),
+ this, SLOT(updateSuggestionList(UrlSuggestionList, QString)));
+ _resList = res->orderedSearchItems();
+
+ // NOTE: It's important to call this AFTER orderedSearchItems() to let everything work
+ res->computeSuggestions();
+}
diff --git a/src/urlbar/completionwidget.h b/src/urlbar/completionwidget.h
new file mode 100644
index 00000000..098aa9f9
--- /dev/null
+++ b/src/urlbar/completionwidget.h
@@ -0,0 +1,93 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 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
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// Local Includes
+#include "urlsuggester.h"
+
+// KDE Includes
+#include <KService>
+
+// Qt Includes
+#include <QFrame>
+
+// Forward Declarations
+class ListItem;
+
+
+class CompletionWidget : public QFrame
+{
+ Q_OBJECT
+
+public:
+ CompletionWidget(QWidget *parent);
+
+ virtual bool eventFilter(QObject *obj, QEvent *ev);
+ void setVisible(bool visible);
+
+ void suggestUrls(const QString &text);
+
+private Q_SLOTS:
+ void itemChosen(ListItem *item, Qt::MouseButton = Qt::LeftButton, Qt::KeyboardModifiers = Qt::NoModifier);
+ void updateSuggestionList(const UrlSuggestionList &list, const QString& text);
+ void updateList();
+
+Q_SIGNALS:
+ void chosenUrl(const KUrl &, Rekonq::OpenType);
+ void nextItemSubChoice();
+
+private:
+ void insertItems(const UrlSuggestionList &list, const QString& text, int offset = 0);
+
+ void popup();
+ void clear();
+
+ void sizeAndPosition();
+ void up();
+ void down();
+ void activateCurrentListItem();
+
+ QWidget *_parent;
+
+ UrlSuggestionList _list;
+
+ int _currentIndex;
+
+ KService::Ptr _searchEngine;
+
+ QString _typedString;
+ bool _hasSuggestions;
+
+ UrlSuggestionList _resList;
+};
+
+#endif // COMPLETION_WIDGET_H
diff --git a/src/urlbar/favoritewidget.cpp b/src/urlbar/favoritewidget.cpp
new file mode 100644
index 00000000..6a4ffaba
--- /dev/null
+++ b/src/urlbar/favoritewidget.cpp
@@ -0,0 +1,115 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2011 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 "favoritewidget.h"
+#include "favoritewidget.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local includes
+#include "application.h"
+#include "bookmarkmanager.h"
+#include "bookmarkowner.h"
+#include "webtab.h"
+
+// KDE Includes
+#include <KLocalizedString>
+#include <KIcon>
+#include <KLineEdit>
+
+// Qt Includes
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QPushButton>
+
+
+FavoriteWidget::FavoriteWidget(WebTab *tab, QWidget *parent)
+ : QMenu(parent)
+ , m_tab(tab)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ setFixedWidth(350);
+
+ QFormLayout *layout = new QFormLayout(this);
+ QVBoxLayout *vLay = new QVBoxLayout;
+
+ // Favorite icon
+ QLabel *bookmarkIcon = new QLabel(this);
+ bookmarkIcon->setPixmap(KIcon("emblem-favorite").pixmap(32, 32));
+
+ // Title
+ QLabel *favoriteInfo = new QLabel(this);
+ favoriteInfo->setText(i18n("<h4>Remove this favorite?</h4>"));
+ vLay->addWidget(favoriteInfo);
+
+ // Favorite name
+ QLabel *nameLabel = new QLabel(this);
+ nameLabel->setText(i18n("Name: %1", m_tab->view()->title()));
+ vLay->addWidget(nameLabel);
+
+ // Favorite url
+ QLabel *urlLabel = new QLabel(this);
+ urlLabel->setText(i18n("URL: %1", m_tab->url().url()));
+ vLay->addWidget(urlLabel);
+
+ layout->addRow(bookmarkIcon, vLay);
+
+ // Ok & Cancel buttons
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
+ layout->addWidget(buttonBox);
+}
+
+
+void FavoriteWidget::showAt(const QPoint &pos)
+{
+ adjustSize();
+
+ QPoint p(pos.x() - width(), pos.y() + 10);
+ move(p);
+ show();
+}
+
+
+void FavoriteWidget::accept()
+{
+ QStringList urls = ReKonfig::previewUrls();
+ if (urls.removeOne(m_tab->url().url()))
+ {
+ ReKonfig::setPreviewUrls(urls);
+ QStringList titles = ReKonfig::previewNames();
+ titles.removeOne(m_tab->view()->title());
+ ReKonfig::setPreviewNames(titles);
+
+ emit updateIcon();
+ }
+
+ close();
+}
diff --git a/src/urlbar/favoritewidget.h b/src/urlbar/favoritewidget.h
new file mode 100644
index 00000000..d0b05f14
--- /dev/null
+++ b/src/urlbar/favoritewidget.h
@@ -0,0 +1,58 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2011 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 FAVORITE_WIDGET_H
+#define FAVORITE_WIDGET_H
+
+
+// Qt Includes
+#include <QMenu>
+#include <QCheckBox>
+
+// Forward Declarations
+class WebTab;
+
+
+class FavoriteWidget : public QMenu
+{
+ Q_OBJECT
+
+public:
+ explicit FavoriteWidget(WebTab *tab, QWidget *parent = 0);
+
+ void showAt(const QPoint &pos);
+
+Q_SIGNALS:
+ void updateIcon();
+
+private Q_SLOTS:
+ void accept();
+
+private:
+ WebTab *m_tab;
+};
+
+#endif // FAVORITE_WIDGET_H
diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp
new file mode 100644
index 00000000..b47d23bf
--- /dev/null
+++ b/src/urlbar/listitem.cpp
@@ -0,0 +1,664 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 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"
+#include "listitem.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// Local Includes
+#include "iconmanager.h"
+
+#include "urlsuggester.h"
+#include "completionwidget.h"
+
+#include "websnap.h"
+#include "searchengine.h"
+
+// KDE Includes
+#include <KIcon>
+#include <KAction>
+#include <kio/jobclasses.h>
+#include <kio/scheduler.h>
+
+// Qt Includes
+#include <QApplication>
+#include <QActionGroup>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QSizePolicy>
+#include <QPixmap>
+#include <QStylePainter>
+#include <QMouseEvent>
+#include <QWebSettings>
+#include <QFile>
+#include <QTextDocument>
+#include <QBitArray>
+
+
+ListItem::ListItem(const UrlSuggestionItem &item, QWidget *parent)
+ : QWidget(parent)
+ , m_option()
+ , m_url(item.url)
+{
+ m_option.initFrom(this);
+ m_option.direction = Qt::LeftToRight;
+
+ // use the same application palette (hence, the same colors)
+ // Qt docs says that using this cctor is possible & fast (qt:qpalette)
+ QPalette p(QApplication::palette());
+ setPalette(p);
+
+ deactivate();
+}
+
+
+ListItem::~ListItem()
+{
+ disconnect();
+}
+
+
+void ListItem::activate()
+{
+ m_option.state |= QStyle::State_Selected;
+ update();
+}
+
+
+void ListItem::deactivate()
+{
+ m_option.state &= ~QStyle::State_Selected;
+ update();
+}
+
+
+void ListItem::paintEvent(QPaintEvent *event)
+{
+ Q_UNUSED(event);
+
+ QWidget::paintEvent(event);
+ QPainter painter(this);
+ m_option.rect = QRect(QPoint(), size());
+ painter.fillRect(m_option.rect, palette().brush(backgroundRole()));
+
+ if (m_option.state.testFlag(QStyle::State_Selected) || m_option.state.testFlag(QStyle::State_MouseOver))
+ {
+ style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &m_option, &painter, this);
+ }
+
+}
+
+
+void ListItem::enterEvent(QEvent *e)
+{
+ m_option.state |= QStyle::State_MouseOver;
+ update();
+ QWidget::enterEvent(e);
+}
+
+
+void ListItem::leaveEvent(QEvent *e)
+{
+ m_option.state &= ~QStyle::State_MouseOver;
+ update();
+ QWidget::enterEvent(e);
+}
+
+
+void ListItem::mousePressEvent(QMouseEvent *e)
+{
+ emit itemClicked(this, e->button(), e->modifiers());
+ QWidget::mousePressEvent(e);
+}
+
+
+KUrl ListItem::url()
+{
+ return m_url;
+}
+
+
+QString ListItem::text()
+{
+ return m_url.url();
+}
+
+
+void ListItem::nextItemSubChoice()
+{
+ // will be override
+}
+
+
+// ---------------------------------------------------------------
+
+
+TypeIconLabel::TypeIconLabel(int type, QWidget *parent)
+ : QLabel(parent)
+{
+ setMinimumWidth(16);
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->setMargin(0);
+ hLayout->setAlignment(Qt::AlignRight);
+ setLayout(hLayout);
+
+ if (type & UrlSuggestionItem::Search)
+ hLayout->addWidget(getIcon("edit-find"));
+ if (type & UrlSuggestionItem::Browse)
+ hLayout->addWidget(getIcon("applications-internet"));
+ if (type & UrlSuggestionItem::Bookmark)
+ hLayout->addWidget(getIcon("rating"));
+ if (type & UrlSuggestionItem::History)
+ hLayout->addWidget(getIcon("view-history"));
+ if (type & UrlSuggestionItem::Suggestion)
+ hLayout->addWidget(getIcon("help-hint"));
+}
+
+
+QLabel *TypeIconLabel::getIcon(QString icon)
+{
+ QLabel *iconLabel = new QLabel(this);
+ iconLabel->setFixedSize(16, 16);
+ QPixmap pixmap = KIcon(icon).pixmap(16);
+ iconLabel->setPixmap(pixmap);
+ return iconLabel;
+}
+
+
+// ---------------------------------------------------------------
+
+
+IconLabel::IconLabel(const QString &icon, QWidget *parent)
+ : QLabel(parent)
+{
+ QPixmap pixmapIcon = IconManager::self()->iconForUrl(KUrl(icon)).pixmap(16);
+ setFixedSize(16, 16);
+ setPixmap(pixmapIcon);
+}
+
+
+IconLabel::IconLabel(const KIcon &icon, QWidget *parent)
+ : QLabel(parent)
+{
+ QPixmap pixmapIcon = icon.pixmap(16);
+ setFixedSize(16, 16);
+ setPixmap(pixmapIcon);
+}
+
+
+// ---------------------------------------------------------------
+
+
+static QString highlightWordsInText(const QString &text, const QStringList &words)
+{
+ QString ret = text;
+ QBitArray boldSections(ret.size());
+ Q_FOREACH(const QString & wordToPointOut, words)
+ {
+ int index = ret.indexOf(wordToPointOut, 0, Qt::CaseInsensitive);
+ while (index > -1)
+ {
+ boldSections.fill(true, index, index + wordToPointOut.size());
+ index = ret.indexOf(wordToPointOut, index + wordToPointOut.size(), Qt::CaseInsensitive);
+ }
+ }
+
+
+ if (boldSections.isEmpty())
+ return ret;
+
+ int numSections = 0;
+ for (int i = 0; i < boldSections.size() - 1; ++i)
+ {
+ if (boldSections.testBit(i) && !boldSections.testBit(i + 1))
+ ++numSections;
+ }
+ if (boldSections.testBit(boldSections.size() - 1)) //last char was still part of a bold section
+ ++numSections;
+ const int tagLength = 7; // length of "<b>" and "</b>" we're going to add for each bold section.
+ ret.reserve(ret.size() + numSections * tagLength);
+ bool bold = false;
+ for (int i = boldSections.size() - 1; i >= 0; --i)
+ {
+ if (!bold && boldSections.testBit(i))
+ {
+ ret.insert(i + 1, QL1S("</b>"));
+ bold = true;
+ }
+ else if (bold && !boldSections.testBit(i))
+ {
+ ret.insert(i + 1, QL1S("<b>"));
+ bold = false;
+ }
+ }
+ if (bold)
+ ret.insert(0, QL1S("<b>"));
+ return ret;
+}
+
+
+TextLabel::TextLabel(const QString &text, const QString &textToPointOut, QWidget *parent)
+ : QLabel(parent)
+{
+ setTextFormat(Qt::RichText);
+ setMouseTracking(false);
+ QString t = text;
+ const bool wasItalic = t.startsWith(QL1S("<i>"));
+ if (wasItalic)
+ t.remove(QRegExp(QL1S("<[/ib]*>")));
+ t = Qt::escape(t);
+ QStringList words = Qt::escape(textToPointOut.simplified()).split(QL1C(' '));
+ t = highlightWordsInText(t, words);
+ if (wasItalic)
+ t = QL1S("<i>") + t + QL1S("</i>");
+ setText(t);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
+}
+
+
+TextLabel::TextLabel(QWidget *parent)
+ : QLabel(parent)
+{
+ setTextFormat(Qt::RichText);
+ setMouseTracking(false);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
+}
+
+
+void TextLabel::setEngineText(const QString &engine, const QString &text)
+{
+ setText(i18nc("%1=search engine, e.g. Google, Wikipedia %2=text to search for", "Search %1 for <b>%2</b>", engine, Qt::escape(text)));
+}
+
+
+// ---------------------------------------------------------------
+
+
+DescriptionLabel::DescriptionLabel(const QString &text, QWidget *parent)
+ : QLabel(parent)
+{
+ QString t = text;
+ const bool wasItalic = t.startsWith(QL1S("<i>"));
+ if (wasItalic)
+ t.remove(QRegExp("<[/ib]*>"));
+
+ if (wasItalic)
+ t = QL1S("<i>") + t + QL1S("</i>");
+
+ setWordWrap(false); //NOTE: why setWordWrap(true) make items have a strange behavior ?
+ setText(t);
+ setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);
+}
+
+
+//--------------------------------------------------------------------------------------------
+
+
+PreviewListItem::PreviewListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent)
+ : ListItem(item, parent)
+{
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->setSpacing(4);
+
+ // icon
+ hLayout->addWidget(new TypeIconLabel(item.type, this));
+
+ // url + text
+ QVBoxLayout *vLayout = new QVBoxLayout;
+ vLayout->setMargin(0);
+
+ QString title = item.title;
+ if (title.isEmpty())
+ {
+ title = item.url;
+ title = title.remove("http://");
+ title.truncate(title.indexOf("/"));
+ }
+
+ vLayout->addWidget(new TextLabel(title, text, this));
+ vLayout->addWidget(new TextLabel("<i>" + item.url + "</i>", text, this));
+ hLayout->addLayout(vLayout);
+
+ // preview label icon
+ QLabel *previewLabelIcon = new QLabel(this);
+ previewLabelIcon->setFixedSize(45, 33);
+ new PreviewLabel(item.url, 38, 29, previewLabelIcon);
+ IconLabel* icon = new IconLabel(item.url, previewLabelIcon);
+ icon->move(27, 16);
+ hLayout->addWidget(previewLabelIcon);
+
+ setLayout(hLayout);
+}
+
+
+// ---------------------------------------------------------------
+
+
+PreviewLabel::PreviewLabel(const QString &url, int width, int height, QWidget *parent)
+ : QLabel(parent)
+{
+ setFixedSize(width, height);
+ setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
+
+ KUrl u = KUrl(url);
+ if (WebSnap::existsImage(KUrl(u)))
+ {
+ QPixmap preview;
+ preview.load(WebSnap::imagePathFromUrl(u));
+ setPixmap(preview.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ }
+}
+
+
+// ---------------------------------------------------------------
+
+
+ImageLabel::ImageLabel(const QString &url, int width, int height, QWidget *parent)
+ : QLabel(parent),
+ m_url(url)
+{
+ setFixedSize(width, height);
+ if (WebSnap::existsImage(KUrl(url)))
+ {
+ QPixmap pix;
+ pix.load(WebSnap::imagePathFromUrl(url));
+ setPixmap(pix);
+ }
+ else
+ {
+ KIO::TransferJob *job = KIO::get(KUrl(url), KIO::NoReload, KIO::HideProgressInfo);
+ connect(job, SIGNAL(data(KIO::Job*, QByteArray)),
+ this, SLOT(slotData(KJob*, QByteArray)));
+ connect(job, SIGNAL(result(KJob*)),
+ this, SLOT(slotResult(KJob*)));
+ }
+}
+
+
+void ImageLabel::slotData(KJob *job, const QByteArray &data)
+{
+ Q_UNUSED(job);
+ m_data.append(data);
+}
+
+
+void ImageLabel::slotResult(KJob *)
+{
+ QPixmap pix;
+ if (!pix.loadFromData(m_data))
+ kDebug() << "error while loading image: ";
+ setPixmap(pix);
+ pix.save(WebSnap::imagePathFromUrl(m_url), "PNG");
+}
+
+
+// ---------------------------------------------------------------
+
+
+SearchListItem::SearchListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent)
+ : ListItem(item, parent)
+ , m_text(text)
+{
+ // FIXME
+// m_iconLabel = new IconLabel(SearchEngine::buildQuery(UrlResolver::searchEngine(), ""), this);
+// m_titleLabel = new TextLabel(this);
+// m_titleLabel->setEngineText(UrlResolver::searchEngine()->name(), item.title);
+// m_engineBar = new EngineBar(UrlResolver::searchEngine(), parent);
+
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->setSpacing(4);
+
+ hLayout->addWidget(m_iconLabel);
+ hLayout->addWidget(m_titleLabel);
+ hLayout->addWidget(new QLabel(i18n("Engines: "), this));
+ hLayout->addWidget(m_engineBar);
+ hLayout->addWidget(new TypeIconLabel(item.type, this));
+
+ setLayout(hLayout);
+
+ connect(m_engineBar, SIGNAL(searchEngineChanged(KService::Ptr)), this, SLOT(changeSearchEngine(KService::Ptr)));
+}
+
+
+QString SearchListItem::text()
+{
+ return m_text;
+}
+
+
+void SearchListItem::changeSearchEngine(KService::Ptr engine)
+{
+ // NOTE: This to let rekonq loading text typed in the requested engine on click.
+ // There probably is a better way to do it. I just cannot see it now...
+ UrlSuggestionItem item = UrlSuggestionItem(UrlSuggestionItem::Search, SearchEngine::buildQuery(engine, m_text), m_text);
+ SearchListItem sItem(item, m_text, this);
+ emit itemClicked(&sItem, Qt::LeftButton, Qt::NoModifier);
+}
+
+
+void SearchListItem::nextItemSubChoice()
+{
+ m_engineBar->selectNextEngine();
+}
+
+
+// -----------------------------------------------------------------------------------------------
+
+
+EngineBar::EngineBar(KService::Ptr selectedEngine, QWidget *parent)
+ : KToolBar(parent)
+{
+ setIconSize(QSize(16, 16));
+ setToolButtonStyle(Qt::ToolButtonIconOnly);
+
+ m_engineGroup = new QActionGroup(this);
+ m_engineGroup->setExclusive(true);
+
+ if (SearchEngine::defaultEngine().isNull())
+ return;
+ m_engineGroup->addAction(newEngineAction(SearchEngine::defaultEngine(), selectedEngine));
+ Q_FOREACH(const KService::Ptr & engine, SearchEngine::favorites())
+ {
+ if (engine->desktopEntryName() != SearchEngine::defaultEngine()->desktopEntryName())
+ {
+ m_engineGroup->addAction(newEngineAction(engine, selectedEngine));
+ }
+ }
+
+ addActions(m_engineGroup->actions());
+}
+
+
+KAction *EngineBar::newEngineAction(KService::Ptr engine, KService::Ptr selectedEngine)
+{
+ QUrl u = engine->property("Query").toUrl();
+ KUrl url = KUrl(u.toString(QUrl::RemovePath | QUrl::RemoveQuery));
+
+ KAction *a = new KAction(IconManager::self()->iconForUrl(url), engine->name(), this);
+ a->setCheckable(true);
+ if (engine->desktopEntryName() == selectedEngine->desktopEntryName()) a->setChecked(true);
+ a->setData(engine->entryPath());
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(changeSearchEngine()));
+ return a;
+}
+
+
+void EngineBar::changeSearchEngine()
+{
+ KAction *a = qobject_cast<KAction*>(sender());
+ emit searchEngineChanged(KService::serviceByDesktopPath(a->data().toString()));
+}
+
+
+void EngineBar::selectNextEngine()
+{
+ QList<QAction *> e = m_engineGroup->actions();
+ int i = 0;
+ while (i < e.count() && !e.at(i)->isChecked())
+ {
+ i++;
+ }
+
+ if (i + 1 == e.count())
+ {
+ e.at(0)->setChecked(true);
+ e.at(0)->trigger();
+ }
+ else
+ {
+ e.at(i + 1)->setChecked(true);
+ e.at(i + 1)->trigger();
+ }
+}
+
+
+// ---------------------------------------------------------------
+
+
+SuggestionListItem::SuggestionListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent)
+ : ListItem(item, parent)
+ , m_text(item.title)
+{
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->setSpacing(4);
+
+ hLayout->addWidget(new IconLabel(item.url, this));
+ hLayout->addWidget(new TextLabel(item.title, text, this));
+ hLayout->addWidget(new TypeIconLabel(item.type, this));
+
+ setLayout(hLayout);
+}
+
+
+QString SuggestionListItem::text()
+{
+ return m_text;
+}
+
+
+// ---------------------------------------------------------------
+
+
+VisualSuggestionListItem::VisualSuggestionListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent)
+ : ListItem(item, parent)
+ , m_text(item.title)
+{
+
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->setSpacing(4);
+ QLabel *previewLabelIcon = new QLabel(this);
+
+ if (!item.image.isEmpty())
+ {
+ previewLabelIcon->setFixedSize(item.image_width + 10, item.image_height + 10);
+ new ImageLabel(item.image, item.image_width, item.image_height, previewLabelIcon);
+ IconLabel* icon = new IconLabel(item.url, previewLabelIcon);
+ icon->move(item.image_width - 10, item.image_height - 10);
+ }
+ else
+ {
+ previewLabelIcon->setFixedSize(18, 18);
+ new IconLabel(item.url, previewLabelIcon);
+ }
+
+ hLayout->addWidget(previewLabelIcon);
+ QVBoxLayout *vLayout = new QVBoxLayout;
+ vLayout->setMargin(0);
+ vLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::MinimumExpanding));
+ vLayout->addWidget(new TextLabel(item.title, text, this));
+ DescriptionLabel *d = new DescriptionLabel("", this);
+ vLayout->addWidget(d);
+ vLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::MinimumExpanding));
+ hLayout->addLayout(vLayout);
+ hLayout->addWidget(new TypeIconLabel(item.type, this));
+ setLayout(hLayout);
+ d->setText("<i>" + item.description + "</i>");
+}
+
+
+QString VisualSuggestionListItem::text()
+{
+ return m_text;
+}
+
+
+// ---------------------------------------------------------------
+
+
+BrowseListItem::BrowseListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent)
+ : ListItem(item, parent)
+{
+ QHBoxLayout *hLayout = new QHBoxLayout;
+ hLayout->setSpacing(4);
+
+ hLayout->addWidget(new IconLabel(item.url, this));
+ hLayout->addWidget(new TextLabel(item.url, text, this));
+ hLayout->addWidget(new TypeIconLabel(item.type, this));
+
+ setLayout(hLayout);
+}
+
+
+// ---------------------------------------------------------------
+
+
+ListItem *ListItemFactory::create(const UrlSuggestionItem &item, const QString &text, QWidget *parent)
+{
+ if (item.type & UrlSuggestionItem::Search)
+ {
+ return new SearchListItem(item, text, parent);
+ }
+
+ if (item.type & UrlSuggestionItem::Browse)
+ {
+ return new BrowseListItem(item, text, parent);
+ }
+
+ if (item.type & UrlSuggestionItem::History)
+ {
+ return new PreviewListItem(item, text, parent);
+ }
+
+ if (item.type & UrlSuggestionItem::Bookmark)
+ {
+ return new PreviewListItem(item, text, parent);
+ }
+
+ if (item.type & UrlSuggestionItem::Suggestion)
+ {
+ if (item.description.isEmpty())
+ {
+ return new SuggestionListItem(item, text, parent);
+ }
+
+ return new VisualSuggestionListItem(item, text, parent);
+ }
+
+ return new PreviewListItem(item, text, parent);
+}
diff --git a/src/urlbar/listitem.h b/src/urlbar/listitem.h
new file mode 100644
index 00000000..21867685
--- /dev/null
+++ b/src/urlbar/listitem.h
@@ -0,0 +1,291 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 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 LISTITEM_H
+#define LISTITEM_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KToolBar>
+#include <KService>
+#include <KUrl>
+
+// Qt Includes
+#include <QWidget>
+#include <QLabel>
+#include <QStyleOptionViewItemV4>
+#include <QString>
+#include <QByteArray>
+
+// Forward Declarations
+class UrlSuggestionItem;
+
+class KAction;
+class KIcon;
+class KJob;
+
+class QActionGroup;
+
+
+class ListItem : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit ListItem(const UrlSuggestionItem &item, QWidget *parent = 0);
+ virtual ~ListItem();
+
+ void activate();
+ void deactivate();
+
+ KUrl url();
+ virtual QString text();
+
+public Q_SLOTS:
+ virtual void nextItemSubChoice();
+
+Q_SIGNALS:
+ void itemClicked(ListItem *item, Qt::MouseButton, Qt::KeyboardModifiers);
+ void updateList();
+
+protected:
+ virtual void paintEvent(QPaintEvent *event);
+ virtual void enterEvent(QEvent *);
+ virtual void leaveEvent(QEvent *);
+ virtual void mousePressEvent(QMouseEvent *e);
+
+private:
+ QStyleOptionViewItemV4 m_option;
+
+protected:
+ KUrl m_url;
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class TypeIconLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit TypeIconLabel(int type, QWidget *parent = 0);
+
+private:
+ QLabel *getIcon(QString icon);
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class IconLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit IconLabel(const QString &icon, QWidget *parent = 0);
+ explicit IconLabel(const KIcon &icon, QWidget *parent = 0);
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class REKONQ_TESTS_EXPORT TextLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit TextLabel(const QString &text, const QString &textToPointOut = QString(), QWidget *parent = 0);
+ explicit TextLabel(QWidget *parent = 0);
+
+ void setEngineText(const QString &engine, const QString &text);
+};
+
+// -------------------------------------------------------------------------
+
+
+class DescriptionLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ explicit DescriptionLabel(const QString &text, QWidget *parent = 0);
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class EngineBar : public KToolBar
+{
+ Q_OBJECT
+
+public:
+ explicit EngineBar(KService::Ptr selectedEngine, QWidget *parent = 0);
+ void selectNextEngine();
+
+Q_SIGNALS:
+ void searchEngineChanged(KService::Ptr engine);
+
+private Q_SLOTS:
+ void changeSearchEngine();
+
+private:
+ KAction *newEngineAction(KService::Ptr engine, KService::Ptr selectedEngine);
+ QActionGroup *m_engineGroup;
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class SearchListItem : public ListItem
+{
+ Q_OBJECT
+
+public:
+ explicit SearchListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent = 0);
+ QString text();
+
+public Q_SLOTS:
+ virtual void nextItemSubChoice();
+
+private Q_SLOTS:
+ void changeSearchEngine(KService::Ptr engine);
+
+private:
+ TextLabel* m_titleLabel;
+ IconLabel* m_iconLabel;
+ EngineBar* m_engineBar;
+ QString m_text;
+ KService::Ptr m_currentEngine;
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class SuggestionListItem : public ListItem
+{
+ Q_OBJECT
+
+public:
+ SuggestionListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent = 0);
+ QString text();
+
+private:
+ QString m_text;
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class VisualSuggestionListItem : public ListItem
+{
+ Q_OBJECT
+
+public:
+ VisualSuggestionListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent = 0);
+ QString text();
+
+private:
+ QString m_text;
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class PreviewListItem : public ListItem
+{
+ Q_OBJECT
+
+public:
+ PreviewListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent = 0);
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class PreviewLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ PreviewLabel(const QString &url, int width, int height, QWidget *parent = 0);
+};
+
+
+// -------------------------------------------------------------------------
+
+class ImageLabel : public QLabel
+{
+ Q_OBJECT
+
+public:
+ ImageLabel(const QString &url, int width, int height, QWidget *parent);
+
+private:
+ QString m_url;
+ QByteArray m_data;
+
+private Q_SLOTS:
+ void slotData(KJob* job, const QByteArray& data);
+ void slotResult(KJob* job);
+};
+
+
+// -------------------------------------------------------------------------
+
+
+class BrowseListItem : public ListItem
+{
+ Q_OBJECT
+
+public:
+ BrowseListItem(const UrlSuggestionItem &item, const QString &text, QWidget *parent = 0);
+};
+
+
+//-------------------------------------------------------------------------------------------------
+
+
+class ListItemFactory
+{
+public:
+ static ListItem *create(const UrlSuggestionItem &item, const QString &text, QWidget *parent);
+};
+
+
+#endif
diff --git a/src/urlbar/rsswidget.cpp b/src/urlbar/rsswidget.cpp
new file mode 100644
index 00000000..0d142d19
--- /dev/null
+++ b/src/urlbar/rsswidget.cpp
@@ -0,0 +1,165 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2011 by Matthieu Gicquel <matgic78 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/>.
+*
+* ============================================================ */
+
+
+// Auto Includes
+#include "rsswidget.h"
+#include "rsswidget.moc"
+
+// Local includes
+#include "application.h"
+#include "tabwindow.h"
+#include "iconmanager.h"
+
+// KDE Includes
+#include <KComboBox>
+#include <KLocalizedString>
+#include <KMessageBox>
+#include <KProcess>
+#include <KUrl>
+
+// Qt Includes
+#include <QDBusConnectionInterface>
+#include <QDBusInterface>
+
+#include <QDialogButtonBox>
+#include <QFormLayout>
+#include <QLabel>
+#include <QPushButton>
+
+
+RSSWidget::RSSWidget(const QMap< KUrl, QString > &map, QWidget *parent)
+ : QMenu(parent)
+ , m_map(map)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ setFixedWidth(350);
+
+ QFormLayout *layout = new QFormLayout(this);
+
+ // Title
+ QLabel *title = new QLabel(this);
+ title->setText(i18n("Subscribe to RSS Feeds"));
+ QFont f = title->font();
+ f.setBold(true);
+ title->setFont(f);
+ layout->addRow(title);
+
+ // Agregators
+ QLabel *agregator = new QLabel(this);
+ agregator->setText(i18n("Aggregator:"));
+
+ m_agregators = new KComboBox(this);
+ m_agregators->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ m_agregators->addItem(KIcon("akregator"), QString("Akregator"));
+ m_agregators->addItem(IconManager::self()->iconForUrl(KUrl("http://google.com/reader")), i18n("Google Reader"));
+
+ layout->addRow(agregator, m_agregators);
+
+ // Feeds List
+ QLabel *feed = new QLabel(this);
+ feed->setText(i18n("Feed:"));
+
+ m_feeds = new KComboBox(this);
+ m_feeds->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ Q_FOREACH(const QString & title, m_map)
+ {
+ m_feeds->addItem(title);
+ }
+
+ layout->addRow(feed, m_feeds);
+
+ // Buttons
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, Qt::Horizontal, this);
+
+ QPushButton *addFeed = new QPushButton(KIcon("list-add"), i18n("Add Feed"), buttonBox);
+ buttonBox->addButton(addFeed, QDialogButtonBox::AcceptRole);
+
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
+
+ layout->addRow(buttonBox);
+}
+
+
+void RSSWidget::showAt(const QPoint &pos)
+{
+ adjustSize();
+
+ QPoint p(pos.x() - width(), pos.y() + 10);
+ move(p);
+ show();
+}
+
+
+void RSSWidget::accept()
+{
+ QString url = m_map.key(m_feeds->currentText()).toMimeDataString();
+
+ if (m_agregators->currentIndex() == 0)
+ addWithAkregator(url);
+ else
+ addWithGoogleReader(url);
+
+ close();
+}
+
+
+void RSSWidget::addWithGoogleReader(const QString &url)
+{
+ KUrl toLoad = KUrl("http://www.google.com/ig/add?feedurl=" + url);
+ rApp->tabWindow()->loadUrl(toLoad);
+}
+
+
+void RSSWidget::addWithAkregator(const QString &url)
+{
+ // Akregator is running
+ if (QDBusConnection::sessionBus().interface()->isServiceRegistered("org.kde.akregator"))
+ {
+ QDBusInterface akregator("org.kde.akregator", "/Akregator", "org.kde.akregator.part");
+ QDBusReply<void> reply = akregator.call("addFeedsToGroup", QStringList(url) , i18n("Imported Feeds"));
+
+ if (!reply.isValid())
+ {
+ KMessageBox::error(0, QString(i18n("Could not add feed to Akregator. Please add it manually:")
+ + "<br /><br /> <a href=\"" + url + "\">" + url + "</a>"));
+ }
+ }
+ // Akregator is not running
+ else
+ {
+ KProcess proc;
+ proc << "akregator" << "-g" << i18n("Imported Feeds");
+ proc << "-a" << url;
+ if (proc.startDetached() == 0)
+ {
+ KMessageBox::error(0, QString(i18n("There was an error. Please verify Akregator is installed on your system.")
+ + "<br /><br /> <a href=\"" + url + "\">" + url + "</a>"));
+ }
+ }
+}
diff --git a/src/urlbar/rsswidget.h b/src/urlbar/rsswidget.h
new file mode 100644
index 00000000..eaa3de7d
--- /dev/null
+++ b/src/urlbar/rsswidget.h
@@ -0,0 +1,61 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2010-2011 by Matthieu Gicquel <matgic78 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 RSSWIDGET_H
+#define RSSWIDGET_H
+
+// Qt Includes
+#include <QMenu>
+
+// Forward Declarations
+class KComboBox;
+class KUrl;
+
+
+class RSSWidget : public QMenu
+{
+ Q_OBJECT
+
+public:
+ // QMap< feedUrl, feedTitle>
+ RSSWidget(const QMap<KUrl, QString> &map, QWidget *parent = 0);
+
+ void showAt(const QPoint &pos);
+
+private Q_SLOTS:
+ void accept();
+
+private:
+ void addWithAkregator(const QString &url);
+ void addWithGoogleReader(const QString &url);
+
+ QMap<KUrl, QString> m_map;
+
+ KComboBox *m_agregators;
+ KComboBox *m_feeds;
+};
+
+#endif // RSSWIDGET_H
diff --git a/src/urlbar/sslwidget.cpp b/src/urlbar/sslwidget.cpp
new file mode 100644
index 00000000..a9d3e9b6
--- /dev/null
+++ b/src/urlbar/sslwidget.cpp
@@ -0,0 +1,251 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2011-2012 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/>.
+*
+* ============================================================ */
+
+
+// Auto Includes
+#include "sslwidget.h"
+#include "sslwidget.moc"
+
+// Local includes
+#include "historymanager.h"
+#include "sslinfodialog.h"
+
+// Qt Includes
+#include <QPointer>
+
+#include <QDialogButtonBox>
+#include <QGridLayout>
+#include <QLabel>
+#include <QPushButton>
+#include <QTextDocument>
+
+
+SSLWidget::SSLWidget(const QUrl &url, const WebSslInfo &info, QWidget *parent)
+ : QMenu(parent)
+ , m_url(url)
+ , m_info(info)
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ setMinimumWidth(400);
+
+ QList<QSslCertificate> certList = m_info.certificateChain();
+ QSslCertificate cert;
+ if (!certList.isEmpty())
+ cert = certList.first();
+
+ QList<QStringList> certErrorList = SslInfoDialog::errorsFromString(m_info.certificateErrors());
+ QStringList firstCertErrorList;
+ if (!certErrorList.isEmpty())
+ firstCertErrorList = certErrorList.first();
+
+ QGridLayout *layout = new QGridLayout(this);
+
+ QLabel *label;
+ QLabel *imageLabel;
+
+ int rows = 0;
+ // ------------------------------------------------------------------------------------------------------
+ imageLabel = new QLabel(this);
+ layout->addWidget(imageLabel, rows , 0, Qt::AlignCenter);
+
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(i18n("Identity"));
+ QFont f1 = label->font();
+ f1.setBold(true);
+ label->setFont(f1);
+ layout->addWidget(label, rows++, 1);
+
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ if (cert.isNull())
+ {
+ label->setText(i18n("Warning: this site is NOT carrying a certificate."));
+ imageLabel->setPixmap(KIcon("security-low").pixmap(32));
+ layout->addWidget(label, rows++, 1);
+ }
+ else
+ {
+ if (cert.isValid() && firstCertErrorList.isEmpty())
+ {
+ label->setText(i18n("The certificate for this site is valid and has been verified by:\n%1.",
+ Qt::escape(cert.issuerInfo(QSslCertificate::CommonName))));
+
+ imageLabel->setPixmap(KIcon("security-high").pixmap(32));
+ }
+ else
+ {
+ QString c = QL1S("<ul>");
+ Q_FOREACH(const QString & s, firstCertErrorList)
+ {
+ c += QL1S("<li>") + s + QL1S("</li>");
+ }
+ c += QL1S("</ul>");
+
+ label->setText(i18n("The certificate for this site is NOT valid, for the following reasons:\n%1.", c));
+ label->setTextFormat(Qt::RichText);
+ imageLabel->setPixmap(KIcon("security-low").pixmap(32));
+ }
+
+ layout->addWidget(label, rows++, 1);
+
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(QL1S("<a href=\"moresslinfos\">") + i18n("Certificate Information") + QL1S("</a>"));
+ connect(label, SIGNAL(linkActivated(QString)), this, SLOT(showMoreSslInfos(QString)));
+ layout->addWidget(label, rows++, 1);
+ }
+
+ // -------------------------------------------------------------------------------------------------------------
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(i18n("Encryption"));
+ QFont f2 = label->font();
+ f2.setBold(true);
+ label->setFont(f2);
+ layout->addWidget(label, rows, 1);
+
+ imageLabel = new QLabel(this);
+ layout->addWidget(imageLabel, rows++ , 0, Qt::AlignCenter);
+
+ QString ciph = m_info.ciphers();
+ if (ciph.isEmpty()) // NOTE: Can I verify encryption in another (better?) way?
+ {
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(i18n("Your connection to %1 is NOT encrypted.\n", m_url.host()));
+ layout->addWidget(label, rows++ , 1);
+
+ imageLabel->setPixmap(KIcon("security-low").pixmap(32));
+ }
+ else
+ {
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(i18n("Your connection to \"%1\" is encrypted.\n", m_url.host()));
+ layout->addWidget(label, rows++, 1);
+
+ QString vers = m_info.protocol();
+ QString sslVersion;
+ if (vers == QL1S("SSLv3"))
+ {
+ sslVersion = QL1S("SSL 3.0");
+ imageLabel->setPixmap(KIcon("security-high").pixmap(32));
+ }
+ else if (vers == QL1S("SSLv2"))
+ {
+ sslVersion = QL1S("SSL 2.0");
+ imageLabel->setPixmap(KIcon("security-low").pixmap(32));
+ }
+ else if (vers == QL1S("TLSv1"))
+ {
+ sslVersion = QL1S("TLS 1.0");
+ imageLabel->setPixmap(KIcon("security-high").pixmap(32));
+ }
+ else
+ {
+ sslVersion = i18n("Unknown");
+ imageLabel->setPixmap(KIcon("security-low").pixmap(32));
+ }
+
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(i18n("It uses protocol: %1.\n", sslVersion));
+ layout->addWidget(label, rows++, 1);
+
+ const QStringList cipherInfo = m_info.ciphers().split('\n', QString::SkipEmptyParts);
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(
+ i18n("It is encrypted using %1 at %2 bits, with %3 for message authentication and %4 with Auth %5 as key exchange mechanism.\n\n",
+ cipherInfo[0],
+ m_info.usedChiperBits(),
+ cipherInfo[3],
+ cipherInfo[2],
+ cipherInfo[1])
+ );
+ layout->addWidget(label, rows++, 1);
+
+ }
+
+ // ------------------------------------------------------------------------------------------------------------------
+ imageLabel = new QLabel(this);
+ layout->addWidget(imageLabel, rows , 0, Qt::AlignCenter);
+
+ label = new QLabel(this);
+ label->setWordWrap(true);
+ label->setText(i18n("Site Information"));
+ QFont f3 = label->font();
+ f3.setBold(true);
+ label->setFont(f3);
+ layout->addWidget(label, rows++, 1);
+
+ label = new QLabel(this);
+ label->setWordWrap(true);
+
+ QList<HistoryItem> hList = HistoryManager::self()->find(url.toString());
+ HistoryItem firstVisit = hList.isEmpty() ?
+ HistoryItem() :
+ hList.first() ;
+
+ if (firstVisit.visitCount == 1)
+ {
+ label->setText(i18n("It is your first time visiting this site."));
+ imageLabel->setPixmap(KIcon("security-medium").pixmap(32));
+ }
+ else
+ {
+ label->setText(i18n("You just visited this site.\nYour first visit was on %1.\n", firstVisit.firstDateTimeVisit.toString()));
+ imageLabel->setPixmap(KIcon("security-high").pixmap(32));
+ }
+ layout->addWidget(label, rows++, 1);
+
+}
+
+
+void SSLWidget::showAt(const QPoint &pos)
+{
+ adjustSize();
+
+ QPoint p(pos.x() - width(), pos.y() + 10);
+ move(p);
+ show();
+}
+
+
+void SSLWidget::accept()
+{
+ close();
+}
+
+
+void SSLWidget::showMoreSslInfos(const QString &)
+{
+ QPointer<SslInfoDialog> dlg = new SslInfoDialog(m_url.host(), m_info, this);
+ dlg->exec();
+ delete dlg;
+
+ return;
+}
diff --git a/src/urlbar/sslwidget.h b/src/urlbar/sslwidget.h
new file mode 100644
index 00000000..dd6f020d
--- /dev/null
+++ b/src/urlbar/sslwidget.h
@@ -0,0 +1,58 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2011-2012 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 SSL_WIDGET_H
+#define SSL_WIDGET_H
+
+
+// Local Includes
+#include "websslinfo.h"
+
+// Qt Includes
+#include <QMenu>
+
+#include <QUrl>
+
+
+class SSLWidget : public QMenu
+{
+ Q_OBJECT
+
+public:
+ SSLWidget(const QUrl &url, const WebSslInfo &info, QWidget *parent = 0);
+
+ void showAt(const QPoint &pos);
+
+private Q_SLOTS:
+ void showMoreSslInfos(const QString &);
+ void accept();
+
+private:
+ QUrl m_url;
+ WebSslInfo m_info;
+};
+
+#endif // SSL_WIDGET_H
diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp
new file mode 100644
index 00000000..c6159594
--- /dev/null
+++ b/src/urlbar/urlbar.cpp
@@ -0,0 +1,776 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2012 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-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* 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 "urlbar.h"
+#include "urlbar.moc"
+
+// Auto Includes
+#include "rekonq.h"
+
+// App Includes
+#include "application.h"
+
+// Local Includes
+#include "bookmarkmanager.h"
+#include "bookmarkowner.h" // FIXME: Why is this needed? Why everything interesting in BookmarkManager is in its owner?
+#include "iconmanager.h"
+
+#include "completionwidget.h"
+#include "bookmarkwidget.h"
+#include "favoritewidget.h"
+#include "urlsuggester.h"
+
+#include "webtab.h"
+#include "webpage.h"
+#include "webview.h"
+#include "searchengine.h"
+#include "websnap.h"
+
+// KDE Includes
+#include <KCompletionBox>
+#include <KStandardDirs>
+#include <KColorScheme>
+#include <KMenu>
+#include <KIcon>
+#include <KIconLoader>
+#include <KStandardAction>
+#include <KAction>
+
+// Qt Includes
+#include <QPainter>
+#include <QPaintEvent>
+#include <QPalette>
+#include <QVBoxLayout>
+#include <QClipboard>
+#include <QTimer>
+
+// const values
+const int c_iconMargin = 4;
+
+
+IconButton::IconButton(QWidget *parent)
+ : QToolButton(parent)
+{
+ setToolButtonStyle(Qt::ToolButtonIconOnly);
+ setStyleSheet("IconButton { background-color:transparent; border: none; padding: 0px}");
+ setCursor(Qt::ArrowCursor);
+
+ setContextMenuPolicy(Qt::PreventContextMenu);
+}
+
+
+void IconButton::mouseReleaseEvent(QMouseEvent* event)
+{
+ emit clicked(event->globalPos());
+}
+
+
+// -----------------------------------------------------------------------------------------------------------
+
+
+QString guessUrlWithCustomFirstLevel(const QString &str1, const QString &str2)
+{
+ QUrl url(QL1S("http://www.") + str1);
+ QString host = url.host().toLower();
+ if (!host.endsWith(str2, Qt::CaseInsensitive))
+ {
+ host += str2;
+ url.setHost(host);
+ }
+ return url.toString();
+}
+
+// -----------------------------------------------------------------------------------------------------------
+
+
+UrlBar::UrlBar(QWidget *parent)
+ : KLineEdit(parent)
+ , _tab(0)
+ , _icon(new IconButton(this))
+ , _suggestionTimer(new QTimer(this))
+{
+ setLayoutDirection(Qt::LeftToRight);
+
+ // set initial icon
+ _icon->setIcon(KIcon("arrow-right"));
+
+ // initial style
+ setStyleSheet(QString("UrlBar { padding: 2px 0 2px %1px; height: %1px } ").arg(_icon->sizeHint().width()));
+
+ // doesn't show the clear button
+ setClearButtonShown(false);
+
+ // enable dragging
+ setDragEnabled(true);
+
+ // insert decoded URLs
+ setUrlDropsEnabled(true);
+
+ // tooltip
+ setToolTip(i18n("Type here to search your bookmarks, history and the web..."));
+
+ // accept focus, via tabbing, clicking & wheeling
+ setFocusPolicy(Qt::WheelFocus);
+
+ // disable completion object (we have our own :) )
+ setCompletionObject(0);
+
+ _tab = qobject_cast<WebTab *>(parent);
+
+ connect(_tab, SIGNAL(loadProgressing()), this, SLOT(update()));
+
+ connect(_tab->view(), SIGNAL(urlChanged(QUrl)), this, SLOT(setQUrl(QUrl)));
+ connect(_tab->view(), SIGNAL(loadFinished(bool)), this, SLOT(loadFinished()));
+ connect(_tab->view(), SIGNAL(loadStarted()), this, SLOT(clearRightIcons()));
+ connect(_tab->view(), SIGNAL(iconChanged()), this, SLOT(refreshFavicon()));
+
+ // bookmark icon
+ connect(BookmarkManager::self(), SIGNAL(bookmarksUpdated()), this, SLOT(updateRightIcons()));
+
+ _suggestionTimer->setSingleShot(true);
+ connect(_suggestionTimer, SIGNAL(timeout()), this, SLOT(suggest()));
+
+ activateSuggestions(true);
+}
+
+
+UrlBar::~UrlBar()
+{
+ _suggestionTimer->stop();
+ activateSuggestions(false);
+ _box.clear();
+
+ disconnect();
+}
+
+
+void UrlBar::setQUrl(const QUrl& url)
+{
+ if (url.scheme() == QL1S("about"))
+ {
+ clear();
+ setFocus();
+ }
+ else
+ {
+ clearFocus();
+ KLineEdit::setUrl(url);
+ setCursorPosition(0);
+ refreshFavicon();
+ }
+}
+
+
+void UrlBar::loadRequestedUrl(const KUrl& url, Rekonq::OpenType type)
+{
+ activateSuggestions(false);
+ clearFocus();
+ setUrl(url);
+ rApp->loadUrl(url, type);
+}
+
+
+void UrlBar::loadDigitedUrl()
+{
+ UrlSuggester res(text());
+ UrlSuggestionList list = res.orderedSearchItems();
+ if (list.isEmpty())
+ {
+ loadRequestedUrl(KUrl(text()));
+ }
+ else
+ {
+ loadRequestedUrl(list.first().url);
+ }
+}
+
+
+void UrlBar::paintEvent(QPaintEvent *event)
+{
+ KColorScheme colorScheme(palette().currentColorGroup());
+ QColor backgroundColor;
+ QColor foregroundColor;
+
+ if (QWebSettings::globalSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled))
+ {
+ backgroundColor = QColor(220, 220, 220); // light gray
+ foregroundColor = Qt::black;
+ }
+ else
+ {
+ backgroundColor = rApp->palette().color(QPalette::Base);
+ foregroundColor = rApp->palette().color(QPalette::Text);
+ }
+
+ // set background color of UrlBar
+ QPalette p = palette();
+
+ int progr = _tab->progress();
+ if (progr == 0 || progr == 100)
+ {
+ if (_tab->url().scheme() == QL1S("https"))
+ {
+ backgroundColor = _tab->page()->hasSslValid()
+ ? colorScheme.background(KColorScheme::PositiveBackground).color()
+ : colorScheme.background(KColorScheme::NegativeBackground).color();
+
+ foregroundColor = colorScheme.foreground(KColorScheme::NormalText).color();
+ }
+ p.setBrush(QPalette::Base, backgroundColor);
+ p.setBrush(QPalette::Text, foregroundColor);
+ }
+ else
+ {
+ QColor highlight = rApp->palette().color(QPalette::Highlight);
+
+ int r = (highlight.red() + 2 * backgroundColor.red()) / 3;
+ int g = (highlight.green() + 2 * backgroundColor.green()) / 3;
+ int b = (highlight.blue() + 2 * backgroundColor.blue()) / 3;
+
+ QColor loadingColor(r, g, b);
+
+ if (abs(loadingColor.lightness() - backgroundColor.lightness()) < 20) //eg. Gaia color scheme
+ {
+ r = (2 * highlight.red() + backgroundColor.red()) / 3;
+ g = (2 * highlight.green() + backgroundColor.green()) / 3;
+ b = (2 * highlight.blue() + backgroundColor.blue()) / 3;
+ loadingColor = QColor(r, g, b);
+ }
+
+ QLinearGradient gradient(QPoint(0, 0), QPoint(width(), 0));
+ gradient.setColorAt(0, loadingColor);
+ gradient.setColorAt(((double)progr) / 100 - .000001, loadingColor);
+ gradient.setColorAt(((double)progr) / 100, backgroundColor);
+ p.setBrush(QPalette::Base, gradient);
+ }
+ setPalette(p);
+
+ // you need this before our code to draw inside the line edit..
+ KLineEdit::paintEvent(event);
+
+ if (text().isEmpty() && (progr == 0 || progr == 100))
+ {
+ QStyleOptionFrame option;
+ initStyleOption(&option);
+ QRect textRect = style()->subElementRect(QStyle::SE_LineEditContents, &option, this);
+ QPainter painter(this);
+ painter.setPen(Qt::gray);
+ painter.drawText(textRect,
+ Qt::AlignVCenter | Qt::AlignCenter,
+ i18n("Type here to search your bookmarks, history and the web...")
+ );
+ }
+}
+
+
+void UrlBar::keyPressEvent(QKeyEvent *event)
+{
+ QString currentText = text().trimmed();
+
+ if (currentText.isEmpty())
+ return KLineEdit::keyPressEvent(event);
+
+ // this handles the Modifiers + Return key combinations
+ if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter)
+ {
+ switch (event->modifiers())
+ {
+ case Qt::AltModifier:
+ loadRequestedUrl(currentText, Rekonq::NewFocusedTab);
+ break;
+
+ case Qt::ControlModifier:
+ loadRequestedUrl(guessUrlWithCustomFirstLevel(currentText, QL1S(".com")));
+ break;
+
+ case 0x06000000: // Qt::ControlModifier | Qt::ShiftModifier:
+ loadRequestedUrl(guessUrlWithCustomFirstLevel(currentText, QL1S(".org")));
+ break;
+
+ case Qt::ShiftModifier:
+ loadRequestedUrl(guessUrlWithCustomFirstLevel(currentText, QL1S(".net")));
+ break;
+
+ default:
+ loadRequestedUrl(currentText);
+ break;
+ }
+ }
+
+ if (event->key() == Qt::Key_Escape)
+ {
+ clearFocus();
+ if (!(_tab->url().protocol() == QL1S("about")))
+ setText(_tab->url().url());
+ event->accept();
+ }
+
+ KLineEdit::keyPressEvent(event);
+}
+
+
+void UrlBar::focusInEvent(QFocusEvent *event)
+{
+ activateSuggestions(true);
+ KLineEdit::focusInEvent(event);
+}
+
+
+void UrlBar::dropEvent(QDropEvent *event)
+{
+ // handles only plain-text with url format
+ if (event->mimeData()->hasFormat("text/plain") && event->source() != this)
+ {
+ QUrl url = QUrl::fromUserInput(event->mimeData()->data("text/plain"));
+
+ if (url.isValid())
+ {
+ setQUrl(url);
+ loadRequestedUrl(text());
+ return;
+ }
+ }
+
+ // handles everything else
+ KLineEdit::dropEvent(event);
+ loadRequestedUrl(text());
+}
+
+
+void UrlBar::loadFinished()
+{
+ if (_tab->url().scheme() == QL1S("about"))
+ {
+ update();
+ return;
+ }
+
+ // show bookmark info
+ IconButton *bt = addRightIcon(UrlBar::BK);
+ connect(bt, SIGNAL(clicked(QPoint)), this, SLOT(manageBookmarks()));
+
+ // show favorite icon
+ IconButton *fbt = addRightIcon(UrlBar::Favorite);
+ connect(fbt, SIGNAL(clicked(QPoint)), this, SLOT(manageFavorites(QPoint)));
+
+ // show KGet downloads??
+ if (!KStandardDirs::findExe("kget").isNull() && ReKonfig::kgetList())
+ {
+ IconButton *bt = addRightIcon(UrlBar::KGet);
+ connect(bt, SIGNAL(clicked(QPoint)), _tab->page(), SLOT(downloadAllContentsWithKGet()));
+ }
+
+ // show RSS
+ if (_tab->hasRSSInfo())
+ {
+ IconButton *bt = addRightIcon(UrlBar::RSS);
+ connect(bt, SIGNAL(clicked(QPoint)), this, SLOT(showRSSInfo(QPoint)));
+ }
+
+ // show SSL
+ if (_tab->url().scheme() == QL1S("https"))
+ {
+ // NOTE: the choice for the right SSL icon is done in the addRightIcon method
+ IconButton *bt = addRightIcon(UrlBar::SSL);
+ connect(bt, SIGNAL(clicked(QPoint)), _tab->page(), SLOT(showSSLInfo(QPoint)));
+ }
+
+ // show add search engine
+ if (_tab->hasNewSearchEngine())
+ {
+ IconButton *bt = addRightIcon(UrlBar::SearchEngine);
+ connect(bt, SIGNAL(clicked(QPoint)), this, SLOT(showSearchEngine(QPoint)));
+ }
+
+// FIXME Reimplement if (_tab->hasAdBlockedElements())
+// {
+// IconButton *bt = addRightIcon(UrlBar::AdBlock);
+// connect(bt, SIGNAL(clicked(QPoint)), (QObject *) AdBlockManager::self(), SLOT(showBlockedItemDialog()));
+// }
+
+ // we need to update urlbar after the right icon settings
+ // removing this code (where setStyleSheet automatically calls update) needs adding again
+ // an update call
+ int oneIconWidth = _icon->sizeHint().width();
+ int rightIconWidth = (oneIconWidth + c_iconMargin) * (_rightIconsList.count());
+ setStyleSheet(QString("UrlBar { padding: 2px %2px 2px %1px; height: %1px } ").arg(oneIconWidth).arg(rightIconWidth));
+}
+
+
+void UrlBar::updateRightIcons()
+{
+ if (!_tab->isPageLoading())
+ {
+ clearRightIcons();
+ loadFinished();
+ }
+}
+
+
+void UrlBar::activateSuggestions(bool b)
+{
+ if (b)
+ {
+ if (_box.isNull())
+ {
+ _box = new CompletionWidget(this);
+ installEventFilter(_box.data());
+ connect(_box.data(), SIGNAL(chosenUrl(KUrl, Rekonq::OpenType)), this, SLOT(loadRequestedUrl(KUrl, Rekonq::OpenType)));
+
+ // activate suggestions on edit text
+ connect(this, SIGNAL(textChanged(QString)), this, SLOT(detectTypedString(QString)));
+ }
+ }
+ else
+ {
+ disconnect(this, SIGNAL(textChanged(QString)), this, SLOT(detectTypedString(QString)));
+ removeEventFilter(_box.data());
+ if (!_box.isNull())
+ _box.data()->deleteLater();
+ }
+}
+
+
+void UrlBar::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ Q_UNUSED(event);
+
+ selectAll();
+}
+
+
+void UrlBar::contextMenuEvent(QContextMenuEvent* event)
+{
+ KMenu menu;
+ const bool clipboardFilled = !rApp->clipboard()->text().isEmpty();
+
+ // Cut
+ KAction *a = KStandardAction::cut(this, SLOT(cut()), this);
+ a->setEnabled(hasSelectedText());
+ menu.addAction(a);
+
+ // Copy
+ a = KStandardAction::copy(this, SLOT(copy()), this);
+ a->setEnabled(hasSelectedText());
+ menu.addAction(a);
+
+ // Paste
+ a = KStandardAction::paste(this, SLOT(paste()), this);
+ a->setEnabled(clipboardFilled);
+ menu.addAction(a);
+
+ // Paste & Go
+ const QString clipboardText = rApp->clipboard()->text();
+ if (isValidURL(clipboardText) || clipboardText.isEmpty())
+ {
+ a = new KAction(i18n("Paste && Go"), this);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(pasteAndGo()));
+ }
+ else
+ {
+ a = new KAction(i18n("Paste && Search"), this);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(pasteAndSearch()));
+ }
+ a->setEnabled(clipboardFilled);
+ menu.addAction(a);
+
+ // Delete
+ a = new KAction(KIcon("edit-delete"), i18n("Delete"), this);
+ connect(a, SIGNAL(triggered(bool)), this, SLOT(delSlot()));
+ a->setEnabled(hasSelectedText());
+ menu.addAction(a);
+
+ menu.addSeparator();
+
+ // Select All
+ a = KStandardAction::selectAll(this, SLOT(selectAll()), this);
+ a->setEnabled(!text().isEmpty());
+ menu.addAction(a);
+
+ menu.exec(event->globalPos());
+}
+
+
+bool UrlBar::isValidURL(QString url)
+{
+ bool isValid = false;
+ if (url.startsWith(QL1S("http://"))
+ || url.startsWith(QL1S("https://"))
+ || url.startsWith(QL1S("ftp://"))
+ )
+ url = url.remove(QRegExp("(http|https|ftp)://"));
+
+ if (url.contains(QL1C('.'))
+ && url.indexOf(QL1C('.')) > 0
+ && url.indexOf(QL1C('.')) < url.length()
+ && !url.trimmed().contains(QL1C(' '))
+ && QUrl::fromUserInput(url).isValid()
+ )
+ isValid = true;
+
+ return isValid;
+}
+
+
+IconButton *UrlBar::addRightIcon(UrlBar::icon ic)
+{
+ IconButton *rightIcon = new IconButton(this);
+
+ switch (ic)
+ {
+ case UrlBar::KGet:
+ rightIcon->setIcon(KIcon("download"));
+ rightIcon->setToolTip(i18n("List all links with KGet"));
+ break;
+ case UrlBar::RSS:
+ rightIcon->setIcon(KIcon("application-rss+xml"));
+ rightIcon->setToolTip(i18n("List all available RSS feeds"));
+ break;
+ case UrlBar::SSL:
+ _tab->page()->hasSslValid()
+ ? rightIcon->setIcon(KIcon("object-locked"))
+ : rightIcon->setIcon(KIcon("object-unlocked"));
+ rightIcon->setToolTip(i18n("Show SSL Info"));
+ break;
+ case UrlBar::BK:
+ if (BookmarkManager::self()->bookmarkForUrl(_tab->url()).isNull())
+ {
+ rightIcon->setIcon(KIcon("bookmarks").pixmap(32, 32, QIcon::Disabled));
+ rightIcon->setToolTip(i18n("Bookmark this page"));
+ }
+ else
+ {
+ rightIcon->setIcon(KIcon("bookmarks"));
+ rightIcon->setToolTip(i18n("Edit this bookmark"));
+ }
+ break;
+ case UrlBar::SearchEngine:
+ {
+ KIcon wsIcon("edit-web-search");
+ if (wsIcon.isNull())
+ {
+ wsIcon = KIcon("preferences-web-browser-shortcuts");
+ }
+ rightIcon->setIcon(wsIcon);
+ rightIcon->setToolTip(i18n("Add search engine"));
+ break;
+ }
+ case UrlBar::Favorite:
+ if (ReKonfig::previewUrls().contains(_tab->url().url()))
+ {
+ rightIcon->setIcon(KIcon("emblem-favorite"));
+ rightIcon->setToolTip(i18n("Remove from favorite"));
+ }
+ else
+ {
+ rightIcon->setIcon(KIcon("emblem-favorite").pixmap(32, 32, QIcon::Disabled));
+ rightIcon->setToolTip(i18n("Add to favorites"));
+ }
+ break;
+ case UrlBar::AdBlock:
+ rightIcon->setIcon(KIcon("preferences-web-browser-adblock"));
+ rightIcon->setToolTip(i18n("There are elements blocked by AdBlock"));
+ break;
+ default:
+ ASSERT_NOT_REACHED("ERROR.. default non extant case!!");
+ break;
+ }
+
+ _rightIconsList << rightIcon;
+
+ int iconsCount = _rightIconsList.count();
+ updateRightIconPosition(rightIcon, iconsCount);
+
+ rightIcon->show();
+
+ return rightIcon;
+}
+
+
+void UrlBar::clearRightIcons()
+{
+ qDeleteAll(_rightIconsList);
+ _rightIconsList.clear();
+}
+
+
+void UrlBar::resizeEvent(QResizeEvent *event)
+{
+ int ih = _icon->sizeHint().height();
+ int iconsCount = _rightIconsList.count();
+ int iconHeight = (height() - ih) / 2;
+
+ _icon->move(c_iconMargin, iconHeight);
+
+ for (int i = 0; i < iconsCount; ++i)
+ {
+ IconButton *bt = _rightIconsList.at(i);
+ updateRightIconPosition(bt, i + 1);
+ }
+
+ KLineEdit::resizeEvent(event);
+}
+
+
+void UrlBar::detectTypedString(const QString &typed)
+{
+ if (typed.count() == 1)
+ {
+ QTimer::singleShot(0, this, SLOT(suggest()));
+ return;
+ }
+
+ if (_suggestionTimer->isActive())
+ _suggestionTimer->stop();
+ _suggestionTimer->start(50);
+}
+
+
+void UrlBar::suggest()
+{
+ if (!_box.isNull())
+ _box.data()->suggestUrls(text());
+}
+
+
+void UrlBar::refreshFavicon()
+{
+ if (QWebSettings::globalSettings()->testAttribute(QWebSettings::PrivateBrowsingEnabled))
+ {
+ _icon->setIcon(KIcon("view-media-artist"));
+ return;
+ }
+
+ KUrl u = _tab->url();
+ if (u.scheme() == QL1S("about"))
+ {
+ _icon->setIcon(KIcon("arrow-right"));
+ return;
+ }
+
+ _icon->setIcon(IconManager::self()->iconForUrl(u));
+}
+
+
+void UrlBar::pasteAndGo()
+{
+ loadRequestedUrl(rApp->clipboard()->text());
+}
+
+
+void UrlBar::pasteAndSearch()
+{
+ KService::Ptr defaultEngine = SearchEngine::defaultEngine();
+ if (defaultEngine)
+ loadRequestedUrl(KUrl(SearchEngine::buildQuery(defaultEngine, QApplication::clipboard()->text())));
+}
+
+
+void UrlBar::delSlot()
+{
+ del();
+}
+
+
+void UrlBar::manageBookmarks()
+{
+ if (_tab->url().scheme() == QL1S("about"))
+ return;
+
+ KBookmark bookmark = BookmarkManager::self()->bookmarkForUrl(_tab->url());
+
+ if (bookmark.isNull())
+ {
+ bookmark = BookmarkManager::self()->owner()->bookmarkCurrentPage();
+ }
+
+ // calculate position
+ int iconSize = IconSize(KIconLoader::Small) + c_iconMargin;
+
+ // Add a generic 10 to move it a bit below and right.
+ // No need to be precise...
+ int iconWidth = 10 + width() - ((iconSize + c_iconMargin));
+ int iconHeight = 10 + (height() - iconSize) / 2;
+
+ QPoint p = mapToGlobal(QPoint(iconWidth, iconHeight));
+
+ // show bookmark widget
+ BookmarkWidget *widget = new BookmarkWidget(bookmark, window());
+ widget->showAt(p);
+}
+
+
+void UrlBar::manageFavorites(QPoint pos)
+{
+ IconButton *bt = qobject_cast<IconButton *>(this->sender());
+ if (!bt)
+ return;
+
+ if (_tab->url().scheme() == QL1S("about"))
+ return;
+
+ if (ReKonfig::previewUrls().contains(_tab->url().url()))
+ {
+ // remove site from favorites
+ FavoriteWidget *widget = new FavoriteWidget(_tab, window());
+ connect(widget, SIGNAL(updateIcon()), this, SLOT(updateRightIcons()));
+ widget->showAt(pos);
+ return;
+ }
+
+ // else, add as favorite
+ QStringList urls = ReKonfig::previewUrls();
+ urls << _tab->url().url();
+ ReKonfig::setPreviewUrls(urls);
+
+ QStringList titles = ReKonfig::previewNames();
+ titles << _tab->view()->title();
+ ReKonfig::setPreviewNames(titles);
+
+ // also, save a site snapshot
+ WebSnap *snap = new WebSnap(_tab->url(), this);
+ Q_UNUSED(snap);
+
+ updateRightIcons();
+}
+
+
+void UrlBar::updateRightIconPosition(IconButton *icon, int iconsCount)
+{
+ // NOTE: cannot show a (let's say) 16x16 icon in a 16x16 square.
+ // It needs some margin. It usually is 3, but using 4 (default rekonq icon margin)
+ // seems NOT a big problem and let's us using just one const ;)
+ int iconSize = IconSize(KIconLoader::Small) + c_iconMargin;
+
+ int iconWidth = width() - ((iconSize + c_iconMargin) * iconsCount);
+ int iconHeight = (height() - iconSize) / 2;
+
+ icon->move(iconWidth, iconHeight);
+}
diff --git a/src/urlbar/urlbar.h b/src/urlbar/urlbar.h
new file mode 100644
index 00000000..b2cf44ac
--- /dev/null
+++ b/src/urlbar/urlbar.h
@@ -0,0 +1,156 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2008-2012 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-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+*
+*
+* 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 URLBAR_H
+#define URLBAR_H
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KUrl>
+#include <KLineEdit>
+
+// Qt Includes
+#include <QWeakPointer>
+#include <QToolButton>
+
+// Forward Declarations
+class QWidget;
+class CompletionWidget;
+class WebTab;
+class QTimer;
+
+
+class IconButton : public QToolButton
+{
+ Q_OBJECT
+
+public:
+ IconButton(QWidget *parent = 0);
+
+Q_SIGNALS:
+ void clicked(QPoint);
+
+protected:
+ void mouseReleaseEvent(QMouseEvent *event);
+};
+
+
+// Definitions
+typedef QList<IconButton *> IconButtonPointerList;
+
+
+// ------------------------------------------------------------------------------------
+
+
+class REKONQ_TESTS_EXPORT UrlBar : public KLineEdit
+{
+ Q_OBJECT
+
+public:
+
+ enum icon
+ {
+ KGet = 0x00000001,
+ RSS = 0x00000010,
+ SSL = 0x00000100,
+ BK = 0x00001000,
+ SearchEngine = 0x00010000,
+ Favorite = 0x00100000,
+ AdBlock = 0x01000000
+ };
+
+ explicit UrlBar(QWidget *parent = 0);
+ ~UrlBar();
+
+ void activateSuggestions(bool);
+
+public Q_SLOTS:
+ void setQUrl(const QUrl &url);
+
+ /**
+ * Let us add bookmarks as the major browsers do
+ *
+ */
+ void manageBookmarks();
+
+private Q_SLOTS:
+ void loadRequestedUrl(const KUrl& url, Rekonq::OpenType = Rekonq::CurrentTab);
+
+ void loadFinished();
+
+ void clearRightIcons();
+ void updateRightIcons();
+
+ void detectTypedString(const QString &);
+ void suggest();
+
+ void manageFavorites(QPoint);
+
+ void refreshFavicon();
+
+ void pasteAndGo();
+ void pasteAndSearch();
+ void delSlot();
+ bool isValidURL(QString url);
+
+ /**
+ * Load digited url
+ */
+ void loadDigitedUrl();
+
+protected:
+ void paintEvent(QPaintEvent *event);
+ void keyPressEvent(QKeyEvent *event);
+ void focusInEvent(QFocusEvent *event);
+ void dropEvent(QDropEvent *event);
+ void mouseDoubleClickEvent(QMouseEvent *);
+ void contextMenuEvent(QContextMenuEvent *event);
+ void resizeEvent(QResizeEvent *);
+
+private:
+ /**
+ * Updates right icon position, given its number in the right icons list
+ * and considering rekonq window position/dimension
+ */
+ void updateRightIconPosition(IconButton *, int);
+ IconButton *addRightIcon(UrlBar::icon);
+
+ QWeakPointer<CompletionWidget> _box;
+ WebTab *_tab;
+
+ IconButton *_icon;
+ IconButtonPointerList _rightIconsList;
+
+ QTimer *_suggestionTimer;
+};
+
+
+#endif
diff --git a/src/urlbar/urlsuggester.cpp b/src/urlbar/urlsuggester.cpp
new file mode 100644
index 00000000..52ba7640
--- /dev/null
+++ b/src/urlbar/urlsuggester.cpp
@@ -0,0 +1,397 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 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 "urlsuggester.h"
+#include "urlsuggester.moc"
+
+// Local Includes
+#include "historymanager.h"
+#include "bookmarkmanager.h"
+
+#include "searchengine.h"
+
+// KDE Includes
+#include <KBookmark>
+#include <KService>
+#include <KProtocolInfo>
+
+// Qt Includes
+#include <QByteArray>
+
+
+// NOTE
+// default kurifilter plugin list (at least in my box):
+// 1. "kshorturifilter"
+// 2. "kurisearchfilter"
+// 3. "localdomainurifilter"
+// 4 ."kuriikwsfilter"
+// 5. "fixhosturifilter"
+
+
+// ------------------------------------------------------------------------
+
+
+// NOTE
+// Induce an order in the history items
+bool isHistoryItemRelevant(const HistoryItem &a, const HistoryItem &b)
+{
+ return a.relevance() > b.relevance();
+}
+
+
+// ------------------------------------------------------------------------
+
+
+QRegExp UrlSuggester::_browseRegexp;
+QRegExp UrlSuggester::_searchEnginesRegexp;
+
+
+UrlSuggester::UrlSuggester(const QString &typedUrl)
+ : QObject()
+ , _typedString(typedUrl.trimmed())
+{
+ if (_browseRegexp.isEmpty())
+ {
+ QString protocol = QString("^(%1)").arg(KProtocolInfo::protocols().join("|"));
+
+ QString localhost = QL1S("^localhost");
+
+ QString local = QL1S("^/");
+
+ QString ipv4 = QL1S("^0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])"\
+ "\\.0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])\\.0*([1-9]?\\d|1\\d\\d|2[0-4]\\d|25[0-5])");
+
+ QString ipv6 = QL1S("^([0-9a-fA-F]{4}|0)(\\:([0-9a-fA-F]{4}|0)){7}");
+
+ QString address = QL1S("[\\d\\w-.]+\\.(a[cdefgilmnoqrstuwz]|b[abdefghijmnorstvwyz]|"\
+ "c[acdfghiklmnoruvxyz]|d[ejkmnoz]|e[ceghrstu]|f[ijkmnor]|g[abdefghilmnpqrstuwy]|"\
+ "h[kmnrtu]|i[delmnoqrst]|j[emop]|k[eghimnprwyz]|l[abcikrstuvy]|"\
+ "m[acdghklmnopqrstuvwxyz]|n[acefgilopruz]|om|p[aefghklmnrstwy]|qa|r[eouw]|"\
+ "s[abcdeghijklmnortuvyz]|t[cdfghjkmnoprtvwz]|u[augkmsyz]|v[aceginu]|w[fs]|"\
+ "y[etu]|z[amw]|aero|arpa|biz|com|coop|edu|info|int|gov|local|mil|museum|name|net|org|"\
+ "pro)");
+
+ QString joiner = QL1S(")|(");
+ _browseRegexp = QRegExp(QL1C('(') +
+ protocol + joiner +
+ localhost + joiner +
+ local + joiner +
+ address + joiner +
+ ipv6 + joiner +
+ ipv4 + QL1C(')')
+ );
+ }
+
+ if (_searchEnginesRegexp.isEmpty())
+ {
+ QString reg;
+ QString engineUrl;
+ Q_FOREACH(KService::Ptr s, SearchEngine::favorites())
+ {
+ engineUrl = QRegExp::escape(s->property("Query").toString()).replace(QL1S("\\\\\\{@\\}"), QL1S("[\\d\\w-.]+"));
+ if (reg.isEmpty())
+ reg = QL1C('(') + engineUrl + QL1C(')');
+ else
+ reg = reg + QL1S("|(") + engineUrl + QL1C(')');
+ }
+ _searchEnginesRegexp = QRegExp(reg);
+ }
+}
+
+
+UrlSuggestionList UrlSuggester::orderedSearchItems()
+{
+ if (_typedString.startsWith(QL1S("about:")))
+ {
+ QStringList aboutUrlList;
+ aboutUrlList
+ << QL1S("about:home")
+ << QL1S("about:favorites")
+ << QL1S("about:closedTabs")
+ << QL1S("about:bookmarks")
+ << QL1S("about:history")
+ << QL1S("about:downloads")
+ << QL1S("about:tabs")
+ << QL1S("about:info");
+
+ QStringList aboutUrlResults = aboutUrlList.filter(_typedString, Qt::CaseInsensitive);
+
+ UrlSuggestionList list;
+
+ if (aboutUrlResults.isEmpty())
+ {
+ UrlSuggestionItem info(UrlSuggestionItem::Browse, QL1S("about:info"), QL1S("info"));
+ list << info;
+
+ return list;
+ }
+
+ Q_FOREACH(const QString & urlResult, aboutUrlResults)
+ {
+ QString name = urlResult;
+ name.remove(0, 6);
+ UrlSuggestionItem item(UrlSuggestionItem::Browse, urlResult, name);
+ list << item;
+ }
+
+ return list;
+ }
+
+ //compute lists
+ computeHistory();
+ computeQurlFromUserInput();
+ computeWebSearches();
+ computeBookmarks();
+
+ return orderLists();
+}
+
+
+UrlSuggestionList UrlSuggester::orderLists()
+{
+ // NOTE
+ // The const int here decides the number of proper suggestions, taken from history & bookmarks
+ // You have to add here the "browse & search" options, always available.
+ const int availableEntries = 8;
+
+ bool webSearchFirst = false;
+ // Browse & Search results
+ UrlSuggestionList browseSearch;
+ QString lowerTypedString = _typedString.toLower();
+ if (_browseRegexp.indexIn(lowerTypedString) != -1)
+ {
+ webSearchFirst = true;
+ browseSearch << _webSearches;
+ }
+ else
+ {
+ browseSearch << _webSearches;
+ browseSearch << _qurlFromUserInput;
+ }
+
+
+ // find relevant items (the one you are more probably searching...)
+ UrlSuggestionList relevant;
+
+ // history
+ Q_FOREACH(const UrlSuggestionItem & item, _history)
+ {
+ QString hst = KUrl(item.url).host();
+ if (item.url.startsWith(_typedString)
+ || hst.startsWith(_typedString)
+ || hst.remove("www.").startsWith(_typedString))
+ {
+ relevant << item;
+ _history.removeOne(item);
+ break;
+ }
+ }
+
+ // bookmarks
+ Q_FOREACH(const UrlSuggestionItem & item, _bookmarks)
+ {
+ QString hst = KUrl(item.url).host();
+ if (item.url.startsWith(_typedString)
+ || hst.startsWith(_typedString)
+ || hst.remove("www.").startsWith(_typedString))
+ {
+ relevant << item;
+ _bookmarks.removeOne(item);
+ break;
+ }
+ }
+
+ // decide history & bookmarks number
+ int historyCount = _history.count();
+ int bookmarksCount = _bookmarks.count();
+ int relevantCount = relevant.count();
+
+ const int historyEntries = (availableEntries - relevantCount) / 2;
+ const int bookmarksEntries = availableEntries - relevantCount - historyEntries;
+
+ if (historyCount >= historyEntries && bookmarksCount >= bookmarksEntries)
+ {
+ _history = _history.mid(0, historyEntries);
+ _bookmarks = _bookmarks.mid(0, bookmarksEntries);
+ }
+ else if (historyCount < historyEntries && bookmarksCount >= bookmarksEntries)
+ {
+ if (historyCount + bookmarksCount > availableEntries)
+ {
+ _bookmarks = _bookmarks.mid(0, availableEntries - historyCount);
+ }
+ }
+ else if (historyCount >= historyEntries && bookmarksCount < bookmarksEntries)
+ {
+ if (historyCount + bookmarksCount > availableEntries)
+ {
+ _history = _history.mid(0, availableEntries - bookmarksCount);
+ }
+ }
+
+ // and finally, results
+ UrlSuggestionList list;
+
+ if (webSearchFirst)
+ list << _qurlFromUserInput;
+ list += relevant + browseSearch + _history + _bookmarks;
+ return list;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// PRIVATE ENGINES
+
+
+// QUrl from User Input (easily the best solution... )
+void UrlSuggester::computeQurlFromUserInput()
+{
+ QString url = _typedString;
+ QUrl urlFromUserInput = QUrl::fromUserInput(url);
+ if (urlFromUserInput.isValid())
+ {
+ // ensure http(s) hosts are lower cases
+ if (urlFromUserInput.scheme().startsWith(QL1S("http")))
+ {
+ QString hst = urlFromUserInput.host();
+ urlFromUserInput.setHost(hst.toLower());
+ }
+
+ QString urlString = urlFromUserInput.toString();
+ QString gTitle = i18nc("Browse a website", "Browse");
+ UrlSuggestionItem gItem(UrlSuggestionItem::Browse, urlString, gTitle);
+ _qurlFromUserInput << gItem;
+ }
+}
+
+
+// webSearches
+void UrlSuggester::computeWebSearches()
+{
+ QString query = _typedString;
+ KService::Ptr engine = SearchEngine::fromString(_typedString);
+ if (engine)
+ {
+ query = query.remove(0, _typedString.indexOf(SearchEngine::delimiter()) + 1);
+
+ UrlSuggestionItem item = UrlSuggestionItem(UrlSuggestionItem::Search, SearchEngine::buildQuery(engine, query), query);
+ UrlSuggestionList list;
+ list << item;
+ _webSearches = list;
+ }
+}
+
+
+// history
+void UrlSuggester::computeHistory()
+{
+ QList<HistoryItem> found = HistoryManager::self()->find(_typedString);
+ qSort(found.begin(), found.end(), isHistoryItemRelevant);
+
+ Q_FOREACH(const HistoryItem & i, found)
+ {
+ if (_searchEnginesRegexp.isEmpty() || _searchEnginesRegexp.indexIn(i.url) == -1) //filter all urls that are search engine results
+ {
+ UrlSuggestionItem gItem(UrlSuggestionItem::History, i.url, i.title);
+ _history << gItem;
+ }
+ }
+}
+
+
+// bookmarks
+void UrlSuggester::computeBookmarks()
+{
+ QList<KBookmark> found = BookmarkManager::self()->find(_typedString);
+ Q_FOREACH(const KBookmark & b, found)
+ {
+ UrlSuggestionItem gItem(UrlSuggestionItem::Bookmark, b.url().url(), b.fullText());
+ _bookmarks << gItem;
+ }
+}
+
+
+// opensearch suggestion
+void UrlSuggester::computeSuggestions()
+{
+ // NOTE
+ // This attempt basically cuts out open search suggestions.
+ UrlSuggestionList list;
+ emit suggestionsReady(list, _typedString);
+ return;
+
+// // if a string startsWith /, it is probably a local path
+// // so, no need for suggestions...
+// if (_typedString.startsWith('/') || !rApp->opensearchManager()->isSuggestionAvailable())
+// {
+// UrlSuggestionList list;
+// emit suggestionsReady(list, _typedString);
+// return;
+// }
+//
+// QString query = _typedString;
+// KService::Ptr engine = SearchEngine::fromString(_typedString);
+// if (engine)
+// {
+// query = query.remove(0, _typedString.indexOf(SearchEngine::delimiter()) + 1);
+// setSearchEngine(engine);
+// }
+//
+// connect(rApp->opensearchManager(),
+// SIGNAL(suggestionsReceived(QString,ResponseList)),
+// this,
+// SLOT(suggestionsReceived(QString,ResponseList)));
+//
+// _typedQuery = query;
+// rApp->opensearchManager()->requestSuggestion(query);
+}
+
+
+// void UrlSuggester::suggestionsReceived(const QString &text, const ResponseList &suggestions)
+// {
+// if (text != _typedString)
+// return;
+//
+// UrlSuggestionList sugList;
+// QString urlString;
+// Q_FOREACH(const Response & i, suggestions)
+// {
+// if (text == i.title)
+// continue;
+//
+// urlString = i.url;
+// if (urlString.isEmpty())
+// {
+// urlString = SearchEngine::buildQuery(UrlSuggester::searchEngine(), i.title);
+// }
+//
+// UrlSuggestionItem gItem(UrlSuggestionItem::Suggestion, urlString, i.title, i.description, i.image, i.image_width, i.image_height);
+// sugList << gItem;
+// }
+// emit suggestionsReady(sugList, _typedString);
+// this->deleteLater();
+// }
diff --git a/src/urlbar/urlsuggester.h b/src/urlbar/urlsuggester.h
new file mode 100644
index 00000000..4f20e701
--- /dev/null
+++ b/src/urlbar/urlsuggester.h
@@ -0,0 +1,155 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009-2012 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_SUGGESTER_H
+#define URL_SUGGESTER_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KUrl>
+#include <KService>
+
+// Qt Includes
+#include <QString>
+#include <QList>
+
+
+class UrlSuggestionItem
+{
+public:
+
+ enum types
+ {
+ Undefined = 0x00000000,
+ Search = 0x00000001,
+ Browse = 0x00000010,
+ History = 0x00000100,
+ Bookmark = 0x00001000,
+ Suggestion = 0x00010000
+ };
+
+ int type;
+ QString url;
+ QString title;
+ QString description;
+ QString image;
+ int image_width;
+ int image_height;
+ QString bookmarkPath;
+
+ UrlSuggestionItem(const UrlSuggestionItem &item)
+ : type(item.type)
+ , url(item.url)
+ , title(item.title)
+ , description(item.description)
+ , image(item.image)
+ , image_width(item.image_width)
+ , image_height(item.image_height)
+ {};
+
+ UrlSuggestionItem()
+ : type(UrlSuggestionItem::Undefined)
+ , url(QString())
+ , title(QString())
+ , description(QString())
+ , image(QString())
+ , image_width(0)
+ , image_height(0)
+ {};
+
+ UrlSuggestionItem(const int &_type,
+ const QString &_url,
+ const QString &_title = QString(),
+ const QString &_description = QString(),
+ const QString &_image = QString(),
+ const int &_image_width = 0,
+ const int &_image_height = 0
+ )
+ : type(_type)
+ , url(_url)
+ , title(_title)
+ , description(_description)
+ , image(_image)
+ , image_width(_image_width)
+ , image_height(_image_height)
+ {};
+
+ inline bool operator==(const UrlSuggestionItem &i) const
+ {
+ return i.url == url;//TODO && i.title == title;
+ }
+};
+
+
+typedef QList <UrlSuggestionItem> UrlSuggestionList;
+
+
+// ----------------------------------------------------------------------
+
+
+class HistoryItem;
+
+
+class UrlSuggester : public QObject
+{
+ Q_OBJECT
+
+public:
+ UrlSuggester(const QString &typedUrl);
+
+ UrlSuggestionList orderedSearchItems();
+
+ void computeSuggestions();
+
+Q_SIGNALS:
+ void suggestionsReady(const UrlSuggestionList &, const QString &);
+
+private:
+ void computeWebSearches();
+ void computeHistory();
+ void computeQurlFromUserInput();
+ void computeBookmarks();
+
+ UrlSuggestionList orderLists();
+
+ QString _typedString;
+
+ UrlSuggestionList _webSearches;
+ UrlSuggestionList _qurlFromUserInput;
+ UrlSuggestionList _history;
+ UrlSuggestionList _bookmarks;
+ UrlSuggestionList _suggestions;
+
+ static QRegExp _browseRegexp;
+ static QRegExp _searchEnginesRegexp;
+};
+
+// ------------------------------------------------------------------------------
+
+#endif // URL_SUGGESTER_H
diff --git a/src/urlbar/webshortcutwidget.cpp b/src/urlbar/webshortcutwidget.cpp
new file mode 100644
index 00000000..c6dc3b79
--- /dev/null
+++ b/src/urlbar/webshortcutwidget.cpp
@@ -0,0 +1,163 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Fredy Yanardi <fyanardi@gmail.com>
+* Copyright (C) 2010-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+* Copyright (C) 2012 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 "webshortcutwidget.h"
+#include "webshortcutwidget.moc"
+
+// KDE Includes
+#include <KGlobalSettings>
+#include <KIcon>
+#include <KLocale>
+#include <KServiceTypeTrader>
+
+// Qt Includes
+#include <QSet>
+#include <QLabel>
+#include <QLineEdit>
+#include <QDialogButtonBox>
+#include <QFormLayout>
+
+
+WebShortcutWidget::WebShortcutWidget(QWidget *parent)
+ : QMenu(parent)
+ , m_wsLineEdit(new QLineEdit(this))
+ , m_nameLineEdit(new QLineEdit(this))
+ , m_noteLabel(new QLabel(this))
+{
+ setAttribute(Qt::WA_DeleteOnClose);
+ setFixedWidth(350);
+
+ QFormLayout *layout = new QFormLayout(this);
+ QVBoxLayout *vLay = new QVBoxLayout;
+
+ // Web Search Icon
+ QLabel *webSearchIcon = new QLabel(this);
+ webSearchIcon->setPixmap(KIcon("edit-web-search").pixmap(32, 32));
+
+ // Title
+ QLabel *titleLabel = new QLabel(this);
+ titleLabel->setText("<h4>" + i18n("Add Search Engine") + "</h4>");
+ vLay->addWidget(titleLabel);
+
+ // Name
+ vLay->addWidget(m_nameLineEdit);
+
+ layout->addRow(webSearchIcon, vLay);
+
+ // Shortcuts
+ QLabel *shortcutsLabel = new QLabel(i18n("Shortcuts:"), this);
+ layout->addRow(shortcutsLabel, m_wsLineEdit);
+ connect(m_wsLineEdit, SIGNAL(textChanged(QString)), SLOT(shortcutsChanged(QString)));
+
+ // Note
+ m_noteLabel->setWordWrap(true);
+ layout->addRow(m_noteLabel);
+ m_noteLabel->hide();
+
+ // Ok & Cancel buttons
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, this);
+ connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
+ connect(buttonBox, SIGNAL(rejected()), this, SLOT(close()));
+ layout->addWidget(buttonBox);
+
+ m_providers = KServiceTypeTrader::self()->query("SearchProvider");
+
+ m_wsLineEdit->setFocus();
+}
+
+
+void WebShortcutWidget::showAt(const QPoint &pos)
+{
+ adjustSize();
+
+ QPoint p(pos.x() - width(), pos.y() + 10);
+ move(p);
+ exec();
+}
+
+
+void WebShortcutWidget::show(const KUrl &url, const QString &openSearchName, const QPoint &pos)
+{
+ m_wsLineEdit->clear();
+ m_nameLineEdit->setText(openSearchName);
+ m_url = url;
+ showAt(pos);
+}
+
+
+void WebShortcutWidget::accept()
+{
+ emit webShortcutSet(m_url, m_nameLineEdit->text(), m_wsLineEdit->text());
+
+ // close widget (and destroy it)
+ close();
+}
+
+
+void WebShortcutWidget::shortcutsChanged(const QString& newShorthands)
+{
+ int savedCursorPosition = m_wsLineEdit->cursorPosition();
+ QString normalizedShorthands = QString(newShorthands).replace(QL1C(' '), QL1C(','));
+ m_wsLineEdit->setText(normalizedShorthands);
+ m_wsLineEdit->setCursorPosition(savedCursorPosition);
+
+ QSet<QString> shorthands = normalizedShorthands.split(QL1C(',')).toSet();
+ QString contenderName = "";
+ QString contenderWS = "";
+
+ Q_FOREACH(const QString & shorthand, shorthands)
+ {
+ Q_FOREACH(KService::Ptr provider, m_providers)
+ {
+ if (provider->property("Keys").toStringList().contains(shorthand))
+ {
+ contenderName = provider->property("Name").toString();
+ contenderWS = shorthand;
+ break;
+ }
+ }
+ }
+
+ if (!contenderName.isEmpty())
+ {
+ m_noteLabel->setText(i18n("The shortcut \"%1\" is already assigned to \"%2\".", contenderWS, contenderName));
+ m_noteLabel->setVisible(true);
+ resize(minimumSize().width(), minimumSizeHint().height() + 15);
+ }
+ else
+ {
+ m_noteLabel->clear();
+ bool noteIsVisible = m_noteLabel->isVisible();
+ m_noteLabel->setVisible(false);
+ if (noteIsVisible)
+ {
+ resize(minimumSize());
+ }
+ }
+}
diff --git a/src/urlbar/webshortcutwidget.h b/src/urlbar/webshortcutwidget.h
new file mode 100644
index 00000000..d1291714
--- /dev/null
+++ b/src/urlbar/webshortcutwidget.h
@@ -0,0 +1,76 @@
+/* ============================================================
+*
+* This file is a part of the rekonq project
+*
+* Copyright (C) 2009 by Fredy Yanardi <fyanardi@gmail.com>
+* Copyright (C) 2010-2011 by Lionel Chauvin <megabigbug@yahoo.fr>
+* Copyright (C) 2012 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 WEBSHORTCUTWIDGET_H
+#define WEBSHORTCUTWIDGET_H
+
+
+// Rekonq Includes
+#include "rekonq_defines.h"
+
+// KDE Includes
+#include <KUrl>
+#include <KService>
+
+// Qt Includes
+#include <QMenu>
+
+// Forward Declarations
+class QLabel;
+class QLineEdit;
+class QPushButton;
+
+
+class REKONQ_TESTS_EXPORT WebShortcutWidget : public QMenu
+{
+ Q_OBJECT
+public:
+ WebShortcutWidget(QWidget *parent = 0);
+
+ void show(const KUrl &url, const QString &openSearchName, const QPoint &pos);
+
+private Q_SLOTS:
+ void accept();
+ void shortcutsChanged(const QString& newShorthands);
+
+Q_SIGNALS:
+ void webShortcutSet(const KUrl &url, const QString &openSearchName, const QString &webShortcut);
+
+private:
+ QLineEdit *m_wsLineEdit;
+ QLineEdit *m_nameLineEdit;
+ QLabel *m_noteLabel;
+
+ KService::List m_providers;
+ KUrl m_url;
+
+ void showAt(const QPoint &pos);
+};
+
+#endif // WEBSHORTCUTWIDGET_H
+
diff --git a/src/webtab/webtab.cpp b/src/webtab/webtab.cpp
index 2dce52d4..27e711fd 100644
--- a/src/webtab/webtab.cpp
+++ b/src/webtab/webtab.cpp
@@ -168,6 +168,24 @@ bool WebTab::isPageLoading()
}
+bool WebTab::hasRSSInfo()
+{
+ QWebElementCollection col = page()->mainFrame()->findAllElements("link[type=\"application/rss+xml\"]");
+ col.append(page()->mainFrame()->findAllElements("link[type=\"application/atom+xml\"]"));
+ if (col.count() != 0)
+ return true;
+
+ return false;
+}
+
+
+bool WebTab::hasNewSearchEngine()
+{
+ QWebElement e = page()->mainFrame()->findFirstElement(QL1S("head >link[rel=\"search\"][ type=\"application/opensearchdescription+xml\"]"));
+ return !e.isNull(); // FIXME && !rApp->opensearchManager()->engineExists(extractOpensearchUrl(e));
+}
+
+
void WebTab::createWalletBar(const QString &key, const QUrl &url)
{
// check if the url is in the wallet blacklist
diff --git a/src/webtab/webtab.h b/src/webtab/webtab.h
index f875071d..5984ea53 100644
--- a/src/webtab/webtab.h
+++ b/src/webtab/webtab.h
@@ -70,6 +70,9 @@ public:
KUrl url();
+ bool hasRSSInfo();
+ bool hasNewSearchEngine();
+
void createPreviewSelectorBar(int index);
void hideSelectorBar();