diff options
| author | megabigbug <megabigbug@arrakis.(none)> | 2010-03-29 18:36:34 +0200 | 
|---|---|---|
| committer | megabigbug <megabigbug@arrakis.(none)> | 2010-03-29 18:36:34 +0200 | 
| commit | 3be011352dc0f354723269cbc8f07f4d5fbcc3d6 (patch) | |
| tree | be795a064f8723c0d58448d77094beebb536f5e6 | |
| parent | Merge branch 'master' of git://gitorious.org/rekonq/mainline (diff) | |
| parent | rekonq 0.4.57 (diff) | |
| download | rekonq-3be011352dc0f354723269cbc8f07f4d5fbcc3d6.tar.xz | |
Merge branch 'master' of git://gitorious.org/rekonq/mainline
| -rw-r--r-- | CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/bookmarks/bookmarksmanager.cpp | 18 | ||||
| -rw-r--r-- | src/bookmarks/bookmarksmanager.h | 11 | ||||
| -rw-r--r-- | src/bookmarks/bookmarkspanel.cpp | 408 | ||||
| -rw-r--r-- | src/bookmarks/bookmarkspanel.h | 32 | ||||
| -rw-r--r-- | src/bookmarks/bookmarkstreemodel.cpp | 283 | ||||
| -rw-r--r-- | src/bookmarks/bookmarkstreemodel.h | 52 | ||||
| -rw-r--r-- | src/history/historymodels.cpp | 8 | ||||
| -rw-r--r-- | src/history/historypanel.cpp | 91 | ||||
| -rw-r--r-- | src/history/historypanel.h | 10 | ||||
| -rw-r--r-- | src/mainview.cpp | 3 | ||||
| -rw-r--r-- | src/mainwindow.cpp | 6 | ||||
| -rw-r--r-- | src/urlbar/completionwidget.cpp | 242 | ||||
| -rw-r--r-- | src/urlbar/completionwidget.h | 77 | ||||
| -rw-r--r-- | src/urlbar/lineedit.cpp | 4 | ||||
| -rw-r--r-- | src/urlbar/lineedit.h | 12 | ||||
| -rw-r--r-- | src/urlbar/listitem.cpp | 173 | ||||
| -rw-r--r-- | src/urlbar/listitem.h | 59 | ||||
| -rw-r--r-- | src/urlbar/urlbar.cpp | 208 | ||||
| -rw-r--r-- | src/urlbar/urlbar.h | 28 | ||||
| -rw-r--r-- | src/urlbar/urlresolver.cpp | 177 | ||||
| -rw-r--r-- | src/urlbar/urlresolver.h | 72 | ||||
| -rw-r--r-- | src/urltreeview.cpp | 195 | ||||
| -rw-r--r-- | src/urltreeview.h | 69 | 
25 files changed, 1964 insertions, 280 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d41552a4..5fa7cf4e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ PROJECT( rekonq )  # Informations to update before to release this package.  # rekonq info -SET(REKONQ_VERSION "0.4.55" ) +SET(REKONQ_VERSION "0.4.57" )  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version.h ) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bc4e91c8..a68faa59 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,6 +19,7 @@ SET( rekonq_KDEINIT_SRCS      protocolhandler.cpp      sessionmanager.cpp      tabbar.cpp +    urltreeview.cpp      walletbar.cpp      webinspectorpanel.cpp      webpage.cpp @@ -48,6 +49,9 @@ SET( rekonq_KDEINIT_SRCS      #----------------------------------------      urlbar/urlbar.cpp      urlbar/lineedit.cpp +    urlbar/completionwidget.cpp +    urlbar/urlresolver.cpp +    urlbar/listitem.cpp  ) diff --git a/src/bookmarks/bookmarksmanager.cpp b/src/bookmarks/bookmarksmanager.cpp index cfe26a55..89e39ef8 100644 --- a/src/bookmarks/bookmarksmanager.cpp +++ b/src/bookmarks/bookmarksmanager.cpp @@ -161,7 +161,12 @@ BookmarkProvider::BookmarkProvider(QObject *parent)          , m_actionCollection(new KActionCollection(this))          , m_bookmarkMenu(0)          , m_bookmarkToolBar(0) +        , m_completion(0)  { +    // take care of the completion object +    m_completion = new KCompletion; +    m_completion->setOrder( KCompletion::Weighted ); +      KUrl bookfile = KUrl("~/.kde/share/apps/konqueror/bookmarks.xml");  // share konqueror bookmarks      if (!QFile::exists(bookfile.path())) @@ -178,7 +183,9 @@ BookmarkProvider::BookmarkProvider(QObject *parent)              bookfile = KUrl(bookmarksPath);          }      } -    m_manager = KBookmarkManager::managerForExternalFile(bookfile.path()); +    // A workaround to avoid a long delay between the two changed signals of the bookmark manager +    m_manager = KBookmarkManager::managerForFile(bookfile.path(), "rekonq"); +          connect(m_manager, SIGNAL(changed(const QString &, const QString &)),              this, SLOT(slotBookmarksChanged(const QString &, const QString &))); @@ -220,6 +227,7 @@ void BookmarkProvider::slotBookmarksChanged(const QString &group, const QString          return;      m_bookmarkToolBar->clear(); // FIXME CRASH +    m_completion->clear();      KBookmark bookmark = toolBarGroup.first();      while (!bookmark.isNull()) @@ -285,7 +293,8 @@ KAction *BookmarkProvider::fillBookmarkBar(const KBookmark &bookmark)          return a;      }      else -    { +    {         +        m_completion->addItem(bookmark.url().path());          return new KBookmarkAction(bookmark, m_owner, this);      }  } @@ -295,3 +304,8 @@ KBookmarkGroup BookmarkProvider::rootGroup()  {      return m_manager->root();  } + +KCompletion *BookmarkProvider::completionObject() const +{ +    return m_completion; +} diff --git a/src/bookmarks/bookmarksmanager.h b/src/bookmarks/bookmarksmanager.h index d4afb997..18ff3ef0 100644 --- a/src/bookmarks/bookmarksmanager.h +++ b/src/bookmarks/bookmarksmanager.h @@ -39,6 +39,7 @@  // KDE Includes  #include <KBookmarkOwner> +#include <KCompletion>  // Forward Declarations  class BookmarkProvider; @@ -210,7 +211,14 @@ public:       */      KBookmarkGroup rootGroup(); -	KBookmarkManager *bookmarkManager() { return m_manager; } +    KBookmarkManager *bookmarkManager() { return m_manager; } +    BookmarkOwner *bookmarkOwner() { return m_owner; } +     +    /** +    * @returns the KCompletion object. +    */ +    KCompletion *completionObject() const; +  signals:      /**      * @short This signal is emitted when an url has to be loaded @@ -245,6 +253,7 @@ private:      KActionCollection *m_actionCollection;      BookmarkMenu *m_bookmarkMenu;      KToolBar *m_bookmarkToolBar; +    KCompletion *m_completion;  };  #endif diff --git a/src/bookmarks/bookmarkspanel.cpp b/src/bookmarks/bookmarkspanel.cpp index 48ca6537..2f530c6c 100644 --- a/src/bookmarks/bookmarkspanel.cpp +++ b/src/bookmarks/bookmarkspanel.cpp @@ -29,6 +29,7 @@  #include "bookmarkspanel.moc"  // Local Includes +#include "bookmarksmanager.h"  #include "bookmarkstreemodel.h"  #include "bookmarksproxy.h" @@ -44,12 +45,20 @@  // KDE includes  #include <KLineEdit>  #include <KLocalizedString> +#include <KAction> +#include <KMenu> +#include <KBookmarkDialog> +#include <KMessageBox>  BookmarksPanel::BookmarksPanel(const QString &title, QWidget *parent, Qt::WindowFlags flags) -    : QDockWidget(title, parent, flags) +    : QDockWidget(title, parent, flags), +    m_treeView(new UrlTreeView(this)), +    m_ac(new KActionCollection(this)), +    m_loadingState(false)  {      setup(); +    setupActions();      setShown(ReKonfig::showBookmarksPanel());  } @@ -60,13 +69,6 @@ BookmarksPanel::~BookmarksPanel()  } -void BookmarksPanel::bookmarkActivated( const QModelIndex &index ) -{ -    if( index.isValid() ) -        emit openUrl( qVariantValue< KUrl >( index.data( Qt::UserRole ) ) ); -} - -  void BookmarksPanel::setup()  {      setObjectName("bookmarksPanel"); @@ -85,19 +87,20 @@ void BookmarksPanel::setup()      searchLabel->setBuddy( search );      // setup tree view -    QTreeView *treeView = new QTreeView(ui); -    treeView->setUniformRowHeights(true); -    treeView->setSelectionBehavior(QAbstractItemView::SelectRows); -    treeView->setTextElideMode(Qt::ElideMiddle); -    treeView->setAlternatingRowColors(true); -    treeView->header()->hide(); -    treeView->setRootIsDecorated( false ); +    m_treeView->setUniformRowHeights(true); +    m_treeView->setTextElideMode(Qt::ElideMiddle); +    m_treeView->setAlternatingRowColors(true); +    m_treeView->header()->hide(); +    m_treeView->setDragEnabled(true); +    m_treeView->setAutoExpandDelay(750); +    m_treeView->setDefaultDropAction(Qt::MoveAction); +    m_treeView->viewport()->setAcceptDrops(true);      // put everything together      QVBoxLayout *vBoxLayout = new QVBoxLayout;      vBoxLayout->setContentsMargins(0, 0, 0, 0);      vBoxLayout->addLayout(searchLayout); -    vBoxLayout->addWidget(treeView); +    vBoxLayout->addWidget(m_treeView);      // add it to the UI      ui->setLayout(vBoxLayout); @@ -106,8 +109,375 @@ void BookmarksPanel::setup()      BookmarksTreeModel *model = new BookmarksTreeModel( this );      BookmarksProxy *proxy = new BookmarksProxy(ui);      proxy->setSourceModel( model ); -    treeView->setModel( proxy ); +    m_treeView->setModel( proxy ); + +    connect(m_treeView, SIGNAL(contextMenuItemRequested(const QPoint &)), this, SLOT(contextMenuBk(const QPoint &))); +    connect(m_treeView, SIGNAL(contextMenuGroupRequested(const QPoint &)), this, SLOT(contextMenuBkGroup(const QPoint &))); +    connect(m_treeView, SIGNAL(contextMenuEmptyRequested(const QPoint &)), this, SLOT(contextMenuBlank(const QPoint &))); +    connect(m_treeView, SIGNAL(delKeyPressed()), this, SLOT(deleteBookmark())); +    connect(m_treeView, SIGNAL(collapsed(const QModelIndex &)), this, SLOT(onCollapse(const QModelIndex &))); +    connect(m_treeView, SIGNAL(expanded(const QModelIndex &)), this, SLOT(onExpand(const QModelIndex &))); +    connect(search, SIGNAL(textChanged(const QString &)), proxy, SLOT(setFilterFixedString(const QString &))); +    loadFoldedState(); +} + + +void BookmarksPanel::onCollapse(const QModelIndex &index) +{ +    if(m_loadingState) +        return; + +    KBookmark bookmark = bookmarkForIndex(index); +    bookmark.internalElement().setAttribute("folded", "yes"); +    emit saveOnlyRequested(); +} + + +void BookmarksPanel::onExpand(const QModelIndex &index) +{ +    if(m_loadingState) +        return; + +    KBookmark bookmark = bookmarkForIndex(index); +    bookmark.internalElement().setAttribute("folded", "no"); +    emit saveOnlyRequested(); +} + + +void BookmarksPanel::loadFoldedState() +{ +    m_loadingState = true; +    loadFoldedState(QModelIndex()); +    m_loadingState = false; +} + + +void BookmarksPanel::loadFoldedState(const QModelIndex &root) +{ + +    int count = m_treeView->model()->rowCount(root); +    QModelIndex index; + +    for(int i = 0; i < count; i++) +    { +        index = m_treeView->model()->index(i, 0, root); +        if(index.isValid() && bookmarkForIndex(index).isGroup()) +        { +            m_treeView->setExpanded(index, bookmarkForIndex(index).toGroup().isOpen()); +            loadFoldedState(index); +        } +    } +} + + +void BookmarksPanel::setupActions() +{ +    KAction* action; + +    action = new KAction(KIcon("tab-new"), i18n("Open"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInCurrentTab())); +    m_ac->addAction("open", action); + +    action = new KAction(KIcon("tab-new"), i18n("Open in New Tab"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewTab())); +    m_ac->addAction("open_tab", action); + +    action = new KAction(KIcon("window-new"), i18n("Open in New Window"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewWindow())); +    m_ac->addAction("open_window", action); + +    action = new KAction(KIcon("bookmark-new"), i18n("Add Bookmark Here"), this); +    connect(action, SIGNAL(triggered()), this, SLOT(bookmarkCurrentPage())); +    m_ac->addAction("bookmark_page", action); + +    action = new KAction(KIcon("folder-new"), i18n("New Bookmark Folder"), this); +    connect(action, SIGNAL(triggered()), this, SLOT(newBookmarkGroup())); +    m_ac->addAction("folder_new", action); + +    action = new KAction(KIcon("edit-clear"), i18n("New Separator"), this); +    connect(action, SIGNAL(triggered()), this, SLOT(newSeparator())); +    m_ac->addAction("separator_new", action); + +    action = new KAction(KIcon("edit-copy"), i18n("Copy Link Address"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(copyToClipboard())); +    m_ac->addAction("copy", action); + +    action = new KAction(KIcon("edit-delete"), i18n("Delete Bookmark"), this); +    connect(action, SIGNAL(triggered()), this, SLOT(deleteBookmark())); +    m_ac->addAction("delete", action); + +    action = new KAction(KIcon("configure"), i18n("Properties"), this); +    connect(action, SIGNAL(triggered()), this, SLOT(editBookmark())); +    m_ac->addAction("properties", action); + +    action = new KAction(KIcon("tab-new"), i18n("Open Folder in Tabs"), this); +    connect(action, SIGNAL(triggered()), this, SLOT(openFolderInTabs())); +    m_ac->addAction("open_all", action); +} + + +KBookmark BookmarksPanel::bookmarkForIndex(const QModelIndex &index) +{ +    if(!index.isValid()) +        return KBookmark(); + +    const QAbstractProxyModel* proxyModel = dynamic_cast< const QAbstractProxyModel* >(index.model()); +    QModelIndex originalIndex = proxyModel->mapToSource(index); + +    BtmItem *node = static_cast< BtmItem* >( originalIndex.internalPointer() ); +    return node->getBkm(); +} + + +void BookmarksPanel::contextMenuBk(const QPoint &pos) +{ +    QPoint position = m_treeView->mapToGlobal(pos); +    QModelIndex index = m_treeView->indexAt(pos); +    if(!index.isValid() || m_loadingState) +        return; + +    KBookmark selected = bookmarkForIndex(index); + +    if(selected.isGroup()) +    { +        contextMenuBkGroup(pos, true); +        return; +    } + +    if(selected.isSeparator()) +    { +        contextMenuSeparator(pos); +        return; +    } + +    KMenu *menu = new KMenu(this); + +    menu->addAction(m_ac->action("open")); +    menu->addAction(m_ac->action("open_tab")); +    menu->addAction(m_ac->action("open_window")); + +    menu->addSeparator(); + +    menu->addAction(m_ac->action("bookmark_page")); +    menu->addAction(m_ac->action("folder_new")); +    menu->addAction(m_ac->action("separator_new")); + +    menu->addSeparator(); + +    menu->addAction(m_ac->action("copy")); + +    menu->addSeparator(); + +    menu->addAction(m_ac->action("delete")); +    menu->addAction(m_ac->action("properties")); + +    menu->popup(position); +} + + +void BookmarksPanel::contextMenuBkGroup(const QPoint &pos, bool emptyGroup) +{ +    if(m_loadingState) +        return; + +    QPoint position = m_treeView->mapToGlobal(pos); +    KMenu *menu = new KMenu(this); + +    if(!emptyGroup) +    { +        menu->addAction(m_ac->action("open_all")); +        menu->addSeparator(); +    } + +    menu->addAction(m_ac->action("bookmark_page")); +    menu->addAction(m_ac->action("folder_new")); +    menu->addAction(m_ac->action("separator_new")); + +    menu->addSeparator(); + +    menu->addAction(m_ac->action("delete")); +    menu->addAction(m_ac->action("properties")); + +    menu->popup(position); +} + + +void BookmarksPanel::contextMenuSeparator(const QPoint &pos) +{ +    QPoint position = m_treeView->mapToGlobal(pos); +    KMenu *menu = new KMenu(this); + +    menu->addAction(m_ac->action("bookmark_page")); +    menu->addAction(m_ac->action("folder_new")); +    menu->addAction(m_ac->action("separator_new")); + +    menu->addSeparator(); + +    menu->addAction(m_ac->action("delete")); + +    menu->popup(position); +} + + +void BookmarksPanel::contextMenuBlank(const QPoint &pos) +{ +    QPoint position = m_treeView->mapToGlobal(pos); +    KMenu *menu = new KMenu(this); + +    menu->addAction(m_ac->action("bookmark_page")); +    menu->addAction(m_ac->action("folder_new")); +    menu->addAction(m_ac->action("separator_new")); + +    menu->popup(position); +} + + +void BookmarksPanel::deleteBookmark() +{ +    QModelIndex index = m_treeView->currentIndex(); +    if(!index.isValid()) +        return; + +    KBookmark bm = bookmarkForIndex(index); +    bool folder = bm.isGroup(); + +    if (KMessageBox::warningContinueCancel( +            QApplication::activeWindow(), +            folder ? i18n("Are you sure you wish to remove the bookmark folder\n\"%1\"?", bm.text()) +                   : i18n("Are you sure you wish to remove the bookmark\n\"%1\"?", bm.text()), +            folder ? i18n("Bookmark Folder Deletion") +                   : i18n("Bookmark Deletion"), +            KStandardGuiItem::del()) +          != KMessageBox::Continue +        ) +        return; + + +    bm.parentGroup().deleteBookmark(bm); +    Application::instance()->bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksPanel::editBookmark() +{ +    QModelIndex index = m_treeView->currentIndex(); +    if(!index.isValid()) +        return; + +    KBookmark selected = bookmarkForIndex(index); + +    KBookmarkDialog *dialog = Application::bookmarkProvider()->bookmarkOwner()->bookmarkDialog(Application::bookmarkProvider()->bookmarkManager(), QApplication::activeWindow()); +    dialog->editBookmark(selected); +    delete dialog; +} + + +void BookmarksPanel::openFolderInTabs() +{ +    QModelIndex index = m_treeView->currentIndex(); +    if(!index.isValid() || !bookmarkForIndex(index).isGroup()) +        return; + +    QList<KUrl> allChild = bookmarkForIndex(index).toGroup().groupUrlList(); + +    if(allChild.length() > 8) // 8, a good choice ? +    { +        if(!(KMessageBox::warningContinueCancel(this, i18n("You are about to open a lot of tabs : %1\nAre you sure  ?", QString::number(allChild.length()))) == KMessageBox::Continue)) +            return; +    } + +    for(int i = 0; i < allChild.length(); i++) +        emit openUrl(allChild.at(i).url(), Rekonq::SettingOpenTab); +} + + +void BookmarksPanel::newBookmarkGroup() +{ +    QModelIndex index = m_treeView->currentIndex(); +    KBookmark newBk; + +    KBookmarkDialog *dialog = Application::bookmarkProvider()->bookmarkOwner()->bookmarkDialog(Application::bookmarkProvider()->bookmarkManager(), QApplication::activeWindow()); + +    if(index.isValid()) +    { +        KBookmark selected = bookmarkForIndex(index); + +        if(selected.isGroup()) +        { +            newBk = dialog->createNewFolder("New folder", selected); +        } + +        else +        { +            newBk = dialog->createNewFolder("New folder", selected.parentGroup()); +            selected.parentGroup().moveBookmark(newBk, selected); +            Application::bookmarkProvider()->bookmarkManager()->emitChanged(); +        }  +    } + +    else +    { +        dialog->createNewFolder("New folder"); +    } + +    delete dialog; +} + + +void BookmarksPanel::newSeparator() +{ +    QModelIndex index = m_treeView->currentIndex(); + +    KBookmark selected; +    KBookmark newBk; + +    if(index.isValid()) +    { +        selected = bookmarkForIndex(index); + +        if(selected.isGroup()) +            newBk = selected.toGroup().createNewSeparator(); +        else +            newBk = selected.parentGroup().createNewSeparator(); +    } + +    else +    { +        newBk = Application::bookmarkProvider()->rootGroup().createNewSeparator(); +    } + +    KBookmarkGroup parent = newBk.parentGroup(); +    newBk.setIcon(("edit-clear")); +    parent.addBookmark(newBk); + +    if(index.isValid()) +        parent.moveBookmark(newBk, selected); + +    Application::bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksPanel::bookmarkCurrentPage() +{ +    QModelIndex index = m_treeView->currentIndex(); +    KBookmarkGroup parent = Application::bookmarkProvider()->rootGroup(); + +    if(index.isValid()) +    { +        KBookmark selected = bookmarkForIndex(index); +        parent = selected.parentGroup(); + +        if(selected.isGroup()) +            parent = selected.toGroup(); + +        KBookmark newBk = parent.addBookmark(Application::bookmarkProvider()->bookmarkOwner()->currentTitle(), KUrl(Application::bookmarkProvider()->bookmarkOwner()->currentUrl()), "text-html"); +        parent.moveBookmark(newBk, selected.parentGroup().previous(selected)); +    } + +    else +    { +       parent.addBookmark(Application::bookmarkProvider()->bookmarkOwner()->currentTitle(), KUrl(Application::bookmarkProvider()->bookmarkOwner()->currentUrl()), "text-html"); +    } -    connect(search, SIGNAL(textChanged(QString)), proxy, SLOT(setFilterFixedString(QString))); -    connect(treeView, SIGNAL( activated(QModelIndex) ), this, SLOT( bookmarkActivated(QModelIndex) ) ); +    Application::bookmarkProvider()->bookmarkManager()->emitChanged();  } diff --git a/src/bookmarks/bookmarkspanel.h b/src/bookmarks/bookmarkspanel.h index f5376d98..f8528b71 100644 --- a/src/bookmarks/bookmarkspanel.h +++ b/src/bookmarks/bookmarkspanel.h @@ -31,10 +31,16 @@  // Local Includes  #include "rekonqprivate_export.h" +#include "application.h" +#include "urltreeview.h"  // Qt Includes  #include <QDockWidget> +// KDE Includes +#include <KBookmark> +#include <KActionCollection> +  // Forward Declarations  class KUrl;  class QModelIndex; @@ -49,13 +55,35 @@ public:      ~BookmarksPanel();  signals: -    void openUrl(const KUrl &); +    void openUrl(const KUrl &, const Rekonq::OpenType &); +    void itemHovered(const QString &); +    void saveOnlyRequested();  private slots: -    void bookmarkActivated( const QModelIndex &index ); +    void contextMenuBk(const QPoint &pos); +    void contextMenuBkGroup(const QPoint &pos, const bool emptyGroup = false); +    void contextMenuBlank(const QPoint &pos); +    void deleteBookmark(); +    void openFolderInTabs(); +    void editBookmark(); +    void newBookmarkGroup(); +    void newSeparator(); +    void onCollapse(const QModelIndex &index); +    void onExpand(const QModelIndex &index); +    void bookmarkCurrentPage(); +    void loadFoldedState(const QModelIndex &root); +    void loadFoldedState(); +  private:      void setup(); +    void setupActions(); +    void contextMenuSeparator(const QPoint &pos); +    KBookmark bookmarkForIndex(const QModelIndex &index); + +    UrlTreeView *m_treeView; +    KActionCollection *m_ac; +    bool m_loadingState;  };  #endif // BOOKMARKSPANEL_H diff --git a/src/bookmarks/bookmarkstreemodel.cpp b/src/bookmarks/bookmarkstreemodel.cpp index 95e5ad41..836401a6 100644 --- a/src/bookmarks/bookmarkstreemodel.cpp +++ b/src/bookmarks/bookmarkstreemodel.cpp @@ -33,94 +33,112 @@  #include "application.h"  #include "bookmarksmanager.h" +// Qt Includes +#include <QMimeData> +  // KDE includes  #include <KBookmarkGroup>  #include <KLocalizedString> -class BookmarksTreeModel::BtmItem +BtmItem::BtmItem(const KBookmark &bm) +    : m_parent(0) +    , m_kbm(bm)  { -public: -    BtmItem(const KBookmark &bm) -        : m_parent(0) -        , m_kbm(bm) -    { -    } -     -     -    ~BtmItem() -    { -        qDeleteAll(m_children); -    } +} -    QVariant data( int role = Qt::DisplayRole ) const -    { -        if( m_kbm.isNull() ) -            return QVariant();  // should only happen for root item +BtmItem::~BtmItem() +{ +    qDeleteAll(m_children); +} -        if( role == Qt::DisplayRole ) -            return m_kbm.text(); -        if( role == Qt::DecorationRole ) -            return KIcon( m_kbm.icon() ); -        if( role == Qt::UserRole ) -            return m_kbm.url(); -        return QVariant(); +QVariant BtmItem::data( int role ) const +{ +    if( m_kbm.isNull() ) +        return QVariant();  // should only happen for root item + +    if( role == Qt::DisplayRole ) +        return m_kbm.text(); +    if( role == Qt::DecorationRole ) +        return KIcon( m_kbm.icon() ); +    if( role == Qt::UserRole ) +        return m_kbm.url(); +    if( role == Qt::ToolTipRole) +    { +        QString tooltip = ""; +	 +        if(!m_kbm.text().isEmpty()) +	{ +            tooltip += m_kbm.text(); +	} +        if(m_kbm.isGroup()) +	{ +            tooltip += " [" + QString::number(childCount()) + " " + i18n("Items") + "]"; +	} +        if(!m_kbm.url().url().isEmpty()) +        { +            if(!tooltip.isEmpty()) +                tooltip += "\n"; +            tooltip += m_kbm.url().url(); +        } +        return tooltip;      } +    return QVariant(); +} -    int row() const -    { -        if(m_parent) -            return m_parent->m_children.indexOf( const_cast< BtmItem* >( this ) ); -        return 0; -    } +int BtmItem::row() const +{ +    if(m_parent) +        return m_parent->m_children.indexOf( const_cast< BtmItem* >( this ) ); +    return 0; +} -    int childCount() const -    { -        return m_children.count(); -    } +int BtmItem::childCount() const +{ +    return m_children.count(); +} -    BtmItem* child( int n ) -    { -        Q_ASSERT(n>=0); -        Q_ASSERT(n<childCount()); -        return m_children.at(n); -    } +BtmItem* BtmItem::child( int n ) +{ +    Q_ASSERT(n>=0); +    Q_ASSERT(n<childCount()); +    return m_children.at(n); +} -    BtmItem* parent() const -    { -        return m_parent; -    } +BtmItem* BtmItem::parent() const +{ +    return m_parent; +} -    void appendChild(BtmItem *child) -    { -        if( !child ) -            return; -        child->m_parent = this; -        m_children << child; -    } +void BtmItem::appendChild(BtmItem *child) +{ +    if( !child ) +        return; +    child->m_parent = this; +    m_children << child; +} -    void clear() -    { -        qDeleteAll(m_children); -        m_children.clear(); -    } -private: -    BtmItem *m_parent; -    QList< BtmItem* > m_children; -    KBookmark m_kbm; -}; +void BtmItem::clear() +{ +    qDeleteAll(m_children); +    m_children.clear(); +} +KBookmark BtmItem::getBkm() const +{ +    return m_kbm; +}  // ------------------------------------------------------------------------------------- @@ -130,8 +148,9 @@ BookmarksTreeModel::BookmarksTreeModel(QObject *parent)      , m_root(0)  {      resetModel(); -    connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( changed(QString,QString) ), this, SLOT( bookmarksChanged(QString) ) ); -    connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( bookmarksChanged(QString) ), this, SLOT( bookmarksChanged(QString) ) ); +    connect( this, SIGNAL(bookmarksUpdated()), parent, SLOT(loadFoldedState())); +    connect( Application::bookmarkProvider()->bookmarkManager(), SIGNAL( changed(QString,QString) ), this, SLOT( bookmarksChanged() ) ); +    connect( parent, SIGNAL(saveOnlyRequested()), this, SLOT(saveOnly()) );  } @@ -179,8 +198,17 @@ QVariant BookmarksTreeModel::headerData(int section, Qt::Orientation orientation  Qt::ItemFlags BookmarksTreeModel::flags(const QModelIndex &index) const  { -    Q_UNUSED(index) -    return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +    Qt::ItemFlags flags = QAbstractItemModel::flags(index); +     +    if(!index.isValid()) +        return flags | Qt::ItemIsDropEnabled; + +    flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; + +    if(bookmarkForIndex(index).isGroup()) +        flags |= Qt::ItemIsDropEnabled; +     +    return flags;  } @@ -256,32 +284,10 @@ QVariant BookmarksTreeModel::data(const QModelIndex &index, int role) const  } -void BookmarksTreeModel::bookmarksChanged( const QString &groupAddress ) +void BookmarksTreeModel::bookmarksChanged()  { -    if( groupAddress.isEmpty() ) -    { -        resetModel(); -        return; -    } - -    BtmItem *node = m_root; -    QModelIndex nodeIndex; - -    QStringList indexChain( groupAddress.split( '/', QString::SkipEmptyParts) ); -    foreach( const QString &sIndex, indexChain )  -    { -        bool ok; -        int i = sIndex.toInt( &ok ); -        if( !ok ) -            break; - -        if( i < 0 || i >= node->childCount() ) -            break; - -        node = node->child( i ); -        nodeIndex = index( i, 0, nodeIndex ); -    } -    emit dataChanged( index( 0, 0, nodeIndex ), index( node->childCount(), 0, nodeIndex ) ); +    resetModel(); +    emit bookmarksUpdated();  } @@ -322,3 +328,100 @@ void BookmarksTreeModel::populate( BtmItem *node, KBookmarkGroup bmg)          bm = bmg.next( bm );      }  } + + +KBookmark BookmarksTreeModel::bookmarkForIndex(const QModelIndex index) const +{ +    return static_cast<BtmItem*>(index.internalPointer())->getBkm(); +} + + +void BookmarksTreeModel::saveOnly() +{ +    disconnect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL(changed(QString,QString)), this, SLOT(bookmarksChanged())); +    connect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL(changed(QString,QString)), this, SLOT(reconnectManager())); +    Application::bookmarkProvider()->bookmarkManager()->emitChanged(); +} + + +void BookmarksTreeModel::reconnectManager() +{ +    connect(Application::bookmarkProvider()->bookmarkManager(), SIGNAL( changed(QString,QString) ), this, SLOT(bookmarksChanged())); +} + + +Qt::DropActions BookmarksTreeModel::supportedDropActions () const +{ +    return Qt::MoveAction; +} + + +QStringList BookmarksTreeModel::mimeTypes () const +{ +    return KBookmark::List::mimeDataTypes(); +} + + +QMimeData* BookmarksTreeModel::mimeData( const QModelIndexList & indexes ) const +{ +    QMimeData *mimeData = new QMimeData; + +    QByteArray addresse = bookmarkForIndex(indexes.first()).address().toLatin1(); +    mimeData->setData( "application/rekonq-bookmark", addresse); +    bookmarkForIndex(indexes.first()).populateMimeData(mimeData); + +    return mimeData; +} + + +bool BookmarksTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex & parent) +{ +    if(action == Qt::MoveAction) +    { +        if(data->hasFormat("application/rekonq-bookmark")) +        { +            QByteArray addresses = data->data("application/rekonq-bookmark"); +            KBookmark bookmark = Application::bookmarkProvider()->bookmarkManager()->findByAddress(QString::fromLatin1(addresses.data())); + +            QModelIndex destIndex = index(row, column, parent); + +            KBookmark dropDestBookmark; +            if(destIndex.isValid()) +                dropDestBookmark = bookmarkForIndex(destIndex); + +            KBookmarkGroup root = Application::bookmarkProvider()->rootGroup(); +            if(parent.isValid()) +                root = bookmarkForIndex(parent).toGroup(); + +            if(!destIndex.isValid()) +            { +                if(!parent.isValid()) // Drop into a blank area +                { +                    Application::bookmarkProvider()->rootGroup().deleteBookmark(bookmark); +                    Application::bookmarkProvider()->rootGroup().addBookmark(bookmark); +                } +                else // Drop at the last item of the group or directly on the main item of the group +                { +                    root.deleteBookmark(bookmark); +                    root.addBookmark(bookmark); +                } +            } + +            else +            { +                if(row == -1) +                { +                    root.deleteBookmark(bookmark); +                    root.addBookmark(bookmark); +                } +                else // A classic drop +                { +                    root.moveBookmark(bookmark, root.previous(dropDestBookmark)); +                } +            } + +            Application::bookmarkProvider()->bookmarkManager()->emitChanged(root); +        } +    } +    return true; +} diff --git a/src/bookmarks/bookmarkstreemodel.h b/src/bookmarks/bookmarkstreemodel.h index dfad52ba..b312ab2d 100644 --- a/src/bookmarks/bookmarkstreemodel.h +++ b/src/bookmarks/bookmarkstreemodel.h @@ -38,6 +38,26 @@  // Qt Includes  #include <QAbstractItemModel> +class BtmItem +{ +public: +    BtmItem(const KBookmark &bm); +    ~BtmItem(); +    QVariant data( int role = Qt::DisplayRole ) const; +    int row() const; +    int childCount() const; +    BtmItem* child( int n ); +    BtmItem* parent() const; +    void appendChild(BtmItem *child); +    void clear(); +    KBookmark getBkm() const; + +private: +    BtmItem *m_parent; +    QList< BtmItem* > m_children; +    KBookmark m_kbm; +}; +  class REKONQ_TESTS_EXPORT BookmarksTreeModel : public QAbstractItemModel  { @@ -48,28 +68,36 @@ public:      explicit BookmarksTreeModel(QObject *parent = 0);      ~BookmarksTreeModel(); -	virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; +    virtual int rowCount(const QModelIndex &parent = QModelIndex()) const;      virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; -	virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; -	virtual Qt::ItemFlags flags(const QModelIndex &index) const; +    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; +    virtual Qt::ItemFlags flags(const QModelIndex &index) const; -	virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; +    virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;      virtual QModelIndex parent(const QModelIndex &index) const; -	virtual QVariant data(const QModelIndex &index, int role) const; -//     virtual bool setData(const QModelIndex &index, const QVariant &value, int role); +    virtual QVariant data(const QModelIndex &index, int role) const; + +    virtual QStringList mimeTypes () const; +    virtual bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent); +    virtual Qt::DropActions supportedDropActions () const; +    virtual QMimeData *mimeData( const QModelIndexList & indexes ) const;  private slots: -	void bookmarksChanged( const QString &groupAddress ); +    void bookmarksChanged(); +    void saveOnly(); +    void reconnectManager(); -private: -	class BtmItem; -	BtmItem *m_root; +signals: +    void bookmarksUpdated(); -	void resetModel(); +private: +    BtmItem *m_root; +    void resetModel();      void setRoot(KBookmarkGroup bmg); -	void populate( BtmItem *node, KBookmarkGroup bmg); +    void populate( BtmItem *node, KBookmarkGroup bmg); +    KBookmark bookmarkForIndex(const QModelIndex index) const;  };  #endif // BOOKMARKSTREEMODEL_H diff --git a/src/history/historymodels.cpp b/src/history/historymodels.cpp index 709d0523..736dbcd7 100644 --- a/src/history/historymodels.cpp +++ b/src/history/historymodels.cpp @@ -118,6 +118,8 @@ QVariant HistoryModel::data(const QModelIndex &index, int role) const          return item.dateTime.date();      case UrlRole:          return QUrl(item.url); +    case Qt::UserRole: +	return KUrl(item.url);      case UrlStringRole:          return item.url;      case Qt::DisplayRole: @@ -144,6 +146,12 @@ QVariant HistoryModel::data(const QModelIndex &index, int role) const          {              return Application::icon(item.url);          } +    case Qt::ToolTipRole: +        QString tooltip = ""; +        if(!item.title.isEmpty()) +            tooltip = item.title + "\n"; +        tooltip += item.dateTime.toString(Qt::SystemLocaleShortDate) + "\n" + item.url; +        return tooltip;      }      return QVariant();  } diff --git a/src/history/historypanel.cpp b/src/history/historypanel.cpp index 8c8eae75..03f2b880 100644 --- a/src/history/historypanel.cpp +++ b/src/history/historypanel.cpp @@ -46,10 +46,14 @@  // KDE Includes  #include <KLineEdit>  #include <KLocalizedString> +#include <KMenu> +#include <KAction> +#include <KMessageBox>  HistoryPanel::HistoryPanel(const QString &title, QWidget *parent, Qt::WindowFlags flags) -    : QDockWidget(title, parent, flags) +    : QDockWidget(title, parent, flags), +    m_treeView(new UrlTreeView(this))  {      setup();      setShown(ReKonfig::showHistoryPanel()); @@ -70,11 +74,11 @@ void HistoryPanel::setup()      QWidget *ui = new QWidget(this); -    QTreeView *historyTreeView = new QTreeView(this); -    historyTreeView->setUniformRowHeights(true); -    historyTreeView->setSelectionBehavior(QAbstractItemView::SelectRows); -    historyTreeView->setTextElideMode(Qt::ElideMiddle); -    historyTreeView->setAlternatingRowColors(true); +    m_treeView->setUniformRowHeights(true); +    m_treeView->setSelectionBehavior(QAbstractItemView::SelectRows); +    m_treeView->setTextElideMode(Qt::ElideMiddle); +    m_treeView->setAlternatingRowColors(true); +    m_treeView->header()->hide();      // add search bar      QHBoxLayout *hBoxLayout = new QHBoxLayout; @@ -91,7 +95,7 @@ void HistoryPanel::setup()      QVBoxLayout *vBoxLayout = new QVBoxLayout;      vBoxLayout->setContentsMargins(0, 0, 0, 0);      vBoxLayout->addWidget(searchBar); -    vBoxLayout->addWidget(historyTreeView); +    vBoxLayout->addWidget(m_treeView);      // add it to the UI      ui->setLayout(vBoxLayout); @@ -103,19 +107,78 @@ void HistoryPanel::setup()      TreeProxyModel *treeProxyModel = new TreeProxyModel(this);      treeProxyModel->setSourceModel(model); -    historyTreeView->setModel(treeProxyModel); -    historyTreeView->setExpanded(treeProxyModel->index(0, 0), true); -    historyTreeView->header()->hideSection(1); +    m_treeView->setModel(treeProxyModel); +    m_treeView->setExpanded(treeProxyModel->index(0, 0), true); +    m_treeView->header()->hideSection(1);      QFontMetrics fm(font());      int header = fm.width(QLatin1Char('m')) * 40; -    historyTreeView->header()->resizeSection(0, header); +    m_treeView->header()->resizeSection(0, header);      connect(search, SIGNAL(textChanged(QString)), treeProxyModel, SLOT(setFilterFixedString(QString))); -    connect(historyTreeView, SIGNAL(activated(const QModelIndex &)), this, SLOT(itemActivated(const QModelIndex &))); +    connect(m_treeView, SIGNAL(contextMenuItemRequested(const QPoint &)), this, SLOT(contextMenuItem(const QPoint &))); +    connect(m_treeView, SIGNAL(contextMenuGroupRequested(const QPoint &)), this, SLOT(contextMenuGroup(const QPoint &)));  } +void HistoryPanel::contextMenuItem(const QPoint &pos) +{ +    QPoint position = m_treeView->mapToGlobal(pos); +    KMenu *menu = new KMenu(this); +    KAction* action; + +    action = new KAction(KIcon("tab-new"), i18n("Open"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInCurrentTab())); +    menu->addAction(action); + +    action = new KAction(KIcon("tab-new"), i18n("Open in New Tab"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewTab())); +    menu->addAction(action); + +    action = new KAction(KIcon("window-new"), i18n("Open in New Window"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(openInNewWindow())); +    menu->addAction(action); + +    action = new KAction(KIcon("edit-copy"), i18n("Copy Link Address"), this); +    connect(action, SIGNAL(triggered()), m_treeView, SLOT(copyToClipboard())); +    menu->addAction(action); -void HistoryPanel::itemActivated(const QModelIndex &item) +    if (!menu) +        return; +    menu->popup(position); +} + +void HistoryPanel::contextMenuGroup(const QPoint &pos)  { -    emit openUrl( item.data(HistoryModel::UrlRole).toUrl() ); +    QPoint position = m_treeView->mapToGlobal(pos); +    KMenu *menu = new KMenu(this); +    KAction* action; + +    action = new KAction(KIcon("tab-new"), i18n("Open Folder in Tabs"), this); +    connect(action, SIGNAL(triggered()), this, SLOT(openAll())); + +    menu->addAction(action); + +    if (!menu) +        return; +    menu->popup(position); +} + +void HistoryPanel::openAll() +{ +    QModelIndex index = m_treeView->currentIndex(); +    if(!index.isValid()) +        return; + +    QList<KUrl> allChild; + +    for(int i = 0; i < index.model()->rowCount(index); i++) +        allChild << qVariantValue<KUrl>(index.child(i, 0).data(Qt::UserRole)); + +    if(allChild.length() > 8) // 8, a good choice ? +    { +        if(!(KMessageBox::warningContinueCancel(this, i18n("You are about to open a lot of tabs : %1\nAre you sure  ?", QString::number(allChild.length()))) == KMessageBox::Continue)) +            return; +    } + +    for(int i = 0; i < allChild.length(); i++) +        emit openUrl(allChild.at(i).url(), Rekonq::SettingOpenTab);  } diff --git a/src/history/historypanel.h b/src/history/historypanel.h index 6e6a9162..0c01189c 100644 --- a/src/history/historypanel.h +++ b/src/history/historypanel.h @@ -31,6 +31,8 @@  // Local Includes  #include "rekonqprivate_export.h" +#include "application.h" +#include "urltreeview.h"  // Qt Includes  #include <QDockWidget> @@ -50,13 +52,17 @@ public:      ~HistoryPanel();  signals: -    void openUrl(const KUrl &); +    void openUrl(const KUrl &, const Rekonq::OpenType &); +    void itemHovered(const QString &);  private slots: -    void itemActivated(const QModelIndex &); +    void contextMenuItem(const QPoint &pos); +    void contextMenuGroup(const QPoint &pos); +    void openAll();  private:      void setup(); +    UrlTreeView *m_treeView;  };  #endif // HISTORYPANEL_H diff --git a/src/mainview.cpp b/src/mainview.cpp index f2152364..6643becb 100644 --- a/src/mainview.cpp +++ b/src/mainview.cpp @@ -242,8 +242,7 @@ void MainView::clear()  {      // FIXME (the programmer, not the code)      // What exactly do we need to clear here? -    m_urlBar->clearHistory(); -    m_urlBar->clear(); +     m_urlBar->clear();      m_recentlyClosedTabs.clear();  } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 6a17d1b8..6efd58ed 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -500,7 +500,8 @@ void MainWindow::setupPanels()      // STEP 1      // Setup history panel      m_historyPanel = new HistoryPanel(i18n("History Panel"), this); -    connect(m_historyPanel, SIGNAL(openUrl(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); +    connect(m_historyPanel, SIGNAL(openUrl(const KUrl&, const Rekonq::OpenType &)), Application::instance(), SLOT(loadUrl(const KUrl&, const Rekonq::OpenType &))); +    connect(m_historyPanel, SIGNAL(itemHovered(QString)), this, SLOT(notifyMessage(QString)));      connect(m_historyPanel, SIGNAL(destroyed()), Application::instance(), SLOT(saveConfiguration()));      addDockWidget(Qt::LeftDockWidgetArea, m_historyPanel); @@ -514,7 +515,8 @@ void MainWindow::setupPanels()      // STEP 2      // Setup bookmarks panel      m_bookmarksPanel = new BookmarksPanel(i18n("Bookmarks Panel"), this); -    connect(m_bookmarksPanel, SIGNAL(openUrl(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); +    connect(m_bookmarksPanel, SIGNAL(openUrl(const KUrl&, const Rekonq::OpenType &)), Application::instance(), SLOT(loadUrl(const KUrl&, const Rekonq::OpenType &))); +    connect(m_bookmarksPanel, SIGNAL(itemHovered(QString)), this, SLOT(notifyMessage(QString)));      connect(m_bookmarksPanel, SIGNAL(destroyed()), Application::instance(), SLOT(saveConfiguration()));      addDockWidget(Qt::LeftDockWidgetArea, m_bookmarksPanel); diff --git a/src/urlbar/completionwidget.cpp b/src/urlbar/completionwidget.cpp new file mode 100644 index 00000000..42abcb73 --- /dev/null +++ b/src/urlbar/completionwidget.cpp @@ -0,0 +1,242 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy  +* defined in Section 14 of version 3 of the license. +*  +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "completionwidget.h" +#include "completionwidget.moc" + +// KDE Includes +#include <KGlobalSettings> +#include <KDebug> +#include <KUrl> + +// Qt Includes +#include <QPoint> +#include <QSize> +#include <QVBoxLayout> +#include <QString> +#include <QEvent> +#include <QKeyEvent> + +#define MAX_ELEMENTS 9 +#include "application.h" + +CompletionWidget::CompletionWidget( QWidget *parent) +:QFrame( parent, Qt::ToolTip) +    , _parent(parent) +    , _currentIndex(-1) +{ +    QPalette p(palette()); +    p.setColor(QPalette::Background, Qt::white); //todo: choose the correct color +    setPalette(p); +    setFrameStyle(QFrame::Panel); +    setLayoutDirection(Qt::LeftToRight); +    QVBoxLayout *layout = new QVBoxLayout; +    layout->setMargin(0); +    setLayout(layout); + +} + + +void CompletionWidget::insertSearchList(const UrlSearchList &list) +{ +    _list = list; +    int min = MAX_ELEMENTS; +    if(list.count() < min) +        min = list.count(); +     +    for(int i = 0; i<min ; ++i) +    { +        UrlSearchItem item = list.at(i); +        ListItem *suggestion = new ListItem(item); +        connect(suggestion, SIGNAL(itemClicked(ListItem *)), this, SLOT(itemChosen(ListItem *))); +        suggestion->setObjectName( QString::number(i) ); +        layout()->addWidget( suggestion ); +    } +} + + +void CompletionWidget::sizeAndPosition() +{ +    // size +    setFixedHeight(layout()->count() * 44 ); +    setFixedWidth( _parent->width() ); + +    // position +    QPoint p = _parent->mapToGlobal( QPoint(0,0) ); +    move(p.x(), p.y() + _parent->height()); +} + + +void CompletionWidget::popup() +{ +    down(); +    sizeAndPosition(); +    if (!isVisible())  +        show(); +} + + +void CompletionWidget::up() +{ +    // deactivate previous +    if(_currentIndex != -1) +    { +        ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) ); +        widget->deactivate(); +    } + +    if(_currentIndex > 0) +        _currentIndex--; +    else +        _currentIndex=layout()->count()-1;        + +    // activate "new" current +    ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) ); +    widget->activate(); +} + +KUrl CompletionWidget::currentUrl() +{ +    return _list.at(_currentIndex).url; +} + +void CompletionWidget::down() +{ +    // deactivate previous +    if(_currentIndex != -1) +    { +        ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) ); +        widget->deactivate(); +    } +     +    if(_currentIndex < _list.count() -1) +        _currentIndex++; +    else +        _currentIndex=0; +             +    // activate "new" current +    ListItem *widget = findChild<ListItem *>( QString::number(_currentIndex) ); +    widget->activate(); +} + +void CompletionWidget::clear() +{ +    QLayoutItem *child; +    while ((child = layout()->takeAt(0)) != 0)  +    { +        delete child->widget();  +        delete child; +    } +    _currentIndex = -1; +} + + +bool CompletionWidget::eventFilter( QObject *o, QEvent *e ) +{ +    int type = e->type(); +    QWidget *wid = qobject_cast<QWidget*>(o); +     +    if (o == this)  +    { +        return false; +    } + +    //hide conditions of the CompletionWidget +    if (wid  +        && ((wid == _parent && (type == QEvent::Move || type == QEvent::Resize))   +        || ((wid->windowFlags() & Qt::Window)  +            && (type == QEvent::Move || type == QEvent::Hide || type == QEvent::WindowDeactivate)  +            && wid == _parent->window()) +        || (type == QEvent::MouseButtonPress && !isAncestorOf(wid))) +       ) +    { +        hide(); +        return false; +    } + +    //actions on the CompletionWidget +    if (wid && wid->isAncestorOf(_parent) && isVisible())  +    { +        if ( type == QEvent::KeyPress )  +        { +            QKeyEvent *ev = static_cast<QKeyEvent *>( e ); +            switch ( ev->key() )  +            { +                case Qt::Key_Up: +                case Qt::Key_Backtab: +                    if (ev->modifiers() == Qt::NoButton || (ev->modifiers() & Qt::ShiftModifier))  +                    { +                        up(); +                        ev->accept(); +                        return true; +                    } +                    break; + +                case Qt::Key_Down: +                case Qt::Key_Tab: +                    if (ev->modifiers() == Qt::NoButton) +                    { +                        down(); +                        ev->accept(); +                        return true; +                    } +                    break; + +                case Qt::Key_Return: +                        hide(); +                        emit chosenUrl(currentUrl().url()); +                        ev->accept(); +                        return true; +                    break; +            } +        } +    } + +    return QFrame::eventFilter(o,e); +} + + +void CompletionWidget::setVisible( bool visible ) +{ +    if (visible)  +    { +        Application::instance()->installEventFilter(this); +    } +    else +    { +        Application::instance()->removeEventFilter(this); +    } +     +    QFrame::setVisible(visible); +} + + +void CompletionWidget::itemChosen(ListItem *item) +{ +    emit chosenUrl(_list.at(layout()->indexOf(item)).url); +    hide(); +}
\ No newline at end of file diff --git a/src/urlbar/completionwidget.h b/src/urlbar/completionwidget.h new file mode 100644 index 00000000..7b474bd8 --- /dev/null +++ b/src/urlbar/completionwidget.h @@ -0,0 +1,77 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy  +* defined in Section 14 of version 3 of the license. +*  +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef COMPLETION_WIDGET_H +#define COMPLETION_WIDGET_H + + +// Local Includes +#include "urlresolver.h" +#include "listitem.h" + +// Qt Includes +#include <QFrame> + +// KDE Includes +#include <KLineEdit> + +// Forward Declarations +class KUrl; + + +class CompletionWidget : public QFrame +{ +Q_OBJECT + +public: +    CompletionWidget(QWidget *parent); + +    void insertSearchList(const UrlSearchList &list); +    void popup(); + +    void up(); +    void down(); +    void clear(); +    virtual bool eventFilter(QObject *obj, QEvent *ev); +    void setVisible(bool visible); +    KUrl currentUrl(); +     +private slots: +    void itemChosen(ListItem *item); + +signals: +    void chosenUrl(const QString&); + +private: +    void sizeAndPosition(); +     +    QWidget *_parent; + +    UrlSearchList _list; +    int _currentIndex; +}; + +#endif // COMPLETION_WIDGET_H diff --git a/src/urlbar/lineedit.cpp b/src/urlbar/lineedit.cpp index db36bd0c..f3c93e8e 100644 --- a/src/urlbar/lineedit.cpp +++ b/src/urlbar/lineedit.cpp @@ -2,9 +2,9 @@  *  * This file is a part of the rekonq project  * -* Copyright (C) 2009-2010 by Andrea Diamantini <adjam7 at gmail dot com> +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>  * Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com> -* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr> +* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>  *  *  * This program is free software; you can redistribute it and/or diff --git a/src/urlbar/lineedit.h b/src/urlbar/lineedit.h index 1ac3af2e..d76a5fcb 100644 --- a/src/urlbar/lineedit.h +++ b/src/urlbar/lineedit.h @@ -2,9 +2,9 @@  *  * This file is a part of the rekonq project  * -* Copyright (C) 2009-2010 by Andrea Diamantini <adjam7 at gmail dot com> +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com>  * Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com> -* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr> +* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>  *  *  * This program is free software; you can redistribute it and/or @@ -30,9 +30,6 @@  #define LINEEDIT_H -// Local Includes -#include "rekonqprivate_export.h" -  // KDE Includes  #include <KLineEdit> @@ -42,7 +39,7 @@ class QFocusEvent;  class QKeyEvent; -class REKONQ_TESTS_EXPORT LineEdit : public KLineEdit +class LineEdit : public KLineEdit  {      Q_OBJECT @@ -50,9 +47,12 @@ public:      explicit LineEdit(QWidget *parent = 0);      virtual ~LineEdit(); +      protected:      virtual void keyPressEvent(QKeyEvent*);      virtual void mouseDoubleClickEvent(QMouseEvent *); + +  };  #endif // LINEEDIT_H diff --git a/src/urlbar/listitem.cpp b/src/urlbar/listitem.cpp new file mode 100644 index 00000000..92951cb7 --- /dev/null +++ b/src/urlbar/listitem.cpp @@ -0,0 +1,173 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy  +* defined in Section 14 of version 3 of the license. +*  +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "listitem.h"    + +// Local Includes +#include "urlresolver.h" +#include "application.h" + +// KDE Includes +#include <KIcon> +#include <KStandardDirs> +#include <KDebug> + +// Qt Includes +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QLabel> +#include <QSizePolicy> +#include <QPixmap> +#include <QStylePainter> +#include <QFile> + +ListItem::ListItem(const UrlSearchItem &item, QWidget *parent) +    : QWidget(parent), +    m_option() +{ +    QHBoxLayout *hLayout = new QHBoxLayout; +    QVBoxLayout *vLayout = new QVBoxLayout; + +    QLabel *previewLabel = new QLabel; +    previewLabel->setFixedSize(40,30); +    QPixmap preview; +    QString path = KStandardDirs::locateLocal("cache", QString("thumbs/") + guessNameFromUrl(item.url) + ".png", true); +    if(QFile::exists(path)) +    { +        preview.load(path); +        previewLabel->setPixmap(preview.scaled(40,30)); +    } +    else +    { +        if(item.icon.startsWith( QLatin1String("http://") ) ) +            preview = Application::icon( item.icon ).pixmap(22); +    } +    previewLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); +     +    hLayout->addWidget(previewLabel); +    hLayout->addLayout(vLayout); +     +    QLabel *titleLabel = new QLabel("<b>" + item.title + "</b>"); +    titleLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +     +    QLabel *urlLabel = new QLabel("<i>" + item.url + "</i>"); +    urlLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); +         +    vLayout->addWidget(titleLabel); +    vLayout->addWidget(urlLabel); + + +    QLabel *iconLabel = new QLabel; +    QPixmap pixmap; +    if(item.icon.startsWith( QLatin1String("http://") ) ) +        pixmap = Application::icon( item.icon ).pixmap(18); +    else +        pixmap = KIcon(item.icon).pixmap(18); + +    iconLabel->setPixmap(pixmap); +    iconLabel->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Minimum); +    hLayout->addWidget(iconLabel); + +    setLayout(hLayout); +     +    m_option.initFrom(this); +    m_option.direction = Qt::LeftToRight; +     +    deactivate(); +} + +ListItem::~ListItem() +{ +    disconnect(); +} + + +//TODO: REMOVE DUPLICATE CODE WITH PREVIEWIMAGE +QString ListItem::guessNameFromUrl(QUrl url) +{ +    QString name = url.toString( QUrl::RemoveScheme | QUrl::RemoveUserInfo | QUrl::StripTrailingSlash ); +     +    // TODO learn Regular Expressions :) +    // and implement something better here.. +    name.remove('/'); +    name.remove('&'); +    name.remove('.'); +    name.remove('-'); +    name.remove('_'); +    name.remove('?'); +    name.remove('='); +    name.remove('+'); +     +    return name; +} + + +void ListItem::activate() +{ +    m_option.state |= QStyle::State_Selected; +    repaint(); +} + + +void ListItem::deactivate() +{ +    m_option.state  &= ~QStyle::State_Selected; +    repaint(); +} + +void ListItem::paintEvent(QPaintEvent *event) +{ +    Q_UNUSED(event); +     +    if( m_option.state.testFlag(QStyle::State_Selected) ||  m_option.state.testFlag(QStyle::State_MouseOver)) +    { +        QPainter painter(this); +        m_option.rect=QRect(QPoint(),size()); +        style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &m_option, &painter, this); +    } +} + +void ListItem::enterEvent(QEvent *e) +{ +    m_option.state |= QStyle::State_MouseOver; +    repaint(); +    QWidget::enterEvent(e); +} + +void ListItem::leaveEvent(QEvent *e) +{ +    m_option.state &= ~QStyle::State_MouseOver; +    repaint(); +    QWidget::enterEvent(e); +} + +void ListItem::mousePressEvent(QMouseEvent *e) +{ +    emit itemClicked(this); +    QWidget::mousePressEvent(e); +} + diff --git a/src/urlbar/listitem.h b/src/urlbar/listitem.h new file mode 100644 index 00000000..6aa3f1e9 --- /dev/null +++ b/src/urlbar/listitem.h @@ -0,0 +1,59 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy  +* defined in Section 14 of version 3 of the license. +*  +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Qt Includes +#include <QWidget> +#include <QStyleOptionViewItemV4> + +// Forward Declarations +class UrlSearchItem; + + +class ListItem : public QWidget +{ +Q_OBJECT + +public: +    ListItem(const UrlSearchItem &item, QWidget *parent = 0); +    ~ListItem(); + +    void activate(); +    void deactivate(); + +signals: +    void itemClicked(ListItem *item); + +protected: +   virtual void paintEvent(QPaintEvent *event); +   virtual void enterEvent(QEvent *); +   virtual void leaveEvent(QEvent *); +   virtual void mousePressEvent(QMouseEvent *e); + +private: +    QStyleOptionViewItemV4 m_option; +    QString guessNameFromUrl(QUrl url); + +}; diff --git a/src/urlbar/urlbar.cpp b/src/urlbar/urlbar.cpp index 718d9f67..54a0a02d 100644 --- a/src/urlbar/urlbar.cpp +++ b/src/urlbar/urlbar.cpp @@ -2,10 +2,10 @@  *  * This file is a part of the rekonq project  * -* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com> +* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>  * Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@gmail.com>  * Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com> -* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr> +* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>  *  *  * This program is free software; you can redistribute it and/or @@ -36,8 +36,7 @@  #include "lineedit.h"  #include "mainwindow.h"  #include "webview.h" -#include "historymanager.h" -#include "webtab.h" +#include "urlresolver.h"  // KDE Includes  #include <KDebug> @@ -49,43 +48,44 @@  #include <QPaintEvent>  #include <QPalette>  #include <QTimer> - +#include <QVBoxLayout>  QColor UrlBar::s_defaultBaseColor;  UrlBar::UrlBar(QWidget *parent) -        : KHistoryComboBox(true, parent) -        , m_lineEdit(new LineEdit) -        , m_progress(0) +    : KComboBox(true, parent) +    , m_lineEdit(new LineEdit) +    , m_progress(0) +    , m_box(new CompletionWidget(this))  { -    setUrlDropsEnabled(true); -    setAutoDeleteCompletionObject(true); -      //cosmetic      setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);      setMinimumWidth(180); -     -    setTrapReturnKey(true); - -    setupLineEdit(); -    // add every item to history -    connect(this, SIGNAL(returnPressed(const QString&)), SLOT(activated(const QString&))); -    connect(completionBox(), SIGNAL(activated(const QString&)), SLOT(activated(const QString&))); +    // signal handlings +    setTrapReturnKey(true); +    setUrlDropsEnabled(true); +     +    // Make m_lineEdit background transparent +    QPalette p = m_lineEdit->palette(); +    p.setColor(QPalette::Base, Qt::transparent); +    m_lineEdit->setPalette(p); -    connect(this, SIGNAL(cleared()), SLOT(cleared())); +    if (!s_defaultBaseColor.isValid()) +    { +        s_defaultBaseColor = palette().color(QPalette::Base); +    } -    // setup completion box -    setCompletionObject( Application::historyManager()->completionObject() ); -     -    // set dropdown list background -    QPalette p = view()->palette(); -    p.setColor(QPalette::Base, palette().color(QPalette::Base)); -    view()->setPalette(p); +    setLineEdit(m_lineEdit); +    // clear the URL bar +    m_lineEdit->clear();      // load urls on activated urlbar signal -    connect(this, SIGNAL(activated(const KUrl&)), Application::instance(), SLOT(loadUrl(const KUrl&))); +    connect(this, SIGNAL(returnPressed(const QString&)), SLOT(activated(const QString&))); +     +    installEventFilter(m_box); +    connect(m_box, SIGNAL(chosenUrl(const QString&)), SLOT(activated(const QString&)));  } @@ -96,7 +96,7 @@ UrlBar::~UrlBar()  void UrlBar::selectAll() const  { -    lineEdit()->selectAll(); +    m_lineEdit->selectAll();  } @@ -106,42 +106,12 @@ KUrl UrlBar::url() const  } -KLineEdit *UrlBar::lineEdit() const -{ -    return m_lineEdit; -} - - -void UrlBar::setupLineEdit() -{ -    // Make m_lineEdit background transparent -    QPalette p = m_lineEdit->palette(); -    p.setColor(QPalette::Base, Qt::transparent); -    m_lineEdit->setPalette(p); - -    if (!s_defaultBaseColor.isValid()) -    { -        s_defaultBaseColor = palette().color(QPalette::Base); -    } - -    setLineEdit(m_lineEdit); - -    // Make the lineedit consume the Qt::Key_Enter event... -    lineEdit()->setTrapReturnKey(true); - -    lineEdit()->setHandleSignals(true); - -    // clear the URL bar -    lineEdit()->clear(); -} - -  void UrlBar::setUrl(const QUrl& url)  {      if(url.scheme() == "about")      {          m_currentUrl = KUrl(); -        updateUrl();    // updateUrl before setFocus         +        updateUrl();          setFocus();      }      else @@ -149,13 +119,14 @@ void UrlBar::setUrl(const QUrl& url)          m_currentUrl = KUrl(url);          updateUrl();      } +  }  void UrlBar::setProgress(int progress)  {      m_progress = progress; -    repaint(); +    update();  } @@ -195,29 +166,21 @@ void UrlBar::updateUrl()      // Must be AFTER setCurrentIndex      if (!hasFocus())      { -        lineEdit()->setCursorPosition(0); +        m_lineEdit->setCursorPosition(0);      }  }  void UrlBar::activated(const QString& urlString)  { +    disconnect(this, SIGNAL(editTextChanged(const QString &)), this, SLOT(suggestUrls(const QString &))); +          if (urlString.isEmpty())          return; -    // this fix urlbar behaviour, removing focus from there and enabling -    // loading animation. Temporary fix?? -    Application::instance()->mainWindow()->currentTab()->setFocus(); - -    setUrl( KUrl(urlString) ); -    emit activated( KUrl(urlString) ); -} - - -void UrlBar::cleared() -{ -    // clear the history on user's request from context menu -    clear(); +    clearFocus(); +    setUrl(urlString); +    Application::instance()->loadUrl(m_currentUrl);  } @@ -225,14 +188,14 @@ void UrlBar::loadFinished(bool)  {      // reset progress bar after small delay      m_progress = 0; -    QTimer::singleShot(200, this, SLOT(repaint())); +    QTimer::singleShot(200, this, SLOT(update()));  }  void UrlBar::updateProgress(int progress)  {      m_progress = progress; -    repaint(); +    update();  } @@ -243,7 +206,7 @@ void UrlBar::paintEvent(QPaintEvent *event)      p.setColor(QPalette::Base, s_defaultBaseColor);      setPalette(p); -    KHistoryComboBox::paintEvent(event); +    KComboBox::paintEvent(event);      if (!hasFocus())      { @@ -261,7 +224,7 @@ void UrlBar::paintEvent(QPaintEvent *event)          painter.setBrush(generateGradient(loadingColor, height()));          painter.setPen(Qt::transparent); -        QRect backgroundRect = lineEdit()->frameGeometry(); +        QRect backgroundRect = m_lineEdit->frameGeometry();          int mid = backgroundRect.width() * m_progress / 100;          QRect progressRect(backgroundRect.x(), backgroundRect.y(), mid, backgroundRect.height());          painter.drawRect(progressRect); @@ -272,7 +235,7 @@ void UrlBar::paintEvent(QPaintEvent *event)  QSize UrlBar::sizeHint() const  { -    return lineEdit()->sizeHint(); +    return m_lineEdit->sizeHint();  } @@ -295,7 +258,7 @@ QLinearGradient UrlBar::generateGradient(const QColor &color, int height)  void UrlBar::setBackgroundColor(QColor c)  {      s_defaultBaseColor = c; -    repaint(); +    update();  } @@ -308,43 +271,70 @@ bool UrlBar::isLoading()      return true;  } -  void UrlBar::keyPressEvent(QKeyEvent *event)  { + +    // this handles the Modifiers + Return key combinations      QString currentText = m_lineEdit->text().trimmed(); -    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) +    if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) +        && !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive))      { -        if( !currentText.startsWith(QLatin1String("http://"), Qt::CaseInsensitive) ) +        QString append; +        if (event->modifiers() == Qt::ControlModifier)          { -            QString append; -            if (event->modifiers() == Qt::ControlModifier) -            { -                append = QLatin1String(".com"); -            } -            else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) -            { -                append = QLatin1String(".org"); -            } -            else if (event->modifiers() == Qt::ShiftModifier) -            { -                append = QLatin1String(".net"); -            } - -            QUrl url(QLatin1String("http://www.") + currentText); -            QString host = url.host(); -            if (!host.endsWith(append, Qt::CaseInsensitive)) -            { -                host += append; -                url.setHost(host); -                m_lineEdit->setText(url.toString()); -            } +            append = QLatin1String(".com");          } -        else +        else if (event->modifiers() == (Qt::ControlModifier | Qt::ShiftModifier)) +        { +            append = QLatin1String(".org"); +        } +        else if (event->modifiers() == Qt::ShiftModifier) +        { +            append = QLatin1String(".net"); +        } + +        QUrl url(QLatin1String("http://www.") + currentText); +        QString host = url.host(); +        if (!host.endsWith(append, Qt::CaseInsensitive))          { -            // fill lineEdit with its stripped contents to remove trailing spaces -            m_lineEdit->setText(currentText); +            host += append; +            url.setHost(host); +            m_lineEdit->setText(url.toString());          }      } +     +    KComboBox::keyPressEvent(event); +} + + +void UrlBar::suggestUrls(const QString &text) +{    +    if (!hasFocus()) +    { +        return; +    } + +    if(text.isEmpty()) +    { +        m_box->hide(); +        return; +    } + +    UrlResolver res(text); +    UrlSearchList list = res.orderedSearchItems(); + +    if(list.count() > 0) +    { +        m_box->clear(); +        m_box->insertSearchList(list); +        m_box->popup(); +    } +} -    KHistoryComboBox::keyPressEvent(event); +void UrlBar::focusInEvent(QFocusEvent *event) +{ +    // activate suggestions on edit text +    connect(this, SIGNAL(editTextChanged(const QString &)), this, SLOT(suggestUrls(const QString &))); +     +    KComboBox::focusInEvent(event);  } diff --git a/src/urlbar/urlbar.h b/src/urlbar/urlbar.h index 39911bb2..ef53d63a 100644 --- a/src/urlbar/urlbar.h +++ b/src/urlbar/urlbar.h @@ -2,10 +2,10 @@  *  * This file is a part of the rekonq project  * -* Copyright (C) 2008-2010 by Andrea Diamantini <adjam7 at gmail dot com> +* Copyright (C) 2008-2009 by Andrea Diamantini <adjam7 at gmail dot com>  * Copyright (C) 2009 by Domrachev Alexandr <alexandr.domrachev@gmail.com>  * Copyright (C) 2009 by Paweł Prażak <pawelprazak at gmail dot com> -* Copyright (C) 2009-2010 by Lionel Chauvin <megabigbug@yahoo.fr> +* Copyright (C) 2009 by Lionel Chauvin <megabigbug@yahoo.fr>  *  *  * This program is free software; you can redistribute it and/or @@ -32,23 +32,23 @@  // Local Includes -#include "rekonqprivate_export.h"  #include "lineedit.h" +#include "completionwidget.h"  // KDE Includes  #include <KUrl> -#include <KHistoryComboBox> +#include <KComboBox>  // Qt Includes  #include <QUrl> +#include <QPointer>  // Forward Declarations  class QLinearGradient;  class QWidget; -class KCompletion; -class REKONQ_TESTS_EXPORT UrlBar : public KHistoryComboBox +class UrlBar : public KComboBox  {      Q_OBJECT @@ -61,31 +61,24 @@ public:      QSize sizeHint() const;      void setBackgroundColor(QColor);      bool isLoading(); -          void setProgress(int progress); -signals: -    void activated(const KUrl&); -  public slots:      void setUrl(const QUrl &url);      void updateProgress(int progress);      void updateUrl(); -     +  private slots:      void activated(const QString& url);      void loadFinished(bool); -    void cleared(); +    void suggestUrls(const QString &editedText);  protected:      virtual void paintEvent(QPaintEvent *event);      virtual void keyPressEvent(QKeyEvent *event); +    virtual void focusInEvent(QFocusEvent *event);  private: -    void setupLineEdit(); - -    KLineEdit *lineEdit() const; -      static QLinearGradient generateGradient(const QColor &color, int height);      static QColor s_defaultBaseColor; @@ -94,6 +87,9 @@ private:      KUrl m_currentUrl;      int m_progress; + +    CompletionWidget *m_box; +    KUrl m_suggestedUrl;  };  #endif diff --git a/src/urlbar/urlresolver.cpp b/src/urlbar/urlresolver.cpp new file mode 100644 index 00000000..b2bf50af --- /dev/null +++ b/src/urlbar/urlresolver.cpp @@ -0,0 +1,177 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy  +* defined in Section 14 of version 3 of the license. +*  +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "urlresolver.h" + +// Local Includes +#include "application.h" +#include "historymanager.h" +#include "bookmarksmanager.h" + +// KDE Includes +#include <KUriFilter> +#include <KCompletion> +#include <KDebug> +#include <KService> +#include <KConfig> +#include <KConfigGroup> + +// Qt Includes +#include <QString> +#include <QByteArray> +#include <QUrl> + + +// NOTE default kurifilter plugin list (at least in my box) +// 1. "kshorturifilter" +// 2. "kurisearchfilter" +// 3. "localdomainurifilter" +// 4 ."kuriikwsfilter" +// 5. "fixhosturifilter" + + +UrlResolver::UrlResolver(const QString &typedUrl) +    : _urlString(typedUrl) +{ +} + + +UrlSearchList UrlResolver::orderedSearchItems() +{ +    // NOTE: the logic here is : "we wanna suggest (at least) 9 elements" +    // so we have (more or less) 3 from first results (1 from QUrl Resolutions, 2 from  +    // default search engines). +    // There are 6 remaining: if bookmarkResults + historyResults <= 6, catch all, else +    // catch first 3 results from the two resulting lists :) +     +    UrlSearchList list; +     +    list << qurlFromUserInputResolution(); +    list << webSearchesResolution(); +    int firstResults = list.count(); +    int checkPoint = 9 - firstResults; +     +    UrlSearchList historyList = historyResolution(); +    int historyResults = historyList.count(); +     +    UrlSearchList bookmarksList = bookmarksResolution(); +    int bookmarkResults = bookmarksList.count(); +     +    if(historyResults + bookmarkResults > checkPoint) +    { +        historyList = historyList.mid(0,3); +        bookmarksList = bookmarksList.mid(0,3); +    } +    list << historyList; +    list << bookmarksList; +     +    return list; +} + + +////////////////////////////////////////////////////////////////////////// +// PRIVATE ENGINES + + +// STEP 1 = QUrl from User Input (easily the best solution... ) +UrlSearchList UrlResolver::qurlFromUserInputResolution() +{ +    UrlSearchList list; +     +    QString url2 = _urlString; +    QUrl urlFromUserInput = QUrl::fromUserInput(url2); +    if(urlFromUserInput.isValid()) +    { +        QByteArray ba = urlFromUserInput.toEncoded(); +        if(!ba.isEmpty()) +        { +            QString str(ba); +            UrlSearchItem it(str); +            list << it; +        } +    } +     +    return list; +} + + +// STEP 2 = Web Searches +UrlSearchList UrlResolver::webSearchesResolution() +{ +    UrlSearchList list; +     +    QString url1 = _urlString; +    if(KUrl(url1).isRelative() && !url1.contains('.')) +    { +        // KUriFilter has the worst performance possible here and let this trick unusable +        QString gUrl = QString("http://www.google.com/search?q=%1&ie=UTF-8&oe=UTF-8").arg(url1); +        QString gTitle = i18n("Search Google for ") + url1; +        UrlSearchItem gItem(gUrl, gTitle, QString("http://www.google.com") ); +        list << gItem; +         +        QString wUrl = QString("http://en.wikipedia.org/wiki/Special:Search?search=%1&go=Go").arg(url1); +        QString wTitle = i18n("Search Wikipedia for ") + url1; +        UrlSearchItem wItem(wUrl, wTitle, QString("http://wikipedia.org") ); +        list << wItem; +    } + +    return list; +} + + +// STEP 3 = history completion +UrlSearchList UrlResolver::historyResolution() +{ +    UrlSearchList list; +     +    KCompletion *historyCompletion = Application::historyManager()->completionObject(); +    QStringList historyResults = historyCompletion->substringCompletion(_urlString); +    Q_FOREACH(const QString &s, historyResults) +    { +        UrlSearchItem it(s, s, QString("view-history")); +        list << it; +    } + +    return list; +} + + +// STEP 4 = bookmarks completion +UrlSearchList UrlResolver::bookmarksResolution() +{ +    UrlSearchList list; +     +    KCompletion *bookmarkCompletion = Application::bookmarkProvider()->completionObject(); +    QStringList bookmarkResults = bookmarkCompletion->substringCompletion(_urlString); +    Q_FOREACH(const QString &s, bookmarkResults) +    { +        UrlSearchItem it( s, QString(), QString("rating") ); +        list << it; +    } + +    return list; +} diff --git a/src/urlbar/urlresolver.h b/src/urlbar/urlresolver.h new file mode 100644 index 00000000..0a880150 --- /dev/null +++ b/src/urlbar/urlresolver.h @@ -0,0 +1,72 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2009 by Andrea Diamantini <adjam7 at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy  +* defined in Section 14 of version 3 of the license. +*  +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef URL_RESOLVER_H +#define URL_RESOLVER_H + + +// Qt Includes +#include <QString> +#include <QList> + +// Forward Declarations +class KUrl; + +class UrlSearchItem +{ +public: +    QString url; +    QString title; +    QString icon; +     +    UrlSearchItem(const QString &_url, const QString &_title = QString(), const QString &_icon = QString()) +        : url(_url), title(_title), icon(_icon) +    {}; +}; + +typedef QList <UrlSearchItem> UrlSearchList; + + +// ---------------------------------------------------------------------- + + +class UrlResolver +{ +public: +    UrlResolver(const QString &typedUrl); +     +    UrlSearchList orderedSearchItems(); + +private: +    QString _urlString; + +    UrlSearchList webSearchesResolution(); +    UrlSearchList historyResolution(); +    UrlSearchList qurlFromUserInputResolution(); +    UrlSearchList bookmarksResolution(); +}; + +#endif // URL_RESOLVER_H diff --git a/src/urltreeview.cpp b/src/urltreeview.cpp new file mode 100644 index 00000000..507a7973 --- /dev/null +++ b/src/urltreeview.cpp @@ -0,0 +1,195 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2010 by Yoann Laissus <yoann dot laissus at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +// Self Includes +#include "urltreeview.h" + +// Local Includes +#include "application.h" + +// Qt Includes +#include <QMouseEvent> +#include <QClipboard> + + +UrlTreeView::UrlTreeView(QWidget *parent) +    : QTreeView(parent) +{ +    connect(this, SIGNAL(itemHovered(const QString &)), parent, SIGNAL(itemHovered(const QString &))); +    connect(this, SIGNAL(openUrl(const KUrl &, Rekonq::OpenType)), parent, SIGNAL(openUrl(const KUrl &, Rekonq::OpenType))); +    setMouseTracking(true); +    setExpandsOnDoubleClick(false); +} + + +UrlTreeView::~UrlTreeView() +{ +} + + +void UrlTreeView::mousePressEvent(QMouseEvent *event) +{ +    const QModelIndex index = indexAt(event->pos()); +    bool expanded = isExpanded(index); + +    QTreeView::mousePressEvent(event); + +    // A change of an item expansion is handle by mouseReleaseEvent() +    // So toggle again the item +    if(expanded != isExpanded(index)) +        setExpanded(index, !isExpanded(index)); +     +    if(!index.isValid()) +    { +        clearSelection(); +        setCurrentIndex(QModelIndex()); + +        if(event->button() == Qt::RightButton) +            emit contextMenuEmptyRequested(event->pos()); +        return; +    } + +    if(event->button() == Qt::RightButton) +    { +        if(model()->rowCount(index) == 0) +        { +            // An empty group needs to be handle by the panels +            emit contextMenuItemRequested(event->pos()); +        } +        else +        { +            emit contextMenuGroupRequested(event->pos()); +        } +    } +} + + +void UrlTreeView::mouseReleaseEvent(QMouseEvent *event) +{ +    QTreeView::mouseReleaseEvent(event); + +    const QModelIndex index = indexAt(event->pos()); +    if(!index.isValid()) +        return; + +    if(event->button() == Qt::MidButton) +        validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole)), Rekonq::NewCurrentTab); + +    else if(event->button() == Qt::LeftButton) +    { +        if(model()->rowCount(index) == 0) +            validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole))); +        else +            setExpanded(index, !isExpanded(index)); +    } +} + + +void UrlTreeView::keyPressEvent(QKeyEvent *event) +{ +    QTreeView::keyPressEvent(event); +    QModelIndex index = currentIndex(); + +    if(!index.isValid()) +        return; + +    if(event->key() == Qt::Key_Return) +    { +        if(model()->rowCount(index) == 0) +            validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole))); +        else +            setExpanded(index, !isExpanded(index)); +    } + +    else if(event->key() == Qt::Key_Delete) +    { +        emit delKeyPressed(); +    } +} + + +void UrlTreeView::validOpenUrl(const KUrl &url, Rekonq::OpenType openType) +{ +    // To workaround a crash when the url is about:blank +    if(url.url() == "about:blank") +        emit openUrl(KUrl("about:home"), openType); +    else +        emit openUrl(url, openType); +} + + +void UrlTreeView::mouseMoveEvent(QMouseEvent *event) +{ +    QTreeView::mouseMoveEvent(event); +    const QModelIndex index = indexAt(event->pos()); +    if(!index.isValid()) +    { +        emit itemHovered(""); +        return; +    } +    emit itemHovered(qVariantValue< KUrl >(index.data(Qt::UserRole)).url()); +} + + +void UrlTreeView::openInCurrentTab() +{ +    QModelIndex index = currentIndex(); +    if(!index.isValid()) +        return; + +    validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole))); +} + + +void UrlTreeView::copyToClipboard() +{ +    QModelIndex index = currentIndex(); +    if(!index.isValid()) +        return; + +    QClipboard *cb = QApplication::clipboard(); +    cb->setText(qVariantValue< KUrl >(index.data(Qt::UserRole)).url()); +} + + +void UrlTreeView::openInNewTab() +{ +    QModelIndex index = currentIndex(); +    if(!index.isValid()) +        return; + +    validOpenUrl(qVariantValue< KUrl >(index.data(Qt::UserRole)), Rekonq::SettingOpenTab); +} + + +void UrlTreeView::openInNewWindow() +{ +    QModelIndex index = currentIndex(); +    if(!index.isValid()) +        return; + +    validOpenUrl( qVariantValue< KUrl >(index.data(Qt::UserRole)), Rekonq::NewWindow); +} diff --git a/src/urltreeview.h b/src/urltreeview.h new file mode 100644 index 00000000..cce7a257 --- /dev/null +++ b/src/urltreeview.h @@ -0,0 +1,69 @@ +/* ============================================================ +* +* This file is a part of the rekonq project +* +* Copyright (C) 2010 by Yoann Laissus <yoann dot laissus at gmail dot com> +* +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License as +* published by the Free Software Foundation; either version 2 of +* the License or (at your option) version 3 or any later version +* accepted by the membership of KDE e.V. (or its successor approved +* by the membership of KDE e.V.), which shall act as a proxy +* defined in Section 14 of version 3 of the license. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program.  If not, see <http://www.gnu.org/licenses/>. +* +* ============================================================ */ + + +#ifndef URLTREEVIEW_H +#define URLTREEVIEW_H + +// Local Includes +#include "application.h" + +// Qt Includes +#include <QTreeView> + + +class UrlTreeView : public QTreeView +{ +    Q_OBJECT + +public: +    UrlTreeView(QWidget *parent = 0); +    ~UrlTreeView(); + +signals: +    void openUrl(const KUrl &, const Rekonq::OpenType &); +    void itemHovered(const QString &); +    void delKeyPressed(); +    void contextMenuItemRequested(const QPoint &pos); +    void contextMenuGroupRequested(const QPoint &pos); +    void contextMenuEmptyRequested(const QPoint &pos); + +public slots: +    void copyToClipboard(); +    void openInCurrentTab(); +    void openInNewTab(); +    void openInNewWindow(); + +protected: +    void mouseReleaseEvent(QMouseEvent *event); +    void mousePressEvent(QMouseEvent *event); +    void mouseMoveEvent(QMouseEvent *event); +    void keyPressEvent(QKeyEvent *event); + +private: +    void validOpenUrl(const KUrl &url, Rekonq::OpenType openType = Rekonq::CurrentTab); +}; + +#endif // URLTREEVIEW_H  | 
