Merge lp:~abreu-alexandre/webbrowser-app/text-color-for-theme-color-webapps into lp:webbrowser-app

Proposed by Alexandre Abreu on 2016-02-24
Status: Merged
Approved by: Alberto Mardegan on 2016-04-05
Approved revision: 1372
Merged at revision: 1395
Proposed branch: lp:~abreu-alexandre/webbrowser-app/text-color-for-theme-color-webapps
Merge into: lp:webbrowser-app
Diff against target: 356 lines (+218/-10)
9 files modified
src/app/webcontainer/CMakeLists.txt (+1/-0)
src/app/webcontainer/Chrome.qml (+3/-0)
src/app/webcontainer/ColorUtils.js (+73/-0)
src/app/webcontainer/WebApp.qml (+10/-2)
src/app/webcontainer/webapp-container-helper.cpp (+40/-7)
src/app/webcontainer/webapp-container-helper.h (+10/-1)
tests/unittests/CMakeLists.txt (+2/-0)
tests/unittests/webapp-container-color-helper/CMakeLists.txt (+17/-0)
tests/unittests/webapp-container-color-helper/tst_WebappContainerColorTests.cpp (+62/-0)
To merge this branch: bzr merge lp:~abreu-alexandre/webbrowser-app/text-color-for-theme-color-webapps
Reviewer Review Type Date Requested Status
Alberto Mardegan (community) 2016-02-24 Approve on 2016-04-05
PS Jenkins bot continuous-integration Needs Fixing on 2016-02-29
Review via email: mp+287058@code.launchpad.net

Commit Message

Set address bar text color to a darker version of the theme color if one is defined in a webapp

Description of the Change

Set address bar text color to a darker version of the theme color if one is defined in a webapp

To post a comment you must log in.
Michael Terry (mterry) wrote :

What about a black theme color?

Alexandre Abreu (abreu-alexandre) wrote :

> What about a black theme color?

updated to be a bit more clever about the color choice,

1369. By Alexandre Abreu on 2016-02-29

Set address bar text color to a darker version of the theme color if one is defined in a webapp

1370. By Alexandre Abreu on 2016-04-04

Fix container color unit test running in jenkins env (no xcb)

Alberto Mardegan (mardy) wrote :

A few minor issues inline.

review: Needs Information
1371. By Alexandre Abreu on 2016-04-05

Tweaks

Alexandre Abreu (abreu-alexandre) wrote :

Updates to address comments (see reply to the QColor one)

1372. By Alexandre Abreu on 2016-04-05

Allow #NNN to be treated as #RGB to account for CSS & QColor supported behavior

Alberto Mardegan (mardy) wrote :

LGTM.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app/webcontainer/CMakeLists.txt'
2--- src/app/webcontainer/CMakeLists.txt 2016-03-16 15:03:44 +0000
3+++ src/app/webcontainer/CMakeLists.txt 2016-04-05 15:38:49 +0000
4@@ -30,6 +30,7 @@
5 target_link_libraries(${WEBAPP_CONTAINER}
6 Qt5::Core
7 Qt5::DBus
8+ Qt5::Gui
9 Qt5::Qml
10 Qt5::Quick
11 Qt5::Sql
12
13=== modified file 'src/app/webcontainer/Chrome.qml'
14--- src/app/webcontainer/Chrome.qml 2015-08-10 15:22:00 +0000
15+++ src/app/webcontainer/Chrome.qml 2016-04-05 15:38:49 +0000
16@@ -25,6 +25,7 @@
17
18 property bool navigationButtonsVisible: false
19 property bool accountSwitcher: false
20+ property alias chromeTextLabelColor: chromeTextLabel.color
21
22 signal chooseAccount()
23
24@@ -90,6 +91,8 @@
25 }
26
27 Label {
28+ id: chromeTextLabel
29+
30 anchors {
31 left: faviconContainer.right
32 right: reloadButton.left
33
34=== added file 'src/app/webcontainer/ColorUtils.js'
35--- src/app/webcontainer/ColorUtils.js 1970-01-01 00:00:00 +0000
36+++ src/app/webcontainer/ColorUtils.js 2016-04-05 15:38:49 +0000
37@@ -0,0 +1,73 @@
38+/*
39+ * Copyright 2016 Canonical Ltd.
40+ *
41+ * This file is part of webbrowser-app.
42+ *
43+ * webbrowser-app is free software; you can redistribute it and/or modify
44+ * it under the terms of the GNU General Public License as published by
45+ * the Free Software Foundation; version 3.
46+ *
47+ * webbrowser-app is distributed in the hope that it will be useful,
48+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
49+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50+ * GNU General Public License for more details.
51+ *
52+ * You should have received a copy of the GNU General Public License
53+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
54+ */
55+
56+/**
57+ * Returns the color which has the most contrast with a base color.
58+ *
59+ * The contrast is based on the contrast ration found definition found here:
60+ * https://www.w3.org/TR/WCAG20/#contrast-ratiodef
61+ *
62+ * @param baseColor a string with format <int>,<int>,<int> corresponding to the base color
63+ * @param darkenedBaseColor the darker version of the base color
64+ * @param lightenedBaseColor the lighter version of the base color
65+ * @return defaultLightenColor or defaultDarkenColor depending on better contrast
66+ * color string for special cases ("white", "black")
67+ */
68+
69+function getMostConstrastedColor(
70+ baseColor,
71+ darkenedBaseColor,
72+ lightenedBaseColor) {
73+ function toLuminanceFactor(cc) {
74+ return (cc <= 0.03928)
75+ ? (cc / 12.92)
76+ : Math.pow(((cc + 0.055) / 1.055), 2.4)
77+ }
78+ function getRelativeLuminance(c) {
79+ return 0.2126 * toLuminanceFactor(c.r)
80+ + 0.7152 * toLuminanceFactor(c.g)
81+ + 0.0722 * toLuminanceFactor(c.b)
82+ }
83+ function getContrastRatio(lighterColorLuminance, darkerColorLuminance) {
84+ return (lighterColorLuminance + 0.05) / (darkerColorLuminance + 0.05)
85+ }
86+ var components = baseColor.split(",")
87+
88+ // special case for black
89+ if (components[0].trim() === "0"
90+ && components[1].trim() === "0"
91+ && components[2].trim() === "0") {
92+ return "white"
93+ }
94+ if (components[0].trim() === "255"
95+ && components[1].trim() === "255"
96+ && components[2].trim() === "255") {
97+ return "black"
98+ }
99+
100+ var color = {
101+ r: parseInt(components[0])/255,
102+ g: parseInt(components[1])/255,
103+ b: parseInt(components[2])/255
104+ }
105+ var CONTRAST_LIGHT_ITEM_THRESHOLD = 3.0
106+ if (getContrastRatio(0.0, getRelativeLuminance(color)) >= CONTRAST_LIGHT_ITEM_THRESHOLD) {
107+ return darkenedBaseColor
108+ }
109+ return lightenedBaseColor
110+}
111
112=== modified file 'src/app/webcontainer/WebApp.qml'
113--- src/app/webcontainer/WebApp.qml 2016-02-09 17:04:23 +0000
114+++ src/app/webcontainer/WebApp.qml 2016-04-05 15:38:49 +0000
115@@ -1,5 +1,5 @@
116 /*
117- * Copyright 2013-2015 Canonical Ltd.
118+ * Copyright 2013-2016 Canonical Ltd.
119 *
120 * This file is part of webbrowser-app.
121 *
122@@ -24,6 +24,7 @@
123 import Qt.labs.settings 1.0
124 import "../actions" as Actions
125 import ".."
126+import "ColorUtils.js" as ColorUtils
127
128 BrowserView {
129 id: webapp
130@@ -50,6 +51,7 @@
131 property bool backForwardButtonsVisible: false
132 property bool chromeVisible: false
133 readonly property bool chromeless: !chromeVisible && !backForwardButtonsVisible && !accountSwitcher
134+ readonly property real themeColorTextContrastFactor: 3.0
135
136 signal chooseAccount()
137
138@@ -141,8 +143,14 @@
139 developerExtrasEnabled: webapp.developerExtrasEnabled
140
141 onThemeColorMetaInformationDetected: {
142- if (!webapp.chromeless && chromeLoader.item) {
143+ var color = webappContainerHelper.rgbColorFromCSSColor(theme_color)
144+ if (!webapp.chromeless && chromeLoader.item && color.length) {
145 chromeLoader.item.backgroundColor = theme_color
146+ chromeLoader.item.chromeTextLabelColor =
147+ ColorUtils.getMostConstrastedColor(
148+ color,
149+ Qt.darker(theme_color, themeColorTextContrastFactor),
150+ Qt.lighter(theme_color, themeColorTextContrastFactor))
151 }
152 }
153 onSamlRequestUrlPatternReceived: {
154
155=== modified file 'src/app/webcontainer/webapp-container-helper.cpp'
156--- src/app/webcontainer/webapp-container-helper.cpp 2015-05-27 16:19:45 +0000
157+++ src/app/webcontainer/webapp-container-helper.cpp 2016-04-05 15:38:49 +0000
158@@ -1,5 +1,5 @@
159 /*
160- * Copyright 2014 Canonical Ltd.
161+ * Copyright 2014-2016 Canonical Ltd.
162 *
163 * This file is part of webbrowser-app.
164 *
165@@ -18,9 +18,11 @@
166
167 #include "webapp-container-helper.h"
168
169+#include <QColor>
170 #include <QMetaObject>
171 #include <QMetaProperty>
172-
173+#include <QRegExp>
174+#include <QDebug>
175
176 WebappContainerHelper::WebappContainerHelper(QObject* parent)
177 : QObject(parent)
178@@ -38,15 +40,46 @@
179
180 void WebappContainerHelper::browseToUrl(QObject* webview, const QUrl& url)
181 {
182- if ( ! webview)
183+ if ( ! webview) {
184 return;
185+ }
186 const QMetaObject* metaobject = webview->metaObject();
187 int urlPropIdx = metaobject->indexOfProperty("url");
188- if (urlPropIdx == -1)
189+ if (urlPropIdx == -1) {
190 return;
191+ }
192 metaobject->property(urlPropIdx).write(webview, QVariant(url));
193 }
194
195-
196-
197-
198+QString WebappContainerHelper::rgbColorFromCSSColor(const QString& cssColor)
199+{
200+ QString color = cssColor.trimmed().toLower();
201+ if (color.isEmpty()) {
202+ return QString();
203+ }
204+ QString returnColorFormat = "%1,%2,%3";
205+ if (color.startsWith("rgb")) {
206+ QRegExp rgbColorRe("rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)");
207+ if (rgbColorRe.exactMatch(color)) {
208+ return returnColorFormat
209+ .arg(rgbColorRe.cap(1).toInt())
210+ .arg(rgbColorRe.cap(2).toInt())
211+ .arg(rgbColorRe.cap(3).toInt());
212+ }
213+ return QString();
214+ } else if (color.startsWith("#")) {
215+ QString hexColor = color.mid(1);
216+ if (hexColor.size() < 6 && hexColor.size() != 3) {
217+ color = "#" + QString(6 - hexColor.size(), '0') + hexColor;
218+ }
219+ }
220+
221+ QColor returnColor(color);
222+ return returnColor.isValid()
223+ ? returnColorFormat
224+ .arg(returnColor.red())
225+ .arg(returnColor.green())
226+ .arg(returnColor.blue())
227+ .toLower()
228+ : QString();
229+}
230
231=== modified file 'src/app/webcontainer/webapp-container-helper.h'
232--- src/app/webcontainer/webapp-container-helper.h 2015-05-27 16:19:45 +0000
233+++ src/app/webcontainer/webapp-container-helper.h 2016-04-05 15:38:49 +0000
234@@ -1,5 +1,5 @@
235 /*
236- * Copyright 2014 Canonical Ltd.
237+ * Copyright 2014, 2016 Canonical Ltd.
238 *
239 * This file is part of webbrowser-app.
240 *
241@@ -31,6 +31,15 @@
242 WebappContainerHelper(QObject* parent = 0);
243 ~WebappContainerHelper();
244
245+ /**
246+ * Expects a CSS color string http://www.w3schools.com/css/css_colors.asp
247+ * and returns a rr,gg,bb formatted string.
248+ *
249+ * If the provided string is not a valid CSS color string, an empty string
250+ * is returned.
251+ */
252+ Q_INVOKABLE QString rgbColorFromCSSColor(const QString& cssColor);
253+
254 private Q_SLOTS:
255
256 void browseToUrl(QObject* webview, const QUrl& url);
257
258=== modified file 'tests/unittests/CMakeLists.txt'
259--- tests/unittests/CMakeLists.txt 2016-02-09 13:02:16 +0000
260+++ tests/unittests/CMakeLists.txt 2016-04-05 15:38:49 +0000
261@@ -23,3 +23,5 @@
262 add_subdirectory(downloads-model)
263 add_subdirectory(single-instance-manager)
264 add_subdirectory(meminfo)
265+add_subdirectory(webapp-container-color-helper)
266+
267
268=== added directory 'tests/unittests/webapp-container-color-helper'
269=== added file 'tests/unittests/webapp-container-color-helper/CMakeLists.txt'
270--- tests/unittests/webapp-container-color-helper/CMakeLists.txt 1970-01-01 00:00:00 +0000
271+++ tests/unittests/webapp-container-color-helper/CMakeLists.txt 2016-04-05 15:38:49 +0000
272@@ -0,0 +1,17 @@
273+find_package(Qt5Core REQUIRED)
274+find_package(Qt5Gui REQUIRED)
275+find_package(Qt5Test REQUIRED)
276+set(TEST tst_WebappContainerColorTests)
277+set(SOURCES
278+ ${webapp-container_SOURCE_DIR}/webapp-container-helper.cpp
279+ tst_WebappContainerColorTests.cpp
280+)
281+add_executable(${TEST} ${SOURCES})
282+include_directories(${webapp-container_SOURCE_DIR})
283+target_link_libraries(${TEST}
284+ Qt5::Core
285+ Qt5::Gui
286+ Qt5::Test
287+)
288+add_test(${TEST} ${CMAKE_CURRENT_BINARY_DIR}/${TEST} -xunitxml -o ${TEST}.xml)
289+set_tests_properties(${TEST} PROPERTIES ENVIRONMENT "QT_QPA_PLATFORM=minimal")
290
291=== added file 'tests/unittests/webapp-container-color-helper/tst_WebappContainerColorTests.cpp'
292--- tests/unittests/webapp-container-color-helper/tst_WebappContainerColorTests.cpp 1970-01-01 00:00:00 +0000
293+++ tests/unittests/webapp-container-color-helper/tst_WebappContainerColorTests.cpp 2016-04-05 15:38:49 +0000
294@@ -0,0 +1,62 @@
295+/*
296+ * Copyright 2016 Canonical Ltd.
297+ *
298+ * This file is part of webbrowser-app.
299+ *
300+ * webbrowser-app is free software; you can redistribute it and/or modify
301+ * it under the terms of the GNU General Public License as published by
302+ * the Free Software Foundation; version 3.
303+ *
304+ * webbrowser-app is distributed in the hope that it will be useful,
305+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
306+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
307+ * GNU General Public License for more details.
308+ *
309+ * You should have received a copy of the GNU General Public License
310+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
311+ */
312+
313+// Qt
314+#include <QtCore/QString>
315+#include <QtTest/QtTest>
316+
317+// local
318+#include "webapp-container-helper.h"
319+
320+class ContainerColorTests : public QObject
321+{
322+ Q_OBJECT
323+
324+private Q_SLOTS:
325+
326+ void cssColorToRgbTest_data()
327+ {
328+ QTest::addColumn<QString>("csscolor");
329+ QTest::addColumn<QString>("rgb");
330+
331+ QTest::newRow("Empty CSS color") << " " << "";
332+ QTest::newRow("Invalid CSS color") << " invalid " << "";
333+ QTest::newRow("Invalid RGB CSS color") << " rgb (1,1," << "";
334+ QTest::newRow("Invalid RGB CSS color 2") << " rgb (1,1 0)" << "";
335+ QTest::newRow("Invalid RGB CSS color 3") << " rgb (1, e, 0)" << "";
336+ QTest::newRow("Valid SVG name CSS color") << " red " << "255,0,0";
337+ QTest::newRow("Valid RGB CSS color") << " rgb (255, 0, 0) " << "255,0,0";
338+ QTest::newRow("Valid plain RGB CSS color") << " #FF0000 " << "255,0,0";
339+ QTest::newRow("Valid short plain RGB CSS color") << " #36699 " << "3,102,153";
340+ QTest::newRow("Valid shortest plain RGB CSS color") << " #366 " << "51,102,102";
341+ QTest::newRow("Valid very short plain RGB CSS color") << " #000 " << "0,0,0";
342+ QTest::newRow("Valid SVG name CSS color") << " #FF000044 " << "0,0,68";
343+ }
344+
345+ void cssColorToRgbTest()
346+ {
347+ QFETCH(QString, csscolor);
348+ QFETCH(QString, rgb);
349+
350+ WebappContainerHelper helper;
351+ QCOMPARE(helper.rgbColorFromCSSColor(csscolor), rgb);
352+ }
353+};
354+
355+QTEST_MAIN(ContainerColorTests)
356+#include "tst_WebappContainerColorTests.moc"

Subscribers

People subscribed via source and target branches

to status/vote changes: