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

Proposed by Jonas G. Drange
Status: Work in progress
Proposed branch: lp:~jonas-drange/ubuntu-system-settings/displays-mir
Merge into: lp:ubuntu-system-settings
Prerequisite: lp:~jonas-drange/ubuntu-system-settings/displays-stub
Diff against target: 1995 lines (+1080/-214) (has conflicts)
28 files modified
debian/control (+1/-0)
plugins/brightness/CMakeLists.txt (+25/-5)
plugins/brightness/PageComponent.qml (+43/-26)
plugins/brightness/brightness.cpp (+91/-12)
plugins/brightness/brightness.h (+16/-3)
plugins/brightness/displays/display.cpp (+155/-39)
plugins/brightness/displays/display.h (+76/-52)
plugins/brightness/displays/displaymodel.cpp (+64/-14)
plugins/brightness/displays/displaymodel.h (+16/-5)
plugins/brightness/displays/helpers.cpp (+131/-0)
plugins/brightness/displays/helpers.h (+25/-0)
plugins/brightness/displays/mirclient.h (+25/-0)
plugins/brightness/displays/mirclient_impl.cpp (+86/-0)
plugins/brightness/displays/mirclient_impl.h (+26/-0)
plugins/brightness/plugin.cpp (+2/-2)
plugins/brightness/plugin/brightness-plugin.cpp (+2/-18)
tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt (+4/-5)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp (+11/-1)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h (+10/-4)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h (+32/-13)
tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h (+3/-3)
tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp (+2/-1)
tests/mocks/plugins/brightness/fakemirclient.h (+36/-0)
tests/plugins/CMakeLists.txt (+1/-0)
tests/plugins/brightness/CMakeLists.txt (+25/-0)
tests/plugins/brightness/tst_BrightnessPageComponent.qml (+99/-11)
tests/plugins/brightness/tst_brightness.cpp (+41/-0)
tests/plugins/brightness/tst_displayplugin_displaymodel.cpp (+32/-0)
Text conflict in debian/changelog
To merge this branch: bzr merge lp:~jonas-drange/ubuntu-system-settings/displays-mir
Reviewer Review Type Date Requested Status
system-apps-ci-bot continuous-integration Needs Fixing
Ubuntu Touch System Settings Pending
Review via email: mp+309943@code.launchpad.net

Commit message

implement display config for mir displays

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

make config work well for rotation and resolution (mode9

1743. By Jonas G. Drange

minor tweaks

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

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

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

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

PASSED: Continuous integration, rev:1743
https://jenkins.canonical.com/system-apps/job/lp-ubuntu-system-settings-ci/223/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build/1927
    SUCCESS: https://jenkins.canonical.com/system-apps/job/test-0-autopkgtest/label=phone-armhf,release=vivid+overlay,testname=default/462
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1928
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=yakkety/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=yakkety/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1767/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1767
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=yakkety/1767/artifact/output/*zip*/output.zip

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

review: Approve (continuous-integration)
1744. By Jonas G. Drange

create namespace for displayplugin

1745. By Jonas G. Drange

consume new namespace DisplayPlugin

1746. By Jonas G. Drange

rename mirdisplays to less ambiguous mirclient

1747. By Jonas G. Drange

add framework for testing brightness and displayplugin classes

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

FAILED: Continuous integration, rev:1747
https://jenkins.canonical.com/system-apps/job/lp-ubuntu-system-settings-ci/224/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/system-apps/job/build/1936/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-0-fetch/1937
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=vivid+overlay/1776/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1776
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1776/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=zesty/1776
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=amd64,release=zesty/1776/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=vivid+overlay/1776/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1776
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1776/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=zesty/1776
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=armhf,release=zesty/1776/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=vivid+overlay/1776/console
    SUCCESS: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1776
        deb: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=xenial+overlay/1776/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/system-apps/job/build-2-binpkg/arch=i386,release=zesty/1776/console

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

review: Needs Fixing (continuous-integration)

Unmerged revisions

1747. By Jonas G. Drange

add framework for testing brightness and displayplugin classes

1746. By Jonas G. Drange

rename mirdisplays to less ambiguous mirclient

1745. By Jonas G. Drange

consume new namespace DisplayPlugin

1744. By Jonas G. Drange

create namespace for displayplugin

1743. By Jonas G. Drange

minor tweaks

1742. By Jonas G. Drange

make config work well for rotation and resolution (mode9

1741. By Jonas G. Drange

working changed filter

1740. By Jonas G. Drange

add mdoes

1739. By Jonas G. Drange

add mir specific read of config, add helpers

1738. By Jonas G. Drange

merge prereq

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2016-11-04 18:56:02 +0000
3+++ debian/control 2016-11-04 18:56:02 +0000
4@@ -17,6 +17,7 @@
5 libglib2.0-dev (>= 2.37.92),
6 libevdev-dev,
7 libicu-dev,
8+ libmirclient-dev (>= 0.24),
9 libnm-glib-dev,
10 libpolkit-agent-1-dev,
11 libqmenumodel-dev,
12
13=== modified file 'plugins/brightness/CMakeLists.txt'
14--- plugins/brightness/CMakeLists.txt 2016-11-04 18:56:02 +0000
15+++ plugins/brightness/CMakeLists.txt 2016-11-04 18:56:02 +0000
16@@ -1,6 +1,29 @@
17 include_directories(${ANDR_PROP_INCLUDE_DIRS})
18 add_subdirectory(plugin)
19
20+pkg_search_module(MIR REQUIRED mirclient)
21+find_package(Qt5Gui)
22+include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS} ${MIR_INCLUDE_DIRS})
23+
24+add_library(uss-displays SHARED
25+ displays/helpers.h
26+
27+ displays/display.h
28+ displays/displaymodel.h
29+
30+ displays/mirclient.h
31+ displays/mirclient_impl.h
32+
33+ displays/helpers.cpp
34+ displays/display.cpp
35+ displays/displaymodel.cpp
36+ displays/mirclient_impl.cpp
37+ ../../src/i18n.cpp
38+)
39+qt5_use_modules(uss-displays Quick)
40+set_target_properties(uss-displays PROPERTIES VERSION 0.0 SOVERSION 0.0)
41+target_link_libraries(uss-displays ${Qt5Gui_PRIVATE_LDFLAGS} ${MIR_LDFLAGS})
42+
43 set(QML_SOURCES
44 PageComponent.qml
45 WifiDisplays.qml
46@@ -16,8 +39,6 @@
47 aethercast/displays.h
48 aethercast/freedesktop_properties.h
49 aethercast/freedesktop_objectmanager.h
50- displays/display.h
51- displays/displaymodel.h
52 plugin.h
53 brightness.h
54 aethercast/aethercast_device.cpp
55@@ -27,15 +48,14 @@
56 aethercast/displays.cpp
57 aethercast/freedesktop_properties.cpp
58 aethercast/freedesktop_objectmanager.cpp
59- displays/display.cpp
60- displays/displaymodel.cpp
61 plugin.cpp
62 brightness.cpp
63 ${QML_SOURCES})
64 qt5_use_modules(UbuntuBrightnessPanel Quick Qml DBus)
65-target_link_libraries(UbuntuBrightnessPanel SystemSettings ${ANDR_PROP_LDFLAGS})
66+target_link_libraries(UbuntuBrightnessPanel SystemSettings ${ANDR_PROP_LDFLAGS} uss-displays)
67
68 set(PLUG_DIR ${PLUGIN_PRIVATE_MODULE_DIR}/Ubuntu/SystemSettings/Brightness)
69+install(TARGETS uss-displays DESTINATION ${PLUGIN_MODULE_DIR})
70 install(TARGETS UbuntuBrightnessPanel DESTINATION ${PLUG_DIR})
71 install(FILES qmldir.in DESTINATION ${PLUG_DIR} RENAME qmldir)
72 install(FILES brightness.settings DESTINATION ${PLUGIN_MANIFEST_DIR})
73
74=== modified file 'plugins/brightness/PageComponent.qml'
75--- plugins/brightness/PageComponent.qml 2016-11-04 18:56:02 +0000
76+++ plugins/brightness/PageComponent.qml 2016-11-04 18:56:02 +0000
77@@ -36,14 +36,6 @@
78 title: brightnessPanel.widiSupported ? i18n.tr("Brightness & Display") : i18n.tr("Brightness")
79 flickable: scrollWidget
80
81- function formatMode(mode) {
82- mode = mode.split("x");
83- /* TRANSLATORS: %1 refer to the amount of horizontal pixels in a
84- display resolution, and %2 to the vertical pixels. E.g. 1200x720.
85- %3 is the refresh rate in hz. */
86- return i18n.tr("%1×%2 @ %3hz").arg(mode[0]).arg(mode[1]).arg(mode[2]);
87- }
88-
89 GSettings {
90 id: gsettings
91 schema.id: "com.ubuntu.touch.system"
92@@ -53,7 +45,7 @@
93 id: aethercastDisplays
94 objectName: "aethercastDisplays"
95 onEnabledChanged: {
96- /* This is a hack to ensure the aethercast enabled switch stays
97+ /* This is a hack to ensure the aethercast enabled switch stays
98 * in sync with the enabled property
99 */
100 enabledCheck.serverChecked = enabled;
101@@ -181,7 +173,7 @@
102
103 Repeater {
104 objectName: "displayConfigurationRepeater"
105- model: brightnessPanel.allDisplays
106+ model: brightnessPanel.connectedDisplays
107
108 Column {
109 objectName: "displayConfiguration_" + displayName
110@@ -190,15 +182,29 @@
111 right: parent.right
112 }
113
114+ Item {
115+ width: units.gu(1)
116+ height: units.gu(1)
117+ }
118+
119 Label {
120- visible: brightnessPanel.allDisplays.count > 1
121- anchors {
122- left: parent.left
123- right: parent.right
124- margins: units.gu(2)
125- }
126-
127 text: displayName
128+
129+ anchors {
130+ left: parent.left
131+ right: parent.right
132+ margins: units.gu(2)
133+ }
134+
135+ Switch {
136+ objectName: "enabledSwitch"
137+ anchors {
138+ right: parent.right
139+ verticalCenter: parent.verticalCenter
140+ }
141+ checked: model.enabled
142+ onCheckedChanged: model.enabled = checked
143+ }
144 }
145
146 SettingsItemTitle {
147@@ -216,6 +222,8 @@
148 }
149 containerHeight: itemHeight * 4
150 model: [
151+ /* TRANSLATORS: None means no rotation, or
152+ 0 degrees. */
153 i18n.tr("None"),
154 i18n.tr("90° clockwise"),
155 i18n.tr("180°"),
156@@ -223,15 +231,19 @@
157 ]
158 onDelegateClicked: {
159 expanded = !currentlyExpanded;
160+ orientation = index;
161 }
162+ selectedIndex: orientation
163 }
164
165 SettingsItemTitle {
166- text: availableModes.length > 1 ?
167+ objectName: "resolutionLabel"
168+ text: modes.length > 1 ?
169 i18n.tr("Resolution:") :
170- /* TRANSLATORS: %1 is a display mode, e.g.
171- 1200x720x24. */
172- i18n.tr("Resolution: %1").arg(formatMode(mode))
173+ /* TRANSLATORS: %1 is a display resolution, e.g.
174+ 1200x720x24. Unknown refers to an unknown
175+ resolution (in case of an error). */
176+ i18n.tr("Resolution: %1").arg(modes[mode] || i18n.tr("Unknown"))
177 }
178
179 OptionSelector {
180@@ -243,13 +255,17 @@
181 right: parent.right
182 margins: units.gu(2)
183 }
184- visible: availableModes.length > 1
185- containerHeight: itemHeight * availableModes.length
186- model: availableModes
187- onDelegateClicked: expanded = !currentlyExpanded
188+ visible: modes.length > 1
189+ containerHeight: itemHeight * modes.length
190+ model: modes
191+ onDelegateClicked: {
192+ expanded = !currentlyExpanded;
193+ mode = index;
194+ }
195 delegate: OptionSelectorDelegate {
196- text: formatMode(modelData)
197+ text: modelData
198 }
199+ selectedIndex: mode
200 }
201
202 SettingsItemTitle {
203@@ -282,6 +298,7 @@
204
205 visible: brightnessPanel.allDisplays.count > 0
206 height: units.gu(6)
207+
208 Button {
209 id: applyButton
210 objectName: "applyButton"
211
212=== modified file 'plugins/brightness/brightness.cpp'
213--- plugins/brightness/brightness.cpp 2016-11-04 18:56:02 +0000
214+++ plugins/brightness/brightness.cpp 2016-11-04 18:56:02 +0000
215@@ -19,6 +19,10 @@
216 */
217
218 #include "brightness.h"
219+#include "displays/display.h"
220+#include "displays/helpers.h"
221+#include "displays/mirclient_impl.h"
222+
223 #include <hybris/properties/properties.h>
224
225 #include <QDBusArgument>
226@@ -26,6 +30,8 @@
227 #include <QDBusMetaType>
228 #include <QDebug>
229 #include <QQmlEngine>
230+#include <QSharedPointer>
231+#include <QScopedPointer>
232
233 // Returned data from getBrightnessParams
234 struct BrightnessParams {
235@@ -55,16 +61,32 @@
236 return argument;
237 }
238
239-Brightness::Brightness(QObject *parent) :
240- QObject(parent),
241- m_systemBusConnection (QDBusConnection::systemBus()),
242- m_powerdIface ("com.canonical.powerd",
243- "/com/canonical/powerd",
244- "com.canonical.powerd",
245- m_systemBusConnection),
246- m_powerdRunning(false),
247- m_autoBrightnessAvailable(false)
248+Brightness::Brightness(QDBusConnection dbus,
249+ DisplayPlugin::MirClient *mirClient,
250+ QObject *parent)
251+ : QObject(parent)
252+ , m_systemBusConnection(dbus)
253+ , m_mirClient(mirClient)
254+ , m_powerdIface("com.canonical.powerd",
255+ "/com/canonical/powerd",
256+ "com.canonical.powerd",
257+ m_systemBusConnection)
258+ , m_powerdRunning(false)
259+ , m_autoBrightnessAvailable(false)
260+
261 {
262+ m_changedDisplays.filterOnUncommittedChanges(true);
263+ m_changedDisplays.setSourceModel(&m_displays);
264+
265+ m_connectedDisplays.filterOnConnected(true);
266+ m_connectedDisplays.setSourceModel(&m_displays);
267+
268+ if (m_mirClient->isConnected()) {
269+ refreshMirDisplays();
270+ connect(m_mirClient, SIGNAL(configurationChanged()),
271+ this, SLOT(refreshMirDisplays()));
272+ }
273+
274 qRegisterMetaType<BrightnessParams>();
275 m_powerdRunning = m_powerdIface.isValid();
276
277@@ -82,8 +104,14 @@
278 QDBusArgument result(reply.arguments()[0].value<QDBusArgument>());
279 BrightnessParams params = qdbus_cast<BrightnessParams>(result);
280 m_autoBrightnessAvailable = params.automatic;
281- m_changedDisplays.filterOnUncommittedChanges(true);
282- m_changedDisplays.setSourceModel(&m_displays);
283+
284+ m_mirClient->setParent(this);
285+}
286+
287+Brightness::Brightness(QObject *parent) :
288+ Brightness(QDBusConnection::systemBus(),
289+ new DisplayPlugin::MirClientImpl(), parent)
290+{
291 }
292
293 bool Brightness::getAutoBrightnessAvailable() const
294@@ -95,7 +123,7 @@
295 return m_powerdRunning;
296 }
297
298-bool Brightness::getWidiSupported() const
299+bool Brightness::getWidiSupported() const
300 {
301 char widi[PROP_VALUE_MAX];
302 property_get("ubuntu.widi.supported", widi, "0");
303@@ -115,3 +143,54 @@
304 QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
305 return ret;
306 }
307+
308+
309+QAbstractItemModel* Brightness::connectedDisplays()
310+{
311+ auto ret = &m_connectedDisplays;
312+ QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
313+ return ret;
314+}
315+
316+void Brightness::applyDisplayConfiguration()
317+{
318+ auto conf = m_mirClient->getConfiguration();
319+
320+ if (!conf) {
321+ qWarning() << __PRETTY_FUNCTION__ << "config invalid";
322+ return;
323+ }
324+
325+ for(uint i = 0; i < conf->num_outputs; ++i) {
326+ MirDisplayOutput output = conf->outputs[i];
327+ auto display = m_displays.getById(output.output_id);
328+ if (display) {
329+ output.current_mode = display->mode();
330+ output.used = display->enabled();
331+ output.orientation =
332+ DisplayPlugin::Helpers::orientationToMirOrientation(
333+ display->orientation()
334+ );
335+ }
336+ conf->outputs[i] = output;
337+ }
338+ m_mirClient->applyConfiguration(conf);
339+}
340+
341+void Brightness::refreshMirDisplays()
342+{
343+ auto conf = m_mirClient->getConfiguration();
344+
345+ if (!conf) {
346+ qWarning() << __PRETTY_FUNCTION__ << "config invalid";
347+ return;
348+ }
349+
350+ for(uint i = 0; i < conf->num_outputs; ++i) {
351+ MirDisplayOutput output = conf->outputs[i];
352+ auto display = QSharedPointer<DisplayPlugin::Display>(
353+ new DisplayPlugin::Display(output)
354+ );
355+ m_displays.addDisplay(display);
356+ }
357+}
358
359=== modified file 'plugins/brightness/brightness.h'
360--- plugins/brightness/brightness.h 2016-11-04 18:56:02 +0000
361+++ plugins/brightness/brightness.h 2016-11-04 18:56:02 +0000
362@@ -22,6 +22,7 @@
363 #define BRIGHTNESS_H
364
365 #include "displays/displaymodel.h"
366+#include "displays/mirclient.h"
367
368 #include <QAbstractItemModel>
369 #include <QDBusInterface>
370@@ -45,23 +46,35 @@
371 Q_PROPERTY (QAbstractItemModel* changedDisplays
372 READ changedDisplays
373 CONSTANT)
374+ Q_PROPERTY (QAbstractItemModel* connectedDisplays
375+ READ connectedDisplays
376+ CONSTANT)
377
378 public:
379 explicit Brightness(QObject *parent = 0);
380+ explicit Brightness(QDBusConnection dbus,
381+ DisplayPlugin::MirClient *mirClient, QObject *parent = 0);
382 bool getPowerdRunning() const;
383 bool getAutoBrightnessAvailable() const;
384 bool getWidiSupported() const;
385 QAbstractItemModel* allDisplays();
386 QAbstractItemModel* changedDisplays();
387+ QAbstractItemModel* connectedDisplays();
388+ Q_INVOKABLE void applyDisplayConfiguration();
389
390 private:
391 QDBusConnection m_systemBusConnection;
392+ DisplayPlugin::MirClient *m_mirClient;
393+ QDBusInterface m_powerdIface;
394 QString m_objectPath;
395- QDBusInterface m_powerdIface;
396 bool m_powerdRunning;
397 bool m_autoBrightnessAvailable;
398- DisplayModel m_displays;
399- DisplaysFilter m_changedDisplays;
400+ DisplayPlugin::DisplayModel m_displays;
401+ DisplayPlugin::DisplaysFilter m_changedDisplays;
402+ DisplayPlugin::DisplaysFilter m_connectedDisplays;
403+
404+private slots:
405+ void refreshMirDisplays();
406 };
407
408 #endif // BRIGHTNESS_H
409
410=== modified file 'plugins/brightness/displays/display.cpp'
411--- plugins/brightness/displays/display.cpp 2016-11-04 18:56:02 +0000
412+++ plugins/brightness/displays/display.cpp 2016-11-04 18:56:02 +0000
413@@ -1,12 +1,67 @@
414 #include "display.h"
415+#include "helpers.h"
416+
417+#include <QDebug>
418+
419+namespace DisplayPlugin
420+{
421+QString DisplayMode::toString() const
422+{
423+ /* TRANSLATORS: %1 refer to the amount of horizontal pixels in a
424+ display resolution, and %2 to the vertical pixels. E.g. 1200x720.
425+ %3 is the refresh rate in hz. */
426+ return SystemSettings::_("%1×%2 @ %3hz")
427+ .arg(horizontal_resolution)
428+ .arg(vertical_resolution)
429+ .arg(refresh_rate);
430+}
431+bool DisplayMode::operator==(const DisplayMode &other) const
432+{
433+ return (
434+ horizontal_resolution == other.horizontal_resolution
435+ && vertical_resolution == other.vertical_resolution
436+ && refresh_rate == other.refresh_rate
437+ );
438+}
439
440 Display::Display(QObject *parent)
441 : QObject(parent)
442 {
443- QObject::connect(this, SIGNAL(nameChanged()),
444- this, SLOT(changedSlot()));
445- QObject::connect(this, SIGNAL(typeChanged()),
446- this, SLOT(changedSlot()));
447+ initialize();
448+}
449+
450+Display::Display(MirDisplayOutput &output, QObject *parent)
451+ : Display(parent)
452+{
453+ m_type = DisplayPlugin::Helpers::mirTypeToString(output.type);
454+ setConnected(output.connected);
455+ setEnabled(output.used);
456+
457+ auto modes = QList<DisplayMode>();
458+ for(uint j = 0; j < output.num_modes; j++) {
459+ DisplayMode mode(output.modes[j]);
460+ modes.append(mode);
461+
462+ if (j == output.current_mode)
463+ m_mode = mode;
464+ }
465+ m_modes = modes;
466+ m_orientation = DisplayPlugin::Helpers::mirOrientationToOritentation(output.orientation);
467+ m_powerMode = DisplayPlugin::Helpers::mirPowerModeToPowerMode(output.power_mode);
468+ m_id = output.output_id;
469+
470+ m_physicalWidthMm = output.physical_width_mm;
471+ m_physicalHeightMm = output.physical_height_mm;
472+ m_name = QString("%1").arg(DisplayPlugin::Helpers::mirTypeToString(output.type));
473+ qWarning() << m_name << "current_mode" << mode();
474+
475+ changedSlot();
476+ storeConfiguration();
477+}
478+
479+
480+void Display::initialize()
481+{
482 QObject::connect(this, SIGNAL(mirroredChanged()),
483 this, SLOT(changedSlot()));
484 QObject::connect(this, SIGNAL(connectedChanged()),
485@@ -15,7 +70,7 @@
486 this, SLOT(changedSlot()));
487 QObject::connect(this, SIGNAL(modeChanged()),
488 this, SLOT(changedSlot()));
489- QObject::connect(this, SIGNAL(availableModesChanged()),
490+ QObject::connect(this, SIGNAL(modesChanged()),
491 this, SLOT(changedSlot()));
492 QObject::connect(this, SIGNAL(orientationChanged()),
493 this, SLOT(changedSlot()));
494@@ -25,6 +80,52 @@
495 this, SLOT(changedSlot()));
496 }
497
498+void Display::storeConfiguration()
499+{
500+ m_storedConfig["name"] = QVariant(m_name);
501+ m_storedConfig["type"] = QVariant(m_type);
502+ m_storedConfig["mirrored"] = QVariant(m_mirrored);
503+ m_storedConfig["enabled"] = QVariant(m_enabled);
504+ m_storedConfig["mode"] = QVariant(mode());
505+ m_storedConfig["orientation"] = QVariant::fromValue(m_orientation);
506+ m_storedConfig["scale"] = QVariant(m_scale);
507+}
508+
509+bool Display::hasChanged() const
510+{
511+ // qWarning()
512+ // << m_storedConfig["name"].toString() << m_name
513+ // << m_storedConfig["type"].toString() << m_type
514+ // << m_storedConfig["mirrored"].toBool() << m_mirrored
515+ // << m_storedConfig["enabled"].toBool() << m_enabled
516+ // << m_storedConfig["mode"].toUInt() << mode()
517+ // << (uint) m_storedConfig["orientation"].value<Orientation>() << (uint) m_orientation
518+ // << m_storedConfig["scale"].toUInt() << m_scale
519+ // << "truth values"
520+ // << (m_storedConfig["name"].toString() != m_name)
521+ // << (m_storedConfig["type"].toString() != m_type)
522+ // << (m_storedConfig["mirrored"].toBool() != m_mirrored)
523+ // << (m_storedConfig["enabled"].toBool() != m_enabled)
524+ // << (m_storedConfig["mode"].toUInt() != mode())
525+ // << (m_storedConfig["orientation"].value<Orientation>() != m_orientation)
526+ // << (m_storedConfig["scale"].toUInt() != m_scale);
527+
528+ return (
529+ m_storedConfig["name"].toString() != m_name
530+ || m_storedConfig["type"].toString() != m_type
531+ || m_storedConfig["mirrored"].toBool() != m_mirrored
532+ || m_storedConfig["enabled"].toBool() != m_enabled
533+ || m_storedConfig["mode"].toUInt() != mode()
534+ || m_storedConfig["orientation"].value<Orientation>() != m_orientation
535+ || m_storedConfig["scale"].toUInt() != m_scale
536+ );
537+}
538+
539+uint Display::id() const
540+{
541+ return m_id;
542+}
543+
544 QString Display::name() const
545 {
546 return m_name;
547@@ -50,14 +151,23 @@
548 return m_enabled;
549 }
550
551-QString Display::mode() const
552-{
553- return m_mode;
554-}
555-
556-QStringList Display::availableModes() const
557-{
558- return m_availableModes;
559+uint Display::mode() const
560+{
561+ return m_modes.empty() ? 0 : m_modes.indexOf(m_mode);
562+}
563+
564+QStringList Display::modes() const
565+{
566+ QStringList modes;
567+ Q_FOREACH(const DisplayMode &mode, m_modes) {
568+ modes.append(mode.toString());
569+ }
570+ return modes;
571+}
572+
573+QList<DisplayMode> Display::availableModes() const
574+{
575+ return m_modes;
576 }
577
578 Display::Orientation Display::orientation() const
579@@ -75,67 +185,73 @@
580 return m_uncommittedChanges;
581 }
582
583-void Display::setName(const QString &name)
584+uint Display::physicalWidthMm() const
585 {
586- m_name = name;
587- Q_EMIT nameChanged();
588+ return m_physicalWidthMm;
589 }
590
591-void Display::setType(const QString &type)
592+uint Display::physicalHeightMm() const
593 {
594- m_type = type;
595- Q_EMIT typeChanged();
596+ return m_physicalHeightMm;
597 }
598
599 void Display::setMirrored(const bool &mirrored)
600 {
601- m_mirrored = mirrored;
602- Q_EMIT mirroredChanged();
603+ if (m_mirrored != mirrored) {
604+ m_mirrored = mirrored;
605+ Q_EMIT mirroredChanged();
606+ }
607 }
608
609 void Display::setConnected(const bool &connected)
610 {
611- m_connected = connected;
612- Q_EMIT connectedChanged();
613+ if (m_connected != connected) {
614+ m_connected = connected;
615+ Q_EMIT connectedChanged();
616+ }
617 }
618
619 void Display::setEnabled(const bool &enabled)
620 {
621- m_enabled = enabled;
622- Q_EMIT enabledChanged();
623+ if (m_enabled != enabled) {
624+ m_enabled = enabled;
625+ Q_EMIT enabledChanged();
626+ }
627 }
628
629-void Display::setMode(const QString &mode)
630+void Display::setMode(const uint &mode)
631 {
632- m_mode = mode;
633+ m_mode = m_modes.value(mode);
634 Q_EMIT modeChanged();
635 }
636
637-void Display::setAvailableModes(const QStringList &availableModes)
638-{
639- m_availableModes = availableModes;
640- Q_EMIT availableModesChanged();
641-}
642-
643 void Display::setOrientation(const Display::Orientation &orientation)
644 {
645- m_orientation = orientation;
646- Q_EMIT orientationChanged();
647+ if (m_orientation != orientation) {
648+ m_orientation = orientation;
649+ Q_EMIT orientationChanged();
650+ }
651 }
652
653 void Display::setScale(const double &scale)
654 {
655- m_scale = scale;
656- Q_EMIT scaleChanged();
657+ if (m_scale != scale) {
658+ m_scale = scale;
659+ Q_EMIT scaleChanged();
660+ }
661 }
662
663 void Display::setUncommitedChanges(const bool uncommittedChanges)
664 {
665- m_uncommittedChanges = uncommittedChanges;
666- Q_EMIT uncommittedChangesChanged();
667+ if (m_uncommittedChanges != uncommittedChanges) {
668+ m_uncommittedChanges = uncommittedChanges;
669+ Q_EMIT uncommittedChangesChanged();
670+ }
671 }
672
673 void Display::changedSlot()
674 {
675+ setUncommitedChanges(hasChanged());
676 Q_EMIT displayChanged(this);
677 }
678+} // DisplayPlugin
679
680=== modified file 'plugins/brightness/displays/display.h'
681--- plugins/brightness/displays/display.h 2016-11-04 18:56:02 +0000
682+++ plugins/brightness/displays/display.h 2016-11-04 18:56:02 +0000
683@@ -1,57 +1,62 @@
684 #ifndef DISPLAY_H
685 #define DISPLAY_H
686
687+#include "../../../src/i18n.h"
688+
689+#include <mir_toolkit/mir_client_library.h>
690+
691+#include <QList>
692 #include <QObject>
693 #include <QString>
694 #include <QStringList>
695+#include <QVariantMap>
696+
697+namespace DisplayPlugin
698+{
699+class DisplayMode
700+{
701+public:
702+ DisplayMode() {}
703+ explicit DisplayMode(const MirDisplayMode &mirMode)
704+ : vertical_resolution(mirMode.vertical_resolution)
705+ , horizontal_resolution(mirMode.horizontal_resolution)
706+ , refresh_rate(mirMode.refresh_rate) {}
707+ uint vertical_resolution = 0;
708+ uint horizontal_resolution = 0;
709+ double refresh_rate = 0.0;
710+ Q_INVOKABLE QString toString() const;
711+ bool operator==(const DisplayMode &other) const;
712+};
713
714 class Display : public QObject
715 {
716 Q_OBJECT
717- Q_PROPERTY(QString name
718- READ name
719- NOTIFY nameChanged)
720- Q_PROPERTY(QString type
721- READ type
722- NOTIFY typeChanged)
723- Q_PROPERTY(bool mirrored
724- READ mirrored
725- WRITE setMirrored
726+ Q_PROPERTY(uint id READ id CONSTANT)
727+ Q_PROPERTY(QString name READ name CONSTANT)
728+ Q_PROPERTY(QString type READ type CONSTANT)
729+ Q_PROPERTY(bool mirrored READ mirrored WRITE setMirrored
730 NOTIFY mirroredChanged)
731- Q_PROPERTY(bool connected
732- READ connected
733- NOTIFY connectedChanged)
734- Q_PROPERTY(bool enabled
735- READ enabled
736- WRITE setEnabled
737+ Q_PROPERTY(bool connected READ connected NOTIFY connectedChanged)
738+ Q_PROPERTY(bool enabled READ enabled WRITE setEnabled
739 NOTIFY enabledChanged)
740- Q_PROPERTY(QString mode
741- READ mode
742- WRITE setMode
743+ Q_PROPERTY(uint mode READ mode WRITE setMode
744 NOTIFY modeChanged)
745- Q_PROPERTY(QStringList availableModes
746- READ availableModes
747- NOTIFY availableModesChanged)
748- Q_PROPERTY(Orientation orientation
749- READ orientation
750- WRITE setOrientation
751+ Q_PROPERTY(QStringList modes READ modes
752+ NOTIFY modesChanged)
753+ Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation
754 NOTIFY orientationChanged)
755- Q_PROPERTY(double scale
756- READ scale
757- WRITE setScale
758- NOTIFY scaleChanged)
759- Q_PROPERTY(bool uncommittedChanges
760- READ uncommittedChanges
761+ Q_PROPERTY(double scale READ scale WRITE setScale NOTIFY scaleChanged)
762+ Q_PROPERTY(bool uncommittedChanges READ uncommittedChanges
763 NOTIFY uncommittedChangesChanged)
764+ Q_PROPERTY(uint physicalWidthMm READ physicalWidthMm CONSTANT)
765+ Q_PROPERTY(uint physicalHeightMm READ physicalHeightMm CONSTANT)
766
767 Q_SIGNALS:
768- void nameChanged();
769- void typeChanged();
770 void mirroredChanged();
771 void connectedChanged();
772 void enabledChanged();
773 void modeChanged();
774- void availableModesChanged();
775+ void modesChanged();
776 void orientationChanged();
777 void scaleChanged();
778 void uncommittedChangesChanged();
779@@ -59,54 +64,73 @@
780
781 public:
782 explicit Display(QObject *parent = nullptr);
783+ explicit Display(MirDisplayOutput &output, QObject *parent = nullptr);
784 ~Display() {};
785+
786 enum class Orientation : uint {
787- Normal, PortraitMode, LandscapeInvertedMode,
788- PortraitInvertedMode
789- };
790- enum class DisplayType : uint {
791- PhysicalType, AethercastType
792- };
793- Q_ENUMS(Orientation DisplayType)
794+ NormalOrientation, PortraitModeOrientation,
795+ LandscapeInvertedModeOrientation,
796+ PortraitInvertedModeOrientation
797+ };
798+ enum class PowerMode : uint {
799+ OnMode, StandbyMode, SuspendMode, OffMode
800+ };
801+ Q_ENUMS(Orientation PowerMode)
802
803+ uint id() const;
804 QString name() const;
805 QString type() const;
806 bool mirrored() const;
807 bool connected() const;
808 bool enabled() const;
809- QString mode() const;
810- QStringList availableModes() const;
811+ uint mode() const;
812+ QList<DisplayMode> availableModes() const;
813+ QStringList modes() const;
814 Orientation orientation() const;
815 double scale() const;
816 bool uncommittedChanges() const;
817+ uint physicalWidthMm() const;
818+ uint physicalHeightMm() const;
819
820 void setMirrored(const bool &mirrored);
821 void setEnabled(const bool &enabled);
822- void setMode(const QString &mode);
823+ void setMode(const uint &mode);
824 void setOrientation(const Orientation &orientation);
825 void setScale(const double &scale);
826
827 protected:
828- void setName(const QString &name);
829- void setAvailableModes(const QStringList &availableModes);
830+ void setUncommitedChanges(const bool uncommittedChanges);
831 void setConnected(const bool &connected);
832- void setType(const QString &type);
833- void setUncommitedChanges(const bool uncommittedChanges);
834+ void storeConfiguration();
835+
836+ uint m_id = 0;
837 QString m_name = QString::null;
838 QString m_type = QString::null;
839 bool m_mirrored = false;
840 bool m_connected = false;
841 bool m_enabled = false;
842- QString m_mode = QString::null;
843- QStringList m_availableModes = QStringList();
844- Orientation m_orientation = Orientation::Normal;
845+ DisplayMode m_mode;
846+ QList<DisplayMode> m_modes;
847+ Orientation m_orientation = Orientation::NormalOrientation;
848 double m_scale = 1;
849 bool m_uncommittedChanges = false;
850+ uint m_physicalWidthMm = 0;
851+ uint m_physicalHeightMm = 0;
852+ PowerMode m_powerMode = PowerMode::OffMode;
853
854-private slots:
855+protected slots:
856 void changedSlot();
857+
858+private:
859+ void initialize();
860+ bool hasChanged() const;
861+
862+ QVariantMap m_storedConfig;
863 };
864
865-Q_DECLARE_METATYPE(Display*)
866+} // DisplayPlugin
867+
868+Q_DECLARE_METATYPE(DisplayPlugin::Display*)
869+Q_DECLARE_METATYPE(DisplayPlugin::Display::Orientation)
870
871 #endif // DISPLAY_H
872
873=== modified file 'plugins/brightness/displays/displaymodel.cpp'
874--- plugins/brightness/displays/displaymodel.cpp 2016-11-04 18:56:02 +0000
875+++ plugins/brightness/displays/displaymodel.cpp 2016-11-04 18:56:02 +0000
876@@ -2,6 +2,8 @@
877
878 #include <QDebug>
879
880+namespace DisplayPlugin
881+{
882 DisplayModel::DisplayModel(QObject *parent)
883 {
884 }
885@@ -42,8 +44,8 @@
886 case ModeRole:
887 ret = display->mode();
888 break;
889- case AvailableModesRole:
890- ret = display->availableModes();
891+ case ModesRole:
892+ ret = display->modes();
893 break;
894 case OrientationRole:
895 ret = (uint) display->orientation();
896@@ -64,11 +66,9 @@
897 int role)
898 {
899 if ((0 <= index.row()) && (index.row() < m_displays.size())) {
900-
901 auto display = m_displays[index.row()];
902
903 switch (role) {
904-
905 case MirroredRole:
906 display->setMirrored(value.toBool());
907 break;
908@@ -76,7 +76,7 @@
909 display->setEnabled(value.toBool());
910 break;
911 case ModeRole:
912- display->setMode(value.toString());
913+ display->setMode(value.toUInt());
914 break;
915 case OrientationRole:
916 display->setOrientation((Display::Orientation) value.toUInt());
917@@ -87,7 +87,7 @@
918 case Qt::DisplayRole:
919 case TypeRole:
920 case ConnectedRole:
921- case AvailableModesRole:
922+ case ModesRole:
923 case UncommittedChangesRole:
924 default:
925 return false;
926@@ -108,7 +108,7 @@
927 names[ConnectedRole] = "connected";
928 names[EnabledRole] = "enabled";
929 names[ModeRole] = "mode";
930- names[AvailableModesRole] = "availableModes";
931+ names[ModesRole] = "modes";
932 names[OrientationRole] = "orientation";
933 names[ScaleRole] = "scale";
934 names[UncommittedChangesRole] = "uncommittedChanges";
935@@ -118,8 +118,7 @@
936
937 void DisplayModel::addDisplay(const QSharedPointer<Display> &display)
938 {
939- // TODO: find display
940- int row = -1;
941+ int row = findRowFromId(display->id());
942
943 if (row >= 0) { // update existing display
944 m_displays[row] = display;
945@@ -131,7 +130,7 @@
946 endInsertRows();
947 }
948
949- if (display) {
950+ if (display) {
951 QObject::connect(display.data(), SIGNAL(displayChanged(const Display*)),
952 this, SLOT(displayChangedSlot(const Display*)));
953 }
954@@ -143,7 +142,7 @@
955 {
956 if (0 <= row && row < m_displays.size()) {
957 QModelIndex qmi = index(row, 0);
958- Q_EMIT(dataChanged(qmi, qmi));
959+ Q_EMIT dataChanged(qmi, qmi);
960 }
961 }
962
963@@ -160,6 +159,32 @@
964 emitRowChanged(row);
965 }
966
967+QSharedPointer<Display> DisplayModel::getById(const uint &id)
968+{
969+ Q_FOREACH(auto display, m_displays) {
970+ if (display->id() == id)
971+ return display;
972+ }
973+ return QSharedPointer<Display>(nullptr);
974+}
975+
976+int DisplayModel::findRowFromId(const uint &id)
977+{
978+ for (int i = 0; i < m_displays.size(); i++) {
979+ if (m_displays[i]->id() == id)
980+ return i;
981+ }
982+ return -1;
983+}
984+
985+DisplaysFilter::DisplaysFilter()
986+{
987+ connect(this, SIGNAL(rowsInserted(const QModelIndex&, int, int)),
988+ this, SLOT(rowsChanged(const QModelIndex&, int, int)));
989+ connect(this, SIGNAL(rowsRemoved(const QModelIndex&, int, int)),
990+ this, SLOT(rowsChanged(const QModelIndex&, int, int)));
991+}
992+
993 bool DisplaysFilter::lessThan(const QModelIndex &left,
994 const QModelIndex &right) const
995 {
996@@ -168,13 +193,20 @@
997 return a < b;
998 }
999
1000-void DisplaysFilter::filterOnUncommittedChanges(const bool apply)
1001+void DisplaysFilter::filterOnUncommittedChanges(const bool uncommitted)
1002 {
1003- m_uncommittedChanges = apply;
1004+ m_uncommittedChanges = uncommitted;
1005 m_uncommittedChangesEnabled = true;
1006 invalidateFilter();
1007 }
1008
1009+void DisplaysFilter::filterOnConnected(const bool connected)
1010+{
1011+ m_connected = connected;
1012+ m_connectedEnabled = true;
1013+ invalidateFilter();
1014+}
1015+
1016 bool DisplaysFilter::filterAcceptsRow(int sourceRow,
1017 const QModelIndex &sourceParent) const
1018 {
1019@@ -182,9 +214,27 @@
1020 QModelIndex childIndex = sourceModel()->index(sourceRow, 0, sourceParent);
1021
1022 if (accepts && m_uncommittedChangesEnabled) {
1023- const bool uncommittedChanges = childIndex.model()->data(childIndex, DisplayModel::UncommittedChangesRole).value<bool>();
1024+ const bool uncommittedChanges = childIndex.model()->data(
1025+ childIndex, DisplayModel::UncommittedChangesRole
1026+ ).value<bool>();
1027 accepts = (m_uncommittedChanges == uncommittedChanges);
1028 }
1029
1030+ if (accepts && m_connectedEnabled) {
1031+ const bool connected = childIndex.model()->data(
1032+ childIndex, DisplayModel::ConnectedRole
1033+ ).value<bool>();
1034+ accepts = (m_connected == connected);
1035+ }
1036+
1037 return accepts;
1038 }
1039+
1040+void DisplaysFilter::rowsChanged(const QModelIndex &parent, int first, int last)
1041+{
1042+ Q_UNUSED(parent)
1043+ Q_UNUSED(first)
1044+ Q_UNUSED(last)
1045+ Q_EMIT countChanged();
1046+}
1047+} // DisplayPlugin
1048
1049=== modified file 'plugins/brightness/displays/displaymodel.h'
1050--- plugins/brightness/displays/displaymodel.h 2016-11-04 18:56:02 +0000
1051+++ plugins/brightness/displays/displaymodel.h 2016-11-04 18:56:02 +0000
1052@@ -12,6 +12,8 @@
1053 #include <QSortFilterProxyModel>
1054 #include <QVariant>
1055
1056+namespace DisplayPlugin
1057+{
1058 class DisplayModel : public QAbstractListModel
1059 {
1060 Q_OBJECT
1061@@ -28,7 +30,7 @@
1062 ConnectedRole,
1063 EnabledRole,
1064 ModeRole,
1065- AvailableModesRole,
1066+ ModesRole,
1067 OrientationRole,
1068 ScaleRole,
1069 UncommittedChangesRole,
1070@@ -40,13 +42,15 @@
1071 bool setData(const QModelIndex &index, const QVariant &value,
1072 int role = Qt::EditRole);
1073 QHash<int,QByteArray> roleNames() const;
1074+ void addDisplay(const QSharedPointer<Display> &display);
1075+ QSharedPointer<Display> getById(const uint &id);
1076+ int findRowFromId(const uint &id);
1077
1078 Q_SIGNALS:
1079 void countChanged();
1080
1081 protected:
1082 void emitRowChanged(const int &row);
1083- void addDisplay(const QSharedPointer<Display> &display);
1084
1085 private:
1086 QList<QSharedPointer<Display> > m_displays;
1087@@ -61,13 +65,14 @@
1088 Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
1089
1090 public:
1091- DisplaysFilter() {}
1092+ DisplaysFilter();
1093 virtual ~DisplaysFilter() {}
1094
1095- void filterOnUncommittedChanges(const bool apply);
1096+ void filterOnUncommittedChanges(const bool uncommitted);
1097+ void filterOnConnected(const bool connected);
1098
1099 Q_SIGNALS:
1100- void countChanged(int count);
1101+ void countChanged();
1102
1103 protected:
1104 virtual bool filterAcceptsRow(int, const QModelIndex&) const;
1105@@ -77,6 +82,12 @@
1106 bool m_uncommittedChanges = false;
1107 bool m_uncommittedChangesEnabled = false;
1108
1109+ bool m_connected = false;
1110+ bool m_connectedEnabled = false;
1111+
1112+private slots:
1113+ void rowsChanged(const QModelIndex &parent, int first, int last);
1114 };
1115+} // DisplayPlugin
1116
1117 #endif // DISPLAY_MODEL_H
1118
1119=== added file 'plugins/brightness/displays/helpers.cpp'
1120--- plugins/brightness/displays/helpers.cpp 1970-01-01 00:00:00 +0000
1121+++ plugins/brightness/displays/helpers.cpp 2016-11-04 18:56:02 +0000
1122@@ -0,0 +1,131 @@
1123+#include "helpers.h"
1124+
1125+namespace DisplayPlugin
1126+{
1127+Display::Orientation Helpers::mirOrientationToOritentation(const MirOrientation &mirOrientation)
1128+{
1129+ Display::Orientation orientation;
1130+ switch (mirOrientation) {
1131+ case mir_orientation_normal:
1132+ orientation = Display::Orientation::NormalOrientation;
1133+ break;
1134+ case mir_orientation_left:
1135+ orientation = Display::Orientation::PortraitModeOrientation;
1136+ break;
1137+ case mir_orientation_inverted:
1138+ orientation = Display::Orientation::LandscapeInvertedModeOrientation;
1139+ break;
1140+ case mir_orientation_right:
1141+ orientation = Display::Orientation::PortraitInvertedModeOrientation;
1142+ break;
1143+ default:
1144+ orientation = Display::Orientation::NormalOrientation;
1145+ }
1146+ return orientation;
1147+}
1148+
1149+MirOrientation Helpers::orientationToMirOrientation(const Display::Orientation &orientation)
1150+{
1151+ MirOrientation mirOrientation;
1152+ switch (orientation) {
1153+ case Display::Orientation::NormalOrientation:
1154+ mirOrientation = mir_orientation_normal;
1155+ break;
1156+ case Display::Orientation::PortraitModeOrientation:
1157+ mirOrientation = mir_orientation_left;
1158+ break;
1159+ case Display::Orientation::LandscapeInvertedModeOrientation:
1160+ mirOrientation = mir_orientation_inverted;
1161+ break;
1162+ case Display::Orientation::PortraitInvertedModeOrientation:
1163+ mirOrientation = mir_orientation_right;
1164+ break;
1165+ default:
1166+ mirOrientation = mir_orientation_normal;
1167+ }
1168+ return mirOrientation;
1169+}
1170+
1171+QString Helpers::mirTypeToString(const MirDisplayOutputType &type)
1172+{
1173+ QString ret;
1174+ switch (type) {
1175+ default:
1176+ case mir_display_output_type_unknown:
1177+ ret = "";
1178+ break;
1179+ case mir_display_output_type_vga:
1180+ ret = "vga";
1181+ break;
1182+ case mir_display_output_type_dvii:
1183+ ret = "dvii";
1184+ break;
1185+ case mir_display_output_type_dvid:
1186+ ret = "dvid";
1187+ break;
1188+ case mir_display_output_type_dvia:
1189+ ret = "dvia";
1190+ break;
1191+ case mir_display_output_type_composite:
1192+ ret = "composite";
1193+ break;
1194+ case mir_display_output_type_svideo:
1195+ ret = "svideo";
1196+ break;
1197+ case mir_display_output_type_lvds:
1198+ ret = "lvds";
1199+ break;
1200+ case mir_display_output_type_component:
1201+ ret = "component";
1202+ break;
1203+ case mir_display_output_type_ninepindin:
1204+ ret = "ninepindin";
1205+ break;
1206+ case mir_display_output_type_displayport:
1207+ ret = "displayport";
1208+ break;
1209+ case mir_display_output_type_hdmia:
1210+ ret = "hdmia";
1211+ break;
1212+ case mir_display_output_type_hdmib:
1213+ ret = "hdmib";
1214+ break;
1215+ case mir_display_output_type_tv:
1216+ ret = "tv";
1217+ break;
1218+ case mir_display_output_type_edp:
1219+ ret = "edp";
1220+ break;
1221+ }
1222+
1223+ return ret;
1224+}
1225+
1226+Display::PowerMode Helpers::mirPowerModeToPowerMode(const MirPowerMode &mode)
1227+{
1228+ switch(mode) {
1229+ case mir_power_mode_on:
1230+ return Display::PowerMode::OnMode;
1231+ case mir_power_mode_standby:
1232+ return Display::PowerMode::StandbyMode;
1233+ case mir_power_mode_suspend:
1234+ return Display::PowerMode::SuspendMode;
1235+ case mir_power_mode_off:
1236+ return Display::PowerMode::OffMode;
1237+ }
1238+}
1239+
1240+MirPowerMode Helpers::powerModeToMirPowerMode(const Display::PowerMode &mode)
1241+{
1242+ switch(mode) {
1243+ case Display::PowerMode::OnMode:
1244+ return mir_power_mode_on;
1245+ case Display::PowerMode::StandbyMode:
1246+ return mir_power_mode_standby;
1247+ case Display::PowerMode::SuspendMode:
1248+ return mir_power_mode_suspend;
1249+ case Display::PowerMode::OffMode:
1250+ return mir_power_mode_off;
1251+ }
1252+}
1253+} // DisplayPlugin
1254
1255=== added file 'plugins/brightness/displays/helpers.h'
1256--- plugins/brightness/displays/helpers.h 1970-01-01 00:00:00 +0000
1257+++ plugins/brightness/displays/helpers.h 2016-11-04 18:56:02 +0000
1258@@ -0,0 +1,25 @@
1259+#ifndef DISPLAY_PLUGIN_HELPERS_H
1260+#define DISPLAY_PLUGIN_HELPERS_H
1261+
1262+#include "display.h"
1263+
1264+#include <mir_toolkit/mir_client_library.h>
1265+
1266+namespace DisplayPlugin
1267+{
1268+struct Helpers
1269+{
1270+public:
1271+ static Display::Orientation mirOrientationToOritentation(const MirOrientation &mirOrientation);
1272+ static MirOrientation orientationToMirOrientation(const Display::Orientation &orientation);
1273+ static QString mirTypeToString(const MirDisplayOutputType &type);
1274+ static QString mirModeToString(const MirDisplayOutputType &type);
1275+ static Display::PowerMode mirPowerModeToPowerMode(const MirPowerMode &mode);
1276+ static MirPowerMode powerModeToMirPowerMode(const Display::PowerMode &mode);
1277+
1278+ // Return a sorted list of modes in horizontalxverticalxrate format.
1279+ // static QString mirModesToStringList(const MirDisplayOutputType &type);
1280+};
1281+} // DisplayPlugin
1282+
1283+#endif // DISPLAY_PLUGIN_HELPERS_H
1284
1285=== added file 'plugins/brightness/displays/mirclient.h'
1286--- plugins/brightness/displays/mirclient.h 1970-01-01 00:00:00 +0000
1287+++ plugins/brightness/displays/mirclient.h 2016-11-04 18:56:02 +0000
1288@@ -0,0 +1,25 @@
1289+#ifndef MIRCLIENT_H
1290+#define MIRCLIENT_H
1291+
1292+#include <mir_toolkit/mir_client_library.h>
1293+#include <QObject>
1294+
1295+namespace DisplayPlugin
1296+{
1297+class MirClient : public QObject
1298+{
1299+ Q_OBJECT
1300+public:
1301+ explicit MirClient(QObject *parent = 0) : QObject(parent) {}
1302+ virtual ~MirClient() {};
1303+ virtual MirDisplayConfiguration* getConfiguration() const = 0;
1304+ virtual void setConfiguration(MirDisplayConfiguration *conf) = 0;
1305+ virtual bool applyConfiguration(MirDisplayConfiguration *conf) = 0;
1306+ virtual bool isConnected() = 0;
1307+
1308+Q_SIGNALS:
1309+ void configurationChanged() const;
1310+};
1311+} // DisplayPlugin
1312+
1313+#endif // MIRCLIENT_H
1314
1315=== added file 'plugins/brightness/displays/mirclient_impl.cpp'
1316--- plugins/brightness/displays/mirclient_impl.cpp 1970-01-01 00:00:00 +0000
1317+++ plugins/brightness/displays/mirclient_impl.cpp 2016-11-04 18:56:02 +0000
1318@@ -0,0 +1,86 @@
1319+#include "mirclient_impl.h"
1320+
1321+#include <QDebug>
1322+#include <QQmlEngine>
1323+#include <QGuiApplication>
1324+#include <qpa/qplatformnativeinterface.h>
1325+
1326+namespace DisplayPlugin
1327+{
1328+static void mir_display_change_callback(MirConnection *connection, void *context) {
1329+ MirDisplayConfiguration *conf = mir_connection_create_display_config(
1330+ connection);
1331+ static_cast<MirClientImpl*>(context)->setConfiguration(conf);
1332+}
1333+
1334+MirClientImpl::MirClientImpl(QObject *parent)
1335+ : MirClient(parent)
1336+ , m_mir_connection(nullptr)
1337+ , m_configuration(nullptr)
1338+{
1339+ connect();
1340+ if (isConnected()) {
1341+ setConfiguration(
1342+ mir_connection_create_display_config(m_mir_connection)
1343+ );
1344+ }
1345+}
1346+
1347+MirClientImpl::~MirClientImpl() {
1348+ mir_display_config_destroy(m_configuration);
1349+ mir_connection_release(m_mir_connection);
1350+}
1351+
1352+MirDisplayConfiguration* MirClientImpl::getConfiguration() const {
1353+ return m_configuration;
1354+}
1355+
1356+bool MirClientImpl::isConnected() {
1357+ return mir_connection_is_valid(m_mir_connection);
1358+}
1359+
1360+void MirClientImpl::setConfiguration(MirDisplayConfiguration *conf) {
1361+ if (m_configuration != conf) {
1362+ m_configuration = conf;
1363+ Q_EMIT configurationChanged();
1364+ }
1365+}
1366+
1367+bool MirClientImpl::applyConfiguration(MirDisplayConfiguration *conf) {
1368+ MirWaitHandle* handle = mir_connection_set_base_display_config(
1369+ m_mir_connection, conf
1370+ );
1371+
1372+ if (!handle) {
1373+ qWarning() << __PRETTY_FUNCTION__ << "Failed to get handle.";
1374+ return false;
1375+ }
1376+
1377+ mir_wait_for(handle);
1378+ QString error(mir_connection_get_error_message(m_mir_connection));
1379+ if (error.isEmpty()) {
1380+ qWarning() << "Mir apply config successfully.";
1381+ } else {
1382+ qWarning() << "Mir configuration error:" << error;
1383+ }
1384+ return error.isEmpty();
1385+}
1386+
1387+void MirClientImpl::connect() {
1388+ qWarning() << "Connecting to a Mir server...";
1389+ m_mir_connection = static_cast<MirConnection*>(
1390+ QGuiApplication::platformNativeInterface()
1391+ ->nativeResourceForIntegration("mirConnection")
1392+ );
1393+ if (m_mir_connection == nullptr || !isConnected()) {
1394+ const char *error = "Unknown error";
1395+ if (m_mir_connection != nullptr)
1396+ error = mir_connection_get_error_message(m_mir_connection);
1397+ qWarning() << __PRETTY_FUNCTION__ << "Could not connect to Mir:" << error;
1398+ } else {
1399+ qWarning() << "Using a Mir server.";
1400+ mir_connection_set_display_config_change_callback(
1401+ m_mir_connection, mir_display_change_callback, this);
1402+ }
1403+}
1404+} // DisplayPlugin
1405
1406=== added file 'plugins/brightness/displays/mirclient_impl.h'
1407--- plugins/brightness/displays/mirclient_impl.h 1970-01-01 00:00:00 +0000
1408+++ plugins/brightness/displays/mirclient_impl.h 2016-11-04 18:56:02 +0000
1409@@ -0,0 +1,26 @@
1410+#ifndef MIRCLIENT_IMPL_H
1411+#define MIRCLIENT_IMPL_H
1412+
1413+#include "mirclient.h"
1414+
1415+namespace DisplayPlugin
1416+{
1417+class MirClientImpl : public MirClient
1418+{
1419+ Q_OBJECT
1420+public:
1421+ explicit MirClientImpl(QObject *parent = 0);
1422+ ~MirClientImpl();
1423+ virtual MirDisplayConfiguration* getConfiguration() const;
1424+ virtual void setConfiguration(MirDisplayConfiguration *conf) override;
1425+ virtual bool applyConfiguration(MirDisplayConfiguration *conf) override;
1426+ virtual bool isConnected() override;
1427+
1428+private:
1429+ void connect();
1430+ MirConnection *m_mir_connection;
1431+ MirDisplayConfiguration *m_configuration;
1432+};
1433+} // DisplayPlugin
1434+
1435+#endif // MIRCLIENT_IMPL_H
1436
1437=== modified file 'plugins/brightness/plugin.cpp'
1438--- plugins/brightness/plugin.cpp 2016-11-04 18:56:02 +0000
1439+++ plugins/brightness/plugin.cpp 2016-11-04 18:56:02 +0000
1440@@ -43,8 +43,8 @@
1441 qmlRegisterType<Device>(uri, 1, 0, "AethercastDevice");
1442 qmlRegisterType<Displays>(uri, 1, 0, "AethercastDisplays");
1443
1444- qmlRegisterType<DisplayModel>(uri, 1, 0, "DisplayModel");
1445- qmlRegisterType<Display>(uri, 1, 0, "Display");
1446+ qmlRegisterType<DisplayPlugin::DisplayModel>(uri, 1, 0, "DisplayModel");
1447+ qmlRegisterUncreatableType<DisplayPlugin::Display>(uri, 1, 0, "Display", "Use UbuntuBrightnessPanel.");
1448 }
1449
1450 void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
1451
1452=== modified file 'plugins/brightness/plugin/brightness-plugin.cpp'
1453--- plugins/brightness/plugin/brightness-plugin.cpp 2016-04-27 16:55:42 +0000
1454+++ plugins/brightness/plugin/brightness-plugin.cpp 2016-11-04 18:56:02 +0000
1455@@ -48,24 +48,8 @@
1456 BrightnessItem::BrightnessItem(const QVariantMap &staticData, QObject *parent):
1457 ItemBase(staticData, parent)
1458 {
1459- QDBusInterface m_powerdIface ("com.canonical.powerd",
1460- "/com/canonical/powerd",
1461- "com.canonical.powerd",
1462- QDBusConnection::systemBus());
1463-
1464- // Hide the plugin if powerd isn't running; it's currently redundant
1465- setVisibility(m_powerdIface.isValid());
1466-
1467- char widi[PROP_VALUE_MAX] = "";
1468- property_get("ubuntu.widi.supported", widi, "0");
1469- // We want to log this property to help aid debugging
1470- qWarning() << Q_FUNC_INFO << "ubuntu.widi.supported:" << widi;
1471-
1472- if (strcmp(widi, "0") == 0) {
1473- setDisplayName(_("Brightness"));
1474- } else {
1475- setDisplayName(_("Brightness & Display"));
1476- }
1477+ setVisibility(true);
1478+ setDisplayName(_("Brightness"));
1479 }
1480
1481 void BrightnessItem::setDisplayName(const QString &name)
1482
1483=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt'
1484--- tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt 2016-11-04 18:56:02 +0000
1485+++ tests/mocks/Ubuntu/SystemSettings/Brightness/CMakeLists.txt 2016-11-04 18:56:02 +0000
1486@@ -1,7 +1,10 @@
1487+pkg_search_module(MIR REQUIRED mirclient)
1488+
1489 include_directories(
1490 ${CMAKE_CURRENT_BINARY_DIR}
1491 ${CMAKE_SOURCE_DIR}/plugins/brightness/
1492 ${CMAKE_SOURCE_DIR}/plugins/brightness/displays
1493+ ${MIR_INCLUDE_DIRS}
1494 )
1495
1496 set(MOCK_BRIGHTNESS_SRCS
1497@@ -10,18 +13,14 @@
1498 MockAethercastDisplays.cpp
1499 MockBrightness.cpp
1500
1501- ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/display.h
1502- ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/displaymodel.h
1503 MockDisplay.h
1504 MockDisplayModel.h
1505- ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/display.cpp
1506- ${CMAKE_SOURCE_DIR}/plugins/brightness/displays/displaymodel.cpp
1507 plugin.cpp
1508 )
1509
1510 add_library(MockBrightnessPanel MODULE ${MOCK_BRIGHTNESS_SRCS})
1511
1512-target_link_libraries(MockBrightnessPanel)
1513+target_link_libraries(MockBrightnessPanel ${MIR_LDFLAGS} uss-displays)
1514 qt5_use_modules(MockBrightnessPanel Qml Quick Core)
1515
1516 add_uss_mock(Ubuntu.SystemSettings.Brightness 1.0 Ubuntu/SystemSettings/Brightness
1517
1518=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp'
1519--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp 2016-11-04 18:56:02 +0000
1520+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.cpp 2016-11-04 18:56:02 +0000
1521@@ -27,6 +27,9 @@
1522 {
1523 m_changedDisplays.filterOnUncommittedChanges(true);
1524 m_changedDisplays.setSourceModel(&m_displays);
1525+
1526+ m_connectedDisplays.filterOnConnected(true);
1527+ m_connectedDisplays.setSourceModel(&m_displays);
1528 }
1529
1530 bool MockBrightness::getPowerdRunning() const
1531@@ -76,9 +79,16 @@
1532 return ret;
1533 }
1534
1535+QAbstractItemModel* MockBrightness::connectedDisplays()
1536+{
1537+ auto ret = &m_connectedDisplays;
1538+ QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership);
1539+ return ret;
1540+}
1541+
1542 void MockBrightness::applyDisplayConfiguration()
1543 {
1544-
1545+ Q_EMIT applied();
1546 }
1547
1548 MockDisplayModel* MockBrightness::displayModel()
1549
1550=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h'
1551--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h 2016-11-04 18:56:02 +0000
1552+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockBrightness.h 2016-11-04 18:56:02 +0000
1553@@ -43,6 +43,9 @@
1554 Q_PROPERTY (QAbstractItemModel* changedDisplays
1555 READ changedDisplays
1556 CONSTANT)
1557+ Q_PROPERTY (QAbstractItemModel* connectedDisplays
1558+ READ connectedDisplays
1559+ CONSTANT)
1560
1561 public:
1562 explicit MockBrightness(QObject *parent = 0);
1563@@ -54,20 +57,23 @@
1564 Q_INVOKABLE void setWidiSupported(const bool supported);
1565 QAbstractItemModel* allDisplays();
1566 QAbstractItemModel* changedDisplays();
1567+ QAbstractItemModel* connectedDisplays();
1568 Q_INVOKABLE void applyDisplayConfiguration();
1569 Q_INVOKABLE MockDisplayModel* displayModel(); // mock only
1570
1571 Q_SIGNALS:
1572- void powerdRunningChanged(); // mock only
1573- void autoBrightnessAvailableChanged(); // mock only
1574- void widiSupportedChanged(); // mock only
1575+ void powerdRunningChanged();
1576+ void autoBrightnessAvailableChanged();
1577+ void widiSupportedChanged();
1578+ void applied(); // mock only
1579
1580 private:
1581 bool m_powerdRunning = false;
1582 bool m_autoBrightnessAvailable = false;
1583 bool m_widiSupported = false;
1584 MockDisplayModel m_displays;
1585- DisplaysFilter m_changedDisplays;
1586+ DisplayPlugin::DisplaysFilter m_changedDisplays;
1587+ DisplayPlugin::DisplaysFilter m_connectedDisplays;
1588 };
1589
1590 #endif // MOCK_BRIGHTNESS_H
1591
1592=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h'
1593--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h 2016-11-04 18:56:02 +0000
1594+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplay.h 2016-11-04 18:56:02 +0000
1595@@ -6,7 +6,8 @@
1596 #include <QObject>
1597 #include <QDebug>
1598
1599-struct MockDisplay : public Display
1600+
1601+struct MockDisplay : public DisplayPlugin::Display
1602 {
1603 Q_OBJECT
1604 public:
1605@@ -22,31 +23,49 @@
1606 Q_EMIT typeChanged();
1607 }
1608
1609+ Q_INVOKABLE void setEnabled(const bool &enabled) // mock only
1610+ {
1611+ m_enabled = enabled;
1612+ Q_EMIT enabledChanged();
1613+ }
1614+
1615 Q_INVOKABLE void setConnected(const bool &connected) // mock only
1616 {
1617 m_connected = connected;
1618 Q_EMIT connectedChanged();
1619 }
1620
1621- Q_INVOKABLE void setAvailableModes(const QStringList &availableModes) // mock only
1622- {
1623- m_availableModes = availableModes;
1624- Q_EMIT availableModesChanged();
1625- }
1626-
1627 Q_INVOKABLE void setUncommitedChanges(const bool uncommittedChanges) // mock only
1628 {
1629 m_uncommittedChanges = uncommittedChanges;
1630 Q_EMIT uncommittedChangesChanged();
1631 }
1632
1633- Q_INVOKABLE void addMode(const QString &mode) // mock only
1634- {
1635- m_availableModes.append(mode);
1636- Q_EMIT availableModesChanged();
1637- }
1638+ // Return at what index the new mode was placed.
1639+ Q_INVOKABLE uint addMode(const uint &horizontal, const uint &vertical,
1640+ const uint &refresh) // mock only
1641+ {
1642+ DisplayPlugin::DisplayMode mode;
1643+ mode.vertical_resolution = vertical;
1644+ mode.horizontal_resolution = horizontal;
1645+ mode.refresh_rate = refresh;
1646+
1647+ m_modes.append(mode);
1648+ Q_EMIT modesChanged();
1649+ return m_modes.indexOf(mode);
1650+ }
1651+
1652+ // Mark a display as unchanged, and save the current config.
1653+ Q_INVOKABLE void save()
1654+ {
1655+ storeConfiguration();
1656+ setUncommitedChanges(false);
1657+ }
1658+Q_SIGNALS:
1659+ void nameChanged();
1660+ void typeChanged();
1661 };
1662
1663-Q_DECLARE_METATYPE(MockDisplay*)
1664+// Q_DECLARE_METATYPE(MockDisplay*)
1665
1666 #endif // MOCK_DISPLAY_H
1667
1668=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h'
1669--- tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h 2016-11-04 18:56:02 +0000
1670+++ tests/mocks/Ubuntu/SystemSettings/Brightness/MockDisplayModel.h 2016-11-04 18:56:02 +0000
1671@@ -7,12 +7,12 @@
1672 #include <QObject>
1673 #include <QQmlEngine>
1674
1675-class MockDisplayModel : public DisplayModel
1676+class MockDisplayModel : public DisplayPlugin::DisplayModel
1677 {
1678 Q_OBJECT
1679 public:
1680- MockDisplayModel(QObject *parent = 0) : DisplayModel(parent) {
1681- };
1682+ MockDisplayModel(QObject *parent = 0)
1683+ : DisplayPlugin::DisplayModel(parent) {};
1684 ~MockDisplayModel() {};
1685 Q_INVOKABLE MockDisplay* mockAddDisplay() // mock only
1686 {
1687
1688=== modified file 'tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp'
1689--- tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp 2016-11-04 18:56:02 +0000
1690+++ tests/mocks/Ubuntu/SystemSettings/Brightness/plugin.cpp 2016-11-04 18:56:02 +0000
1691@@ -34,6 +34,7 @@
1692 qmlRegisterType<MockAethercastDevice>(uri, 1, 0, "AethercastDevice");
1693 qmlRegisterType<MockAethercastDisplays>(uri, 1, 0, "AethercastDisplays");
1694
1695- qmlRegisterUncreatableType<MockDisplay>(uri, 1, 0, "Display", "Not to be instantiated directly.");
1696 qmlRegisterType<MockDisplayModel>(uri, 1, 0, "DisplayModel");
1697+ qmlRegisterUncreatableType<MockDisplay>(uri, 1, 0, "Display",
1698+ "Not to be instantiated directly.");
1699 }
1700
1701=== added file 'tests/mocks/plugins/brightness/fakemirclient.h'
1702--- tests/mocks/plugins/brightness/fakemirclient.h 1970-01-01 00:00:00 +0000
1703+++ tests/mocks/plugins/brightness/fakemirclient.h 2016-11-04 18:56:02 +0000
1704@@ -0,0 +1,36 @@
1705+#ifndef FAKEMIRCLIENT_H
1706+#define FAKEMIRCLIENT_H
1707+
1708+#include "mirclient.h"
1709+
1710+#include <mir_toolkit/mir_client_library.h>
1711+#include <QObject>
1712+
1713+class FakeMirClient : public DisplayPlugin::MirClient
1714+{
1715+ Q_OBJECT
1716+public:
1717+ explicit FakeMirClient(QObject *parent = 0)
1718+ : DisplayPlugin::MirClient(parent) {}
1719+ virtual ~FakeMirClient() {}
1720+ virtual MirDisplayConfiguration* getConfiguration() const override
1721+ {
1722+
1723+ }
1724+ virtual void setConfiguration(MirDisplayConfiguration *conf) override
1725+ {
1726+
1727+ }
1728+ virtual bool applyConfiguration(MirDisplayConfiguration *conf) override
1729+ {
1730+
1731+ }
1732+ virtual bool isConnected() override
1733+ {
1734+ return connected;
1735+ }
1736+
1737+ bool connected = false;
1738+};
1739+
1740+#endif // FAKEMIRCLIENT_H
1741
1742=== modified file 'tests/plugins/CMakeLists.txt'
1743--- tests/plugins/CMakeLists.txt 2016-11-04 18:56:02 +0000
1744+++ tests/plugins/CMakeLists.txt 2016-11-04 18:56:02 +0000
1745@@ -4,6 +4,7 @@
1746 add_subdirectory(security-privacy)
1747 add_subdirectory(system-update)
1748 add_subdirectory(bluetooth)
1749+add_subdirectory(brightness)
1750 add_subdirectory(wifi)
1751 add_subdirectory(notifications)
1752
1753
1754=== added file 'tests/plugins/brightness/CMakeLists.txt'
1755--- tests/plugins/brightness/CMakeLists.txt 1970-01-01 00:00:00 +0000
1756+++ tests/plugins/brightness/CMakeLists.txt 2016-11-04 18:56:02 +0000
1757@@ -0,0 +1,25 @@
1758+include_directories(
1759+ ${CMAKE_CURRENT_BINARY_DIR}
1760+ ${CMAKE_SOURCE_DIR}/plugins/brightness
1761+ ${CMAKE_SOURCE_DIR}/plugins/brightness/displays
1762+ ${CMAKE_SOURCE_DIR}/tests/mocks/plugins/brightness
1763+ ${QTDBUSMOCK_INCLUDE_DIRS}
1764+ # ${QTDBUSTEST_INCLUDE_DIRS}
1765+ ${MIR_INCLUDE_DIRS}
1766+ ${ANDR_PROP_INCLUDE_DIRS}
1767+)
1768+
1769+pkg_search_module(MIR REQUIRED mirclient)
1770+find_package(Qt5Test REQUIRED)
1771+find_package(Qt5DBus REQUIRED)
1772+
1773+#set(CMAKE_AUTOMOC ON)
1774+#set(CMAKE_INCLUDE_CURRENT_DIR ON)
1775+set(PLUGIN_LIBS uss-displays Qt5::Test Qt5::DBus)
1776+
1777+add_executable(tst-brightness
1778+ ${CMAKE_SOURCE_DIR}/tests/mocks/plugins/brightness/fakemirclient.h
1779+ tst_brightness.cpp
1780+ ${CMAKE_SOURCE_DIR}/plugins/brightness/brightness.cpp)
1781+add_test(tst-brightness tst-brightness)
1782+target_link_libraries(tst-brightness ${PLUGIN_LIBS} ${ANDR_PROP_LDFLAGS} ${QTDBUSMOCK_LIBRARIES} ${QTDBUSTEST_LIBRARIES})
1783
1784=== modified file 'tests/plugins/brightness/tst_BrightnessPageComponent.qml'
1785--- tests/plugins/brightness/tst_BrightnessPageComponent.qml 2016-11-04 18:56:02 +0000
1786+++ tests/plugins/brightness/tst_BrightnessPageComponent.qml 2016-11-04 18:56:02 +0000
1787@@ -87,25 +87,113 @@
1788 compare(entry.value, i18n.tr("Not connected"));
1789 }
1790
1791- // Test that everything is hidden if only aethercast devices (or none)
1792- function test_no_displays() {
1793+ function test_no_mir_displays() {
1794 var repeater = findChild(instance, "displayConfigurationRepeater");
1795 compare(repeater.count, 0);
1796 }
1797
1798- // Test that there's a UI when we have some display available.
1799- function test_one_display() {
1800+ function test_one_mir_display() {
1801 var displayModel = get_panel_plugin().displayModel();
1802 var display = displayModel.mockAddDisplay();
1803- display.setName("Foo")
1804- display.addMode("1600x1200x60")
1805- display.addMode("1280x1024x60")
1806- display.mode = "1600x1200x60"
1807-
1808+ display.setConnected(true);
1809 var repeater = findChild(instance, "displayConfigurationRepeater");
1810- var panel = findChild(instance, "displayConfiguration_" + display.name);
1811- verify(panel.visible);
1812 compare(repeater.count, 1);
1813 }
1814 }
1815+
1816+
1817+ UbuntuTestCase {
1818+ name: "BrightnessPageComponent for one Mir display"
1819+ when: windowShown
1820+
1821+ SignalSpy {
1822+ id: signalSpy
1823+ signalName: ""
1824+ target: null
1825+ }
1826+
1827+ property var instance: null
1828+ property var display: null
1829+
1830+ function init() {
1831+ instance = pageComponent.createObject(testRoot, {});
1832+ var displayModel = get_panel_plugin().displayModel();
1833+ display = displayModel.mockAddDisplay();
1834+ display.setConnected(true);
1835+ display.setName("test");
1836+ display.save();
1837+ }
1838+
1839+ function cleanup() {
1840+ instance.destroy();
1841+ signalSpy.target = null;
1842+ }
1843+
1844+ function get_panel_plugin() {
1845+ return findInvisibleChild(instance, "brightnessPanel");
1846+ }
1847+
1848+ function test_no_changes_disables_apply() {
1849+ var obj = findChild(instance, "applyButton");
1850+ verify(!obj.enabled);
1851+ }
1852+
1853+ function test_a_change_enables_apply() {
1854+ var obj = findChild(instance, "enabledSwitch");
1855+ var apply = findChild(instance, "applyButton");
1856+ mouseClick(obj, obj.width / 2, obj.height / 2);
1857+ }
1858+
1859+ function test_apply() {
1860+ signalSpy.target = get_panel_plugin();
1861+ signalSpy.signalName = "applied";
1862+
1863+ display.setEnabled(true);
1864+ var obj = findChild(instance, "applyButton");
1865+ mouseClick(obj, obj.width / 2, obj.height / 2);
1866+
1867+ signalSpy.wait();
1868+ }
1869+
1870+ function test_default_rotation() {
1871+ var obj = findChild(instance, "rotationSelector");
1872+ compare(obj.selectedIndex, 0);
1873+ }
1874+
1875+ function test_other_rotation() {
1876+ display.orientation = 1;
1877+ var obj = findChild(instance, "rotationSelector");
1878+ compare(obj.selectedIndex, 1);
1879+ }
1880+
1881+ function test_change_rotation() {
1882+ var obj = findChild(instance, "rotationSelector");
1883+ obj.delegateClicked(2);
1884+ compare(display.orientation, 2);
1885+ }
1886+
1887+ function test_one_resolution() {
1888+ display.mode = display.addMode(1024, 768, 60);
1889+ var obj = findChild(instance, "resolutionLabel");
1890+ var res = i18n.tr("%1×%2 @ %3hz").arg(1024).arg(768).arg(60);
1891+ compare(obj.text, i18n.tr("Resolution: %1").arg(res));
1892+ }
1893+
1894+ function test_many_resolutions() {
1895+ display.addMode(1024, 768, 60);
1896+ display.addMode(640, 320, 40);
1897+ display.mode = 1;
1898+ var obj = findChild(instance, "resolutionSelector");
1899+ compare(obj.selectedIndex, 1);
1900+ }
1901+
1902+ function test_change_resolution() {
1903+ display.addMode(1024, 768, 60);
1904+ display.addMode(640, 320, 40);
1905+ display.mode = 1;
1906+ var obj = findChild(instance, "resolutionSelector");
1907+ obj.delegateClicked(0);
1908+ compare(display.mode, 0);
1909+ }
1910+ }
1911 }
1912
1913=== added file 'tests/plugins/brightness/tst_brightness.cpp'
1914--- tests/plugins/brightness/tst_brightness.cpp 1970-01-01 00:00:00 +0000
1915+++ tests/plugins/brightness/tst_brightness.cpp 2016-11-04 18:56:02 +0000
1916@@ -0,0 +1,41 @@
1917+#include "brightness.h"
1918+#include "fakemirclient.h"
1919+
1920+#include <QSignalSpy>
1921+#include <QTest>
1922+
1923+using namespace DisplayPlugin;
1924+
1925+class TstBrightness : public QObject
1926+{
1927+ Q_OBJECT
1928+private slots:
1929+ void initTestCase()
1930+ {
1931+ }
1932+ void cleanupTestCase()
1933+ {
1934+ }
1935+ void init()
1936+ {
1937+ m_mirClient = new FakeMirClient();
1938+ m_instance = new Brightness(QDBusConnection::systemBus(), m_mirClient);
1939+ }
1940+ void cleanup()
1941+ {
1942+ QSignalSpy destroyedSpy(m_instance, SIGNAL(destroyed(QObject*)));
1943+ m_instance->deleteLater();
1944+ QTRY_COMPARE(destroyedSpy.count(), 1);
1945+ }
1946+ void test_foo()
1947+ {
1948+
1949+ }
1950+private:
1951+ MirClient *m_mirClient = nullptr;
1952+ Brightness *m_instance = nullptr;
1953+};
1954+
1955+QTEST_GUILESS_MAIN(TstBrightness)
1956+#include "tst_brightness.moc"
1957+
1958
1959=== added file 'tests/plugins/brightness/tst_displayplugin_display.cpp'
1960=== added file 'tests/plugins/brightness/tst_displayplugin_displaymodel.cpp'
1961--- tests/plugins/brightness/tst_displayplugin_displaymodel.cpp 1970-01-01 00:00:00 +0000
1962+++ tests/plugins/brightness/tst_displayplugin_displaymodel.cpp 2016-11-04 18:56:02 +0000
1963@@ -0,0 +1,32 @@
1964+#include <QSignalSpy>
1965+#include <QTest>
1966+
1967+using namespace DisplayPlugin;
1968+
1969+class TstDisplayModel : public QObject
1970+{
1971+ Q_OBJECT
1972+private slots:
1973+ void initTestCase()
1974+ {
1975+ }
1976+ void cleanupTestCase()
1977+ {
1978+ }
1979+ void init()
1980+ {
1981+ m_instance = nullptr;
1982+ }
1983+ void cleanup()
1984+ {
1985+ // QSignalSpy destroyedSpy(m_instance, SIGNAL(destroyed(QObject*)));
1986+ // m_instance->deleteLater();
1987+ // QTRY_COMPARE(destroyedSpy.count(), 1);
1988+ }
1989+private:
1990+ QObject *m_instance = nullptr;
1991+};
1992+
1993+QTEST_GUILESS_MAIN(TstDisplayModel)
1994+#include "tst_displayplugin_displaymodel.moc"
1995+

Subscribers

People subscribed via source and target branches