[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-active
Subject:    linkpopup patch
From:       Sebastian =?ISO-8859-1?Q?K=FCgler?= <sebas () kde ! org>
Date:       2012-02-03 10:42:06
Message-ID: 2193325.sOA6IYQB2I () marvin ! vizzzion ! net
[Download RAW message or body]

Hey all,

As you might have seen, I've merged the link popup stuff into master, 
basically providing a popup in the webbrowser when a link is pressed and hold.

This involves a few more intrusive changes to link handling, as we now handle 
all link clicked events in the KDeclarativeWebView code, which also means we 
load links for new windows directly now (that's a small regression, but quite 
straight-forward to fix). Opening in new windows is now possible for all links 
though, so quite an improvement for certain workflows.

Attached is a patch you can revert if you run into problems with the above 
changes, until I return and fix those =)

Cheers,
-- 
sebas

http://www.kde.org | http://vizZzion.org | GPG Key ID: 9119 0EF9
["remove-linkpopup.diff" (remove-linkpopup.diff)]

diff --git a/applications/webbrowser/package/contents/ui/content/CompletionPopup.qml \
b/applications/webbrowser/package/contents/ui/content/CompletionPopup.qml index \
                b66d915..52d85be 100644
--- a/applications/webbrowser/package/contents/ui/content/CompletionPopup.qml
+++ b/applications/webbrowser/package/contents/ui/content/CompletionPopup.qml
@@ -189,7 +189,7 @@ Item {
             PlasmaComponents.Label {
                 id: rssActionLabel
                 width: 400
-                text: i18n("Link copied to clipboard")
+                text: i18n("Feed link copied to clipboard")
                 visible: false
                 anchors { top: rssButton.top; bottom: rssButton.bottom; left: \
rssButton.right; leftMargin: 8 }  }
diff --git a/applications/webbrowser/package/contents/ui/content/FlickableWebView.qml \
b/applications/webbrowser/package/contents/ui/content/FlickableWebView.qml index \
                91ca0f3..72c0323 100644
--- a/applications/webbrowser/package/contents/ui/content/FlickableWebView.qml
+++ b/applications/webbrowser/package/contents/ui/content/FlickableWebView.qml
@@ -42,6 +42,7 @@
 import QtQuick 1.0
 import org.kde.kdewebkit 0.1
 import org.kde.plasma.components 0.1 as PlasmaComponents
+import "LinkPopup.js" as LinkPopupHelper
 
 
 Flickable {
@@ -54,6 +55,7 @@ Flickable {
     property alias stop: webView.stop
     property alias reload: webView.reload
     property alias forward: webView.forward
+    property bool interactiveSuspended: false
 
     signal newWindowRequested(string url)
 
@@ -61,7 +63,12 @@ Flickable {
     width: parent.width
     contentWidth: Math.max(parent.width,webView.width)
     contentHeight: Math.max(parent.height,webView.height)
-    interactive: (webView.flickingEnabled && ((webView.height > height) || \
(webView.width > width))) +    interactive: {
+        (webView.flickingEnabled &&
+         !interactiveSuspended &&
+         ((webView.height > height) ||
+         (webView.width > width)))
+    }
     anchors.top: headerSpace.bottom
     anchors.bottom: parent.top
     anchors.left: parent.left
@@ -82,6 +89,7 @@ Flickable {
         //settings.pluginsEnabled: true
 
         //FIXME: glorious hack just to obtain a signal of the url of the new \
requested page +        // Should be replaced with signal from KDeclarativeWebView
         newWindowComponent: Component {
             Item {
                 id: newPageComponent
@@ -143,6 +151,47 @@ Flickable {
             }
         }
 
+        function handleLinkPressed(linkUrl, linkRect)
+        {
+            print("link pressed: " + linkUrl + " | " + linkRect.x + " " + linkRect.y \
+ " " + linkRect.width + " " + linkRect.height); +//            \
flickable.interactiveSuspended = true; +//             highlightRect.x = linkRect.x;
+//             highlightRect.y = linkRect.y;
+//             highlightRect.width = linkRect.width;
+//             highlightRect.height = linkRect.height;
+        }
+
+        function handleLinkPressAndHold(linkUrl, linkRect)
+        {
+//            print("... and hold: " + linkUrl + " | " + linkRect.x + " " + \
linkRect.y + " " + linkRect.width + " " + linkRect.height); +            \
linkPopupLoader.source = "LinkPopup.qml"; +            if (linkPopupLoader.status == \
Loader.Ready) { +                flickable.interactiveSuspended = true;
+                highlightRect.x = linkRect.x;
+                highlightRect.y = linkRect.y;
+                highlightRect.width = linkRect.width;
+                highlightRect.height = linkRect.height;
+
+                var linkPopup = linkPopupLoader.item;
+                linkPopup.url = linkUrl
+                linkPopup.linkRect.x = linkRect.x
+                linkPopup.linkRect.y = linkRect.y
+                linkPopup.linkRect.width = linkRect.width
+                linkPopup.linkRect.height = linkRect.height
+                linkPopup.state  = "expanded";
+                //print(" type: " + typeof(linkRect));
+            }
+        }
+
+        Rectangle {
+            id: highlightRect
+            color: theme.highlightColor
+            opacity: 0.2
+            visible: (linkPopupLoader.source != "" && linkPopupLoader.item.state == \
"expanded") +        }
+
+        Loader { id: linkPopupLoader }
+
         Keys.onLeftPressed: webView.contentsScale -= 0.1
         Keys.onRightPressed: webView.contentsScale += 0.1
 
@@ -245,18 +294,25 @@ Flickable {
             }
         }
         onZoomTo: doZoom(zoom,centerX,centerY)
+        onClick: {
+            //print("fickable click");
+            //if (linkPopupLoader.status == Loader.Ready) linkPopupLoader.item.state \
= "collapsed"; +        }
+        onLinkPressed: handleLinkPressed(linkUrl, linkRect)
+        onLinkPressAndHold: handleLinkPressAndHold(linkUrl, linkRect)
     }
 
     PlasmaComponents.CommonDialog {
         id: alertDialog
         titleText: i18n("JavaScript Alert")
+        buttonTexts: [i18n("Close")]
+        onButtonClicked: close()
 
         property alias text: alertLabel.text
 
         content: PlasmaComponents.Label {
+            anchors.margins: 12
             id: alertLabel
-            anchors.fill: alertDialog
-            text: "Here goes the alert message."
         }
     }
 
diff --git a/applications/webbrowser/package/contents/ui/content/LinkPopup.js \
b/applications/webbrowser/package/contents/ui/content/LinkPopup.js new file mode \
100644 index 0000000..5ea5bd4
--- /dev/null
+++ b/applications/webbrowser/package/contents/ui/content/LinkPopup.js
@@ -0,0 +1,26 @@
+function placeLinkPopup(mouse) {
+    // Find the root item, then map our cursor position to it
+    // in order to check if the edit bubble could end up off-screen
+    var rootItem = parent;
+    while (rootItem.parent) {
+        rootItem = rootItem.parent;
+    }
+    var distanceToTop = webView.mapToItem(rootItem, mouse.x, mouse.y);
+    //var distanceToTop = mouse;
+    print( "   distanceToTop: " + distanceToTop.x);
+    print( " mouse: x: " + mouse.x + " y: " + mouse.y);
+    if (distanceToTop.x < linkPopup.width/2) {
+        print(" hitting the left edge " + distanceToTop.x);
+        //linkPopup.x = mouse.x
+
+    } else {
+        linkPopup.x = mouse.x-(linkPopup.width/2)
+    }
+    if (distanceToTop.y > linkPopup.height + header.height) {
+        print(" placing at mouse.y : " + mouse.y + " " + linkPopup.height)
+        linkPopup.y = mouse.y;
+    } else {
+        //linkPopup.y = mouse.y-(linkPopup.width/2)
+    }
+
+}
diff --git a/applications/webbrowser/package/contents/ui/content/LinkPopup.qml \
b/applications/webbrowser/package/contents/ui/content/LinkPopup.qml new file mode \
100644 index 0000000..1606460
--- /dev/null
+++ b/applications/webbrowser/package/contents/ui/content/LinkPopup.qml
@@ -0,0 +1,190 @@
+/*
+*   Copyright 2011 by Sebastian Kügler <sebas@kde.org>
+*
+*   This program is free software; you can redistribute it and/or modify
+*   it under the terms of the GNU Library General Public License as
+*   published by the Free Software Foundation; either version 2, or
+*   (at your option) any later version.
+*
+*   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 Library General Public
+*   License along with this program; if not, write to the
+*   Free Software Foundation, Inc.,
+*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+*/
+
+import QtQuick 1.1
+import org.kde.plasma.core 0.1 as PlasmaCore
+import org.kde.qtextracomponents 0.1
+import org.kde.plasma.components 0.1 as PlasmaComponents
+
+
+PlasmaCore.FrameSvgItem {
+    id: linkPopup
+    objectName: "linkPopup"
+    property Item linkRect: Item {}
+    property int iconSize: 32
+    property int space: 12
+    property string url
+
+    imagePath: "dialogs/background"
+    //width: (iconSize*2) + iconSize
+    width: space*30
+    height: space*10
+    //height: iconSize*2
+    //width: childrenRect.width
+    //height: childrenRect.height
+    z: 100000
+    state: "collapsed"
+
+    MouseArea {
+        id: hidePopup
+        //anchors.fill: flickable
+        x: -flickable.width; y: -flickable.height; width: flickable.width*2; height: \
flickable.height*2 +        onClicked: linkPopup.state = "collapsed"
+        visible: linkPopup.state == "expanded"
+        //Rectangle {color: "green"; opacity: 0.2; anchors.fill: parent; }
+    }
+
+    Item {
+        id: buttonRow
+        anchors.fill: parent
+        anchors.margins: space*2
+        QIconItem {
+            id: newWindowIcon
+            icon: QIcon("window-new")
+            width: linkPopup.iconSize
+            height: width
+            anchors { top: parent.top; left: parent.left; }
+            MouseArea {
+                anchors.fill: parent;
+            }
+        }
+        PlasmaComponents.Label {
+            id: newWindowLabel
+            anchors { verticalCenter: newWindowIcon.verticalCenter; left: \
newWindowIcon.right; right: parent.right; leftMargin: space } +            text: \
i18n("Open link in new window") +            elide: Text.ElideMiddle
+        }
+        MouseArea {
+            anchors { top: newWindowIcon.top; bottom: newWindowIcon.bottom; left: \
parent.left; right: parent.right; } +            onClicked: {
+                flickable.newWindowRequested(url);
+                print("open in new window " + url);
+                linkPopup.state = "collapsed"; 
+            }
+            onPressed: PropertyAnimation {  target: newWindowIcon; properties: \
"scale"; +                                            from: 1.0; to: 0.75;
+                                            duration: 175; easing.type: \
Easing.OutExpo; } +            onReleased: PropertyAnimation { target: newWindowIcon; \
properties: "scale"; +                                            from: 0.75; to: \
1.0; +                                            duration: 175; easing.type: \
Easing.OutExpo; } +        }
+        QIconItem {
+            id: copyIcon
+            icon: QIcon("edit-copy")
+            width: linkPopup.iconSize
+            height: linkPopup.iconSize
+            anchors { top: newWindowIcon.bottom; left: parent.left; topMargin: \
space; } +            //enabled: textInput.selectedText != ""
+//             MouseArea {
+//                 anchors.fill: parent;
+//             }
+            TextInput { id: textField; visible: false }
+        }
+        PlasmaComponents.Label {
+            id: copyLabel
+            anchors { verticalCenter: copyIcon.verticalCenter; left: copyIcon.right; \
right: parent.right; leftMargin: space } +            text: i18n("Copy link to \
clipboard"); +            elide: Text.ElideMiddle
+        }
+        MouseArea {
+            anchors { top: copyIcon.top; bottom: copyIcon.bottom; left: parent.left; \
right: parent.right; } +            onClicked: {
+                textField.text = url;
+                textField.selectAll();
+                textField.copy();
+                textField.text = ""
+
+                linkPopup.state = "collapsed";
+
+            }
+            onPressed: PropertyAnimation {  target: copyIcon; properties: "scale";
+                                            from: 1.0; to: 0.75;
+                                            duration: 175; easing.type: \
Easing.OutExpo; } +            onReleased: PropertyAnimation { target: copyIcon; \
properties: "scale"; +                                            from: 0.75; to: \
1.0; +                                            duration: 175; easing.type: \
Easing.OutExpo; } +        }
+    }
+    states: [
+        State {
+            id: expanded
+            name: "expanded";
+            PropertyChanges { target: linkPopup; opacity: 1.0; scale: 1.0 }
+        },
+        State {
+            id: collapsed
+            name: "collapsed";
+            PropertyChanges { target: linkPopup; opacity: 0; scale: 0.9 }
+        }
+    ]
+
+    transitions: [
+        Transition {
+            from: "collapsed"; to: "expanded"
+            ParallelAnimation {
+                ScriptAction {
+                    script: {
+                        placePopup();
+                        flickable.interactiveSuspended = true;
+                    }
+                }
+                PropertyAnimation { properties: "opacity"; duration: 175; \
easing.type: Easing.InExpo; } +                PropertyAnimation { properties: \
"scale"; duration: 175; easing.type: Easing.InExpo; } +            }
+        },
+        Transition {
+            from: "expanded"; to: "collapsed"
+            ParallelAnimation {
+                ScriptAction {
+                    script: {
+                        flickable.interactiveSuspended = false;
+                    }
+                }
+                PropertyAnimation { properties: "opacity"; duration: 175; \
easing.type: Easing.OutExpo; } +                PropertyAnimation { properties: \
"scale"; duration: 100; easing.type: Easing.OutExpo; } +            }
+        }
+    ]
+
+    function placePopup () {
+        var rootItem = parent;
+        while (rootItem.parent) {
+            rootItem = rootItem.parent;
+        }
+        var mouse = linkRect;
+        var distanceToTop = webView.mapToItem(rootItem, mouse.x, mouse.y);
+        //var distanceToTop = mouse;
+//         print( "   distanceToTop: " + distanceToTop.x);
+//         print( " mouse: x: " + mouse.x + " y: " + mouse.y);
+        if (distanceToTop.x < linkPopup.width/2) {
+//             print(" hitting the left edge " + distanceToTop.x);
+            //linkPopup.x = mouse.x
+
+        } else {
+            linkPopup.x = mouse.x-(linkPopup.width/2)
+        }
+        if (distanceToTop.y > linkPopup.height + header.height) {
+//             print(" placing at mouse.y : " + mouse.y + " " + linkPopup.height)
+            linkPopup.y = mouse.y - linkPopup.height;
+        } else {
+            //linkPopup.y = mouse.y-(linkPopup.width/2)
+        }
+    }
+
+}
diff --git a/applications/webbrowser/src/kdeclarativewebview.cpp \
b/applications/webbrowser/src/kdeclarativewebview.cpp index f23bcfd..4cba906 100644
--- a/applications/webbrowser/src/kdeclarativewebview.cpp
+++ b/applications/webbrowser/src/kdeclarativewebview.cpp
@@ -135,12 +135,20 @@ void GraphicsWebView::mousePressEvent(QGraphicsSceneMouseEvent* \
event)  QGraphicsWebView::mousePressEvent(event);
 
     QWebHitTestResult hit = \
                page()->mainFrame()->hitTestContent(pressPoint.toPoint());
-    if (hit.isContentEditable())
+    if (hit.isContentEditable()) {
         parent->forceActiveFocus();
-
+    }
     // Comboboxes and flicking don't go together well,
     // disable flicking as long as the combo box is open
     setFlickingEnabled(hit.element().tagName() != "SELECT");
+
+    kDebug() << " - - >  Hit element: " << hit.element().tagName() << \
hit.linkElement().geometry(); +    if (!hit.linkElement().geometry().isNull()) {
+        kDebug() << "XXXXXXXXXX link pressed. .. ";
+        emit linkPressed(hit.linkUrl(), hit.linkElement().geometry());
+    }
+    //QMouseEvent* me = new QMouseEvent(QEvent::MouseButtonDblClick, (event->pos() / \
parent->contentsScale()).toPoint(), event->button(), event->buttons(), 0); +    emit \
click(event->pos().x(), event->pos().y());  setFocus();
 }
 
@@ -159,12 +167,29 @@ void \
GraphicsWebView::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)  delete me;
 }
 
+void GraphicsWebView::handleLinkClicked(const QUrl &link)
+{
+    QUrl u(link);
+    if (pressTimer.isActive()) {
+        kDebug() << "timer is running, loading URL" << link;
+        page()->mainFrame()->load(u);
+    } else {
+        kDebug() << "timer is not running, not loading url" << link;
+    }
+}
+
 void GraphicsWebView::timerEvent(QTimerEvent* event)
 {
     if (event->timerId() == pressTimer.timerId()) {
         pressTimer.stop();
         grabMouse();
         parent->setKeepMouseGrab(true);
+        kDebug() << "handle pressAndHold";
+        QWebHitTestResult hit = \
page()->mainFrame()->hitTestContent(pressPoint.toPoint()); +        if \
(!hit.linkElement().geometry().isNull()) { +            kDebug() << "XXXXXXXXXX link \
pressed AND HOLD. .. "; +            emit linkPressAndHold(hit.linkUrl(), \
hit.linkElement().geometry()); +        }
     }
 }
 
@@ -344,11 +369,21 @@ void KDeclarativeWebView::init()
 #endif
     connect(d->view, SIGNAL(geometryChanged()), this, \
                SLOT(updateDeclarativeWebViewSize()));
     connect(d->view, SIGNAL(flickingEnabledChanged()), this, \
SLOT(updateFlickingEnabled())); +    connect(d->view, SIGNAL(click(int, int)), this, \
                SIGNAL(click(int, int)));
     connect(d->view, SIGNAL(doubleClick(int, int)), this, SIGNAL(doubleClick(int, \
int))); +    
+    //connect(d->view, SIGNAL(loadLink(const QUrl&, const QRect&)), \
SIGNAL(linkClicked(const QUrl&, const QRect&))); +    connect(d->view, \
SIGNAL(linkPressed(const QUrl&, const QRect&)), +            this, \
SIGNAL(linkPressed(const QUrl&, const QRect&))); +    connect(d->view, \
SIGNAL(linkPressAndHold(const QUrl&, const QRect&)), +            this, \
                SIGNAL(linkPressAndHold(const QUrl&, const QRect&)));
     connect(d->view, SIGNAL(scaleChanged()), this, SIGNAL(contentsScaleChanged()));
 
     connect(access, SIGNAL(finished(QNetworkReply*)), page(), \
SLOT(handleNetworkErrors(QNetworkReply*)));  
+    wp->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
+    connect(wp, SIGNAL(linkClicked(const QUrl&)), d->view, \
SLOT(handleLinkClicked(const QUrl&))); +
 
     d->dirWatch = new KDirWatch(this);
     QString configPath = KStandardDirs::locateLocal("config", \
                "active-webbrowserrc");
diff --git a/applications/webbrowser/src/kdeclarativewebview.h \
b/applications/webbrowser/src/kdeclarativewebview.h index e4ea78f..8fac5b5 100644
--- a/applications/webbrowser/src/kdeclarativewebview.h
+++ b/applications/webbrowser/src/kdeclarativewebview.h
@@ -82,6 +82,10 @@ class GraphicsWebView : public QGraphicsWebView {
     Q_OBJECT
 public:
     GraphicsWebView(KDeclarativeWebView* parent = 0);
+
+public Q_SLOTS:
+    void handleLinkClicked(const QUrl &link);
+
 protected:
     void mousePressEvent(QGraphicsSceneMouseEvent* event);
     void mouseReleaseEvent(QGraphicsSceneMouseEvent* event);
@@ -93,8 +97,12 @@ protected:
     void setFlickingEnabled(bool enabled);
 
 Q_SIGNALS:
+    void click(int clickX, int clickY);
     void doubleClick(int clickX, int clickY);
     void flickingEnabledChanged();
+    void linkPressed(const QUrl&, const QRect &linkRect);
+    void linkPressAndHold(const QUrl&, const QRect &linkRect);
+    void linkClicked(const QUrl&, const QRect &linkRect);
 
 private:
     KDeclarativeWebView *parent;
@@ -246,7 +254,11 @@ Q_SIGNALS:
     void loadFinished();
     void loadFailed();
 
+    void click(int clickX, int clickY);
     void doubleClick(int clickX, int clickY);
+    void linkPressed(const QUrl &linkUrl, const QRect &linkRect);
+    void linkPressAndHold(const QUrl &linkUrl, const QRect &linkRect);
+    void linkClicked(const QUrl &linkUrl, const QRect &linkRect);
 
     void zoomTo(qreal zoom, int centerX, int centerY);
 



_______________________________________________
Active mailing list
Active@kde.org
https://mail.kde.org/mailman/listinfo/active


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic