Merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/outTheWindow into lp:ubuntu-ui-toolkit/staging

Proposed by Christian Dywan on 2016-07-27
Status: Merged
Approved by: Zsombor Egri on 2017-01-13
Approved revision: 2063
Merged at revision: 2155
Proposed branch: lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/outTheWindow
Merge into: lp:ubuntu-ui-toolkit/staging
Diff against target: 790 lines (+606/-11)
15 files modified
src/UbuntuToolkit/UbuntuToolkit.pro (+3/-0)
src/UbuntuToolkit/ubuntutoolkitmodule.cpp (+2/-0)
src/UbuntuToolkit/ucmainviewbase.cpp (+1/-0)
src/UbuntuToolkit/ucmainwindow.cpp (+215/-0)
src/UbuntuToolkit/ucmainwindow_p.h (+73/-0)
src/UbuntuToolkit/ucmainwindow_p_p.h (+47/-0)
src/UbuntuToolkit/ucunits.cpp (+32/-6)
src/UbuntuToolkit/ucunits_p.h (+5/-0)
tests/autopilot/ubuntuuitoolkit/tests/test_launcher.mainwindow.qml (+12/-5)
tests/autopilot/ubuntuuitoolkit/tests/test_launcher.py (+12/-0)
tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml (+43/-0)
tests/unit/mainwindow/AppName.qml (+28/-0)
tests/unit/mainwindow/mainwindow.pro (+5/-0)
tests/unit/mainwindow/tst_mainwindow.cpp (+127/-0)
tests/unit/unit.pro (+1/-0)
To merge this branch: bzr merge lp:~ubuntu-sdk-team/ubuntu-ui-toolkit/outTheWindow
Reviewer Review Type Date Requested Status
ubuntu-sdk-build-bot continuous-integration Approve on 2017-01-13
Zsombor Egri 2016-07-27 Approve on 2017-01-13
Loïc Molinari (community) Approve on 2016-09-21
Review via email: mp+301278@code.launchpad.net

Commit message

Add MainWindow to Ubuntu.Components.Labs

To post a comment you must log in.
2042. By Christian Dywan on 2016-08-02

Merge lp:ubuntu-ui-toolkit/staging

Christian Dywan (kalikiana) wrote :

install -m 644 -p /tmp/buildd/ubuntu-ui-toolkit-1.3.2030+16.10.20160726.2/src/Ubuntu/Components/Themes/Ambiance/1.3/HighlightMagnifier.qml /tmp/buildd/ubuntu-ui-toolkit-1.3.2030+16.10.20160726.2/debian/tmp/usr/lib/x86_64-linux-gnu/qt5/qml/Ubuntu/Components/Themes/Ambiance/1.3/
Aborted (core dumped)

2043. By Christian Dywan on 2016-08-08

Merge lp:ubuntu-ui-toolkit/staging

Christian Dywan (kalikiana) wrote :

Aborted (core dumped)
Makefile:357: recipe for target '/tmp/buildd/ubuntu-ui-toolkit-1.3.2030+16.10.20160726.2/qml/Ubuntu/Components/Labs/plugins.qmltypes' failed

2044. By Christian Dywan on 2016-08-10

Pass parent to UbuntuI18n/UCUnits::instance in constructor

2045. By Christian Dywan on 2016-08-10

Add Labs dependency so it's available to AP

Zsombor Egri (zsombi) wrote :

Don't we need more tests?

review: Needs Fixing
Zsombor Egri (zsombi) wrote :

Also, forgot to ask for this inline.

review: Needs Information
Christian Dywan (kalikiana) wrote :

> > + qml-module-ubuntu-components-labs,
> Why is this required here?
Because I'm using MainWindow in the AutoPilot test case.

> You need also an ActionManager instance,
> into which the context must be registered.

As discussed elsewhere, it's not needed.

Note to self: adding test cases so they don't need to be done once the component is promoted to supported API.

2046. By Christian Dywan on 2016-08-15

Units instance per MainWindow and unit tests

Christian Dywan (kalikiana) wrote :

> Why do you derive from PageTreeNode?
An oversight indeed. Thanks for noticing.

> For now this is OK. But in general, as next step, the window should have its own units instance
Between said discussion and now the goal seems to have changed from starting with a proof of concept to having a full implementation including tests - fine by me, I was starting to think about it as well, but just to point out that this is changing the plan :-D

Zsombor Egri (zsombi) wrote :

> > Why do you derive from PageTreeNode?
> An oversight indeed. Thanks for noticing.
>
> > For now this is OK. But in general, as next step, the window should have its
> own units instance
> Between said discussion and now the goal seems to have changed from starting
> with a proof of concept to having a full implementation including tests - fine
> by me, I was starting to think about it as well, but just to point out that
> this is changing the plan :-D

We can have proof of concepts, of course. This component however seemed to me like a complete one, but yes, we can leave the tests for now, and add them once we move them into the main module.

Zsombor Egri (zsombi) wrote :

Why do you move this to the main module? Why haven't you let it stay in Labs?

We discussed some time ago that we need a Window component which exports the units (and a hidden PopupContext), and derive the MainWindow from it, which adds MainView specific things (theme, applicationName, etc). I see you moved the component to main, and these haven't been addressed.

It can go into Labs without this but in the mains would mean API break if we do the super class change. Let's chat about it.

review: Needs Information
Zsombor Egri (zsombi) wrote :

Oh, just seen that you've exported as labs 1.3 Perhaps we go for 1.0 with this one, the module has just been introduced, and all the other components are exported in 1,0 version. Let's keep it that way.

review: Needs Fixing
Christian Dywan (kalikiana) wrote :

> Oh, just seen that you've exported as labs 1.3 Perhaps we go for 1.0

Does it make any difference if it's 5.5 or 0.3? We're not going to support it anyway so I went for 1.3 so one doesn't have to think about the import at all. Any version should work for the sake of convenience.

Christian Dywan (kalikiana) wrote :

Filed bug 1615591 with regard to eventually moving MainWindow out of Labs and adding more tests.

2047. By Christian Dywan on 2016-08-22

Merge lp:ubuntu-ui-toolkit/staging

2048. By Christian Dywan on 2016-08-22

Move MainWindow to Ubuntu.Components.Labs 1.0

2049. By Christian Dywan on 2016-08-24

Remove redundant MainWindow test bits and handle errors better

2050. By Christian Dywan on 2016-08-25

Merge lp:ubuntu-ui-toolkit/staging

2051. By Christian Dywan on 2016-08-25

mainwindow seems to require x11

2052. By Christian Dywan on 2016-09-13

Use custom_qpa for mainwindow unit test

2053. By Christian Dywan on 2016-09-13

Merge lp:ubuntu-ui-toolkit/staging

2054. By Christian Dywan on 2016-09-20

Include test-include.pri so custom_qpa actually works

Loïc Molinari (loic.molinari) wrote :

Hi Christian.

I'm not going to comment on the change in itself but on the header inclusion part that I recently tried to fix and standardise. Everything is explained in the CODING file at the root of the project, it's mostly Qt rules plus a few things. I hope not to be too picky but I think we should try to respect these rules as best as possible to keep it clean and usable outside of the UITK.

I added the comments inline.

review: Needs Fixing
2055. By Christian Dywan on 2016-09-21

Touch up include files to conform to guidelines

2056. By Christian Dywan on 2016-09-21

Add CONFIG before include

Loïc Molinari (loic.molinari) wrote :

Thanks dude!

review: Approve
2057. By Christian Dywan on 2016-09-22

Retain both MainWindow{ and Window { MainView { AP tests

Christian Dywan (kalikiana) wrote :

Program received signal SIGSEGV, Segmentation fault.
0xf68de251 in operator==(QString const&, QString const&) () from /usr/lib/i386-linux-gnu/sse2/libQt5Core.so.5
#0 0xf68de251 in operator==(QString const&, QString const&) () from /usr/lib/i386-linux-gnu/sse2/libQt5Core.so.5
#1 0xf7e3b88a in UCMainWindow::setApplicationName(QString) () from /tmp/buildd/ubuntu-ui-toolkit-gles-1.3.2085+16.10.20160915/lib/libUbuntuToolkit.so.5
#2 0xf7e3bbb6 in UCMainWindow::qt_metacall(QMetaObject::Call, int, void**) () from /tmp/buildd/ubuntu-ui-toolkit-gles-1.3.2085+16.10.20160915/lib/libUbuntuToolkit.so.5
#3 0xf6a93f82 in QMetaObject::metacall(QObject*, QMetaObject::Call, int, void**) () from /usr/lib/i386-linux-gnu/sse2/libQt5Core.so.5
#10 0xf6f41c0a in QQmlComponentPrivate::beginCreate(QQmlContextData*) () from /usr/lib/i386-linux-gnu/libQt5Qml.so.5
#11 0xf6f42051 in QQmlComponent::create(QQmlContext*) () from /usr/lib/i386-linux-gnu/libQt5Qml.so.5
#12 0x08049ade in loadTest (document=..., this=<optimized out>) at tst_mainwindow.cpp:73
#13 testCase_AppName (this=<optimized out>) at tst_mainwindow.cpp:117
#14 tst_MainWindow::qt_static_metacall (_o=0xffffc484, _c=135136696, _id=2, _a=0xffffbc70) at .moc/tst_mainwindow.moc:76
#15 0xf6a960ac in QMetaMethod::invoke(QObject*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) const () from /usr/lib/i386-linux-gnu/sse2/libQt5Core.so.5
#16 0xf6a9b007 in QMetaObject::invokeMethod(QObject*, char const*, Qt::ConnectionType, QGenericReturnArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument, QGenericArgument) () from /usr/lib/i386-linux-gnu/sse2/libQt5Core.so.5
#18 0xf71b2395 in QTest::qExec(QObject*, int, char**) () from /usr/lib/i386-linux-gnu/libQt5Test.so.5
#19 0x0804975c in main (argc=7, argv=0xffffc554) at tst_mainwindow.cpp:125

Gerry Boland (gerboland) wrote :

+ QObject::connect(UbuntuI18n::instance(this), SIGNAL(domainChanged()),
+ this, SIGNAL(i18nChanged()));
+ QObject::connect(UbuntuI18n::instance(this), SIGNAL(languageChanged()),
+ this, SIGNAL(i18nChanged()));
I see the newer style connects used further down, why the old style here?

Zsombor Egri (zsombi) wrote :

> + QObject::connect(UbuntuI18n::instance(this), SIGNAL(domainChanged()),
> + this, SIGNAL(i18nChanged()));
> + QObject::connect(UbuntuI18n::instance(this), SIGNAL(languageChanged()),
> + this, SIGNAL(i18nChanged()));
> I see the newer style connects used further down, why the old style here?

One reason I can see that the new style connect doesn't resolve the situation when the client overrides the i18nChanged signal in JS. For that the meta-method based connect is needed.

2058. By Christian Dywan on 2017-01-09

Merge lp:ubuntu-ui-toolkit/staging

2059. By Christian Dywan on 2017-01-10

Add d_func()->init() to UCMainWindow constructor

2060. By Christian Dywan on 2017-01-11

Cf. applicationName to "" rather than empty like MainView

2061. By Christian Dywan on 2017-01-11

Add debug statements to UCMainWindow for CI

2062. By Christian Dywan on 2017-01-12

Base MainWindowPrivate on QQuickWindowPrivate

2063. By Christian Dywan on 2017-01-12

Drop debug statements

Zsombor Egri (zsombi) wrote :

All fine for now, let's get this in.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/UbuntuToolkit/UbuntuToolkit.pro'
2--- src/UbuntuToolkit/UbuntuToolkit.pro 2016-11-04 09:37:32 +0000
3+++ src/UbuntuToolkit/UbuntuToolkit.pro 2017-01-12 02:42:37 +0000
4@@ -106,6 +106,8 @@
5 $$PWD/uclistitemstyle_p.h \
6 $$PWD/ucmainviewbase_p.h \
7 $$PWD/ucmainviewbase_p_p.h \
8+ $$PWD/ucmainwindow_p.h \
9+ $$PWD/ucmainwindow_p_p.h \
10 $$PWD/ucmargins_p.h \
11 $$PWD/ucmathutils_p.h \
12 $$PWD/ucmouse_p.h \
13@@ -203,6 +205,7 @@
14 $$PWD/uclistitemlayout.cpp \
15 $$PWD/uclistitemstyle.cpp \
16 $$PWD/ucmainviewbase.cpp \
17+ $$PWD/ucmainwindow.cpp \
18 $$PWD/ucmathutils.cpp \
19 $$PWD/ucmousefilters.cpp \
20 $$PWD/ucpagetreenode.cpp \
21
22=== modified file 'src/UbuntuToolkit/ubuntutoolkitmodule.cpp'
23--- src/UbuntuToolkit/ubuntutoolkitmodule.cpp 2016-09-29 10:19:06 +0000
24+++ src/UbuntuToolkit/ubuntutoolkitmodule.cpp 2017-01-12 02:42:37 +0000
25@@ -39,6 +39,7 @@
26 #include "inversemouseareatype_p.h"
27 #include "listener_p.h"
28 #include "livetimer_p.h"
29+#include "ucmainwindow_p.h"
30 #include "menu_p.h"
31 #include "menubar_p.h"
32 #include "menugroup_p.h"
33@@ -439,6 +440,7 @@
34 qmlRegisterType<SplitView>(uri, 1, 0, "SplitView");
35 qmlRegisterType<SplitViewLayout>(uri, 1, 0, "SplitViewLayout");
36 qmlRegisterType<ViewColumn>(uri, 1, 0, "ViewColumn");
37+ qmlRegisterType<UCMainWindow>(uri, 1, 0, "MainWindow");
38 qmlRegisterType<Menu>(uri, 1, 0, "Menu");
39 qmlRegisterType<MenuBar>(uri, 1, 0, "MenuBar");
40 qmlRegisterType<MenuGroup>(uri, 1, 0, "MenuGroup");
41
42=== modified file 'src/UbuntuToolkit/ucmainviewbase.cpp'
43--- src/UbuntuToolkit/ucmainviewbase.cpp 2016-09-12 09:03:50 +0000
44+++ src/UbuntuToolkit/ucmainviewbase.cpp 2017-01-12 02:42:37 +0000
45@@ -145,6 +145,7 @@
46 void UCMainViewBase::setApplicationName(QString applicationName)
47 {
48 Q_D(UCMainViewBase);
49+
50 if (d->m_applicationName == applicationName)
51 return;
52
53
54=== added file 'src/UbuntuToolkit/ucmainwindow.cpp'
55--- src/UbuntuToolkit/ucmainwindow.cpp 1970-01-01 00:00:00 +0000
56+++ src/UbuntuToolkit/ucmainwindow.cpp 2017-01-12 02:42:37 +0000
57@@ -0,0 +1,215 @@
58+/*
59+ * Copyright 2016 Canonical Ltd.
60+ *
61+ * This program is free software; you can redistribute it and/or modify
62+ * it under the terms of the GNU Lesser General Public License as published by
63+ * the Free Software Foundation; version 3.
64+ *
65+ * This program is distributed in the hope that it will be useful,
66+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
67+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68+ * GNU Lesser General Public License for more details.
69+ *
70+ * You should have received a copy of the GNU Lesser General Public License
71+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
72+ */
73+
74+#include "ucmainwindow_p_p.h"
75+
76+#include <QtCore/QCoreApplication>
77+
78+#include "ucactionmanager_p.h"
79+#include "ucactioncontext_p.h"
80+#include "ucapplication_p.h"
81+#include "uctheme_p.h"
82+#include "i18n_p.h"
83+#include "quickutils_p.h"
84+
85+UT_NAMESPACE_BEGIN
86+
87+/*!
88+ \internal
89+ \qmlabstract MainWindow
90+ \inqmlmodule Ubuntu.Components.Labs
91+ \ingroup ubuntu
92+ \brief MainWindow is an alternate window-based root Item providing \l units
93+ and \l i18n as native properties, an \ actionContext and an \l applicationName.
94+ Unlike \l MainView there is no built-in header.
95+
96+ The simplest way to use a MainWindow is to include a single \l Page object:
97+ \qml
98+ import QtQuick 2.4
99+ import Ubuntu.Components 1.3
100+ import Ubuntu.Components.Labs 1.3
101+
102+ MainWindow {
103+ minimumWidth: units.gu(48)
104+ minimumHeight: units.gu(60)
105+
106+ Page {
107+ anchors.fill: parent
108+ header: PageHeader {
109+ title: "Simple page"
110+ }
111+ Button {
112+ anchors {
113+ horizontalCenter: parent.horizontalCenter
114+ top: pageHeader.bottom
115+ topMargin: units.gu(5)
116+ }
117+ width: units.gu(15)
118+ text: "Push me"
119+ onClicked: print("Click!")
120+ }
121+ }
122+ }
123+ \endqml
124+ Anchors need to be set, there's no automatic fill like with \l MainView.
125+
126+ Do not include multiple Pages directly, but use \l AdaptivePageLayout
127+ inside MainWindow to navigate between several Pages.
128+
129+ If the \l Page inside the MainWindow includes a Flickable, set the flickable property of
130+ the PageHeader to automatically hide and show the header when the user scrolls up or down:
131+ \qml
132+ import QtQuick 2.4
133+ import Ubuntu.Components 1.3
134+ import Ubuntu.Components.Labs 1.3
135+
136+ MainWindow {
137+ minimumWidth: units.gu(48)
138+ maximumHeight: units.gu(60)
139+
140+ Page {
141+ anchors.fill: parent
142+ header: PageHeader {
143+ title: "Page with Flickable"
144+ flickable: myFlickable
145+ }
146+
147+ Flickable {
148+ id: myFlickable
149+ anchors.fill: parent
150+ contentHeight: column.height
151+
152+ Column {
153+ id: column
154+ Repeater {
155+ model: 100
156+ Label {
157+ text: "line "+index
158+ }
159+ }
160+ }
161+ }
162+ }
163+ }
164+ \endqml
165+ The same header behavior is automatic when using a ListView instead of a Flickable in the above
166+ example.
167+
168+ The examples above show how to include a single \l Page inside a MainWindow, but more
169+ advanced application structures are possible using \l AdaptivePageLayout.
170+**/
171+UCMainWindowPrivate::UCMainWindowPrivate()
172+ : m_actionContext(nullptr),
173+ m_units(nullptr)
174+{
175+}
176+
177+void UCMainWindowPrivate::init()
178+{
179+ Q_Q(UCMainWindow);
180+
181+ //need to init here because the q pointer is null in constructor
182+ m_actionContext = new UCPopupContext(q);
183+
184+ m_actionContext->setObjectName(QStringLiteral("RootContext"));
185+ m_actionContext->setActive(true);
186+}
187+
188+UCMainWindow::UCMainWindow(QWindow *parent)
189+ : QQuickWindow(*(new UCMainWindowPrivate), parent)
190+{
191+ d_func()->init();
192+
193+ QObject::connect(UbuntuI18n::instance(this), SIGNAL(domainChanged()),
194+ this, SIGNAL(i18nChanged()));
195+ QObject::connect(UbuntuI18n::instance(this), SIGNAL(languageChanged()),
196+ this, SIGNAL(i18nChanged()));
197+}
198+
199+/*!
200+ \qmlproperty string MainWindow::applicationName
201+
202+ The property holds the application's name, which must be the same as the
203+ desktop file's name.
204+ The name also sets the name of the QCoreApplication and defaults for data
205+ and cache folders that work on the desktop and under confinement, as well as
206+ the default gettext domain.
207+ C++ code that writes files may use QStandardPaths::writableLocation with
208+ QStandardPaths::DataLocation or QStandardPaths::CacheLocation.
209+*/
210+QString UCMainWindow::applicationName() const
211+{
212+ return d_func()->m_applicationName;
213+}
214+
215+void UCMainWindow::setApplicationName(QString applicationName)
216+{
217+ Q_D(UCMainWindow);
218+
219+ if (d->m_applicationName == applicationName)
220+ return;
221+
222+ d->m_applicationName = applicationName;
223+
224+ if (applicationName != QStringLiteral("")) {
225+ UbuntuI18n::instance()->setDomain(applicationName);
226+ UCApplication::instance()->setApplicationName(applicationName);
227+ }
228+ Q_EMIT applicationNameChanged(applicationName);
229+}
230+
231+/*!
232+ \qmlproperty Units MainWindow::units
233+
234+ Grid units for this particular window - unlike the global context property
235+ by the same name.
236+*/
237+UCUnits* UCMainWindow::units()
238+{
239+ Q_D(UCMainWindow);
240+
241+ if (!d->m_units) {
242+ d->m_units = new UCUnits(this);
243+ QObject::connect(d->m_units, SIGNAL(gridUnitChanged()),
244+ this, SIGNAL(unitsChanged()));
245+ }
246+ return d->m_units;
247+}
248+
249+/*!
250+ \qmlproperty Units MainWindow::i18n
251+
252+ The property holds its breath for documentation.
253+*/
254+UbuntuI18n* UCMainWindow::i18n() const
255+{
256+ return UbuntuI18n::instance();
257+}
258+
259+/*!
260+ \qmlproperty ActionContext MainWindow::actionContext
261+ \readonly
262+ \since Ubuntu.Components 1.3
263+ The action context of the MainWindow.
264+ */
265+UCPopupContext *UCMainWindow::actionContext() const
266+{
267+ return d_func()->m_actionContext;
268+}
269+
270+UT_NAMESPACE_END
271+
272+#include "moc_ucmainwindow_p.cpp"
273
274=== added file 'src/UbuntuToolkit/ucmainwindow_p.h'
275--- src/UbuntuToolkit/ucmainwindow_p.h 1970-01-01 00:00:00 +0000
276+++ src/UbuntuToolkit/ucmainwindow_p.h 2017-01-12 02:42:37 +0000
277@@ -0,0 +1,73 @@
278+/*
279+ * Copyright 2016 Canonical Ltd.
280+ *
281+ * This program is free software; you can redistribute it and/or modify
282+ * it under the terms of the GNU Lesser General Public License as published by
283+ * the Free Software Foundation; version 3.
284+ *
285+ * This program is distributed in the hope that it will be useful,
286+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
287+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
288+ * GNU Lesser General Public License for more details.
289+ *
290+ * You should have received a copy of the GNU Lesser General Public License
291+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
292+ */
293+
294+#ifndef UCMAINWINDOW_P_H
295+#define UCMAINWINDOW_P_H
296+
297+#include <QtQuick/QQuickWindow>
298+
299+#include <UbuntuToolkit/private/i18n_p.h>
300+#include <UbuntuToolkit/private/ucunits_p.h>
301+
302+UT_NAMESPACE_BEGIN
303+
304+class UCMainWindowPrivate;
305+class UCPopupContext;
306+class UCAction;
307+
308+class UBUNTUTOOLKIT_EXPORT UCMainWindow : public QQuickWindow
309+{
310+ Q_OBJECT
311+ Q_PROPERTY(QString applicationName READ applicationName WRITE setApplicationName NOTIFY applicationNameChanged)
312+#ifndef Q_QDOC
313+ Q_PROPERTY(UT_PREPEND_NAMESPACE(UCUnits)* units READ units NOTIFY unitsChanged)
314+ Q_PROPERTY(UT_PREPEND_NAMESPACE(UbuntuI18n)* i18n READ i18n NOTIFY i18nChanged)
315+ Q_PROPERTY(UT_PREPEND_NAMESPACE(UCPopupContext)* actionContext READ actionContext NOTIFY actionContextChanged)
316+#else
317+ Q_PROPERTY(UCUnits* units READ units NOTIFY unitsChanged)
318+ Q_PROPERTY(UbuntuI18n* i18n READ i18n NOTIFY i18nChanged)
319+ Q_PROPERTY(UCPopupContext* actionContext READ actionContext NOTIFY actionContextChanged)
320+#endif
321+
322+public:
323+ UCMainWindow(QWindow *parent = nullptr);
324+
325+
326+ QString applicationName() const;
327+ void setApplicationName(QString applicationName);
328+
329+ UCUnits* units();
330+ UbuntuI18n* i18n() const;
331+
332+ UCPopupContext* actionContext() const;
333+
334+Q_SIGNALS:
335+ void applicationNameChanged(QString applicationName);
336+ void i18nChanged();
337+ void unitsChanged();
338+#ifndef Q_QDOC
339+ void actionContextChanged(UT_PREPEND_NAMESPACE(UCPopupContext)* actionContext);
340+#else
341+ void actionContextChanged(UCPopupContext* actionContext);
342+#endif
343+
344+private:
345+ Q_DECLARE_PRIVATE(UCMainWindow)
346+};
347+
348+UT_NAMESPACE_END
349+
350+#endif // UCMAINWINDOW_P_H
351
352=== added file 'src/UbuntuToolkit/ucmainwindow_p_p.h'
353--- src/UbuntuToolkit/ucmainwindow_p_p.h 1970-01-01 00:00:00 +0000
354+++ src/UbuntuToolkit/ucmainwindow_p_p.h 2017-01-12 02:42:37 +0000
355@@ -0,0 +1,47 @@
356+/*
357+ * Copyright 2016 Canonical Ltd.
358+ *
359+ * This program is free software; you can redistribute it and/or modify
360+ * it under the terms of the GNU Lesser General Public License as published by
361+ * the Free Software Foundation; version 3.
362+ *
363+ * This program is distributed in the hope that it will be useful,
364+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
365+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
366+ * GNU Lesser General Public License for more details.
367+ *
368+ * You should have received a copy of the GNU Lesser General Public License
369+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
370+ */
371+
372+#ifndef UCMAINWINDOW_P_P_H
373+#define UCMAINWINDOW_P_P_H
374+
375+#include <UbuntuToolkit/private/ucmainwindow_p.h>
376+
377+#include <QtQml/QQmlProperty>
378+
379+#include <QtQuick/private/qquickwindow_p.h>
380+
381+UT_NAMESPACE_BEGIN
382+
383+class UCMainWindow;
384+class UCPopupContext;
385+
386+class UCMainWindowPrivate : public QQuickWindowPrivate
387+{
388+ Q_DECLARE_PUBLIC(UCMainWindow)
389+
390+public:
391+ UCMainWindowPrivate();
392+ void init();
393+
394+ QString m_applicationName;
395+ UCPopupContext* m_actionContext = nullptr;
396+ UCUnits* m_units = nullptr;
397+
398+};
399+
400+UT_NAMESPACE_END
401+
402+#endif // UCMAINWINDOW_P_P_H
403
404=== modified file 'src/UbuntuToolkit/ucunits.cpp'
405--- src/UbuntuToolkit/ucunits.cpp 2016-09-12 09:03:50 +0000
406+++ src/UbuntuToolkit/ucunits.cpp 2017-01-12 02:42:37 +0000
407@@ -97,18 +97,44 @@
408 * isolated from Qt's own scaling concept.
409 */
410
411+UCUnits::UCUnits(QWindow *parent) :
412+ QObject(parent),
413+ m_devicePixelRatio(parent->devicePixelRatio())
414+{
415+ m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
416+ QObject::connect(parent, &QWindow::screenChanged,
417+ this, &UCUnits::screenChanged);
418+ m_screen = parent->screen();
419+ if (m_screen)
420+ QObject::connect(m_screen, &QScreen::physicalDotsPerInchChanged,
421+ this, &UCUnits::devicePixelRatioChanged);
422+}
423+
424+void UCUnits::screenChanged(QScreen *screen)
425+{
426+ if (m_screen)
427+ QObject::disconnect(m_screen, &QScreen::physicalDotsPerInchChanged,
428+ this, &UCUnits::devicePixelRatioChanged);
429+ m_screen = screen;
430+ QObject::connect(m_screen, &QScreen::physicalDotsPerInchChanged,
431+ this, &UCUnits::devicePixelRatioChanged);
432+ m_devicePixelRatio = screen->devicePixelRatio();
433+ setGridUnit(DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
434+}
435+
436+void UCUnits::devicePixelRatioChanged(qreal dpi)
437+{
438+ m_devicePixelRatio = dpi;
439+ setGridUnit(DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
440+}
441+
442 UCUnits *UCUnits::m_units = nullptr;
443
444 UCUnits::UCUnits(QObject *parent) :
445 QObject(parent),
446 m_devicePixelRatio(qGuiApp->devicePixelRatio())
447 {
448- // If GRID_UNIT_PX set, always use it. If not, 1GU := DEFAULT_GRID_UNIT_PX * m_devicePixelRatio
449- if (qEnvironmentVariableIsSet(ENV_GRID_UNIT_PX)) {
450- m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX);
451- } else {
452- m_gridUnit = DEFAULT_GRID_UNIT_PX * m_devicePixelRatio;
453- }
454+ m_gridUnit = getenvFloat(ENV_GRID_UNIT_PX, DEFAULT_GRID_UNIT_PX * m_devicePixelRatio);
455
456 auto nativeInterface = qGuiApp->platformNativeInterface();
457 if (nativeInterface) {
458
459=== modified file 'src/UbuntuToolkit/ucunits_p.h'
460--- src/UbuntuToolkit/ucunits_p.h 2016-09-09 17:49:07 +0000
461+++ src/UbuntuToolkit/ucunits_p.h 2017-01-12 02:42:37 +0000
462@@ -23,6 +23,7 @@
463 #include <QtCore/QObject>
464 #include <QtCore/QString>
465 #include <QtCore/QUrl>
466+#include <QtGui/QWindow>
467
468 #include <UbuntuToolkit/ubuntutoolkitglobal.h>
469
470@@ -48,6 +49,7 @@
471 }
472
473 explicit UCUnits(QObject *parent = 0);
474+ explicit UCUnits(QWindow *parent);
475 ~UCUnits();
476 Q_INVOKABLE float dp(float value);
477 Q_INVOKABLE float gu(float value);
478@@ -68,10 +70,13 @@
479
480 private Q_SLOTS:
481 void windowPropertyChanged(QPlatformWindow *window, const QString &propertyName);
482+ void screenChanged(QScreen *screen);
483+ void devicePixelRatioChanged(qreal dpi);
484
485 private:
486 static UCUnits *m_units;
487 float m_devicePixelRatio;
488+ QScreen *m_screen;
489 float m_gridUnit;
490 };
491
492
493=== renamed file 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml' => 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.mainwindow.qml'
494--- tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml 2016-07-12 12:05:11 +0000
495+++ tests/autopilot/ubuntuuitoolkit/tests/test_launcher.mainwindow.qml 2017-01-12 02:42:37 +0000
496@@ -17,23 +17,30 @@
497 import QtQuick 2.4
498 import QtQuick.Window 2.2 // Not Ubuntu.Test
499 import Ubuntu.Components 1.3
500+import Ubuntu.Components.Labs 1.3
501
502-Window {
503- title: "Hello World"
504+MainWindow {
505+ title: i18n.tr("Hello World")
506 minimumWidth: units.gu(30)
507 minimumHeight: units.gu(50)
508 maximumWidth: units.gu(90)
509 maximumHeight: units.gu(120)
510- MainView {
511+
512+ Item {
513+ anchors.fill: parent
514 objectName: "mainView"
515
516 Page {
517- title: "Launcher/Window"
518+ anchors.fill: parent
519+ header: PageHeader {
520+ title: "Launcher/Window"
521+ }
522
523 Column {
524+ anchors.top: parent.header.bottom
525 Label {
526 objectName: "label"
527- text: "Lorem ipsum dolor sit amet"
528+ text: i18n.tr("Lorem ipsum dolor sit amet")
529 width: units.gu(25)
530 height: units.gu(25)
531 }
532
533=== modified file 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.py'
534--- tests/autopilot/ubuntuuitoolkit/tests/test_launcher.py 2016-07-12 12:05:11 +0000
535+++ tests/autopilot/ubuntuuitoolkit/tests/test_launcher.py 2017-01-12 02:42:37 +0000
536@@ -49,6 +49,18 @@
537 Eventually(Equals("Lorem ipsum dolor sit amet")))
538
539
540+class LauncherMainWindowTestCase(tests.QMLFileAppTestCase):
541+ path = os.path.abspath(__file__)
542+ dir_path = os.path.dirname(path)
543+ test_qml_file_path = os.path.join(
544+ dir_path, 'test_launcher.mainwindow.qml')
545+
546+ def test_window_root_item(self):
547+ label = self.main_view.select_single(objectName="label")
548+ self.assertThat(label.text,
549+ Eventually(Equals("Lorem ipsum dolor sit amet")))
550+
551+
552 class LauncherQtTestTestCase(tests.QMLFileAppTestCase):
553 path = os.path.abspath(__file__)
554 dir_path = os.path.dirname(path)
555
556=== added file 'tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml'
557--- tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml 1970-01-01 00:00:00 +0000
558+++ tests/autopilot/ubuntuuitoolkit/tests/test_launcher.window.qml 2017-01-12 02:42:37 +0000
559@@ -0,0 +1,43 @@
560+/*
561+ * Copyright 2014-2016 Canonical Ltd.
562+ *
563+ * This program is free software; you can redistribute it and/or modify
564+ * it under the terms of the GNU Lesser General Public License as published by
565+ * the Free Software Foundation; version 3.
566+ *
567+ * This program is distributed in the hope that it will be useful,
568+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
569+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
570+ * GNU Lesser General Public License for more details.
571+ *
572+ * You should have received a copy of the GNU Lesser General Public License
573+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
574+ */
575+
576+import QtQuick 2.4
577+import QtQuick.Window 2.2 // Not Ubuntu.Test
578+import Ubuntu.Components 1.3
579+
580+Window {
581+ title: "Hello World"
582+ minimumWidth: units.gu(30)
583+ minimumHeight: units.gu(50)
584+ maximumWidth: units.gu(90)
585+ maximumHeight: units.gu(120)
586+ MainView {
587+ objectName: "mainView"
588+
589+ Page {
590+ title: "Launcher/Window"
591+
592+ Column {
593+ Label {
594+ objectName: "label"
595+ text: "Lorem ipsum dolor sit amet"
596+ width: units.gu(25)
597+ height: units.gu(25)
598+ }
599+ }
600+ }
601+ }
602+}
603
604=== added directory 'tests/unit/mainwindow'
605=== added file 'tests/unit/mainwindow/AppName.qml'
606--- tests/unit/mainwindow/AppName.qml 1970-01-01 00:00:00 +0000
607+++ tests/unit/mainwindow/AppName.qml 2017-01-12 02:42:37 +0000
608@@ -0,0 +1,28 @@
609+/*
610+ * Copyright 2013-2016 Canonical Ltd.
611+ *
612+ * This program is free software; you can redistribute it and/or modify
613+ * it under the terms of the GNU Lesser General Public License as published by
614+ * the Free Software Foundation; version 3.
615+ *
616+ * This program is distributed in the hope that it will be useful,
617+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
618+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
619+ * GNU Lesser General Public License for more details.
620+ *
621+ * You should have received a copy of the GNU Lesser General Public License
622+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
623+ */
624+
625+import QtQuick 2.4
626+import Ubuntu.Components 1.3
627+import Ubuntu.Components.Labs 1.0
628+
629+MainWindow {
630+ objectName: "appName"
631+ applicationName: "org.gnu.wildebeest"
632+
633+ Label {
634+ text: "Lorem ipsum dolor sit amet"
635+ }
636+}
637
638=== added file 'tests/unit/mainwindow/mainwindow.pro'
639--- tests/unit/mainwindow/mainwindow.pro 1970-01-01 00:00:00 +0000
640+++ tests/unit/mainwindow/mainwindow.pro 2017-01-12 02:42:37 +0000
641@@ -0,0 +1,5 @@
642+CONFIG += custom_qpa # needed by test to set device pixel ratio correctly
643+include(../test-include.pri)
644+
645+QT += gui
646+SOURCES += tst_mainwindow.cpp
647
648=== added file 'tests/unit/mainwindow/tst_mainwindow.cpp'
649--- tests/unit/mainwindow/tst_mainwindow.cpp 1970-01-01 00:00:00 +0000
650+++ tests/unit/mainwindow/tst_mainwindow.cpp 2017-01-12 02:42:37 +0000
651@@ -0,0 +1,127 @@
652+/*
653+ * Copyright 2012-2016 Canonical Ltd.
654+ *
655+ * This program is free software; you can redistribute it and/or modify
656+ * it under the terms of the GNU Lesser General Public License as published by
657+ * the Free Software Foundation; version 3.
658+ *
659+ * This program is distributed in the hope that it will be useful,
660+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
661+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
662+ * GNU Lesser General Public License for more details.
663+ *
664+ * You should have received a copy of the GNU Lesser General Public License
665+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
666+ *
667+ * Author: Christian Dywan <christian.dywan@canonical.com>
668+ */
669+
670+#include <QtCore/QString>
671+#include <QtCore/QTextCodec>
672+#include <QtCore/QStandardPaths>
673+#include <QtCore/QProcessEnvironment>
674+#include <QtCore/QDebug>
675+#include <QtTest/QTest>
676+#include <QtTest/QSignalSpy>
677+#include <QtCore/QCoreApplication>
678+#include <QtQml/QQmlEngine>
679+#include <QtQuick/QQuickView>
680+#include <QtQuick/QQuickItem>
681+#include <QtCore/QThread>
682+#include <QtCore/QFileInfo>
683+#include <QtCore/QDir>
684+#include <QtCore/QCryptographicHash>
685+#include <QtCore/QSettings>
686+
687+#include <QtQuick/QQuickItem>
688+#include <QtQuick/QQuickView>
689+#include <QtGui/QGuiApplication>
690+#include <QtQml/QQmlEngine>
691+#include <QtQml/QQmlContext>
692+#include <QtQml/QQmlComponent>
693+
694+#include <UbuntuToolkit/ubuntutoolkitmodule.h>
695+#include <UbuntuToolkit/private/ucapplication_p.h>
696+#include <UbuntuToolkit/private/ucunits_p.h>
697+
698+UT_USE_NAMESPACE
699+
700+class tst_MainWindow : public QObject
701+{
702+ Q_OBJECT
703+
704+public:
705+ tst_MainWindow()
706+ {
707+ }
708+
709+ QQuickWindow *loadTest(const QString &document)
710+ {
711+ // Can't use UbuntuTestCase: We need a Window root item
712+ QPointer<QQmlEngine> engine(new QQmlEngine());
713+ QString modulePath(UBUNTU_QML_IMPORT_PATH);
714+ if (!QDir(modulePath).exists()) {
715+ qWarning("'%s' doesn't exist", qPrintable(modulePath));
716+ return 0;
717+ }
718+ engine->addImportPath(modulePath);
719+ UbuntuToolkitModule::initializeContextProperties(engine);
720+ QPointer<QQmlComponent> component(new QQmlComponent(engine));
721+ component->loadUrl(QUrl::fromLocalFile(document), QQmlComponent::Asynchronous);
722+ while (component->isLoading())
723+ QCoreApplication::processEvents();
724+ QObject *toplevel(component->create());
725+ if (component->errorString() != "") {
726+ qWarning("%s", qPrintable(component->errorString()));
727+ return 0;
728+ }
729+ QQuickWindow* window(qobject_cast<QQuickWindow *>(toplevel));
730+ if (window)
731+ engine->setIncubationController(window->incubationController());
732+ else {
733+ QQuickItem *rootItem = qobject_cast<QQuickItem *>(toplevel);
734+ if (rootItem) {
735+ QQuickView *view(new QQuickView(engine, 0));
736+ window = view;
737+ view->setResizeMode(QQuickView::SizeRootObjectToView);
738+ view->setContent(document, component, rootItem);
739+ }
740+ }
741+ return window;
742+ }
743+
744+ QQuickItem *testItem(QQuickItem *that, const QString &identifier)
745+ {
746+ if (that->property(identifier.toLocal8Bit()).isValid())
747+ return that->property(identifier.toLocal8Bit()).value<QQuickItem*>();
748+
749+ QList<QQuickItem*> children = that->findChildren<QQuickItem*>(identifier);
750+ return (children.count() > 0) ? children[0] : 0;
751+ }
752+
753+private Q_SLOTS:
754+
755+ void initTestCase()
756+ {
757+ }
758+
759+ void cleanupTestCase()
760+ {
761+ }
762+
763+ // Note: tests/unit/mainview contains the UCApplication bits
764+
765+ void testCase_AppName()
766+ {
767+ QString applicationName("org.gnu.wildebeest");
768+ QQuickWindow *mainWindow(loadTest("AppName.qml"));
769+ QVERIFY(mainWindow);
770+ QCOMPARE(applicationName, mainWindow->property("applicationName").toString());
771+ QCOMPARE(applicationName, QCoreApplication::applicationName());
772+ QCOMPARE(QString(""), QCoreApplication::organizationName());
773+ }
774+};
775+
776+QTEST_MAIN(tst_MainWindow)
777+
778+#include "tst_mainwindow.moc"
779
780=== modified file 'tests/unit/unit.pro'
781--- tests/unit/unit.pro 2016-09-30 05:39:57 +0000
782+++ tests/unit/unit.pro 2017-01-12 02:42:37 +0000
783@@ -41,6 +41,7 @@
784 performance \
785 mainview11 \
786 mainview13 \
787+ mainwindow \
788 i18n \
789 arguments \
790 argument \

Subscribers

People subscribed via source and target branches