Merge lp:~jonas-drange/ubuntu-system-settings/displays-stub into lp:ubuntu-system-settings

Proposed by Jonas G. Drange
Status: Work in progress
Proposed branch: lp:~jonas-drange/ubuntu-system-settings/displays-stub
Merge into: lp:ubuntu-system-settings
Prerequisite: lp:~jonas-drange/ubuntu-system-settings/brightness-qml-testing
Diff against target: 1289 lines (+897/-38)
18 files modified
plugins/brightness/CMakeLists.txt (+4/-0)
plugins/brightness/PageComponent.qml (+138/-8)
plugins/brightness/brightness.cpp (+17/-0)
plugins/brightness/brightness.h (+13/-0)
plugins/brightness/displays/display.cpp (+141/-0)
plugins/brightness/displays/display.h (+112/-0)
plugins/brightness/displays/displaymodel.cpp (+190/-0)
plugins/brightness/displays/displaymodel.h (+82/-0)
plugins/brightness/plugin.cpp (+6/-0)
tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt (+8/-0)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.cpp (+20/-20)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.h (+3/-3)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp (+36/-0)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h (+21/-6)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h (+52/-0)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h (+26/-0)
tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp (+7/-1)
tests/plugins/brightness/tst_BrightnessPageComponent.qml (+21/-0)
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-system-settings/displays-stub
Reviewer Review Type Date Requested Status
system-apps-ci-bot continuous-integration Needs Fixing
Ubuntu Touch System Settings Pending
Review via email: mp+309349@code.launchpad.net

This proposal supersedes a proposal from 2016-10-26.

Commit message

* adds display configuration UI
* adds display and displaymodel to serve as backend for new config UI (stubbed out for now)
* tests new UI (minimally)

Description of the change

This branch introduces most of the display configuration UI and some parts of the display and displaymodel API.

The idea is that the displaymodel will contain all configurable displays. The user the modifies a display element and then the displaymodel (or possibly a new class) asks Mir to configure the displays.

To post a comment you must log in.
1734. By Jonas G. Drange

remove the rest of the kbd jazz

1735. By Jonas G. Drange

make one test for when all new things are hidden, and one where a display config is shown

1736. By Jonas G. Drange

drop unecessary whitespace changes

Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

FAILED: Continuous integration, rev:1734
https://jenkins.canonical.com/system-apps/job/lp-ubuntu-system-settings-ci/218/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1908/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1909
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1748
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1748/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1748
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1748/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1748/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1748
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1748/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1748
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1748/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1748
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1748/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1748/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1748
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1748/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1748/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-ubuntu-system-settings-ci/218/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
system-apps-ci-bot (system-apps-ci-bot) wrote :

FAILED: Continuous integration, rev:1736
https://jenkins.canonical.com/system-apps/job/lp-ubuntu-system-settings-ci/219/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1909/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1910
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1749/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1749/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1749/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1749/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1749/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1749/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1749/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1749/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1749
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1749/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/system-apps/job/lp-ubuntu-system-settings-ci/219/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Jonas G. Drange (jonas-drange) wrote :

The test failures should be addressed by silo 2066.

Unmerged revisions

1736. By Jonas G. Drange

drop unecessary whitespace changes

1735. By Jonas G. Drange

make one test for when all new things are hidden, and one where a display config is shown

1734. By Jonas G. Drange

remove the rest of the kbd jazz

1733. By Jonas G. Drange

add setData to display model

1732. By Jonas G. Drange

undo the kbd rectangle, move api forward

1731. By Jonas G. Drange

move api forward

1730. By Jonas G. Drange

merge prereq

1729. By Jonas G. Drange

add initial stub of displays code

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/brightness/CMakeLists.txt'
2--- plugins/brightness/CMakeLists.txt 2016-10-26 14:45:41 +0000
3+++ plugins/brightness/CMakeLists.txt 2016-10-26 14:45:42 +0000
4@@ -16,6 +16,8 @@
5 aethercast/displays.h
6 aethercast/freedesktop_properties.h
7 aethercast/freedesktop_objectmanager.h
8+ displays/display.h
9+ displays/displaymodel.h
10 plugin.h
11 brightness.h
12 aethercast/aethercast_device.cpp
13@@ -25,6 +27,8 @@
14 aethercast/displays.cpp
15 aethercast/freedesktop_properties.cpp
16 aethercast/freedesktop_objectmanager.cpp
17+ displays/display.cpp
18+ displays/displaymodel.cpp
19 plugin.cpp
20 brightness.cpp
21 ${QML_SOURCES})
22
23=== modified file 'plugins/brightness/PageComponent.qml'
24--- plugins/brightness/PageComponent.qml 2016-10-26 14:45:41 +0000
25+++ plugins/brightness/PageComponent.qml 2016-10-26 14:45:42 +0000
26@@ -21,6 +21,7 @@
27 import GSettings 1.0
28 import QtQuick 2.4
29 import SystemSettings 1.0
30+import SystemSettings.ListItems 1.0 as SettingsListItems
31 import Ubuntu.Components 1.3
32 import Ubuntu.Components.ListItems 1.3 as ListItem
33 import Ubuntu.SystemSettings.Brightness 1.0
34@@ -35,6 +36,14 @@
35 title: brightnessPanel.widiSupported ? i18n.tr("Brightness & Display") : i18n.tr("Brightness")
36 flickable: scrollWidget
37
38+ function formatMode(mode) {
39+ mode = mode.split("x");
40+ /* TRANSLATORS: %1 refer to the amount of horizontal pixels in a
41+ display resolution, and %2 to the vertical pixels. E.g. 1200x720.
42+ %3 is the refresh rate in hz. */
43+ return i18n.tr("%1×%2 @ %3hz").arg(mode[0]).arg(mode[1]).arg(mode[2]);
44+ }
45+
46 GSettings {
47 id: gsettings
48 schema.id: "com.ubuntu.touch.system"
49@@ -68,7 +77,12 @@
50
51 Flickable {
52 id: scrollWidget
53- anchors.fill: parent
54+ anchors {
55+ top: parent.top
56+ left: parent.left
57+ right: parent.right
58+ bottom: applyButtonBackground.top
59+ }
60 contentHeight: contentItem.childrenRect.height
61 boundsBehavior: (contentHeight > root.height) ?
62 Flickable.DragAndOvershootBounds :
63@@ -82,7 +96,7 @@
64 anchors.left: parent.left
65 anchors.right: parent.right
66
67- ListItem.Standard {
68+ SettingsListItems.Standard {
69 text: i18n.tr("Display brightness")
70 showDivider: false
71 }
72@@ -113,12 +127,13 @@
73 }
74 }
75
76- ListItem.Standard {
77+ SettingsListItems.Standard {
78 id: adjust
79 text: i18n.tr("Adjust automatically")
80 visible: brightnessPanel.powerdRunning &&
81 brightnessPanel.autoBrightnessAvailable
82- control: CheckBox {
83+
84+ CheckBox {
85 id: autoAdjustCheck
86 property bool serverChecked: gsettings.autoBrightness
87 onServerCheckedChanged: checked = serverChecked
88@@ -138,12 +153,13 @@
89 visible: brightnessPanel.widiSupported
90 }
91
92- ListItem.Standard {
93+ SettingsListItems.Standard {
94 objectName: "externalDisplayControl"
95 text: i18n.tr("External display")
96 enabled: brightnessPanel.widiSupported
97 onClicked: enabledCheck.trigger()
98- control: Switch {
99+
100+ Switch {
101 id: enabledCheck
102 property bool serverChecked: aethercastDisplays.enabled
103 onServerCheckedChanged: checked = serverChecked
104@@ -154,15 +170,129 @@
105 }
106 }
107
108- ListItem.SingleValue {
109+ SettingsListItems.SingleValueProgression {
110 objectName: "displayCasting"
111 visible: brightnessPanel.widiSupported
112 enabled: aethercastDisplays.enabled
113 text: i18n.tr("Wireless display")
114 value: aethercastDisplays.state === "connected" ? i18n.tr("Connected") : i18n.tr("Not connected")
115- progression: true
116 onClicked: pageStack.push(Qt.resolvedUrl("WifiDisplays.qml"))
117 }
118+
119+ Repeater {
120+ objectName: "displayConfigurationRepeater"
121+ model: brightnessPanel.allDisplays
122+
123+ Column {
124+ objectName: "displayConfiguration_" + displayName
125+ anchors {
126+ left: parent.left
127+ right: parent.right
128+ }
129+
130+ Label {
131+ visible: brightnessPanel.allDisplays.count > 1
132+ anchors {
133+ left: parent.left
134+ right: parent.right
135+ margins: units.gu(2)
136+ }
137+
138+ text: displayName
139+ }
140+
141+ SettingsItemTitle {
142+ text: i18n.tr("Rotation:")
143+ }
144+
145+ OptionSelector {
146+ id: rotationSelector
147+ objectName: "rotationSelector"
148+ property bool _expanded: false
149+ anchors {
150+ left: parent.left
151+ right: parent.right
152+ margins: units.gu(2)
153+ }
154+ containerHeight: itemHeight * 4
155+ model: [
156+ i18n.tr("None"),
157+ i18n.tr("90° clockwise"),
158+ i18n.tr("180°"),
159+ i18n.tr("270°")
160+ ]
161+ onDelegateClicked: {
162+ expanded = !currentlyExpanded;
163+ }
164+ }
165+
166+ SettingsItemTitle {
167+ text: availableModes.length > 1 ?
168+ i18n.tr("Resolution:") :
169+ /* TRANSLATORS: %1 is a display mode, e.g.
170+ 1200x720x24. */
171+ i18n.tr("Resolution: %1").arg(formatMode(mode))
172+ }
173+
174+ OptionSelector {
175+ id: resolutionSelector
176+ objectName: "resolutionSelector"
177+ property bool _expanded: false
178+ anchors {
179+ left: parent.left
180+ right: parent.right
181+ margins: units.gu(2)
182+ }
183+ visible: availableModes.length > 1
184+ containerHeight: itemHeight * availableModes.length
185+ model: availableModes
186+ onDelegateClicked: expanded = !currentlyExpanded
187+ delegate: OptionSelectorDelegate {
188+ text: formatMode(modelData)
189+ }
190+ }
191+
192+ SettingsItemTitle {
193+ text: i18n.tr("Scale screen elements:")
194+ }
195+
196+ Menus.SliderMenu {
197+ id: scaleSlider
198+ objectName: "scaleSlider"
199+ minimumValue: 1.0
200+ maximumValue: 100.0
201+ value: scale
202+ minIcon: "image://theme/grip-large"
203+ maxIcon: "image://theme/view-grid-symbolic"
204+ }
205+ }
206+ }
207+ }
208+ }
209+
210+ Rectangle {
211+ id: applyButtonBackground
212+ objectName: "applyButtonBackground"
213+ anchors {
214+ left: parent.left
215+ right: parent.right
216+ bottom: parent.bottom
217+ }
218+ color: Theme.palette.selected.background
219+
220+ visible: brightnessPanel.allDisplays.count > 0
221+ height: units.gu(6)
222+ Button {
223+ id: applyButton
224+ objectName: "applyButton"
225+ anchors {
226+ left: parent.left
227+ leftMargin: units.gu(1)
228+ verticalCenter: parent.verticalCenter
229+ }
230+ enabled: brightnessPanel.changedDisplays.count > 0
231+ text: i18n.tr("Apply Changes…")
232+ onClicked: brightnessPanel.applyDisplayConfiguration()
233 }
234 }
235 }
236
237=== modified file 'plugins/brightness/brightness.cpp'
238--- plugins/brightness/brightness.cpp 2016-04-13 19:21:59 +0000
239+++ plugins/brightness/brightness.cpp 2016-10-26 14:45:42 +0000
240@@ -25,6 +25,7 @@
241 #include <QDBusReply>
242 #include <QDBusMetaType>
243 #include <QDebug>
244+#include <QQmlEngine>
245
246 // Returned data from getBrightnessParams
247 struct BrightnessParams {
248@@ -81,6 +82,8 @@
249 QDBusArgument result(reply.arguments()[0].value<QDBusArgument>());
250 BrightnessParams params = qdbus_cast<BrightnessParams>(result);
251 m_autoBrightnessAvailable = params.automatic;
252+ m_changedDisplays.filterOnUncommittedChanges(true);
253+ m_changedDisplays.setSourceModel(&m_displays);
254 }
255
256 bool Brightness::getAutoBrightnessAvailable() const
257@@ -98,3 +101,17 @@
258 property_get("ubuntu.widi.supported", widi, "0");
259 return (strcmp(widi, "0") > 0);
260 }
261+
262+QAbstractItemModel* Brightness::allDisplays()
263+{
264+ auto ret = &m_displays;
265+ QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
266+ return ret;
267+}
268+
269+QAbstractItemModel* Brightness::changedDisplays()
270+{
271+ auto ret = &m_changedDisplays;
272+ QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
273+ return ret;
274+}
275
276=== modified file 'plugins/brightness/brightness.h'
277--- plugins/brightness/brightness.h 2016-04-13 17:12:35 +0000
278+++ plugins/brightness/brightness.h 2016-10-26 14:45:42 +0000
279@@ -21,6 +21,9 @@
280 #ifndef BRIGHTNESS_H
281 #define BRIGHTNESS_H
282
283+#include "displays/displaymodel.h"
284+
285+#include <QAbstractItemModel>
286 #include <QDBusInterface>
287 #include <QObject>
288
289@@ -36,12 +39,20 @@
290 Q_PROPERTY (bool widiSupported
291 READ getWidiSupported
292 CONSTANT)
293+ Q_PROPERTY (QAbstractItemModel* allDisplays
294+ READ allDisplays
295+ CONSTANT)
296+ Q_PROPERTY (QAbstractItemModel* changedDisplays
297+ READ changedDisplays
298+ CONSTANT)
299
300 public:
301 explicit Brightness(QObject *parent = 0);
302 bool getPowerdRunning() const;
303 bool getAutoBrightnessAvailable() const;
304 bool getWidiSupported() const;
305+ QAbstractItemModel* allDisplays();
306+ QAbstractItemModel* changedDisplays();
307
308 private:
309 QDBusConnection m_systemBusConnection;
310@@ -49,6 +60,8 @@
311 QDBusInterface m_powerdIface;
312 bool m_powerdRunning;
313 bool m_autoBrightnessAvailable;
314+ DisplayModel m_displays;
315+ DisplaysFilter m_changedDisplays;
316 };
317
318 #endif // BRIGHTNESS_H
319
320=== added directory 'plugins/brightness/displays'
321=== added file 'plugins/brightness/displays/display.cpp'
322--- plugins/brightness/displays/display.cpp 1970-01-01 00:00:00 +0000
323+++ plugins/brightness/displays/display.cpp 2016-10-26 14:45:42 +0000
324@@ -0,0 +1,141 @@
325+#include "display.h"
326+
327+Display::Display(QObject *parent)
328+ : QObject(parent)
329+{
330+ QObject::connect(this, SIGNAL(nameChanged()),
331+ this, SLOT(changedSlot()));
332+ QObject::connect(this, SIGNAL(typeChanged()),
333+ this, SLOT(changedSlot()));
334+ QObject::connect(this, SIGNAL(mirroredChanged()),
335+ this, SLOT(changedSlot()));
336+ QObject::connect(this, SIGNAL(connectedChanged()),
337+ this, SLOT(changedSlot()));
338+ QObject::connect(this, SIGNAL(enabledChanged()),
339+ this, SLOT(changedSlot()));
340+ QObject::connect(this, SIGNAL(modeChanged()),
341+ this, SLOT(changedSlot()));
342+ QObject::connect(this, SIGNAL(availableModesChanged()),
343+ this, SLOT(changedSlot()));
344+ QObject::connect(this, SIGNAL(orientationChanged()),
345+ this, SLOT(changedSlot()));
346+ QObject::connect(this, SIGNAL(scaleChanged()),
347+ this, SLOT(changedSlot()));
348+ QObject::connect(this, SIGNAL(uncommittedChangesChanged()),
349+ this, SLOT(changedSlot()));
350+}
351+
352+QString Display::name() const
353+{
354+ return m_name;
355+}
356+
357+QString Display::type() const
358+{
359+ return m_type;
360+}
361+
362+bool Display::mirrored() const
363+{
364+ return m_mirrored;
365+}
366+
367+bool Display::connected() const
368+{
369+ return m_connected;
370+}
371+
372+bool Display::enabled() const
373+{
374+ return m_enabled;
375+}
376+
377+QString Display::mode() const
378+{
379+ return m_mode;
380+}
381+
382+QStringList Display::availableModes() const
383+{
384+ return m_availableModes;
385+}
386+
387+Display::Orientation Display::orientation() const
388+{
389+ return m_orientation;
390+}
391+
392+double Display::scale() const
393+{
394+ return m_scale;
395+}
396+
397+bool Display::uncommittedChanges() const
398+{
399+ return m_uncommittedChanges;
400+}
401+
402+void Display::setName(const QString &name)
403+{
404+ m_name = name;
405+ Q_EMIT nameChanged();
406+}
407+
408+void Display::setType(const QString &type)
409+{
410+ m_type = type;
411+ Q_EMIT typeChanged();
412+}
413+
414+void Display::setMirrored(const bool &mirrored)
415+{
416+ m_mirrored = mirrored;
417+ Q_EMIT mirroredChanged();
418+}
419+
420+void Display::setConnected(const bool &connected)
421+{
422+ m_connected = connected;
423+ Q_EMIT connectedChanged();
424+}
425+
426+void Display::setEnabled(const bool &enabled)
427+{
428+ m_enabled = enabled;
429+ Q_EMIT enabledChanged();
430+}
431+
432+void Display::setMode(const QString &mode)
433+{
434+ m_mode = mode;
435+ Q_EMIT modeChanged();
436+}
437+
438+void Display::setAvailableModes(const QStringList &availableModes)
439+{
440+ m_availableModes = availableModes;
441+ Q_EMIT availableModesChanged();
442+}
443+
444+void Display::setOrientation(const Display::Orientation &orientation)
445+{
446+ m_orientation = orientation;
447+ Q_EMIT orientationChanged();
448+}
449+
450+void Display::setScale(const double &scale)
451+{
452+ m_scale = scale;
453+ Q_EMIT scaleChanged();
454+}
455+
456+void Display::setUncommitedChanges(const bool uncommittedChanges)
457+{
458+ m_uncommittedChanges = uncommittedChanges;
459+ Q_EMIT uncommittedChangesChanged();
460+}
461+
462+void Display::changedSlot()
463+{
464+ Q_EMIT displayChanged(this);
465+}
466
467=== added file 'plugins/brightness/displays/display.h'
468--- plugins/brightness/displays/display.h 1970-01-01 00:00:00 +0000
469+++ plugins/brightness/displays/display.h 2016-10-26 14:45:42 +0000
470@@ -0,0 +1,112 @@
471+#ifndef DISPLAY_H
472+#define DISPLAY_H
473+
474+#include <QObject>
475+#include <QString>
476+#include <QStringList>
477+
478+class Display : public QObject
479+{
480+ Q_OBJECT
481+ Q_PROPERTY(QString name
482+ READ name
483+ NOTIFY nameChanged)
484+ Q_PROPERTY(QString type
485+ READ type
486+ NOTIFY typeChanged)
487+ Q_PROPERTY(bool mirrored
488+ READ mirrored
489+ WRITE setMirrored
490+ NOTIFY mirroredChanged)
491+ Q_PROPERTY(bool connected
492+ READ connected
493+ NOTIFY connectedChanged)
494+ Q_PROPERTY(bool enabled
495+ READ enabled
496+ WRITE setEnabled
497+ NOTIFY enabledChanged)
498+ Q_PROPERTY(QString mode
499+ READ mode
500+ WRITE setMode
501+ NOTIFY modeChanged)
502+ Q_PROPERTY(QStringList availableModes
503+ READ availableModes
504+ NOTIFY availableModesChanged)
505+ Q_PROPERTY(Orientation orientation
506+ READ orientation
507+ WRITE setOrientation
508+ NOTIFY orientationChanged)
509+ Q_PROPERTY(double scale
510+ READ scale
511+ WRITE setScale
512+ NOTIFY scaleChanged)
513+ Q_PROPERTY(bool uncommittedChanges
514+ READ uncommittedChanges
515+ NOTIFY uncommittedChangesChanged)
516+
517+Q_SIGNALS:
518+ void nameChanged();
519+ void typeChanged();
520+ void mirroredChanged();
521+ void connectedChanged();
522+ void enabledChanged();
523+ void modeChanged();
524+ void availableModesChanged();
525+ void orientationChanged();
526+ void scaleChanged();
527+ void uncommittedChangesChanged();
528+ void displayChanged(const Display *display);
529+
530+public:
531+ explicit Display(QObject *parent = nullptr);
532+ ~Display() {};
533+ enum class Orientation : uint {
534+ Normal, PortraitMode, LandscapeInvertedMode,
535+ PortraitInvertedMode
536+ };
537+ enum class DisplayType : uint {
538+ PhysicalType, AethercastType
539+ };
540+ Q_ENUMS(Orientation DisplayType)
541+
542+ QString name() const;
543+ QString type() const;
544+ bool mirrored() const;
545+ bool connected() const;
546+ bool enabled() const;
547+ QString mode() const;
548+ QStringList availableModes() const;
549+ Orientation orientation() const;
550+ double scale() const;
551+ bool uncommittedChanges() const;
552+
553+ void setMirrored(const bool &mirrored);
554+ void setEnabled(const bool &enabled);
555+ void setMode(const QString &mode);
556+ void setOrientation(const Orientation &orientation);
557+ void setScale(const double &scale);
558+
559+protected:
560+ void setName(const QString &name);
561+ void setAvailableModes(const QStringList &availableModes);
562+ void setConnected(const bool &connected);
563+ void setType(const QString &type);
564+ void setUncommitedChanges(const bool uncommittedChanges);
565+ QString m_name = QString::null;
566+ QString m_type = QString::null;
567+ bool m_mirrored = false;
568+ bool m_connected = false;
569+ bool m_enabled = false;
570+ QString m_mode = QString::null;
571+ QStringList m_availableModes = QStringList();
572+ Orientation m_orientation = Orientation::Normal;
573+ double m_scale = 1;
574+ bool m_uncommittedChanges = false;
575+
576+private slots:
577+ void changedSlot();
578+};
579+
580+Q_DECLARE_METATYPE(Display*)
581+
582+#endif // DISPLAY_H
583
584=== added file 'plugins/brightness/displays/displaymodel.cpp'
585--- plugins/brightness/displays/displaymodel.cpp 1970-01-01 00:00:00 +0000
586+++ plugins/brightness/displays/displaymodel.cpp 2016-10-26 14:45:42 +0000
587@@ -0,0 +1,190 @@
588+#include "displaymodel.h"
589+
590+#include <QDebug>
591+
592+DisplayModel::DisplayModel(QObject *parent)
593+{
594+}
595+
596+DisplayModel::~DisplayModel()
597+{
598+}
599+
600+int DisplayModel::rowCount(const QModelIndex &parent) const
601+{
602+ return m_displays.count();
603+}
604+
605+QVariant DisplayModel::data(const QModelIndex &index, int role) const
606+{
607+ QVariant ret;
608+
609+ if ((0 <= index.row()) && (index.row() < m_displays.size())) {
610+
611+ auto display = m_displays[index.row()];
612+
613+ switch (role) {
614+ case Qt::DisplayRole:
615+ ret = display->name();
616+ break;
617+ case TypeRole:
618+ ret = display->type();
619+ break;
620+ case MirroredRole:
621+ ret = display->mirrored();
622+ break;
623+ case ConnectedRole:
624+ ret = display->connected();
625+ break;
626+ case EnabledRole:
627+ ret = display->enabled();
628+ break;
629+ case ModeRole:
630+ ret = display->mode();
631+ break;
632+ case AvailableModesRole:
633+ ret = display->availableModes();
634+ break;
635+ case OrientationRole:
636+ ret = (uint) display->orientation();
637+ break;
638+ case ScaleRole:
639+ ret = display->scale();
640+ break;
641+ case UncommittedChangesRole:
642+ ret = display->uncommittedChanges();
643+ break;
644+ }
645+ }
646+
647+ return ret;
648+}
649+
650+bool DisplayModel::setData(const QModelIndex &index, const QVariant &value,
651+ int role)
652+{
653+ if ((0 <= index.row()) && (index.row() < m_displays.size())) {
654+
655+ auto display = m_displays[index.row()];
656+
657+ switch (role) {
658+
659+ case MirroredRole:
660+ display->setMirrored(value.toBool());
661+ break;
662+ case EnabledRole:
663+ display->setEnabled(value.toBool());
664+ break;
665+ case ModeRole:
666+ display->setMode(value.toString());
667+ break;
668+ case OrientationRole:
669+ display->setOrientation((Display::Orientation) value.toUInt());
670+ break;
671+ case ScaleRole:
672+ display->setScale(value.toInt());
673+ break;
674+ case Qt::DisplayRole:
675+ case TypeRole:
676+ case ConnectedRole:
677+ case AvailableModesRole:
678+ case UncommittedChangesRole:
679+ default:
680+ return false;
681+ }
682+ return true;
683+ } else {
684+ return false;
685+ }
686+}
687+
688+
689+QHash<int,QByteArray> DisplayModel::roleNames() const
690+{
691+ static QHash<int,QByteArray> names;
692+ if (Q_UNLIKELY(names.empty())) {
693+ names[Qt::DisplayRole] = "displayName";
694+ names[MirroredRole] = "mirrored";
695+ names[ConnectedRole] = "connected";
696+ names[EnabledRole] = "enabled";
697+ names[ModeRole] = "mode";
698+ names[AvailableModesRole] = "availableModes";
699+ names[OrientationRole] = "orientation";
700+ names[ScaleRole] = "scale";
701+ names[UncommittedChangesRole] = "uncommittedChanges";
702+ }
703+ return names;
704+}
705+
706+void DisplayModel::addDisplay(const QSharedPointer<Display> &display)
707+{
708+ // TODO: find display
709+ int row = -1;
710+
711+ if (row >= 0) { // update existing display
712+ m_displays[row] = display;
713+ emitRowChanged(row);
714+ } else { // add new display
715+ row = m_displays.size();
716+ beginInsertRows(QModelIndex(), row, row);
717+ m_displays.append(display);
718+ endInsertRows();
719+ }
720+
721+ if (display) {
722+ QObject::connect(display.data(), SIGNAL(displayChanged(const Display*)),
723+ this, SLOT(displayChangedSlot(const Display*)));
724+ }
725+
726+ Q_EMIT countChanged();
727+}
728+
729+void DisplayModel::emitRowChanged(const int &row)
730+{
731+ if (0 <= row && row < m_displays.size()) {
732+ QModelIndex qmi = index(row, 0);
733+ Q_EMIT(dataChanged(qmi, qmi));
734+ }
735+}
736+
737+void DisplayModel::displayChangedSlot(const Display *display)
738+{
739+ // find the row that goes with this display
740+ int row = -1;
741+ if (display != nullptr)
742+ for (int i = 0, n = m_displays.size(); row == -1 && i < n; i++)
743+ if (m_displays[i].data() == display)
744+ row = i;
745+
746+ if (row != -1)
747+ emitRowChanged(row);
748+}
749+
750+bool DisplaysFilter::lessThan(const QModelIndex &left,
751+ const QModelIndex &right) const
752+{
753+ const QString a = sourceModel()->data(left, Qt::DisplayRole).value<QString>();
754+ const QString b = sourceModel()->data(right, Qt::DisplayRole).value<QString>();
755+ return a < b;
756+}
757+
758+void DisplaysFilter::filterOnUncommittedChanges(const bool apply)
759+{
760+ m_uncommittedChanges = apply;
761+ m_uncommittedChangesEnabled = true;
762+ invalidateFilter();
763+}
764+
765+bool DisplaysFilter::filterAcceptsRow(int sourceRow,
766+ const QModelIndex &sourceParent) const
767+{
768+ bool accepts = true;
769+ QModelIndex childIndex = sourceModel()->index(sourceRow, 0, sourceParent);
770+
771+ if (accepts && m_uncommittedChangesEnabled) {
772+ const bool uncommittedChanges = childIndex.model()->data(childIndex, DisplayModel::UncommittedChangesRole).value<bool>();
773+ accepts = (m_uncommittedChanges == uncommittedChanges);
774+ }
775+
776+ return accepts;
777+}
778
779=== added file 'plugins/brightness/displays/displaymodel.h'
780--- plugins/brightness/displays/displaymodel.h 1970-01-01 00:00:00 +0000
781+++ plugins/brightness/displays/displaymodel.h 2016-10-26 14:45:42 +0000
782@@ -0,0 +1,82 @@
783+#ifndef DISPLAY_MODEL_H
784+#define DISPLAY_MODEL_H
785+
786+#include "display.h"
787+
788+#include <QAbstractListModel>
789+#include <QByteArray>
790+#include <QHash>
791+#include <QList>
792+#include <QModelIndex>
793+#include <QSharedPointer>
794+#include <QSortFilterProxyModel>
795+#include <QVariant>
796+
797+class DisplayModel : public QAbstractListModel
798+{
799+ Q_OBJECT
800+ Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
801+public:
802+ explicit DisplayModel(QObject *parent = 0);
803+ ~DisplayModel();
804+
805+ enum Roles
806+ {
807+ // Qt::DisplayRole holds device name
808+ TypeRole = Qt::UserRole,
809+ MirroredRole,
810+ ConnectedRole,
811+ EnabledRole,
812+ ModeRole,
813+ AvailableModesRole,
814+ OrientationRole,
815+ ScaleRole,
816+ UncommittedChangesRole,
817+ LastRole = UncommittedChangesRole
818+ };
819+
820+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
821+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
822+ bool setData(const QModelIndex &index, const QVariant &value,
823+ int role = Qt::EditRole);
824+ QHash<int,QByteArray> roleNames() const;
825+
826+Q_SIGNALS:
827+ void countChanged();
828+
829+protected:
830+ void emitRowChanged(const int &row);
831+ void addDisplay(const QSharedPointer<Display> &display);
832+
833+private:
834+ QList<QSharedPointer<Display> > m_displays;
835+
836+private slots:
837+ void displayChangedSlot(const Display *display);
838+};
839+
840+class DisplaysFilter : public QSortFilterProxyModel
841+{
842+ Q_OBJECT
843+ Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
844+
845+public:
846+ DisplaysFilter() {}
847+ virtual ~DisplaysFilter() {}
848+
849+ void filterOnUncommittedChanges(const bool apply);
850+
851+Q_SIGNALS:
852+ void countChanged(int count);
853+
854+protected:
855+ virtual bool filterAcceptsRow(int, const QModelIndex&) const;
856+ virtual bool lessThan(const QModelIndex&, const QModelIndex&) const;
857+
858+private:
859+ bool m_uncommittedChanges = false;
860+ bool m_uncommittedChangesEnabled = false;
861+
862+};
863+
864+#endif // DISPLAY_MODEL_H
865
866=== modified file 'plugins/brightness/plugin.cpp'
867--- plugins/brightness/plugin.cpp 2016-04-13 18:49:49 +0000
868+++ plugins/brightness/plugin.cpp 2016-10-26 14:45:42 +0000
869@@ -27,6 +27,9 @@
870 #include "aethercast/displays.h"
871 #include "aethercast/device.h"
872
873+#include "displays/display.h"
874+#include "displays/displaymodel.h"
875+
876
877 void BackendPlugin::registerTypes(const char *uri)
878 {
879@@ -39,6 +42,9 @@
880 qmlRegisterType<Brightness>(uri, 1, 0, "UbuntuBrightnessPanel");
881 qmlRegisterType<Device>(uri, 1, 0, "AethercastDevice");
882 qmlRegisterType<Displays>(uri, 1, 0, "AethercastDisplays");
883+
884+ qmlRegisterType<DisplayModel>(uri, 1, 0, "DisplayModel");
885+ qmlRegisterType<Display>(uri, 1, 0, "Display");
886 }
887
888 void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
889
890=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt'
891--- tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt 2016-10-26 14:45:41 +0000
892+++ tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt 2016-10-26 14:45:42 +0000
893@@ -1,6 +1,7 @@
894 include_directories(
895 ${CMAKE_CURRENT_BINARY_DIR}
896 ${CMAKE_SOURCE_DIR}/plugins/brightness/
897+ ${CMAKE_SOURCE_DIR}/plugins/brightness/displays
898 )
899
900 set(MOCK_BRIGHTNESS_SRCS
901@@ -8,6 +9,13 @@
902 MockAethercastDeviceModel.cpp
903 MockAethercastDisplays.cpp
904 MockBrightness.cpp
905+
906+ ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/display.h
907+ ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/displaymodel.h
908+ MockDisplay.h
909+ MockDisplayModel.h
910+ ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/display.cpp
911+ ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/displaymodel.cpp
912 plugin.cpp
913 )
914
915
916=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.cpp'
917--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.cpp 2016-10-26 14:45:41 +0000
918+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.cpp 2016-10-26 14:45:42 +0000
919@@ -19,71 +19,71 @@
920
921 #include <QQmlEngine>
922
923-void MockDisplays::connectDevice(const QString &address)
924-{
925- Q_UNUSED(address)
926-}
927-
928-void MockDisplays::disconnectDevice(const QString &address)
929-{
930- Q_UNUSED(address)
931-}
932-
933-void MockDisplays::scan()
934+void MockAethercastDisplays::connectDevice(const QString &address)
935+{
936+ Q_UNUSED(address)
937+}
938+
939+void MockAethercastDisplays::disconnectDevice(const QString &address)
940+{
941+ Q_UNUSED(address)
942+}
943+
944+void MockAethercastDisplays::scan()
945 {
946 m_scanning = true;
947 Q_EMIT scanningChanged(m_scanning);
948 }
949
950-void MockDisplays::stopScan()
951+void MockAethercastDisplays::stopScan()
952 {
953 m_scanning = false;
954 Q_EMIT scanningChanged(m_scanning);
955 }
956
957-void MockDisplays::setProperties(const QMap<QString, QVariant> &properties)
958+void MockAethercastDisplays::setProperties(const QMap<QString, QVariant> &properties)
959 {
960 Q_UNUSED(properties)
961 }
962
963-QAbstractItemModel* MockDisplays::devices()
964+QAbstractItemModel* MockAethercastDisplays::devices()
965 {
966 auto ret = &m_devices;
967 QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
968 return ret;
969 }
970
971-QAbstractItemModel* MockDisplays::connectedDevices()
972+QAbstractItemModel* MockAethercastDisplays::connectedDevices()
973 {
974 auto ret = &m_connectedDevices;
975 QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
976 return ret;
977 }
978
979-QAbstractItemModel* MockDisplays::disconnectedDevices()
980+QAbstractItemModel* MockAethercastDisplays::disconnectedDevices()
981 {
982 auto ret = &m_disconnectedDevices;
983 QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
984 return ret;
985 }
986
987-bool MockDisplays::scanning() const
988+bool MockAethercastDisplays::scanning() const
989 {
990 return m_scanning;
991 }
992
993-bool MockDisplays::enabled() const
994+bool MockAethercastDisplays::enabled() const
995 {
996 return m_enabled;
997 }
998
999-void MockDisplays::setEnabled(const bool enabled)
1000+void MockAethercastDisplays::setEnabled(const bool enabled)
1001 {
1002 m_enabled = enabled;
1003 Q_EMIT enabledChanged(enabled);
1004 }
1005
1006-QString MockDisplays::state() const
1007+QString MockAethercastDisplays::state() const
1008 {
1009 return m_state;
1010 }
1011
1012=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.h'
1013--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.h 2016-10-26 14:45:41 +0000
1014+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockAethercastDisplays.h 2016-10-26 14:45:42 +0000
1015@@ -23,7 +23,7 @@
1016
1017 #include <QObject>
1018
1019-class MockDisplays : public QObject
1020+class MockAethercastDisplays : public QObject
1021 {
1022 Q_OBJECT
1023 Q_PROPERTY (QAbstractItemModel* devices
1024@@ -46,10 +46,10 @@
1025 READ state
1026 NOTIFY stateChanged)
1027 public:
1028- explicit MockDisplays(QObject *parent = nullptr) {
1029+ explicit MockAethercastDisplays(QObject *parent = nullptr) {
1030 Q_UNUSED(parent)
1031 };
1032- ~MockDisplays() {}
1033+ ~MockAethercastDisplays() {}
1034
1035 enum Error {
1036 None,
1037
1038=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp'
1039--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp 2016-10-26 14:45:41 +0000
1040+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp 2016-10-26 14:45:42 +0000
1041@@ -15,8 +15,20 @@
1042 * You should have received a copy of the GNU General Public License along
1043 * with this program. If not, see <http://www.gnu.org/licenses/>.
1044 */
1045+#include "MockDisplayModel.h"
1046 #include "MockBrightness.h"
1047
1048+#include <QQmlEngine>
1049+
1050+MockBrightness::MockBrightness(QObject *parent)
1051+ : QObject(parent)
1052+ , m_displays()
1053+ , m_changedDisplays()
1054+{
1055+ m_changedDisplays.filterOnUncommittedChanges(true);
1056+ m_changedDisplays.setSourceModel(&m_displays);
1057+}
1058+
1059 bool MockBrightness::getPowerdRunning() const
1060 {
1061 return m_powerdRunning;
1062@@ -49,3 +61,27 @@
1063 m_widiSupported = supported;
1064 Q_EMIT widiSupportedChanged();
1065 }
1066+
1067+QAbstractItemModel* MockBrightness::allDisplays()
1068+{
1069+ auto ret = &m_displays;
1070+ QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
1071+ return ret;
1072+}
1073+
1074+QAbstractItemModel* MockBrightness::changedDisplays()
1075+{
1076+ auto ret = &m_changedDisplays;
1077+ QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
1078+ return ret;
1079+}
1080+
1081+void MockBrightness::applyDisplayConfiguration()
1082+{
1083+
1084+}
1085+
1086+MockDisplayModel* MockBrightness::displayModel()
1087+{
1088+ return (MockDisplayModel*) allDisplays();
1089+}
1090
1091=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h'
1092--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h 2016-10-26 14:45:41 +0000
1093+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h 2016-10-26 14:45:42 +0000
1094@@ -19,7 +19,11 @@
1095 #ifndef MOCK_BRIGHTNESS_H
1096 #define MOCK_BRIGHTNESS_H
1097
1098+#include "MockDisplayModel.h"
1099+
1100+#include <QAbstractItemModel>
1101 #include <QObject>
1102+#include <QSortFilterProxyModel>
1103
1104 class MockBrightness : public QObject
1105 {
1106@@ -33,16 +37,25 @@
1107 Q_PROPERTY (bool widiSupported
1108 READ getWidiSupported
1109 NOTIFY widiSupportedChanged)
1110+ Q_PROPERTY (QAbstractItemModel* allDisplays
1111+ READ allDisplays
1112+ CONSTANT)
1113+ Q_PROPERTY (QAbstractItemModel* changedDisplays
1114+ READ changedDisplays
1115+ CONSTANT)
1116+
1117 public:
1118- explicit MockBrightness(QObject *parent = 0) {
1119- Q_UNUSED(parent)
1120- };
1121+ explicit MockBrightness(QObject *parent = 0);
1122 bool getPowerdRunning() const;
1123 bool getAutoBrightnessAvailable() const;
1124 bool getWidiSupported() const;
1125- Q_INVOKABLE void setPowerdRunning(const bool running); // mock only
1126- Q_INVOKABLE void setAutoBrightnessAvailable(const bool available); // mock only
1127- Q_INVOKABLE void setWidiSupported(const bool supported); // mock only
1128+ Q_INVOKABLE void setPowerdRunning(const bool running);
1129+ Q_INVOKABLE void setAutoBrightnessAvailable(const bool available);
1130+ Q_INVOKABLE void setWidiSupported(const bool supported);
1131+ QAbstractItemModel* allDisplays();
1132+ QAbstractItemModel* changedDisplays();
1133+ Q_INVOKABLE void applyDisplayConfiguration();
1134+ Q_INVOKABLE MockDisplayModel* displayModel(); // mock only
1135
1136 Q_SIGNALS:
1137 void powerdRunningChanged(); // mock only
1138@@ -53,6 +66,8 @@
1139 bool m_powerdRunning = false;
1140 bool m_autoBrightnessAvailable = false;
1141 bool m_widiSupported = false;
1142+ MockDisplayModel m_displays;
1143+ DisplaysFilter m_changedDisplays;
1144 };
1145
1146 #endif // MOCK_BRIGHTNESS_H
1147
1148=== added file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h'
1149--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h 1970-01-01 00:00:00 +0000
1150+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h 2016-10-26 14:45:42 +0000
1151@@ -0,0 +1,52 @@
1152+#ifndef MOCK_DISPLAY_H
1153+#define MOCK_DISPLAY_H
1154+
1155+#include "display.h"
1156+
1157+#include <QObject>
1158+#include <QDebug>
1159+
1160+struct MockDisplay : public Display
1161+{
1162+ Q_OBJECT
1163+public:
1164+ Q_INVOKABLE void setName(const QString &name) // mock only
1165+ {
1166+ m_name = name;
1167+ Q_EMIT nameChanged();
1168+ }
1169+
1170+ Q_INVOKABLE void setType(const QString &type) // mock only
1171+ {
1172+ m_type = type;
1173+ Q_EMIT typeChanged();
1174+ }
1175+
1176+ Q_INVOKABLE void setConnected(const bool &connected) // mock only
1177+ {
1178+ m_connected = connected;
1179+ Q_EMIT connectedChanged();
1180+ }
1181+
1182+ Q_INVOKABLE void setAvailableModes(const QStringList &availableModes) // mock only
1183+ {
1184+ m_availableModes = availableModes;
1185+ Q_EMIT availableModesChanged();
1186+ }
1187+
1188+ Q_INVOKABLE void setUncommitedChanges(const bool uncommittedChanges) // mock only
1189+ {
1190+ m_uncommittedChanges = uncommittedChanges;
1191+ Q_EMIT uncommittedChangesChanged();
1192+ }
1193+
1194+ Q_INVOKABLE void addMode(const QString &mode) // mock only
1195+ {
1196+ m_availableModes.append(mode);
1197+ Q_EMIT availableModesChanged();
1198+ }
1199+};
1200+
1201+Q_DECLARE_METATYPE(MockDisplay*)
1202+
1203+#endif // MOCK_DISPLAY_H
1204
1205=== added file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h'
1206--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h 1970-01-01 00:00:00 +0000
1207+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h 2016-10-26 14:45:42 +0000
1208@@ -0,0 +1,26 @@
1209+#ifndef MOCK_DISPLAY_MODEL_H
1210+#define MOCK_DISPLAY_MODEL_H
1211+
1212+#include "displaymodel.h"
1213+#include "MockDisplay.h"
1214+
1215+#include <QObject>
1216+#include <QQmlEngine>
1217+
1218+class MockDisplayModel : public DisplayModel
1219+{
1220+ Q_OBJECT
1221+public:
1222+ MockDisplayModel(QObject *parent = 0) : DisplayModel(parent) {
1223+ };
1224+ ~MockDisplayModel() {};
1225+ Q_INVOKABLE MockDisplay* mockAddDisplay() // mock only
1226+ {
1227+ QSharedPointer<MockDisplay> d = QSharedPointer<MockDisplay>(new MockDisplay);
1228+ addDisplay(d);
1229+ QQmlEngine::setObjectOwnership(d.data(), QQmlEngine::CppOwnership);
1230+ return d.data();
1231+ }
1232+};
1233+
1234+#endif // MOCK_DISPLAY_MODEL_H
1235
1236=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp'
1237--- tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp 2016-10-26 14:45:41 +0000
1238+++ tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp 2016-10-26 14:45:42 +0000
1239@@ -22,6 +22,9 @@
1240 #include "MockAethercastDeviceModel.h"
1241 #include "MockAethercastDisplays.h"
1242
1243+#include "MockDisplay.h"
1244+#include "MockDisplayModel.h"
1245+
1246 #include <QtQml>
1247
1248 void BackendPlugin::registerTypes(const char *uri)
1249@@ -29,5 +32,8 @@
1250 Q_ASSERT(uri == QLatin1String("Ubuntu.SystemSettings.Brightness"));
1251 qmlRegisterType<MockBrightness>(uri, 1, 0, "UbuntuBrightnessPanel");
1252 qmlRegisterType<MockAethercastDevice>(uri, 1, 0, "AethercastDevice");
1253- qmlRegisterType<MockDisplays>(uri, 1, 0, "AethercastDisplays");
1254+ qmlRegisterType<MockAethercastDisplays>(uri, 1, 0, "AethercastDisplays");
1255+
1256+ qmlRegisterUncreatableType<MockDisplay>(uri, 1, 0, "Display", "Not to be instantiated directly.");
1257+ qmlRegisterType<MockDisplayModel>(uri, 1, 0, "DisplayModel");
1258 }
1259
1260=== modified file 'tests/plugins/brightness/tst_BrightnessPageComponent.qml'
1261--- tests/plugins/brightness/tst_BrightnessPageComponent.qml 2016-10-26 14:45:41 +0000
1262+++ tests/plugins/brightness/tst_BrightnessPageComponent.qml 2016-10-26 14:45:42 +0000
1263@@ -86,5 +86,26 @@
1264 verify(entry.enabled);
1265 compare(entry.value, i18n.tr("Not connected"));
1266 }
1267+
1268+ // Test that everything is hidden if only aethercast devices (or none)
1269+ function test_no_displays() {
1270+ var repeater = findChild(instance, "displayConfigurationRepeater");
1271+ compare(repeater.count, 0);
1272+ }
1273+
1274+ // Test that there's a UI when we have some display available.
1275+ function test_one_display() {
1276+ var displayModel = get_panel_plugin().displayModel();
1277+ var display = displayModel.mockAddDisplay();
1278+ display.setName("Foo")
1279+ display.addMode("1600x1200x60")
1280+ display.addMode("1280x1024x60")
1281+ display.mode = "1600x1200x60"
1282+
1283+ var repeater = findChild(instance, "displayConfigurationRepeater");
1284+ var panel = findChild(instance, "displayConfiguration_" + display.name);
1285+ verify(panel.visible);
1286+ compare(repeater.count, 1);
1287+ }
1288 }
1289 }

Subscribers

People subscribed via source and target branches