Merge lp:~pete-woods/libqtdbusmock/new-templates-in-common-package into lp:libqtdbusmock
- new-templates-in-common-package
- Merge into trunk
Proposed by
Pete Woods
Status: | Merged |
---|---|
Approved by: | Pete Woods |
Approved revision: | 52 |
Merged at revision: | 48 |
Proposed branch: | lp:~pete-woods/libqtdbusmock/new-templates-in-common-package |
Merge into: | lp:libqtdbusmock |
Diff against target: |
399 lines (+288/-2) 10 files modified
CMakeLists.txt (+1/-0) debian/changelog (+8/-0) debian/control (+12/-1) debian/libqtdbusmock1-common.install (+1/-0) debian/libqtdbusmock1.symbols (+2/-0) src/libqtdbusmock/DBusMock.cpp (+28/-1) src/libqtdbusmock/DBusMock.h (+4/-0) templates/CMakeLists.txt (+8/-0) templates/org.freedesktop.hostname1.py (+53/-0) templates/org.freedesktop.login1.py (+171/-0) |
To merge this branch: | bzr merge lp:~pete-woods/libqtdbusmock/new-templates-in-common-package |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Xavi Garcia (community) | Approve | ||
Review via email: mp+319972@code.launchpad.net |
Commit message
Add new templates to new -common package
Description of the change
Add new templates to new -common package
To post a comment you must log in.
- 49. By Pete Woods
-
Remove duplicate property entry
- 50. By Pete Woods
-
Remove multiarch and shlibs depends
- 51. By Pete Woods
-
Fix Xavi's review comment
- 52. By Pete Woods
-
Improve changelog message
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-12-12 12:02:52 +0000 |
3 | +++ CMakeLists.txt 2017-03-16 10:30:45 +0000 |
4 | @@ -59,6 +59,7 @@ |
5 | |
6 | add_subdirectory("src") |
7 | add_subdirectory("data") |
8 | +add_subdirectory("templates") |
9 | |
10 | enable_testing() |
11 | add_subdirectory(tests) |
12 | |
13 | === modified file 'debian/changelog' |
14 | --- debian/changelog 2017-01-06 10:44:45 +0000 |
15 | +++ debian/changelog 2017-03-16 10:30:45 +0000 |
16 | @@ -1,3 +1,11 @@ |
17 | +libqtdbusmock (0.7-0ubuntu1) UNRELEASED; urgency=medium |
18 | + |
19 | + * Add hostname1 and login1 templates to new binary package |
20 | + libqtdbusmock1-common. |
21 | + * Search /usr/share/libqtdbusmock/templates for templates. |
22 | + |
23 | + -- Pete <pete.woods@canonical.com> Wed, 15 Mar 2017 18:17:19 +0000 |
24 | + |
25 | libqtdbusmock (0.6+17.04.20170106-0ubuntu1) zesty; urgency=medium |
26 | |
27 | * Compatibility with unversioned cmake-extras modules (LP: #1563573) |
28 | |
29 | === modified file 'debian/control' |
30 | --- debian/control 2016-12-12 12:02:52 +0000 |
31 | +++ debian/control 2017-03-16 10:30:45 +0000 |
32 | @@ -12,7 +12,7 @@ |
33 | pkg-config, |
34 | python3-dbusmock (>= 0.16), |
35 | qtbase5-dev, |
36 | -Standards-Version: 3.9.4 |
37 | +Standards-Version: 3.9.7 |
38 | Homepage: https://launchpad.net/libqtdbustest |
39 | # If you aren't a member of ~unity-team but need to upload packaging changes, |
40 | # just go ahead. ~unity-team will notice and sync up the code again. |
41 | @@ -24,6 +24,7 @@ |
42 | Multi-Arch: same |
43 | Pre-Depends: ${misc:Pre-Depends}, |
44 | Depends: python3-dbusmock (>= 0.16), |
45 | + libqtdbusmock1-common (= ${binary:Version}), |
46 | ${misc:Depends}, |
47 | ${shlibs:Depends}, |
48 | Description: Library for mocking DBus interactions using Qt |
49 | @@ -41,3 +42,13 @@ |
50 | A simple library for mocking DBus services with a Qt API |
51 | . |
52 | This package contains files that are needed to build. |
53 | + |
54 | +Package: libqtdbusmock1-common |
55 | +Section: libs |
56 | +Architecture: all |
57 | +Pre-Depends: ${misc:Pre-Depends}, |
58 | +Depends: ${misc:Depends}, |
59 | +Description: Library for mocking DBus interactions using Qt |
60 | + A simple library for mocking DBus services with a Qt API |
61 | + . |
62 | + This package contains extra dbusmock templates. |
63 | |
64 | === added file 'debian/libqtdbusmock1-common.install' |
65 | --- debian/libqtdbusmock1-common.install 1970-01-01 00:00:00 +0000 |
66 | +++ debian/libqtdbusmock1-common.install 2017-03-16 10:30:45 +0000 |
67 | @@ -0,0 +1,1 @@ |
68 | +usr/share |
69 | |
70 | === modified file 'debian/libqtdbusmock1.symbols' |
71 | --- debian/libqtdbusmock1.symbols 2016-12-06 12:09:09 +0000 |
72 | +++ debian/libqtdbusmock1.symbols 2017-03-16 10:30:45 +0000 |
73 | @@ -47,6 +47,8 @@ |
74 | (c++)"QtDBusMock::DBusMock::registerURfkill(QMap<QString, QVariant> const&)@Base" 0.5+15.10.20151009 |
75 | (c++)"QtDBusMock::DBusMock::registerTemplate(QString const&, QString const&, QMap<QString, QVariant> const&, QDBusConnection::BusType)@Base" 0.5+15.10.20151009 |
76 | (c++)"QtDBusMock::DBusMock::registerTimeDate(QMap<QString, QVariant> const&)@Base" 0.5+15.10.20151009 |
77 | + (c++)"QtDBusMock::DBusMock::registerLogin1(QMap<QString, QVariant> const&)@Base" 0replaceme |
78 | + (c++)"QtDBusMock::DBusMock::registerHostname1(QMap<QString, QVariant> const&)@Base" 0replaceme |
79 | (c++)"QtDBusMock::DBusMock::registerPolicyKit(QMap<QString, QVariant> const&)@Base" 0.5+15.10.20151009 |
80 | (c++)"QtDBusMock::DBusMock::registerNetworkManager(QMap<QString, QVariant> const&)@Base" 0.5+15.10.20151009 |
81 | (c++)"QtDBusMock::DBusMock::registerGnomeScreensaver(QMap<QString, QVariant> const&)@Base" 0.5+15.10.20151009 |
82 | |
83 | === modified file 'src/libqtdbusmock/DBusMock.cpp' |
84 | --- src/libqtdbusmock/DBusMock.cpp 2016-11-25 13:35:18 +0000 |
85 | +++ src/libqtdbusmock/DBusMock.cpp 2017-03-16 10:30:45 +0000 |
86 | @@ -20,7 +20,9 @@ |
87 | #include <libqtdbustest/QProcessDBusService.h> |
88 | |
89 | #include <NetworkManager.h> |
90 | +#include <QFile> |
91 | #include <QJsonDocument> |
92 | +#include <QStandardPaths> |
93 | |
94 | using namespace QtDBusTest; |
95 | |
96 | @@ -84,7 +86,22 @@ |
97 | QDBusConnection::BusType busType) { |
98 | QStringList arguments; |
99 | arguments << "-m" << "dbusmock"; |
100 | - arguments << "--template" << templateName; |
101 | + |
102 | + bool found = false; |
103 | + if (!templateName.contains(QDir::separator())) { |
104 | + auto dirs = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation); |
105 | + for (const auto & dir : dirs) { |
106 | + auto path = QDir(QDir(QDir(dir).filePath("libqtdbusmock")).filePath("templates")).filePath(templateName + ".py"); |
107 | + if (QFileInfo::exists(path)) { |
108 | + arguments << "--template" << path; |
109 | + found = true; |
110 | + break; |
111 | + } |
112 | + } |
113 | + } |
114 | + if (!found) { |
115 | + arguments << "--template" << templateName; |
116 | + } |
117 | |
118 | if (!parameters.isEmpty()) |
119 | { |
120 | @@ -155,6 +172,16 @@ |
121 | QDBusConnection::SystemBus); |
122 | } |
123 | |
124 | +void DBusMock::registerHostname1(const QVariantMap& parameters) { |
125 | + registerTemplate("org.freedesktop.hostname1", "org.freedesktop.hostname1", parameters, |
126 | + QDBusConnection::SystemBus); |
127 | +} |
128 | + |
129 | +void DBusMock::registerLogin1(const QVariantMap& parameters) { |
130 | + registerTemplate("org.freedesktop.login1", "org.freedesktop.login1", parameters, |
131 | + QDBusConnection::SystemBus); |
132 | +} |
133 | + |
134 | void DBusMock::registerURfkill() { |
135 | registerURfkill(QVariantMap()); |
136 | } |
137 | |
138 | === modified file 'src/libqtdbusmock/DBusMock.h' |
139 | --- src/libqtdbusmock/DBusMock.h 2016-11-25 13:35:18 +0000 |
140 | +++ src/libqtdbusmock/DBusMock.h 2017-03-16 10:30:45 +0000 |
141 | @@ -77,6 +77,10 @@ |
142 | |
143 | virtual void registerTimeDate(const QVariantMap& parameters = QVariantMap()); |
144 | |
145 | + virtual void registerHostname1(const QVariantMap& parameters = QVariantMap()); |
146 | + |
147 | + virtual void registerLogin1(const QVariantMap& parameters = QVariantMap()); |
148 | + |
149 | virtual void registerURfkill(); |
150 | |
151 | virtual void registerURfkill(const QVariantMap& parameters); |
152 | |
153 | === added directory 'templates' |
154 | === added file 'templates/CMakeLists.txt' |
155 | --- templates/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
156 | +++ templates/CMakeLists.txt 2017-03-16 10:30:45 +0000 |
157 | @@ -0,0 +1,8 @@ |
158 | + |
159 | +install( |
160 | + FILES |
161 | + "org.freedesktop.hostname1.py" |
162 | + "org.freedesktop.login1.py" |
163 | + DESTINATION |
164 | + "${CMAKE_INSTALL_DATADIR}/libqtdbusmock/templates/" |
165 | +) |
166 | |
167 | === added file 'templates/org.freedesktop.hostname1.py' |
168 | --- templates/org.freedesktop.hostname1.py 1970-01-01 00:00:00 +0000 |
169 | +++ templates/org.freedesktop.hostname1.py 2017-03-16 10:30:45 +0000 |
170 | @@ -0,0 +1,53 @@ |
171 | +'''Hostname1 mock template |
172 | +''' |
173 | + |
174 | +# This program is free software; you can redistribute it and/or modify it under |
175 | +# the terms of the GNU Lesser General Public License as published by the Free |
176 | +# Software Foundation; either version 3 of the License, or (at your option) any |
177 | +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text |
178 | +# of the license. |
179 | + |
180 | +__author__ = 'Pete Woods' |
181 | +__email__ = 'pete.woods@canonical.com' |
182 | +__copyright__ = '(c) 2016 Canonical Ltd.' |
183 | +__license__ = 'LGPL 3+' |
184 | + |
185 | +import dbus |
186 | +import uuid |
187 | +import binascii |
188 | + |
189 | +from dbusmock import MOCK_IFACE |
190 | +import dbusmock |
191 | + |
192 | + |
193 | +BUS_NAME = 'org.freedesktop.hostname1' |
194 | +MAIN_IFACE = 'org.freedesktop.hostname1' |
195 | +MAIN_OBJ = '/org/freedesktop/hostname1' |
196 | +SYSTEM_BUS = True |
197 | + |
198 | + |
199 | +def load(mock, parameters): |
200 | + mock.AddProperties(MAIN_IFACE, { |
201 | + 'Hostname': parameters.get('Hostname', 'my-computer'), |
202 | + 'StaticHostname': parameters.get('StaticHostname', 'ubuntu'), |
203 | + 'PrettyHostname': parameters.get('PrettyHostname', ''), |
204 | + 'IconName': parameters.get('IconName', 'computer-vm'), # e.g. "computer-laptop", "computer-desktop" |
205 | + 'Chassis': parameters.get('Chassis', 'vm'), # currently defined set: "desktop", "laptop", "server", "tablet", "handset", "vm" and "container" |
206 | + 'Deployment': parameters.get('Deployment', ''), |
207 | + 'Location': parameters.get('Location', ''), |
208 | + 'KernelName': parameters.get('KernelName', 'Linux'), |
209 | + 'KernelRelease': parameters.get('KernelRelease', '4.4.0-53-generic'), |
210 | + 'KernelVersion': parameters.get('KernelVersion', '#74-Ubuntu SMP Fri Dec 2 15:59:10 UTC 2016'), |
211 | + 'OperatingSystemPrettyName': parameters.get('OperatingSystemPrettyName', 'Ubuntu 16.04.1 LTS'), |
212 | + 'OperatingSystemCPEName': parameters.get('OperatingSystemCPEName', ''), |
213 | + }) |
214 | + |
215 | + mock.AddMethods(MAIN_IFACE, [ |
216 | + ('SetHostname', 'sb', '', "ret = self.Set('%s', 'Hostname', args[0])" % MAIN_IFACE), |
217 | + ('SetStaticHostname', 'sb', '', "ret = self.Set('%s', 'StaticHostname', args[0])" % MAIN_IFACE), |
218 | + ('SetPrettyHostname', 'sb', '', "ret = self.Set('%s', 'PrettyHostname', args[0])" % MAIN_IFACE), |
219 | + ('SetIconName', 'sb', '', "ret = self.Set('%s', 'IconName', args[0])" % MAIN_IFACE), |
220 | + ('SetChassis', 'sb', '', "ret = self.Set('%s', 'Chassis', args[0])" % MAIN_IFACE), |
221 | + ('SetDeployment', 'sb', '', "ret = self.Set('%s', 'Deployment', args[0])" % MAIN_IFACE), |
222 | + ('SetLocation', 'sb', '', "ret = self.Set('%s', 'Location', args[0])" % MAIN_IFACE), |
223 | + ]) |
224 | |
225 | === added file 'templates/org.freedesktop.login1.py' |
226 | --- templates/org.freedesktop.login1.py 1970-01-01 00:00:00 +0000 |
227 | +++ templates/org.freedesktop.login1.py 2017-03-16 10:30:45 +0000 |
228 | @@ -0,0 +1,171 @@ |
229 | +'''Login1 mock template |
230 | +''' |
231 | + |
232 | +# This program is free software; you can redistribute it and/or modify it under |
233 | +# the terms of the GNU Lesser General Public License as published by the Free |
234 | +# Software Foundation; either version 3 of the License, or (at your option) any |
235 | +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text |
236 | +# of the license. |
237 | + |
238 | +__author__ = 'Pete Woods' |
239 | +__email__ = 'pete.woods@canonical.com' |
240 | +__copyright__ = '(c) 2017 Canonical Ltd.' |
241 | +__license__ = 'LGPL 3+' |
242 | + |
243 | +import dbus |
244 | +import uuid |
245 | +import binascii |
246 | + |
247 | +from dbusmock import MOCK_IFACE |
248 | +import dbusmock |
249 | + |
250 | + |
251 | +BUS_NAME = 'org.freedesktop.login1' |
252 | +MAIN_IFACE = 'org.freedesktop.login1.Manager' |
253 | +MAIN_OBJ = '/org/freedesktop/login1' |
254 | +SYSTEM_BUS = True |
255 | + |
256 | +SEAT_IFACE = 'org.freedesktop.login1.Seat' |
257 | +SEAT_PATH = '/org/freedesktop/login1/seat/' |
258 | + |
259 | +def load(mock, parameters): |
260 | + mock.seats = {} |
261 | + |
262 | + add_seat(mock, parameters.get('DefaultSeat', {}), True) |
263 | + |
264 | + mock.list_seats = list_seats |
265 | + mock.get_seat = get_seat |
266 | + |
267 | + mock.AddProperties(MAIN_IFACE, { |
268 | + 'EnableWallMessages': parameters.get('EnableWallMessages', False), |
269 | + 'WallMessage': parameters.get('WallMessage', ''), |
270 | + 'NAutoVTs': parameters.get('NAutoVTs', dbus.UInt32(6)), |
271 | + 'KillOnlyUsers': parameters.get('KillOnlyUsers', dbus.Array([], signature='s')), |
272 | + 'KillExcludeUsers': parameters.get('KillExcludeUsers', dbus.Array(['root'], signature='s')), |
273 | + 'KillUserProcesses': parameters.get('KillUserProcesses', False), |
274 | + 'RebootToFirmwareSetup': parameters.get('RebootToFirmwareSetup', False), |
275 | + 'IdleHint': parameters.get('IdleHint', False), |
276 | + 'IdleSinceHint': parameters.get('IdleSinceHint', dbus.UInt64(1489580452083866)), |
277 | + 'IdleSinceHintMonotonic': parameters.get('IdleSinceHintMonotonic', dbus.UInt64(8134597164)), |
278 | + 'BlockInhibited': parameters.get('BlockInhibited', 'handle-power-key:handle-suspend-key:handle-hibernate-key:handle-lid-switch'), |
279 | + 'DelayInhibited': parameters.get('DelayInhibited', 'sleep'), |
280 | + 'InhibitDelayMaxUSec': parameters.get('InhibitDelayMaxUSec', dbus.UInt64(5000000)), |
281 | + 'HandlePowerKey': parameters.get('HandlePowerKey', 'poweroff'), |
282 | + 'HandleSuspendKey': parameters.get('HandleSuspendKey', 'suspend'), |
283 | + 'HandleHibernateKey': parameters.get('HandleHibernateKey', 'hibernate'), |
284 | + 'HandleLidSwitch': parameters.get('HandleLidSwitch', 'suspend'), |
285 | + 'HandleLidSwitchDocked': parameters.get('HandleLidSwitchDocked', 'ignore'), |
286 | + 'HoldoffTimeoutUSec': parameters.get('HoldoffTimeoutUSec', dbus.UInt64(30000000)), |
287 | + 'IdleAction': parameters.get('IdleAction', 'ignore'), |
288 | + 'IdleActionUSec': parameters.get('IdleActionUSec', dbus.UInt64(1800000000)), |
289 | + 'PreparingForShutdown': parameters.get('PreparingForShutdown', False), |
290 | + 'PreparingForSleep': parameters.get('PreparingForSleep', False), |
291 | + 'ScheduledShutdown': parameters.get('ScheduledShutdown', dbus.Struct(('', 0), signature='st')), |
292 | + 'Docked': parameters.get('Docked', False), |
293 | + }) |
294 | + |
295 | + mock.AddMethods(MAIN_IFACE, [ |
296 | + ('GetSession', 's', 'o', "ret = dbus.ObjectPath('/')"), |
297 | + ('GetSessionByPID', 'u', 'o', "ret = dbus.ObjectPath('/')"), |
298 | + ('GetUser', 'u', 'o', "ret = dbus.ObjectPath('/')"), |
299 | + ('GetUserByPID', 'u', 'o', "ret = dbus.ObjectPath('/')"), |
300 | + ('GetSeat', 's', 'o', "ret = self.get_seat(self, args[0])"), |
301 | + |
302 | + ('ListSessions', '', 'a(susso)', ""), |
303 | + ('ListUsers', '', 'a(uso)', ""), |
304 | + ('ListSeats', '', 'a(so)', "ret = self.list_seats(self)"), |
305 | + ('ListInhibitors', '', 'a(ssssuu)', ""), |
306 | + |
307 | + ('CreateSession', 'uusssssussbssa(sv)', 'soshusub', ""), |
308 | + ('ReleaseSession', 's', '', ""), |
309 | + ('ActivateSession', 's', '', ""), |
310 | + ('ActivateSessionOnSeat', 'ss', '', ""), |
311 | + ('LockSession', 's', '', ""), |
312 | + ('UnlockSession', 's', '', ""), |
313 | + ('LockSessions', '', '', ""), |
314 | + ('UnlockSessions', '', '', ""), |
315 | + ('KillSession', 'ssi', '', ""), |
316 | + ('KillUser', 'ui', '', ""), |
317 | + ('TerminateSession', 's', '', ""), |
318 | + ('TerminateUser', 'u', '', ""), |
319 | + ('TerminateSeat', 's', '', ""), |
320 | + ('SetUserLinger', 'ubb', '', ""), |
321 | + ('AttachDevice', 'ssb', '', ""), |
322 | + ('FlushDevices', 'b', '', ""), |
323 | + ('PowerOff', 'b', '', ""), |
324 | + ('Reboot', 'b', '', ""), |
325 | + ('Suspend', 'b', '', ""), |
326 | + ('Hibernate', 'b', '', ""), |
327 | + ('HybridSleep', 'b', '', ""), |
328 | + ('CanPowerOff', '', 's', "ret = ''"), |
329 | + ('CanReboot', '', 's', "ret = ''"), |
330 | + ('CanSuspend', '', 's', "ret = ''"), |
331 | + ('CanHibernate', '', 's', "ret = ''"), |
332 | + ('CanHybridSleep', '', 's', "ret = ''"), |
333 | + ('ScheduleShutdown', 'st', '', ""), |
334 | + ('CancelScheduledShutdown', '', 'b', "ret = False"), |
335 | + ('Inhibit', 'ssss', 'h', "ret = ?"), |
336 | + ('CanRebootToFirmwareSetup', '', 's', "ret = ''"), |
337 | + ('SetRebootToFirmwareSetup', 'b', '', ""), |
338 | + ('SetWallMessage', 'sb', '', ""), |
339 | + ]) |
340 | + |
341 | +def add_seat(self, properties, is_self): |
342 | + # find a new name |
343 | + count = 0 |
344 | + while True: |
345 | + id = 'seat%d' % count |
346 | + if id not in self.seats: |
347 | + break |
348 | + count += 1 |
349 | + |
350 | + path = dbus.ObjectPath(SEAT_PATH + id) |
351 | + |
352 | + seat_props = { |
353 | + 'Id': id, |
354 | + 'ActiveSession': properties.get('ActiveSession', dbus.Struct(('c2', '/org/freedesktop/login1/session/c2'), signature='so')), |
355 | + 'CanMultiSession': properties.get('CanMultiSession', True), |
356 | + 'CanTTY': properties.get('CanTTY', True), |
357 | + 'CanGraphical': properties.get('CanGraphical', True), |
358 | + 'Sessions': properties.get('Sessions', dbus.Array([('c2', '/org/freedesktop/login1/session/c2')], signature='(so)')), |
359 | + 'IdleHint': properties.get('IdleHint', False), |
360 | + 'IdleSinceHint': properties.get('IdleSinceHint', dbus.UInt64(1489590854604069)), |
361 | + 'IdleSinceHintMonotonic': properties.get('IdleSinceHintMonotonic', dbus.UInt64(18537117367)), |
362 | + } |
363 | + |
364 | + seat_methods = [ |
365 | + ('Terminate', '', '', ""), |
366 | + ('ActivateSession', 's', '', ""), |
367 | + ('SwitchTo', 'u', '', ""), |
368 | + ('SwitchToNext', '', '', ""), |
369 | + ('SwitchToPrevious', '', '', ""), |
370 | + ] |
371 | + |
372 | + self.seats[id] = self.AddObject(path, |
373 | + SEAT_IFACE, |
374 | + seat_props, |
375 | + seat_methods) |
376 | + |
377 | + if is_self: |
378 | + self_path = dbus.ObjectPath(SEAT_PATH + 'self') |
379 | + try: |
380 | + self.RemoveObject(self_path) |
381 | + except dbus.exceptions.DBusException: |
382 | + pass |
383 | + self.AddObject(self_path, |
384 | + SEAT_IFACE, |
385 | + seat_props, |
386 | + seat_methods) |
387 | + |
388 | + return path |
389 | + |
390 | +def get_seat(self, id): |
391 | + if id in self.seats: |
392 | + return SEAT_PATH + id |
393 | + raise dbus.exceptions.DBusException() |
394 | + |
395 | +def list_seats(self): |
396 | + result = dbus.Array([], signature='(so)') |
397 | + for id in self.seats: |
398 | + result.append((id, SEAT_PATH + id)) |
399 | + return result |
Looks good to me, thanks!
Just 1 ultra ultra ultra minor thing that is not going to block approving this:
In...
#include <NetworkManager.h>
90 #include <QJsonDocument>
91 +#include <QFile>
92 +#include <QStandardPaths>
QFile should go before QJsonDocument if we follow alphabetical order.