diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/rekonq.kcfg | 3 | ||||
| -rw-r--r-- | src/settings/settings_general.ui | 7 | ||||
| -rw-r--r-- | src/urlbar/bookmarkwidget.cpp | 3 | ||||
| -rw-r--r-- | src/urlbar/bookmarkwidget.h | 1 | ||||
| -rw-r--r-- | src/webview.cpp | 215 | ||||
| -rw-r--r-- | src/webview.h | 17 | 
6 files changed, 239 insertions, 7 deletions
| diff --git a/src/rekonq.kcfg b/src/rekonq.kcfg index bfaece5f..4c3dec40 100644 --- a/src/rekonq.kcfg +++ b/src/rekonq.kcfg @@ -79,6 +79,9 @@      <entry name="enableViShortcuts" type="Bool">          <default>false</default>      </entry> +    <entry name="accessKeysEnabled" type="Bool"> +        <default>false</default> +    </entry>  </group> diff --git a/src/settings/settings_general.ui b/src/settings/settings_general.ui index 7e250c47..908f1c27 100644 --- a/src/settings/settings_general.ui +++ b/src/settings/settings_general.ui @@ -257,6 +257,13 @@          </property>         </widget>        </item> +      <item> +       <widget class="QCheckBox" name="kcfg_accessKeysEnabled"> +        <property name="text"> +         <string>Enable keyboard navigation using the Ctrl key</string> +        </property> +       </widget> +      </item>       </layout>      </widget>     </item> diff --git a/src/urlbar/bookmarkwidget.cpp b/src/urlbar/bookmarkwidget.cpp index 5ac8d2e6..b36af2bc 100644 --- a/src/urlbar/bookmarkwidget.cpp +++ b/src/urlbar/bookmarkwidget.cpp @@ -3,6 +3,7 @@  * 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>  *  *  * This program is free software; you can redistribute it and/or @@ -168,7 +169,7 @@ void BookmarkWidget::setupFolderComboBox()      for (KBookmark bookmark = root.first(); !bookmark.isNull(); bookmark = root.next(bookmark))      { -        if(bookmark.isGroup()) +        if (bookmark.isGroup())          {              m_folder->addItem(bookmark.text(), bookmark.address());          } diff --git a/src/urlbar/bookmarkwidget.h b/src/urlbar/bookmarkwidget.h index 025077c7..f70fc750 100644 --- a/src/urlbar/bookmarkwidget.h +++ b/src/urlbar/bookmarkwidget.h @@ -3,6 +3,7 @@  * 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>  *  *  * This program is free software; you can redistribute it and/or diff --git a/src/webview.cpp b/src/webview.cpp index 8a4cc4ba..da7f802a 100644 --- a/src/webview.cpp +++ b/src/webview.cpp @@ -76,6 +76,7 @@ WebView::WebView(QWidget* parent)      , m_smoothScrolling(false)      , m_dy(0)      , m_smoothScrollSteps(0) +    , m_accessKeysPressed(false)  {      WebPage *page = new WebPage(this);      setPage(page); @@ -99,6 +100,7 @@ WebView::WebView(QWidget* parent)      m_smoothScrollTimer->setInterval(16);      connect(this, SIGNAL(iconChanged()), this, SLOT(changeWindowIcon())); +    connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));  } @@ -109,6 +111,12 @@ WebView::~WebView()  } +void WebView::loadStarted() +{ +    hideAccessKeys(); +} + +  void WebView::changeWindowIcon()  {      if (ReKonfig::useFavicon()) @@ -159,7 +167,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)      if (result.isContentSelected())          resultHit = WebView::TextSelection; -    // -------------------------------------------------------------------------------------------- +    // --------------------------------------------------------------------------------      // Ok, let's start filling up the menu...      // is content editable? Add PASTE @@ -169,7 +177,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)          menu.addSeparator();      } -    // EMPTY PAGE ACTIONS ------------------------------------------------------------------------- +    // EMPTY PAGE ACTIONS -------------------------------------------------------------      if (resultHit == WebView::EmptySelection)      {          // send by mail: page url @@ -226,7 +234,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)          }      } -    // LINK ACTIONS ------------------------------------------------------------------------------- +    // LINK ACTIONS -------------------------------------------------------------------      if (resultHit & WebView::LinkSelection)      {          // send by mail: link url @@ -248,7 +256,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)          menu.addAction(pageAction(KWebPage::CopyLinkToClipboard));      } -    // IMAGE ACTIONS ------------------------------------------------------------------------------ +    // IMAGE ACTIONS ------------------------------------------------------------------      if (resultHit & WebView::ImageSelection)      {          // send by mail: image url @@ -271,7 +279,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)          menu.addAction(a);      } -    // ACTIONS FOR TEXT SELECTION ----------------------------------------------------------------- +    // ACTIONS FOR TEXT SELECTION -----------------------------------------------------      if (resultHit & WebView::TextSelection)      {          // send by mail: text @@ -355,7 +363,7 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)          }      } -    // DEFAULT ACTIONs (on the bottom) --------------------------------------------------- +    // DEFAULT ACTIONs (on the bottom) ------------------------------------------------      menu.addSeparator();      if (resultHit & WebView::LinkSelection)      { @@ -561,6 +569,7 @@ void WebView::viewImage(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifier      }  } +  void WebView::slotCopyImageLocation()  {      KAction *a = qobject_cast<KAction*>(sender()); @@ -609,6 +618,26 @@ void WebView::bookmarkLink()  void WebView::keyPressEvent(QKeyEvent *event)  { +    if (ReKonfig::accessKeysEnabled()) +    { +        m_accessKeysPressed = (event->modifiers() == Qt::ControlModifier +                               && event->key() == Qt::Key_Control); +        if (!m_accessKeysPressed) +        { +            if (checkForAccessKey(event)) +            { +                hideAccessKeys(); +                event->accept(); +                return; +            } +            hideAccessKeys(); +        } +        else +        { +            QTimer::singleShot(200, this, SLOT(accessKeyShortcut())); +        } +    } +      if (event->modifiers() == Qt::ControlModifier)      {          if (event->key() == Qt::Key_C) @@ -898,6 +927,179 @@ void WebView::dragMoveEvent(QDragMoveEvent *event)  } +void WebView::hideAccessKeys() +{ +    if (!m_accessKeyLabels.isEmpty()) +    { +        for (int i = 0; i < m_accessKeyLabels.count(); ++i) +        { +            QLabel *label = m_accessKeyLabels[i]; +            label->hide(); +            label->deleteLater(); +        } +        m_accessKeyLabels.clear(); +        m_accessKeyNodes.clear(); +        update(); +    } +} + + +void WebView::showAccessKeys() +{ +    QStringList supportedElement; +    supportedElement << QLatin1String("a") +                     << QLatin1String("input") +                     << QLatin1String("area") +                     << QLatin1String("button") +                     << QLatin1String("label") +                     << QLatin1String("legend") +                     << QLatin1String("textarea"); + +    QList<QChar> unusedKeys; +    for (char c = 'A'; c <= 'Z'; ++c) +        unusedKeys << QLatin1Char(c); +    for (char c = '0'; c <= '9'; ++c) +        unusedKeys << QLatin1Char(c); + +    QRect viewport = QRect(page()->mainFrame()->scrollPosition(), page()->viewportSize()); +    // Priority first goes to elements with accesskey attributes +    QList<QWebElement> alreadyLabeled; +    Q_FOREACH(const QString & elementType, supportedElement) +    { +        QList<QWebElement> result = page()->mainFrame()->findAllElements(elementType).toList(); +        Q_FOREACH(const QWebElement & element, result) +        { +            const QRect geometry = element.geometry(); +            if (geometry.size().isEmpty() +                    || !viewport.contains(geometry.topLeft())) +            { +                continue; +            } +            QString accessKeyAttribute = element.attribute(QLatin1String("accesskey")).toUpper(); +            if (accessKeyAttribute.isEmpty()) +                continue; +            QChar accessKey; +            for (int i = 0; i < accessKeyAttribute.count(); i += 2) +            { +                const QChar &possibleAccessKey = accessKeyAttribute[i]; +                if (unusedKeys.contains(possibleAccessKey)) +                { +                    accessKey = possibleAccessKey; +                    break; +                } +            } +            if (accessKey.isNull()) +            { +                continue; +            } +            unusedKeys.removeOne(accessKey); +            makeAccessKeyLabel(accessKey, element); +            alreadyLabeled.append(element); +        } +    } + +    // Pick an access key first from the letters in the text and then from the +    // list of unused access keys +    Q_FOREACH(const QString & elementType, supportedElement) +    { +        QWebElementCollection result = page()->mainFrame()->findAllElements(elementType); +        Q_FOREACH(const QWebElement & element, result) +        { +            const QRect geometry = element.geometry(); +            if (unusedKeys.isEmpty() +                    || alreadyLabeled.contains(element) +                    || geometry.size().isEmpty()) +            { +                continue; +            } +            QChar accessKey; +            QString text = element.toPlainText().toUpper(); +            for (int i = 0; i < text.count(); ++i) +            { +                const QChar &c = text.at(i); +                if (unusedKeys.contains(c)) +                { +                    accessKey = c; +                    break; +                } +            } +            if (accessKey.isNull()) +                accessKey = unusedKeys.takeFirst(); +            unusedKeys.removeOne(accessKey); +            makeAccessKeyLabel(accessKey, element); +        } +    } +} + + +void WebView::makeAccessKeyLabel(const QChar &accessKey, const QWebElement &element) +{ +    QLabel *label = new QLabel(this); +    label->setText(QString(QLatin1String("<qt><b>%1</b>")).arg(accessKey)); + +    label->setAutoFillBackground(true); +    label->setFrameStyle(QFrame::Box | QFrame::Plain); +    QPoint point = element.geometry().center(); +    point -= page()->mainFrame()->scrollPosition(); +    label->move(point); +    label->show(); +    point.setX(point.x() - label->width() / 2); +    label->move(point); +    m_accessKeyLabels.append(label); +    m_accessKeyNodes[accessKey] = element; +} + + +bool WebView::checkForAccessKey(QKeyEvent *event) +{ +    if (m_accessKeyLabels.isEmpty()) +        return false; + +    QString text = event->text(); +    if (text.isEmpty()) +        return false; +    QChar key = text.at(0).toUpper(); +    bool handled = false; +    if (m_accessKeyNodes.contains(key)) +    { +        QWebElement element = m_accessKeyNodes[key]; +        QPoint p = element.geometry().center(); +        QWebFrame *frame = element.webFrame(); +        Q_ASSERT(frame); +        do +        { +            p -= frame->scrollPosition(); +            frame = frame->parentFrame(); +        } +        while (frame && frame != page()->mainFrame()); +        QMouseEvent pevent(QEvent::MouseButtonPress, p, Qt::LeftButton, 0, 0); +        rApp->sendEvent(this, &pevent); +        QMouseEvent revent(QEvent::MouseButtonRelease, p, Qt::LeftButton, 0, 0); +        rApp->sendEvent(this, &revent); +        handled = true; +    } +    return handled; +} + + +void WebView::accessKeyShortcut() +{ +    if (!hasFocus() +            || !m_accessKeysPressed +            || !ReKonfig::accessKeysEnabled()) +        return; +    if (m_accessKeyLabels.isEmpty()) +    { +        showAccessKeys(); +    } +    else +    { +        hideAccessKeys(); +    } +    m_accessKeysPressed = false; +} + +  void WebView::sendByMail()  {      KAction *a = qobject_cast<KAction*>(sender()); @@ -906,3 +1108,4 @@ void WebView::sendByMail()      KToolInvocation::invokeMailer("", "", "", "", url);  } + diff --git a/src/webview.h b/src/webview.h index 95f27f17..0d94aaf6 100644 --- a/src/webview.h +++ b/src/webview.h @@ -37,6 +37,8 @@  //Qt Includes  #include <QtCore/QTime> +#include <QLabel> +#include <QToolTip>  // Forward Declarations  class WebPage; @@ -100,6 +102,11 @@ private Q_SLOTS:      void stopScrolling();      void changeWindowIcon(); +    void accessKeyShortcut(); +    void hideAccessKeys(); + +    void loadStarted(); +      Q_SIGNALS:      void loadUrl(const KUrl &, const Rekonq::OpenType &);      void zoomChanged(int); @@ -107,6 +114,11 @@ Q_SIGNALS:      void openNextInHistory();  private: +    bool checkForAccessKey(QKeyEvent *event); +    void showAccessKeys(); +    void makeAccessKeyLabel(const QChar &accessKey, const QWebElement &element); + +private:      QPoint m_mousePos;      QPoint m_clickPos; @@ -125,6 +137,11 @@ private:      bool m_smoothScrolling;      int m_dy;      int m_smoothScrollSteps; + +    // Access Keys +    QList<QLabel*> m_accessKeyLabels; +    QHash<QChar, QWebElement> m_accessKeyNodes; +    bool m_accessKeysPressed;  };  #endif | 
