diff options
author | Andras Becsi <andras.becsi@theqtcompany.com> | 2015-07-27 18:25:58 +0200 |
---|---|---|
committer | Andras Becsi <andras.becsi@theqtcompany.com> | 2015-08-12 17:22:03 +0200 |
commit | 0544031867f31e191f8a1d855dbf33dc81161198 (patch) | |
tree | d509b9ae3e657e9f354a67532db411f201910f90 /src | |
parent | a8061cb3910caca4ca48f0dd7f7883ccca9920d5 (diff) |
Add GridView for HomeScreen
This patch also adds hooks for apple-touch-icon handling
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/BrowserDialog.qml | 56 | ||||
-rw-r--r-- | src/qml/BrowserWindow.qml | 53 | ||||
-rw-r--r-- | src/qml/HomeScreen.qml | 416 | ||||
-rw-r--r-- | src/qml/NavigationBar.qml | 46 | ||||
-rw-r--r-- | src/qml/PageView.qml | 29 | ||||
-rw-r--r-- | src/qml/assets/UIButton.qml | 4 | ||||
-rw-r--r-- | src/resources.qrc | 2 | ||||
-rw-r--r-- | src/src.pro | 2 | ||||
-rw-r--r-- | src/utils.h | 54 |
9 files changed, 553 insertions, 109 deletions
diff --git a/src/qml/BrowserDialog.qml b/src/qml/BrowserDialog.qml deleted file mode 100644 index d463be6..0000000 --- a/src/qml/BrowserDialog.qml +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** -** $QT_BEGIN_LICENSE:BSD$ -** You may use this file under the terms of the BSD license as follows: -** -** "Redistribution and use in source and binary forms, with or without -** modification, are permitted provided that the following conditions are -** met: -** * Redistributions of source code must retain the above copyright -** notice, this list of conditions and the following disclaimer. -** * Redistributions in binary form must reproduce the above copyright -** notice, this list of conditions and the following disclaimer in -** the documentation and/or other materials provided with the -** distribution. -** * Neither the name of The Qt Company Ltd nor the names of its -** contributors may be used to endorse or promote products derived -** from this software without specific prior written permission. -** -** -** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -import QtQuick 2.1 -import QtQuick.Window 2.2 -import QtWebEngine 1.1 - -Window { - property alias defaultProfile: webView.profile - property alias currentWebView: webView - flags: Qt.Dialog - width: 800 - height: 600 - visible: true - onClosing: destroy() - WebEngineView { - id: webView - anchors.fill: parent - } -} diff --git a/src/qml/BrowserWindow.qml b/src/qml/BrowserWindow.qml index bedf57a..7e6a5e4 100644 --- a/src/qml/BrowserWindow.qml +++ b/src/qml/BrowserWindow.qml @@ -35,7 +35,7 @@ ** ****************************************************************************/ -import QtQuick 2.1 +import QtQuick 2.5 import QtWebEngine 1.1 import QtWebEngine.experimental 1.0 @@ -53,15 +53,19 @@ Item { id: browserWindow property Item currentWebView: { - return tabs.get(tabs.currentIndex) ? tabs.get(tabs.currentIndex).item.webView : null + return tabView.get(tabView.currentIndex) ? tabView.get(tabView.currentIndex).item.webView : null } property int toolBarSize: 80 property string uiColor: "#46a2da" property string uiSeparatorColor: "#7ebee5" - property string uiSeparatorColor2: "#a3d1ed" - property string buttonHighlightColor: "#3f91c4" - property string uiSelectionColor: "#fddd5c" + property string tabEditSeparatorColor: "#a3d1ed" + property string buttonPressedColor: "#3f91c4" + property string uiHighlightColor: "#fddd5c" + property string inactivePagerColor: "#bcbdbe" + property string textFieldStrokeColor: "#3882ae" + property string placeholderColor: "#a0a1a2" + property string iconStrokeColor: "#0e202c" property string defaultFontFamily: "Open Sans" property int animationDuration: 200 @@ -109,15 +113,15 @@ Item { id: newTabAction shortcut: "Ctrl+T" onTriggered: { - tabs.createEmptyTab() + tabView.createEmptyTab() navigation.addressBar.forceActiveFocus(); navigation.addressBar.selectAll(); - tabs.currentIndex = tabs.count - 1 + tabView.currentIndex = tabView.count - 1 } } Action { shortcut: "Ctrl+W" - onTriggered: tabs.remove(tabs.currentIndex) + onTriggered: tabView.remove(tabView.currentIndex) } @@ -145,7 +149,7 @@ Item { } visible: opacity != 0.0 - opacity: tabs.viewState == "list" ? 1.0 : 0.0 + opacity: tabView.viewState == "list" ? 1.0 : 0.0 RowLayout { spacing: 0 @@ -163,7 +167,7 @@ Item { top: parent.top bottom: parent.bottom } - color: uiSeparatorColor2 + color: tabEditSeparatorColor } Rectangle { width: 40 @@ -189,10 +193,10 @@ Item { anchors.centerIn: parent Text { anchors.centerIn: parent - text: tabs.count + text: tabView.count color: "white" font.family: defaultFontFamily - font.pointSize: 20 + font.pixelSize: 20 } } } @@ -202,7 +206,7 @@ Item { top: parent.top bottom: parent.bottom } - color: uiSeparatorColor2 + color: tabEditSeparatorColor } UIButton { id:doneButton @@ -212,11 +216,11 @@ Item { anchors.centerIn: parent text: "Done" font.family: defaultFontFamily - font.pointSize: 28 + font.pixelSize: 28 } implicitWidth: 120 onClicked: { - tabs.viewState = "page" + tabView.viewState = "page" } } } @@ -272,8 +276,8 @@ Item { } } PageView { - id: tabs - interactive: !sslDialog.visible + id: tabView + interactive: !sslDialog.visible && homeScreen.state == "disabled" height: parent.height @@ -289,9 +293,9 @@ Item { tab.webView.url = engine.fromUserInput("qt.io") } onCurrentIndexChanged: { - if (!tabs.get(tabs.currentIndex)) + if (!tabView.get(tabView.currentIndex)) return - navigation.webView = tabs.get(tabs.currentIndex).item.webView + navigation.webView = tabView.get(tabView.currentIndex).item.webView } } @@ -343,4 +347,15 @@ Item { informativeText = "SSL error from URL\n\n" + currentError.url + "\n\n" + currentError.description + "\n" } } + + HomeScreen { + id: homeScreen + z: 5 + height: parent.height - toolBarSize + anchors { + top: navigation.bottom + left: parent.left + right: parent.right + } + } } diff --git a/src/qml/HomeScreen.qml b/src/qml/HomeScreen.qml new file mode 100644 index 0000000..881fcb4 --- /dev/null +++ b/src/qml/HomeScreen.qml @@ -0,0 +1,416 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtBrowser project. +** +** $QT_BEGIN_LICENSE:GPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPLv2 included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/gpl-2.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 +import "assets" + +Rectangle { + id: homeScreen + + property int padding: 60 + property int cellSize: width / 5 - padding + + state: "disabled" + + signal add(string title, string url, string iconUrl, string fallbackColor) + onAdd: { + var element = { "title": title, "url": url, "iconUrl": iconUrl, "fallbackColor": fallbackColor } + listModel.append(element) + } + + function contains(url) { + for (var idx = 0; idx < listModel.count; ++idx) { + if (listModel.get(idx).url === url) + return idx; + } + return -1; + } + + function select(index) { + gridView.positionViewAtIndex(index, GridView.Contain) + gridView.draggingChanged() + } + + states: [ + State { + name: "enabled" + AnchorChanges { + target: homeScreen + anchors.top: navigation.bottom + } + }, + State { + name: "disabled" + AnchorChanges { + target: homeScreen + anchors.top: homeScreen.parent.bottom + } + }, + State { + name: "edit" + } + ] + + transitions: Transition { + AnchorAnimation { duration: animationDuration; easing.type : Easing.InSine } + } + + ListModel { + id: listModel + } + + GridView { + id: gridView + + property real dragStart: 0 + property real page: 4 * cellWidth + + anchors.fill: parent + model: listModel + cellWidth: homeScreen.cellSize + homeScreen.padding + cellHeight: cellWidth + flow: GridView.FlowTopToBottom + boundsBehavior: Flickable.StopAtBounds + maximumFlickVelocity: 0 + contentHeight: parent.height + displayMarginEnd: 3 * page + rightMargin: (parent.width - 4 * gridView.cellWidth - homeScreen.padding) / 2 + + Behavior on contentX { + NumberAnimation { duration: 1.5 * animationDuration; easing.type : Easing.InSine} + } + + anchors { + topMargin: toolBarSize + leftMargin: (parent.width - 4 * gridView.cellWidth + homeScreen.padding) / 2 + } + onDraggingChanged: { + if (dragging) { + dragStart = contentX + return + } + if (dragStart == 2 * page && contentX < 2 * page) { + contentX = page + return + } + if (dragStart == page) { + if (contentX < page) { + contentX = 0 + return + } + if (page < contentX) { + contentX = 2 * page + return + } + } + if (dragStart == 0 && 0 < contentX) { + contentX = page + return + } + contentX = 0 + } + + delegate: Rectangle { + id: square + property string iconColor: "white" + width: homeScreen.cellSize + height: width + border.color: iconStrokeColor + border.width: 1 + + Text { + function cleanup(string) { + var t = string.replace("-", " ") + .replace("|", " ").replace(",", " ") + return t + } + + visible: bg.color != "white" + text: cleanup(title) + font.family: defaultFontFamily + font.pixelSize: 18 + color: engine.oppositeColor(square.color) + anchors.centerIn: parent + width: parent.width - 10 + height: parent.height + maximumLineCount: 3 + elide: Text.ElideRight + wrapMode: Text.Wrap + verticalAlignment: Text.AlignVCenter + horizontalAlignment: Text.AlignHCenter + } + + Rectangle { + id: bg + anchors { + left: parent.left + top: parent.top + margins: 1 + } + state: "fallback" + width: { + if (icon.sourceSize.width < 100) + return 32 + return square.width - 2 + } + height: width + states: [ + State { + name: "fallback" + PropertyChanges { + target: square + color: fallbackColor + } + PropertyChanges { + target: bg + color: square.color + } + }, + State { + name: "snapshot" + PropertyChanges { + target: bg + color: "white" + } + }, + State { + name: "normal" + PropertyChanges { + target: square + color: iconColor + } + PropertyChanges { + target: bg + color: square.color + } + } + ] + Timer { + id: timer + onTriggered: { + if (!bg.width || !bg.height) + return + + bg.state = "snapshot" + bg.grabToImage(function(result) { + square.iconColor = engine.colorForIcon(result) + bg.state = "normal" + }); + } + } + + Image { + id: icon + anchors.centerIn: parent + width: bg.width + height: bg.height + source: iconUrl + onSourceChanged: bg.state = "snapshot" + onStatusChanged: { + switch (status) { + case Image.Null: + case Image.Loading: + case Image.Error: + square.iconColor = "white" + bg.state = "fallback" + break + case Image.Ready: + bg.state = "normal" + timer.restart() + break + } + } + } + } + Rectangle { + id: overlay + visible: opacity != 0.0 + anchors.fill: parent + color: iconStrokeColor + opacity: { + if (iconMouse.pressed) { + if (homeScreen.state != "edit") + return 0.1 + return 0.4 + } + if (homeScreen.state == "edit") + return 0.3 + return 0.0 + } + } + MouseArea { + id: iconMouse + anchors.fill: parent + onPressAndHold: { + if (homeScreen.state == "edit") { + homeScreen.state = "visible" + return + } + homeScreen.state = "edit" + } + onPressed: { + console.log("index="+ index +" | title=" + title + " | url=" + url + " | iconUrl=" + iconUrl + " | fallbackColor=" + fallbackColor) + // TODO: open bookmark + } + } + Rectangle { + enabled: homeScreen.state == "edit" + opacity: enabled ? 1.0 : 0.0 + width: image.sourceSize.width + height: image.sourceSize.height - 2 + radius: width / 2 + color: iconStrokeColor + anchors { + horizontalCenter: parent.right + verticalCenter: parent.top + } + Image { + id: image + opacity: { + if (deleteButton.pressed) + return 0.70 + return 1.0 + } + anchors { + top: parent.top + left: parent.left + } + source: "qrc:///delete" + MouseArea { + id: deleteButton + anchors.fill: parent + onClicked: { + mouse.accepted = true + listModel.remove(index) + gridView.forceLayout() + } + } + } + Behavior on opacity { + NumberAnimation { duration: animationDuration } + } + } + } + } + Rectangle { + width: homeScreen.cellSize - homeScreen.padding / 2 - 10 + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + } + MouseArea { + enabled: homeScreen.state == "edit" + anchors.fill: parent + onPressed: homeScreen.state = "visible" + } + } + Rectangle { + width: homeScreen.cellSize - homeScreen.padding / 2 - 10 + anchors { + right: parent.right + top: parent.top + bottom: parent.bottom + } + MouseArea { + enabled: homeScreen.state == "edit" + anchors.fill: parent + onPressed: homeScreen.state = "visible" + } + } + Rectangle { + id: pageIndicator + color: "transparent" + anchors { + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + height: 80 + width: 150 + Rectangle { + property bool active: gridView.contentX < gridView.page + width: enabled && active ? 10 : 8 + height: width + radius: width / 2 + color: active ? iconStrokeColor : uiColor + anchors.verticalCenter: parent.verticalCenter + x: parent.width / 4 - width / 2 + MouseArea { + anchors.fill: parent + onClicked: gridView.contentX = 0 + } + } + Rectangle { + property bool active: gridView.page <= gridView.contentX && gridView.contentX < 2 * gridView.page + width: enabled && active ? 10 : 8 + enabled: gridView.count > 8 + height: width + radius: width / 2 + color: { + if (!enabled) + return inactivePagerColor + + return active ? iconStrokeColor : uiColor + } + anchors.verticalCenter: parent.verticalCenter + x: parent.width / 2 - width / 2 + MouseArea { + anchors.fill: parent + onClicked: gridView.contentX = gridView.page + } + } + Rectangle { + property bool active: 2 * gridView.page <= gridView.contentX + width: enabled && active ? 10 : 8 + enabled: gridView.count > 16 + height: width + radius: width / 2 + color: { + if (!enabled) + return inactivePagerColor + + return active ? iconStrokeColor : uiColor + } + anchors.verticalCenter: parent.verticalCenter + x: 3 * parent.width / 4 - width / 2 + MouseArea { + anchors.fill: parent + onClicked: gridView.contentX = 2 * gridView.page + } + } + } +} diff --git a/src/qml/NavigationBar.qml b/src/qml/NavigationBar.qml index 23cca7e..ce0b80b 100644 --- a/src/qml/NavigationBar.qml +++ b/src/qml/NavigationBar.qml @@ -13,7 +13,7 @@ ToolBar { property Item webView: null visible: opacity != 0.0 - opacity: tabs.viewState == "page" ? 1.0 : 0.0 + opacity: tabView.viewState == "page" ? 1.0 : 0.0 style: ToolBarStyle { background: Rectangle { @@ -100,14 +100,14 @@ ToolBar { style: TextFieldStyle { textColor: "black" font.family: defaultFontFamily - font.pointSize: 28 - selectionColor: uiSelectionColor + font.pixelSize: 28 + selectionColor: uiHighlightColor selectedTextColor: "black" - placeholderTextColor: "#a0a1a2" + placeholderTextColor: placeholderColor background: Rectangle { implicitWidth: 514 implicitHeight: 56 - border.color: "#3881ae" + border.color: textFieldStrokeColor border.width: 1 } padding { @@ -117,7 +117,8 @@ ToolBar { } onAccepted: { webView.url = engine.fromUserInput(text) - tabs.viewState = "page" + homeScreen.state = "disabled" + tabView.viewState = "page" } onEditingFinished: selectAll() onFocusChanged: { @@ -151,7 +152,10 @@ ToolBar { id: homeButton source: "qrc:///home" onClicked: { - console.log("Home clicked") + if (homeScreen.state == "disabled" || homeScreen.state == "edit") + homeScreen.state = "enabled" + else if (homeScreen.state != "disabled") + homeScreen.state = "disabled" } } Rectangle { @@ -166,11 +170,12 @@ ToolBar { id: pageViewButton source: "qrc:///tabs" onClicked: { - if (tabs.viewState == "list") { - tabs.viewState = "page" + if (tabView.viewState == "list") { + tabView.viewState = "page" } else { - tabs.get(tabs.currentIndex).item.webView.takeSnapshot() - tabs.viewState = "list" + tabView.get(tabView.currentIndex).item.webView.takeSnapshot() + homeScreen.state = "disabled" + tabView.viewState = "list" } } Text { @@ -179,9 +184,9 @@ ToolBar { verticalCenterOffset: 4 } - text: tabs.count + text: tabView.count font.family: defaultFontFamily - font.pointSize: 16 + font.pixelSize: 16 font.weight: Font.DemiBold color: "white" } @@ -198,7 +203,16 @@ ToolBar { id: bookmarksButton source: "qrc:///star" onClicked: { - console.log("Bookmarks clicked") + if (!webView) + return + + var idx = homeScreen.contains(webView.url.toString()) + if (idx != -1) { + homeScreen.state = "enabled" + homeScreen.select(idx) + return + } + homeScreen.add(webView.title, webView.url, webView.icon, engine.randomColor()) } } Rectangle { @@ -214,7 +228,7 @@ ToolBar { source: "qrc:///settings" checkable: true checked: false - onClicked: tabs.interactive = !checked + onClicked: tabView.interactive = !checked } } ProgressBar { @@ -233,7 +247,7 @@ ToolBar { color: uiSeparatorColor } progress: Rectangle { - color: uiSelectionColor + color: uiHighlightColor } } minimumValue: 0 diff --git a/src/qml/PageView.qml b/src/qml/PageView.qml index bbe687f..3552a0b 100644 --- a/src/qml/PageView.qml +++ b/src/qml/PageView.qml @@ -58,6 +58,11 @@ Rectangle { property string viewState: "page" + onViewStateChanged: { + if (viewState == "page") + homeScreen.state = "disabled" + } + property QtObject otrProfile: WebEngineProfile { offTheRecord: true } @@ -116,6 +121,7 @@ Rectangle { } profile: defaultProfile + enabled: root.interactive function takeSnapshot() { if (tabItem.image.url == webEngineView.url || tabItem.opacity != 1.0) @@ -148,19 +154,19 @@ Rectangle { if (!request.userInitiated) print("Warning: Blocked a popup window.") else if (request.destination == WebEngineView.NewViewInTab) { - tab = tabs.createEmptyTab() - pathView.positionViewAtIndex(tabs.count - 1, PathView.Center) + tab = tabView.createEmptyTab() + pathView.positionViewAtIndex(tabView.count - 1, PathView.Center) request.openIn(tab.webView) } else if (request.destination == WebEngineView.NewViewInBackgroundTab) { var index = pathView.currentIndex - tab = tabs.createEmptyTab() + tab = tabView.createEmptyTab() request.openIn(tab.webView) pathView.positionViewAtIndex(index, PathView.Center) } else if (request.destination == WebEngineView.NewViewInDialog) { - var dialog = tabs.createEmptyTab() + var dialog = tabView.createEmptyTab() request.openIn(dialog.webView) } else { - var window = tabs.createEmptyTab() + var window = tabView.createEmptyTab() request.openIn(window.webView) } } @@ -194,7 +200,7 @@ Rectangle { TouchTracker { id: tracker - + enabled: root.interactive target: webEngineView anchors.fill: parent onTouchYChanged: browserWindow.touchY = tracker.touchY @@ -282,7 +288,6 @@ Rectangle { } element.item.webView.url = "about:blank" - element.index = listModel.count listModel.append(element) return element.item } @@ -291,10 +296,6 @@ Rectangle { pathView.interactive = false pathView.currentItem.state = "" pathView.currentItem.visible = false - // Update indices of remaining items - for (var idx = index + 1; idx < listModel.count; ++idx) - listModel.get(idx).index -= 1 - listModel.remove(index) pathView.decrementCurrentIndex() pathView.interactive = true @@ -407,7 +408,7 @@ Rectangle { topMargin: 9 horizontalCenter: parent.horizontalCenter } - color: "#0e202c" + color: iconStrokeColor radius: size / 2 width: snapshot.width height: snapshot.height @@ -440,7 +441,7 @@ Rectangle { width: image.sourceSize.width height: image.sourceSize.height - 2 radius: width / 2 - color: "darkgrey" + color: iconStrokeColor anchors { horizontalCenter: parent.right verticalCenter: parent.top @@ -484,7 +485,7 @@ Rectangle { width: parent.width - image.width elide: Text.ElideRight text: item.title - font.pointSize: 16 + font.pixelSize: 16 font.family: defaultFontFamily color: "#0B508C" visible: wrapper.isCurrentItem && wrapper.visibility == 1.0 diff --git a/src/qml/assets/UIButton.qml b/src/qml/assets/UIButton.qml index e83c2e4..3a65c12 100644 --- a/src/qml/assets/UIButton.qml +++ b/src/qml/assets/UIButton.qml @@ -12,11 +12,11 @@ ToolButton { property string source: "" property real radius: 0.0 property string color: uiColor - property string highlightColor: buttonHighlightColor + property string highlightColor: buttonPressedColor style: ButtonStyle { background: Rectangle { opacity: root.enabled ? 1.0 : 0.3 - color: root.pressed ? root.highlightColor : root.color + color: root.pressed || root.checked ? root.highlightColor : root.color radius: root.radius Image { source: root.source diff --git a/src/resources.qrc b/src/resources.qrc index 5d375e1..17e28c8 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -1,11 +1,11 @@ <RCC> <qresource prefix="/"> - <file>qml/BrowserDialog.qml</file> <file>qml/BrowserWindow.qml</file> <file>qml/FeaturePermissionBar.qml</file> <file>qml/MockTouchPoint.qml</file> <file>qml/PageView.qml</file> <file>qml/NavigationBar.qml</file> + <file>qml/HomeScreen.qml</file> <file>qml/assets/UIButton.qml</file> <file alias="home">qml/assets/icons/Btn_Home.png</file> <file alias="tabs">qml/assets/icons/Btn_Tabs.png</file> diff --git a/src/src.pro b/src/src.pro index d0088da..f70fb48 100644 --- a/src/src.pro +++ b/src/src.pro @@ -17,12 +17,12 @@ HEADERS = utils.h \ OTHER_FILES = \ qml/assets/UIButton.qml \ qml/ApplicationRoot.qml \ - qml/BrowserDialog.qml \ qml/BrowserWindow.qml \ qml/FeaturePermissionBar.qml \ qml/MockTouchPoint.qml \ qml/PageView.qml \ qml/NavigationBar.qml \ + qml/HomeScreen.qml \ QT += qml quick webengine QT_PRIVATE += quick-private gui-private core-private diff --git a/src/utils.h b/src/utils.h index 45ba2ad..04c181e 100644 --- a/src/utils.h +++ b/src/utils.h @@ -41,6 +41,8 @@ #include <QtCore/QEvent> #include <QtCore/QFileInfo> #include <QtCore/QUrl> +#include <QtGui/QColor> +#include <QtQuick/QQuickItemGrabResult> namespace utils { inline bool isTouchEvent(const QEvent* event) @@ -68,16 +70,23 @@ inline bool isMouseEvent(const QEvent* event) } } +inline int randomColor() +{ + return qrand() % 255; +} + } class Utils : public QObject { Q_OBJECT Q_PROPERTY(QObject * rootWindow READ rootWindow FINAL CONSTANT) + public: Utils(QObject *parent) : QObject(parent) { + qsrand(255); } QObject *rootWindow() { @@ -86,6 +95,9 @@ public: Q_INVOKABLE static QUrl fromUserInput(const QString& userInput); Q_INVOKABLE static QString domainFromString(const QString& urlString); + Q_INVOKABLE static QString randomColor(); + Q_INVOKABLE static QString colorForIcon(QQuickItemGrabResult *result); + Q_INVOKABLE static QString oppositeColor(const QString & color); }; inline QUrl Utils::fromUserInput(const QString& userInput) @@ -101,4 +113,46 @@ inline QString Utils::domainFromString(const QString& urlString) return QUrl::fromUserInput(urlString).host(); } +inline QString Utils::randomColor() +{ + QColor color(utils::randomColor(), utils::randomColor(), utils::randomColor()); + return color.name(); +} + +inline QString Utils::colorForIcon(QQuickItemGrabResult *result) +{ + QImage image = result->image(); + int hue = 0; + int saturation = 0; + int value = 0; + for (int i = 0, width = image.width(); i < width; ++i) { + int skip = 0; + int h = 0; + int s = 0; + int v = 0; + for (int j = 0, height = image.height(); j < height; ++j) { + const QColor color(QColor(image.pixel(i, j)).toHsv()); + if (color.alpha() < 127) { + ++skip; + continue; + } + + h += color.hsvHue(); + s += color.hsvSaturation(); + v += color.value(); + } + int count = image.height() - skip + 1; + hue = h / count; + saturation = s / count; + value = v / count; + } + return QColor::fromHsv(hue, saturation, value).name(); +} + +inline QString Utils::oppositeColor(const QString &color) +{ + const QColor c(QColor(color).toHsv()); + return QColor::fromHsv(c.hue(), c.saturation(), c.value() < 127 ? 255 : c.value() - 100).name(); +} + #endif // UTILS_H |