Merge lp:~verzegnassi-stefano/ubuntu-docviewer-app/desktop-support2 into lp:ubuntu-docviewer-app

Proposed by Stefano Verzegnassi
Status: Rejected
Rejected by: Stefano Verzegnassi
Proposed branch: lp:~verzegnassi-stefano/ubuntu-docviewer-app/desktop-support2
Merge into: lp:ubuntu-docviewer-app
Diff against target: 2206 lines (+1637/-262)
31 files modified
README-Developers.md (+4/-1)
click/docviewer.apparmor (+3/-2)
debian/control (+3/-1)
src/app/qml/common/ContentHubProxy.qml (+5/-5)
src/app/qml/common/DetailsPage.qml (+2/-2)
src/app/qml/common/PickImportedDialog.qml (+1/-1)
src/app/qml/loView/LOViewDefaultHeader.qml (+1/-1)
src/app/qml/loView/LOViewPage.qml (+1/-1)
src/app/qml/pdfView/PdfPresentation.qml (+1/-1)
src/app/qml/pdfView/PdfView.qml (+1/-1)
src/app/qml/textView/TextView.qml (+1/-1)
src/app/qml/ubuntu-docviewer-app.qml (+8/-1)
src/plugin/file-qml-plugin/CMakeLists.txt (+27/-2)
src/plugin/file-qml-plugin/InputInfo/CMakeLists.txt (+39/-0)
src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux.cpp (+288/-0)
src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux_p.h (+98/-0)
src/plugin/file-qml-plugin/InputInfo/plugin.cpp (+32/-0)
src/plugin/file-qml-plugin/InputInfo/plugin.h (+30/-0)
src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel.cpp (+196/-0)
src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel_p.h (+102/-0)
src/plugin/file-qml-plugin/InputInfo/qinputinfo.cpp (+270/-0)
src/plugin/file-qml-plugin/InputInfo/qinputinfo.h (+143/-0)
src/plugin/file-qml-plugin/InputInfo/qmldir (+3/-0)
src/plugin/file-qml-plugin/backend.cpp (+22/-11)
src/plugin/file-qml-plugin/documentmodel.cpp (+2/-2)
src/plugin/file-qml-plugin/docviewerutils.cpp (+0/-184)
src/plugin/file-qml-plugin/docviewerutils.h (+0/-45)
src/plugin/file-qml-plugin/fileutils.cpp (+174/-0)
src/plugin/file-qml-plugin/fileutils.h (+42/-0)
src/plugin/file-qml-plugin/ubuntuconvergenceutils.cpp (+82/-0)
src/plugin/file-qml-plugin/ubuntuconvergenceutils.h (+56/-0)
To merge this branch: bzr merge lp:~verzegnassi-stefano/ubuntu-docviewer-app/desktop-support2
Reviewer Review Type Date Requested Status
Alan Pope 🍺🐧🐱 πŸ¦„ (community) Needs Fixing
Jenkins Bot continuous-integration Needs Fixing
Stefano Verzegnassi Needs Fixing
Nicholas Skaggs Pending
Review via email: mp+284901@code.launchpad.net

Commit message

Better desktop/pocket-desktop support, by detecting the number of mice and touchpads connected to the device. This uses QInputInfo, available in the Qt snapshots - imported version from unity 8 trunk (rev.2080).

WORKAROUND: This makes new BottomEdge component fully working on desktop

Description of the change

Better desktop/pocket-desktop support, by detecting the number of mice and touchpads connected to the device. This uses QInputInfo, available in the Qt snapshots - imported version from unity 8 trunk (rev.2080).

WORKAROUND: This makes new BottomEdge component fully working on desktop

To post a comment you must log in.
Revision history for this message
Stefano Verzegnassi (verzegnassi-stefano) wrote :

Moved the MP to a new branch

review: Abstain
Revision history for this message
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
290. By Stefano Verzegnassi

Forgot to 'bzr add' new files

291. By Stefano Verzegnassi

...and again

Revision history for this message
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
292. By Stefano Verzegnassi

* Updated README
* Use 'unconfined' template. Apparently there's no other way to get this working...

Revision history for this message
Stefano Verzegnassi (verzegnassi-stefano) wrote :

Ok, this requires an unconfined AppArmor template.

No urge to add the missing packages to Jenkins, nor to merge this branch. I hope the bottom edge will be fixed upstream, because it's not currently usable with a mouse (unless we decide to run unconfined)

review: Needs Fixing
Revision history for this message
Jenkins Bot (ubuntu-core-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Alan Pope 🍺🐧🐱 πŸ¦„ (popey) wrote :

I'm concerned about the unconfined nature of this. Normally for some core apps where there's no other way, I'd probably be okay with this. However, as we're now carrying all of LibreOffice, I'm concerned that we're opening ourselves up by having an unconfined copy of LibreOffice potentially able to be exploited by a dodgy document. That's quite a significantly sized attack surface. Especially when we don't generally roll out new builds of the docviewer with security updated LibreOffice builds very regularly.

What do you think? Should we push this feature back until we have a non-unconfined solution?

Should we bring this up with platform team to find some other way to do this?

review: Needs Fixing
Revision history for this message
Stefano Verzegnassi (verzegnassi-stefano) wrote :

I think so too.
To be fair, we shouldn't have exceptions for accessing to the user's folders too, because of this.

Ideally the platform should provide some service that creates a database with a list of documents, and docviewer should be authorized to access only that database, by default.
When the application asks to access to a specific file, content-hub should mediate the request and ensure that only the single file (or a copy of that file) is accessible.

Anyway, I created this branch a month ago because I thought we were able to release a new version in the store earlier. Also, it wasn't meant to require an unconfined template, but then I discovered that it was broken on the UT platform.

So we can reject this merge proposal.
Let's wait for a fix in the ubuntu-sdk project, it should come soon I guess...

https://code.launchpad.net/~zsombi/ubuntu-ui-toolkit/device_detection/+merge/284282

P.S. If you can ask to the platform team when they expect to release the fix, that would be great. Anyway, all the SDK apps (except addressbook-app) are in the same situation, so I'm not that much worried.

Unmerged revisions

292. By Stefano Verzegnassi

* Updated README
* Use 'unconfined' template. Apparently there's no other way to get this working...

291. By Stefano Verzegnassi

...and again

290. By Stefano Verzegnassi

Forgot to 'bzr add' new files

289. By Stefano Verzegnassi

Added ConvergenceUtils singleton. Improved desktop/pocket desktop support.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README-Developers.md'
2--- README-Developers.md 2015-12-21 13:06:52 +0000
3+++ README-Developers.md 2016-02-03 14:19:17 +0000
4@@ -19,11 +19,14 @@
5 * Install Qt5 private development files:
6 sudo apt install qtdeclarative5-private-dev qtbase5-private-dev
7
8+* Install development files for convergence support:
9+ sudo apt install libudev-dev libevdev-dev
10+
11 * If you want to compile an arm click package, you need to install that package
12 to the arm compilation environment. For example when using QtCreator for
13 Ubuntu Touch, open Options -> Ubuntu -> Maintain, and then enter:
14
15- apt install libpoppler-qt5-dev:armhf qtdeclarative5-private-dev:armhf qtbase5-private-dev:armhf
16+ apt install libpoppler-qt5-dev:armhf qtdeclarative5-private-dev:armhf qtbase5-private-dev:armhf libudev-dev:armhf libevdev-dev:armhf
17
18 LibreOffice viewer support
19 ==========================
20
21=== modified file 'click/docviewer.apparmor'
22--- click/docviewer.apparmor 2016-01-29 12:23:24 +0000
23+++ click/docviewer.apparmor 2016-02-03 14:19:17 +0000
24@@ -13,5 +13,6 @@
25 "@{HOME}/Documents/",
26 "/media/*/*/[Dd][Oo][Cc][Uu][Mm][Ee][Nn][Tt][Ss]/"
27 ],
28- "policy_version": 1.3
29-}
30\ No newline at end of file
31+ "policy_version": 1.3,
32+ "template": "unconfined"
33+}
34
35=== modified file 'debian/control'
36--- debian/control 2016-01-14 21:33:47 +0000
37+++ debian/control 2016-02-03 14:19:17 +0000
38@@ -17,7 +17,9 @@
39 qtdeclarative5-qtquick2-plugin,
40 qtdeclarative5-private-dev,
41 qtbase5-private-dev,
42- qtdeclarative5-test-plugin
43+ qtdeclarative5-test-plugin,
44+ libudev-dev,
45+ libevdev-dev,
46 Standards-Version: 3.9.6
47 Section: misc
48 Homepage: https://launchpad.net/ubuntu-docviewer-app
49
50=== modified file 'src/app/qml/common/ContentHubProxy.qml'
51--- src/app/qml/common/ContentHubProxy.qml 2015-10-10 12:03:30 +0000
52+++ src/app/qml/common/ContentHubProxy.qml 2016-02-03 14:19:17 +0000
53@@ -53,11 +53,11 @@
54 for (var i=0; i<activeTransfer.items.length; i++) {
55 var sourcePath = internal.getPathFromUrl(activeTransfer.items[i].url)
56
57- if (DocumentViewer.isFileSupported(sourcePath)) {
58- var documentsLocation = DocumentViewer.getXdgDocumentsLocation()
59+ if (FileUtils.isFileSupported(sourcePath)) {
60+ var documentsLocation = FileUtils.getXdgDocumentsLocation()
61
62 // Check if we have already imported the same document in the past.
63- var earlierImportedFile = DocumentViewer.checkIfFileAlreadyImported(sourcePath, [documentsLocation])
64+ var earlierImportedFile = FileUtils.checkIfFileAlreadyImported(sourcePath, [documentsLocation])
65 if (earlierImportedFile.length > 0) {
66 // Document has been already imported in the past.
67 // Append the path of the earlier copy of the
68@@ -65,7 +65,7 @@
69 importedDocsModel.append({ path: earlierImportedFile })
70 } else {
71 // No document has been found, so we can safely copy it.
72- var destPath = DocumentViewer.buildDestinationPath(documentsLocation, sourcePath);
73+ var destPath = FileUtils.buildDestinationPath(documentsLocation, sourcePath);
74
75 internal.importDocument(sourcePath, destPath)
76 }
77@@ -120,7 +120,7 @@
78 }
79
80 function importDocument(sourcePath, destPath) {
81- DocumentViewer.copy(sourcePath, destPath)
82+ FileUtils.copy(sourcePath, destPath)
83 importedDocsModel.append({ path: destPath })
84 }
85
86
87=== modified file 'src/app/qml/common/DetailsPage.qml'
88--- src/app/qml/common/DetailsPage.qml 2015-12-27 12:10:06 +0000
89+++ src/app/qml/common/DetailsPage.qml 2016-02-03 14:19:17 +0000
90@@ -40,12 +40,12 @@
91
92 SubtitledListItem {
93 text: i18n.tr("File")
94- subText: DocumentViewer.getFileNameFromPath(file.path)
95+ subText: FileUtils.getFileNameFromPath(file.path)
96 }
97
98 SubtitledListItem {
99 text: i18n.tr("Location")
100- subText: DocumentViewer.getCanonicalPath(file.path)
101+ subText: FileUtils.getCanonicalPath(file.path)
102 }
103
104 SubtitledListItem {
105
106=== modified file 'src/app/qml/common/PickImportedDialog.qml'
107--- src/app/qml/common/PickImportedDialog.qml 2015-12-26 18:27:13 +0000
108+++ src/app/qml/common/PickImportedDialog.qml 2016-02-03 14:19:17 +0000
109@@ -40,7 +40,7 @@
110 }
111
112 Label {
113- text: DocumentViewer.getFileBaseNameFromPath(model.path)
114+ text: FileUtils.getFileBaseNameFromPath(model.path)
115 anchors {
116 left: parent.left; right: parent.right
117 margins: units.gu(2)
118
119=== modified file 'src/app/qml/loView/LOViewDefaultHeader.qml'
120--- src/app/qml/loView/LOViewDefaultHeader.qml 2015-11-30 12:12:10 +0000
121+++ src/app/qml/loView/LOViewDefaultHeader.qml 2016-02-03 14:19:17 +0000
122@@ -73,7 +73,7 @@
123 Layout.preferredHeight: units.gu(4)
124
125 view: targetPage.contentItem.loView
126- visible: targetPage.contentItem && (DocumentViewer.desktopMode || mainView.wideWindow)
127+ visible: targetPage.contentItem && (ConvergenceUtils.desktopMode || mainView.wideWindow)
128 }
129 }
130
131
132=== modified file 'src/app/qml/loView/LOViewPage.qml'
133--- src/app/qml/loView/LOViewPage.qml 2016-01-29 12:12:54 +0000
134+++ src/app/qml/loView/LOViewPage.qml 2016-02-03 14:19:17 +0000
135@@ -32,7 +32,7 @@
136 property bool isTextDocument: loPage.contentItem && (loPage.contentItem.loDocument.documentType === LibreOffice.Document.TextDocument)
137 property bool isSpreadsheet: loPage.contentItem && (loPage.contentItem.loDocument.documentType === LibreOffice.Document.SpreadsheetDocument)
138
139- title: DocumentViewer.getFileBaseNameFromPath(file.path);
140+ title: FileUtils.getFileBaseNameFromPath(file.path);
141 flickable: isTextDocument ? loPage.contentItem.loView : null
142
143 splashScreen: Splashscreen { }
144
145=== modified file 'src/app/qml/pdfView/PdfPresentation.qml'
146--- src/app/qml/pdfView/PdfPresentation.qml 2016-01-23 12:34:25 +0000
147+++ src/app/qml/pdfView/PdfPresentation.qml 2016-02-03 14:19:17 +0000
148@@ -24,7 +24,7 @@
149 property var poppler
150 property bool isPresentation: true
151 anchors.fill: parent
152- title: DocumentViewer.getFileBaseNameFromPath(poppler.path)
153+ title: FileUtils.getFileBaseNameFromPath(poppler.path)
154 focus: true
155
156 header: PageHeader {
157
158=== modified file 'src/app/qml/pdfView/PdfView.qml'
159--- src/app/qml/pdfView/PdfView.qml 2016-01-29 12:23:24 +0000
160+++ src/app/qml/pdfView/PdfView.qml 2016-02-03 14:19:17 +0000
161@@ -26,7 +26,7 @@
162
163 Page {
164 id: pdfPage
165- title: DocumentViewer.getFileBaseNameFromPath(file.path)
166+ title: FileUtils.getFileBaseNameFromPath(file.path)
167
168 header: PageHeader {
169 flickable: pdfView
170
171=== modified file 'src/app/qml/textView/TextView.qml'
172--- src/app/qml/textView/TextView.qml 2015-12-26 18:27:13 +0000
173+++ src/app/qml/textView/TextView.qml 2016-02-03 14:19:17 +0000
174@@ -23,7 +23,7 @@
175
176 Page {
177 id: textPage
178- title: DocumentViewer.getFileBaseNameFromPath(file.path)
179+ title: FileUtils.getFileBaseNameFromPath(file.path)
180
181 // Reset night mode shader settings when closing the page
182 // Component.onDestruction: mainView.nightModeEnabled = false
183
184=== modified file 'src/app/qml/ubuntu-docviewer-app.qml'
185--- src/app/qml/ubuntu-docviewer-app.qml 2016-01-14 13:07:09 +0000
186+++ src/app/qml/ubuntu-docviewer-app.qml 2016-02-03 14:19:17 +0000
187@@ -80,7 +80,7 @@
188 onIsLandscapeChanged: {
189 // If device orientation is landscape and screen width is limited,
190 // force hiding Unity 8 indicators panel.
191- if (!DocumentViewer.desktopMode && mainView.isLandscape &&
192+ if (!ConvergenceUtils.desktopMode && mainView.isLandscape &&
193 mainView.width < units.gu(51)) {
194 mainView.fullscreen = true
195 return;
196@@ -202,6 +202,13 @@
197 }
198 }
199
200+ // WORKAROUND: Not yet implemented in the SDK
201+ Binding {
202+ target: QuickUtils
203+ property: "mouseAttached"
204+ value: ConvergenceUtils.mouseAttached
205+ }
206+
207 property bool nightModeEnabled: false
208 layer.effect: NightModeShader {}
209 layer.enabled: nightModeEnabled && (pageStack.depth > 1) && !pageStack.currentPage.isPresentation
210
211=== modified file 'src/plugin/file-qml-plugin/CMakeLists.txt'
212--- src/plugin/file-qml-plugin/CMakeLists.txt 2015-10-21 13:16:12 +0000
213+++ src/plugin/file-qml-plugin/CMakeLists.txt 2016-02-03 14:19:17 +0000
214@@ -1,23 +1,48 @@
215+# This includes a temporary snapshot of the WIP QInputInfo API as we
216+# require this in docviewer now but upstream isn't finished yet.
217+# Eventually this should be dropped in favor of the upstream
218+# QInputInfo API.
219+
220 set(PLUGIN_DIR DocumentViewer)
221-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
222
223 find_package(Qt5Core)
224 find_package(Qt5Qml)
225 find_package(Qt5Quick)
226
227+pkg_check_modules(LIBUDEV REQUIRED libudev)
228+pkg_check_modules(LIBEVDEV REQUIRED libevdev)
229+
230+include_directories(
231+ ${CMAKE_CURRENT_SOURCE_DIR}
232+ ${LIBUDEV_INCLUDE_DIRS}
233+ ${LIBEVDEV_INCLUDE_DIRS}
234+ InputInfo/
235+)
236+
237+# QInputInfo sources
238+set(inputinfo_SRCS
239+ InputInfo/qinputinfo.cpp
240+ InputInfo/qinputinfo.h
241+ InputInfo/linux/qinputdeviceinfo_linux.cpp
242+ InputInfo/linux/qinputdeviceinfo_linux_p.h
243+)
244+
245 #add the sources to compile
246 set(fileqmlplugin_SRCS
247 backend.cpp
248 documentmodel.cpp
249 fswatcher.cpp
250 docviewerfile.cpp
251- docviewerutils.cpp
252+ fileutils.cpp
253+ ubuntuconvergenceutils.cpp
254 )
255
256 add_library(fileqmlplugin MODULE
257+ ${inputinfo_SRCS}
258 ${fileqmlplugin_SRCS}
259 )
260
261+target_link_libraries(fileqmlplugin ${LIBUDEV_LDFLAGS} ${LIBEVDEV_LDFLAGS} )
262 qt5_use_modules(fileqmlplugin Qml Quick)
263
264 # Copy the plugin, the qmldir file and other assets to the build dir for running in QtCreator
265
266=== added directory 'src/plugin/file-qml-plugin/InputInfo'
267=== added file 'src/plugin/file-qml-plugin/InputInfo/CMakeLists.txt'
268--- src/plugin/file-qml-plugin/InputInfo/CMakeLists.txt 1970-01-01 00:00:00 +0000
269+++ src/plugin/file-qml-plugin/InputInfo/CMakeLists.txt 2016-02-03 14:19:17 +0000
270@@ -0,0 +1,39 @@
271+# This is a temporary snapshot of the WIP QInputInfo API as we
272+# require this in unity now but upstream isn't finished yet.
273+# Eventually this should be dropped in favor of the upstream
274+# QInputInfo API.
275+
276+project(InputInfo)
277+
278+find_package(Qt5Core REQUIRED)
279+find_package(Qt5Quick REQUIRED)
280+
281+pkg_check_modules(LIBUDEV REQUIRED libudev)
282+pkg_check_modules(LIBEVDEV REQUIRED libevdev)
283+
284+include_directories(
285+ ${CMAKE_CURRENT_SOURCE_DIR}
286+ ${CMAKE_CURRENT_BINARY_DIR}
287+ ${LIBUDEV_INCLUDE_DIRS}
288+ ${LIBEVDEV_INCLUDE_DIRS}
289+)
290+
291+set(InputInfo_SOURCES
292+ plugin.cpp
293+ qinputinfo.cpp
294+ qdeclarativeinputdevicemodel.cpp
295+ linux/qinputdeviceinfo_linux.cpp
296+)
297+
298+add_library(InputInfo SHARED
299+ ${InputInfo_SOURCES}
300+)
301+
302+target_link_libraries(InputInfo
303+ ${LIBUDEV_LDFLAGS}
304+ ${LIBEVDEV_LDFLAGS}
305+)
306+
307+qt5_use_modules(InputInfo Core Qml Quick)
308+
309+add_unity8_plugin(Unity.InputInfo 0.1 Unity/InputInfo TARGETS InputInfo)
310
311=== added directory 'src/plugin/file-qml-plugin/InputInfo/linux'
312=== added file 'src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux.cpp'
313--- src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux.cpp 1970-01-01 00:00:00 +0000
314+++ src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux.cpp 2016-02-03 14:19:17 +0000
315@@ -0,0 +1,288 @@
316+/****************************************************************************
317+**
318+** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies).
319+** Contact: http://www.qt-project.org/legal
320+**
321+** This file is part of the QtSystems module of the Qt Toolkit.
322+**
323+** $QT_BEGIN_LICENSE:LGPL$
324+** Commercial License Usage
325+** Licensees holding valid commercial Qt licenses may use this file in
326+** accordance with the commercial license agreement provided with the
327+** Software or, alternatively, in accordance with the terms contained in
328+** a written agreement between you and Digia. For licensing terms and
329+** conditions see http://qt.digia.com/licensing. For further information
330+** use the contact form at http://qt.digia.com/contact-us.
331+**
332+** GNU Lesser General Public License Usage
333+** Alternatively, this file may be used under the terms of the GNU Lesser
334+** General Public License version 2.1 as published by the Free Software
335+** Foundation and appearing in the file LICENSE.LGPL included in the
336+** packaging of this file. Please review the following information to
337+** ensure the GNU Lesser General Public License version 2.1 requirements
338+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
339+**
340+** In addition, as a special exception, Digia gives you certain additional
341+** rights. These rights are described in the Digia Qt LGPL Exception
342+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
343+**
344+** GNU General Public License Usage
345+** Alternatively, this file may be used under the terms of the GNU
346+** General Public License version 3.0 as published by the Free Software
347+** Foundation and appearing in the file LICENSE.GPL included in the
348+** packaging of this file. Please review the following information to
349+** ensure the GNU General Public License version 3.0 requirements will be
350+** met: http://www.gnu.org/copyleft/gpl.html.
351+**
352+**
353+** $QT_END_LICENSE$
354+**
355+****************************************************************************/
356+
357+#include "qinputdeviceinfo_linux_p.h"
358+
359+#include <libudev.h>
360+#include <libevdev/libevdev.h>
361+#include <fcntl.h>
362+#include <QDebug>
363+#include <QSocketNotifier>
364+#include <QTimer>
365+#include <QDir>
366+
367+QInputDeviceManagerPrivate::QInputDeviceManagerPrivate(QObject *parent) :
368+ QObject(parent),
369+ currentFilter(QInputDevice::Unknown),
370+ udevice(0)
371+{
372+ QTimer::singleShot(250,this,SLOT(init()));
373+}
374+
375+QInputDeviceManagerPrivate::~QInputDeviceManagerPrivate()
376+{
377+ udev_unref(udevice);
378+ udev_monitor_unref(udevMonitor);
379+}
380+
381+void QInputDeviceManagerPrivate::init()
382+{
383+ if (!udevice)
384+ udevice = udev_new();
385+
386+ udev_list_entry *devices;
387+ udev_list_entry *dev_list_entry;
388+ udev_device *dev;
389+
390+ QString subsystem = QStringLiteral("input");
391+ struct udev_enumerate *enumerate = 0;
392+
393+ if (udevice) {
394+
395+ udevMonitor = udev_monitor_new_from_netlink(udevice, "udev");
396+ udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, subsystem.toLatin1(), NULL);
397+ enumerate = udev_enumerate_new(udevice);
398+ udev_enumerate_add_match_subsystem(enumerate, subsystem.toLatin1());
399+
400+ udev_monitor_enable_receiving(udevMonitor);
401+ notifierFd = udev_monitor_get_fd(udevMonitor);
402+
403+ notifier = new QSocketNotifier(notifierFd, QSocketNotifier::Read, this);
404+ connect(notifier, SIGNAL(activated(int)), this, SLOT(onUDevChanges()));
405+
406+ udev_enumerate_scan_devices(enumerate);
407+ devices = udev_enumerate_get_list_entry(enumerate);
408+
409+ udev_list_entry_foreach(dev_list_entry, devices) {
410+ const char *path;
411+ path = udev_list_entry_get_name(dev_list_entry);
412+
413+ dev = udev_device_new_from_syspath(udevice, path);
414+ if (qstrcmp(udev_device_get_subsystem(dev), "input") == 0 ) {
415+ QInputDevice *iDevice = addDevice(dev);
416+ if (iDevice && !iDevice->devicePath().isEmpty()) {
417+ deviceMap.insert(iDevice->devicePath(),iDevice);
418+ }
419+ }
420+ udev_device_unref(dev);
421+ }
422+ udev_enumerate_unref(enumerate);
423+ }
424+ // udev_unref(udevice);
425+ Q_FOREACH (const QString &devicePath, deviceMap.keys()) {
426+ Q_EMIT deviceAdded(devicePath);
427+ }
428+ Q_EMIT ready();
429+}
430+
431+QInputDevice::InputTypeFlags QInputDeviceManagerPrivate::getInputTypeFlags(struct udev_device *dev)
432+{
433+ QInputDevice::InputTypeFlags flags = QInputDevice::Unknown;
434+ if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEY"), "1") == 0 ) {
435+ flags |= QInputDevice::Button;
436+ }
437+ if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_MOUSE"), "1") == 0) {
438+ flags |= QInputDevice::Mouse;
439+ }
440+ if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD"), "1") == 0) {
441+ flags |= QInputDevice::TouchPad;
442+ }
443+ if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN"), "1") == 0
444+ || qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TABLET"), "1") == 0) {
445+ flags |= QInputDevice::TouchScreen;
446+ }
447+ if (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD"), "1") == 0 ) {
448+ flags |= QInputDevice::Keyboard;
449+ }
450+ if (!QString::fromLatin1(udev_device_get_property_value(dev, "SW")).isEmpty()) {
451+ flags |= QInputDevice::Switch;
452+ }
453+
454+ return flags;
455+}
456+
457+QInputDevice *QInputDeviceManagerPrivate::addDevice(struct udev_device *udev)
458+{
459+ QString eventPath = QString::fromLatin1(udev_device_get_sysname(udev));
460+
461+ if (eventPath.contains(QStringLiteral("event")))
462+ eventPath.prepend(QStringLiteral("/dev/input/"));
463+
464+ if (deviceMap.contains(eventPath)) {
465+ return Q_NULLPTR;
466+ }
467+ struct libevdev *dev = NULL;
468+ int fd;
469+ int rc = 1;
470+ QInputDevice *inputDevice;
471+ inputDevice = addUdevDevice(udev);
472+ if (!inputDevice) {
473+ return Q_NULLPTR;
474+ }
475+ eventPath = inputDevice->devicePath();
476+
477+ fd = open(eventPath.toLatin1(), O_RDONLY|O_NONBLOCK);
478+ if (fd == -1) {
479+ return inputDevice;
480+ }
481+ rc = libevdev_new_from_fd(fd, &dev);
482+ if (rc < 0) {
483+ qWarning() << "Failed to init libevdev ("<< strerror(-rc) << ")";
484+ return Q_NULLPTR;
485+ }
486+
487+ for (int i = 0; i < EV_MAX; i++) {
488+ if (i == EV_KEY || i == EV_SW || i == EV_REL
489+ || i == EV_REL || i == EV_ABS) {
490+ for (int j = 0; j < libevdev_event_type_get_max(i); j++) {
491+ if (libevdev_has_event_code(dev, i, j)) {
492+ switch (i) {
493+ case EV_KEY:
494+ inputDevice->addButton(j);
495+ break;
496+ case EV_SW:
497+ inputDevice->addSwitch(j);
498+ break;
499+ case EV_REL:
500+ inputDevice->addRelativeAxis(j);
501+ break;
502+ case EV_ABS:
503+ inputDevice->addAbsoluteAxis(j);
504+ break;
505+ };
506+ }
507+ }
508+ }
509+ }
510+
511+ return inputDevice;
512+}
513+
514+void QInputDeviceManagerPrivate::addDetails(struct udev_device *)
515+{
516+}
517+
518+void QInputDeviceManagerPrivate::removeDevice(const QString &path)
519+{
520+ // this path is not a full evdev path
521+ Q_FOREACH (const QString devicePath, deviceMap.keys()) {
522+ if (devicePath.contains(path)) {
523+ deviceMap.remove(devicePath);
524+ Q_EMIT deviceRemoved(devicePath);
525+ }
526+ }
527+}
528+
529+QInputDevice *QInputDeviceManagerPrivate::addUdevDevice(struct udev_device *udev)
530+{
531+ QInputDevice *iDevice;
532+
533+ struct udev_list_entry *list;
534+ struct udev_list_entry *node;
535+
536+ list = udev_device_get_properties_list_entry (udev);
537+ QString syspath = QString::fromLatin1(udev_device_get_syspath(udev));
538+ QDir sysdir(syspath);
539+
540+ QStringList infoList = sysdir.entryList(QStringList() << QStringLiteral("event*"),QDir::Dirs);
541+
542+ if (infoList.count() > 0) {
543+ QString token = infoList.at(0);
544+
545+ token.prepend(QStringLiteral("/dev/input/"));
546+ iDevice = new QInputDevice(this);
547+ iDevice->setDevicePath(token);
548+ } else {
549+ return Q_NULLPTR;
550+ }
551+ udev_list_entry_foreach (node, list) {
552+
553+ QString key = QString::fromLatin1(udev_list_entry_get_name(node));
554+ QString value = QString::fromLatin1(udev_list_entry_get_value(node));
555+
556+ if (key == QStringLiteral("NAME")) {
557+ iDevice->setName(value.remove(QStringLiteral("\"")));
558+ }
559+ }
560+ iDevice->setType(getInputTypeFlags(udev));
561+ return iDevice;
562+}
563+
564+void QInputDeviceManagerPrivate::onUDevChanges()
565+{
566+ if (!udevMonitor)
567+ return;
568+
569+ udev_device *dev = udev_monitor_receive_device(udevMonitor);
570+
571+ if (dev) {
572+ if (qstrcmp(udev_device_get_subsystem(dev), "input") == 0 ) {
573+ QString eventPath = QString::fromLatin1(udev_device_get_sysname(dev));
574+
575+ QString action = QString::fromStdString(udev_device_get_action(dev));
576+
577+ if (!eventPath.contains(QStringLiteral("/dev/input/")))
578+ eventPath.prepend(QStringLiteral("/dev/input/"));
579+
580+ if (action == QStringLiteral("add")) {
581+ if (deviceMap.contains(eventPath)){
582+ udev_device_unref(dev);
583+ return;
584+ }
585+
586+ QInputDevice *iDevice = addDevice(dev);
587+ if (!iDevice) {
588+ delete iDevice;
589+ return;
590+ }
591+ iDevice->setType(getInputTypeFlags(dev));
592+ udev_device_unref(dev);
593+
594+ deviceMap.insert(eventPath,iDevice);
595+
596+ Q_EMIT deviceAdded(eventPath);
597+
598+ } else if (action == QStringLiteral("remove")) {
599+ removeDevice(eventPath);
600+ }
601+ }
602+ }
603+}
604
605=== added file 'src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux_p.h'
606--- src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux_p.h 1970-01-01 00:00:00 +0000
607+++ src/plugin/file-qml-plugin/InputInfo/linux/qinputdeviceinfo_linux_p.h 2016-02-03 14:19:17 +0000
608@@ -0,0 +1,98 @@
609+/****************************************************************************
610+**
611+** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies).
612+** Contact: http://www.qt-project.org/legal
613+**
614+** This file is part of the QtSystems module of the Qt Toolkit.
615+**
616+** $QT_BEGIN_LICENSE:LGPL$
617+** Commercial License Usage
618+** Licensees holding valid commercial Qt licenses may use this file in
619+** accordance with the commercial license agreement provided with the
620+** Software or, alternatively, in accordance with the terms contained in
621+** a written agreement between you and Digia. For licensing terms and
622+** conditions see http://qt.digia.com/licensing. For further information
623+** use the contact form at http://qt.digia.com/contact-us.
624+**
625+** GNU Lesser General Public License Usage
626+** Alternatively, this file may be used under the terms of the GNU Lesser
627+** General Public License version 2.1 as published by the Free Software
628+** Foundation and appearing in the file LICENSE.LGPL included in the
629+** packaging of this file. Please review the following information to
630+** ensure the GNU Lesser General Public License version 2.1 requirements
631+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
632+**
633+** In addition, as a special exception, Digia gives you certain additional
634+** rights. These rights are described in the Digia Qt LGPL Exception
635+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
636+**
637+** GNU General Public License Usage
638+** Alternatively, this file may be used under the terms of the GNU
639+** General Public License version 3.0 as published by the Free Software
640+** Foundation and appearing in the file LICENSE.GPL included in the
641+** packaging of this file. Please review the following information to
642+** ensure the GNU General Public License version 3.0 requirements will be
643+** met: http://www.gnu.org/copyleft/gpl.html.
644+**
645+**
646+** $QT_END_LICENSE$
647+**
648+****************************************************************************/
649+
650+#ifndef QINPUTDEVICEINFO_LINUX_P_H
651+#define QINPUTDEVICEINFO_LINUX_P_H
652+
653+#include <QObject>
654+#include "qinputinfo.h"
655+#include <libudev.h>
656+
657+class QInputDevicePrivate : public QObject
658+{
659+ Q_OBJECT
660+public:
661+ explicit QInputDevicePrivate(QObject *parent = 0);
662+
663+ QString name;
664+ QString devicePath;
665+ QList <int> buttons; //keys
666+ QList <int> switches;
667+ QList <int> relativeAxis;
668+ QList <int> absoluteAxis;
669+ QInputDevice::InputTypeFlags type;
670+};
671+
672+class QInputDeviceManagerPrivate : public QObject
673+{
674+ Q_OBJECT
675+public:
676+ explicit QInputDeviceManagerPrivate(QObject *parent = 0);
677+ ~QInputDeviceManagerPrivate();
678+ QVector <QInputDevice *> deviceList;
679+ QMap <QString, QInputDevice *> deviceMap;
680+ static QInputDeviceManagerPrivate * instance();
681+ QInputDevice::InputType currentFilter;
682+
683+Q_SIGNALS:
684+ void deviceAdded(const QString &);
685+ void deviceRemoved(const QString &);
686+ void ready();
687+
688+private:
689+ QInputDevice *addDevice(struct udev_device *udev);
690+ QInputDevice *addUdevDevice(struct udev_device *);
691+
692+ QInputDevice *addDevice(const QString &path);
693+ void removeDevice(const QString &path);
694+ QSocketNotifier *notifier;
695+ int notifierFd;
696+ struct udev_monitor *udevMonitor;
697+ QInputDevice::InputTypeFlags getInputTypeFlags(struct udev_device *);
698+ struct udev *udevice;
699+ void addDetails(struct udev_device *);
700+
701+private Q_SLOTS:
702+ void onUDevChanges();
703+ void init();
704+};
705+
706+#endif // QINPUTDEVICEINFO_LINUX_P_H
707
708=== added file 'src/plugin/file-qml-plugin/InputInfo/plugin.cpp'
709--- src/plugin/file-qml-plugin/InputInfo/plugin.cpp 1970-01-01 00:00:00 +0000
710+++ src/plugin/file-qml-plugin/InputInfo/plugin.cpp 2016-02-03 14:19:17 +0000
711@@ -0,0 +1,32 @@
712+/*
713+ * Copyright 2015 Canonical Ltd.
714+ *
715+ * This program is free software; you can redistribute it and/or modify
716+ * it under the terms of the GNU Lesser General Public License as published by
717+ * the Free Software Foundation; version 3.
718+ *
719+ * This program is distributed in the hope that it will be useful,
720+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
721+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
722+ * GNU Lesser General Public License for more details.
723+ *
724+ * You should have received a copy of the GNU Lesser General Public License
725+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
726+ */
727+
728+// Qt
729+#include <QtQml/qqml.h>
730+
731+// self
732+#include "plugin.h"
733+
734+// local
735+#include "qdeclarativeinputdevicemodel_p.h"
736+
737+void InputInfoPlugin::registerTypes(const char *uri)
738+{
739+ int major = 0;
740+ int minor = 1;
741+ qmlRegisterType<QDeclarativeInputDeviceModel>(uri, major, minor, "InputDeviceModel");
742+ qmlRegisterType<QInputDevice>(uri, major, minor, "InputInfo");
743+}
744
745=== added file 'src/plugin/file-qml-plugin/InputInfo/plugin.h'
746--- src/plugin/file-qml-plugin/InputInfo/plugin.h 1970-01-01 00:00:00 +0000
747+++ src/plugin/file-qml-plugin/InputInfo/plugin.h 2016-02-03 14:19:17 +0000
748@@ -0,0 +1,30 @@
749+/*
750+ * Copyright 2015 Canonical Ltd.
751+ *
752+ * This program is free software; you can redistribute it and/or modify
753+ * it under the terms of the GNU Lesser General Public License as published by
754+ * the Free Software Foundation; version 3.
755+ *
756+ * This program is distributed in the hope that it will be useful,
757+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
758+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
759+ * GNU Lesser General Public License for more details.
760+ *
761+ * You should have received a copy of the GNU Lesser General Public License
762+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
763+ */
764+
765+#ifndef INPUTINFO_PLUGIN_H
766+#define INPUTINFO_PLUGIN_H
767+
768+#include <QtQml/QQmlExtensionPlugin>
769+
770+class InputInfoPlugin : public QQmlExtensionPlugin
771+{
772+ Q_OBJECT
773+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface")
774+public:
775+ void registerTypes(const char *uri);
776+};
777+
778+#endif // INPUTINFO_PLUGIN_H
779
780=== added file 'src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel.cpp'
781--- src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel.cpp 1970-01-01 00:00:00 +0000
782+++ src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel.cpp 2016-02-03 14:19:17 +0000
783@@ -0,0 +1,196 @@
784+/****************************************************************************
785+**
786+** Copyright (C) 2015 Jolla.
787+** Contact: http://www.qt-project.org/legal
788+**
789+** This file is part of the QtSystems module of the Qt Toolkit.
790+**
791+** $QT_BEGIN_LICENSE:LGPL$
792+** Commercial License Usage
793+** Licensees holding valid commercial Qt licenses may use this file in
794+** accordance with the commercial license agreement provided with the
795+** Software or, alternatively, in accordance with the terms contained in
796+** a written agreement between you and Digia. For licensing terms and
797+** conditions see http://qt.digia.com/licensing. For further information
798+** use the contact form at http://qt.digia.com/contact-us.
799+**
800+** GNU Lesser General Public License Usage
801+** Alternatively, this file may be used under the terms of the GNU Lesser
802+** General Public License version 2.1 as published by the Free Software
803+** Foundation and appearing in the file LICENSE.LGPL included in the
804+** packaging of this file. Please review the following information to
805+** ensure the GNU Lesser General Public License version 2.1 requirements
806+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
807+**
808+** In addition, as a special exception, Digia gives you certain additional
809+** rights. These rights are described in the Digia Qt LGPL Exception
810+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
811+**
812+** GNU General Public License Usage
813+** Alternatively, this file may be used under the terms of the GNU
814+** General Public License version 3.0 as published by the Free Software
815+** Foundation and appearing in the file LICENSE.GPL included in the
816+** packaging of this file. Please review the following information to
817+** ensure the GNU General Public License version 3.0 requirements will be
818+** met: http://www.gnu.org/copyleft/gpl.html.
819+**
820+**
821+** $QT_END_LICENSE$
822+**
823+****************************************************************************/
824+#include "qdeclarativeinputdevicemodel_p.h"
825+#include "qinputinfo.h"
826+
827+QDeclarativeInputDeviceModel::QDeclarativeInputDeviceModel(QObject *parent) :
828+ QAbstractListModel(parent),
829+ deviceInfo(new QInputDeviceManager),
830+ currentFilter(QInputDevice::Unknown)
831+{
832+ connect(deviceInfo,SIGNAL(ready()),this,SLOT(updateDeviceList()));
833+ connect(deviceInfo, &QInputDeviceManager::deviceAdded,this,&QDeclarativeInputDeviceModel::addedDevice);
834+ connect(deviceInfo, &QInputDeviceManager::deviceRemoved,this,&QDeclarativeInputDeviceModel::removedDevice);
835+}
836+
837+QDeclarativeInputDeviceModel::~QDeclarativeInputDeviceModel()
838+{
839+ delete deviceInfo;
840+}
841+
842+QVariant QDeclarativeInputDeviceModel::data(const QModelIndex &index, int role) const
843+{
844+ switch (role) {
845+ case ServiceRole:
846+ return QVariant::fromValue(static_cast<QObject *>(inputDevices.value(index.row())));
847+ break;
848+ case NameRole:
849+ return QVariant::fromValue(static_cast<QString>(inputDevices.value(index.row())->name()));
850+ break;
851+ case DevicePathRole:
852+ return QVariant::fromValue(static_cast<QString>(inputDevices.value(index.row())->devicePath()));
853+ break;
854+ case ButtonsRole:
855+ return QVariant::fromValue(static_cast<QList <int> >(inputDevices.value(index.row())->buttons()));
856+ break;
857+ case SwitchesRole:
858+ return QVariant::fromValue(static_cast<QList <int> >(inputDevices.value(index.row())->switches()));
859+ break;
860+ case RelativeAxisRole:
861+ return QVariant::fromValue(static_cast<QList <int> >(inputDevices.value(index.row())->relativeAxis()));
862+ break;
863+ case AbsoluteAxisRole:
864+ return QVariant::fromValue(static_cast<QList <int> >(inputDevices.value(index.row())->absoluteAxis()));
865+ break;
866+ case TypesRole:
867+ return QVariant::fromValue(static_cast<int>(inputDevices.value(index.row())->type()));
868+ break;
869+ };
870+
871+ return QVariant();
872+}
873+
874+int QDeclarativeInputDeviceModel::rowCount(const QModelIndex &parent) const
875+{
876+ Q_UNUSED(parent);
877+
878+ return inputDevices.count();
879+}
880+
881+int QDeclarativeInputDeviceModel::indexOf(const QString &devicePath) const
882+{
883+ int idx(-1);
884+ Q_FOREACH (QInputDevice *device, inputDevices) {
885+ idx++;
886+ if (device->devicePath() == devicePath) return idx;
887+ }
888+
889+ return -1;
890+}
891+
892+QInputDevice *QDeclarativeInputDeviceModel::get(int index) const
893+{
894+ if (index < 0 || index > inputDevices.count())
895+ return 0;
896+ return inputDevices.value(index);
897+}
898+
899+void QDeclarativeInputDeviceModel::updateDeviceList()
900+{
901+ QVector <QInputDevice *> newDevices = deviceInfo->deviceListOfType(currentFilter);
902+
903+ int numNew = newDevices.count();
904+
905+ for (int i = 0; i < numNew; i++) {
906+ int j = inputDevices.indexOf(newDevices.value(i));
907+
908+ if (j == -1) {
909+ beginInsertRows(QModelIndex(), i, i);
910+ inputDevices.insert(i, newDevices.value(i));
911+ endInsertRows();
912+ Q_EMIT countChanged();
913+ } else if (i != j) {
914+ // changed its position -> move it
915+ QInputDevice* device = inputDevices.value(j);
916+ beginMoveRows(QModelIndex(), j, j, QModelIndex(), i);
917+ inputDevices.remove(j);
918+ inputDevices.insert(i, device);
919+ endMoveRows();
920+ Q_EMIT countChanged();
921+ } //else {
922+ QModelIndex changedIndex(this->index(j, 0, QModelIndex()));
923+ Q_EMIT dataChanged(changedIndex, changedIndex);
924+ }
925+
926+ int numOld = inputDevices.count();
927+ if (numOld > numNew) {
928+ beginRemoveRows(QModelIndex(), numNew, numOld - 1);
929+ inputDevices.remove(numNew, numOld - numNew);
930+ endRemoveRows();
931+ Q_EMIT countChanged();
932+ }
933+}
934+
935+void QDeclarativeInputDeviceModel::addedDevice(const QString &devicePath)
936+{
937+ updateDeviceList();
938+ Q_EMIT deviceAdded(devicePath);
939+}
940+
941+void QDeclarativeInputDeviceModel::removedDevice(const QString &devicePath)
942+{
943+ updateDeviceList();
944+ Q_EMIT deviceRemoved(devicePath);
945+}
946+
947+QHash<int,QByteArray> QDeclarativeInputDeviceModel::roleNames() const
948+{
949+ QHash<int, QByteArray> roles;
950+ roles[NameRole] = "name";
951+ roles[DevicePathRole] = "devicePath";
952+ roles[ButtonsRole] = "buttons";
953+ roles[SwitchesRole] = "switches";
954+ roles[RelativeAxisRole] = "rAxis";
955+ roles[AbsoluteAxisRole] = "aAxis";
956+ roles[TypesRole] = "types";
957+ return roles;
958+}
959+
960+/*
961+ * Returns the currently set device filter.
962+ * */
963+QInputDevice::InputType QDeclarativeInputDeviceModel::deviceFilter()
964+{
965+ return currentFilter;
966+}
967+
968+/*
969+ * Sets the current input device filter to filter.
970+ * */
971+void QDeclarativeInputDeviceModel::setDeviceFilter(QInputDevice::InputType filter)
972+{
973+ if (filter != currentFilter) {
974+ deviceInfo->setDeviceFilter(filter);
975+ currentFilter = filter;
976+ updateDeviceList();
977+ Q_EMIT deviceFilterChanged(filter);
978+ }
979+}
980
981=== added file 'src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel_p.h'
982--- src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel_p.h 1970-01-01 00:00:00 +0000
983+++ src/plugin/file-qml-plugin/InputInfo/qdeclarativeinputdevicemodel_p.h 2016-02-03 14:19:17 +0000
984@@ -0,0 +1,102 @@
985+/****************************************************************************
986+**
987+** Copyright (C) 2015 Jolla.
988+** Contact: http://www.qt-project.org/legal
989+**
990+** This file is part of the QtSystems module of the Qt Toolkit.
991+**
992+** $QT_BEGIN_LICENSE:LGPL$
993+** Commercial License Usage
994+** Licensees holding valid commercial Qt licenses may use this file in
995+** accordance with the commercial license agreement provided with the
996+** Software or, alternatively, in accordance with the terms contained in
997+** a written agreement between you and Digia. For licensing terms and
998+** conditions see http://qt.digia.com/licensing. For further information
999+** use the contact form at http://qt.digia.com/contact-us.
1000+**
1001+** GNU Lesser General Public License Usage
1002+** Alternatively, this file may be used under the terms of the GNU Lesser
1003+** General Public License version 2.1 as published by the Free Software
1004+** Foundation and appearing in the file LICENSE.LGPL included in the
1005+** packaging of this file. Please review the following information to
1006+** ensure the GNU Lesser General Public License version 2.1 requirements
1007+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
1008+**
1009+** In addition, as a special exception, Digia gives you certain additional
1010+** rights. These rights are described in the Digia Qt LGPL Exception
1011+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
1012+**
1013+** GNU General Public License Usage
1014+** Alternatively, this file may be used under the terms of the GNU
1015+** General Public License version 3.0 as published by the Free Software
1016+** Foundation and appearing in the file LICENSE.GPL included in the
1017+** packaging of this file. Please review the following information to
1018+** ensure the GNU General Public License version 3.0 requirements will be
1019+** met: http://www.gnu.org/copyleft/gpl.html.
1020+**
1021+**
1022+** $QT_END_LICENSE$
1023+**
1024+****************************************************************************/
1025+
1026+#ifndef QDECLARATIVEINPUTDEVICEMODEL_H
1027+#define QDECLARATIVEINPUTDEVICEMODEL_H
1028+
1029+#include <QObject>
1030+#include <QAbstractListModel>
1031+#include "qinputinfo.h"
1032+
1033+class QDeclarativeInputDeviceModel : public QAbstractListModel
1034+{
1035+ Q_OBJECT
1036+ Q_DISABLE_COPY(QDeclarativeInputDeviceModel)
1037+ Q_PROPERTY(QInputDevice::InputType deviceFilter READ deviceFilter WRITE setDeviceFilter NOTIFY deviceFilterChanged)
1038+
1039+ Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
1040+
1041+public:
1042+ enum ItemRoles {
1043+ ServiceRole = Qt::UserRole + 1,
1044+ NameRole,
1045+ DevicePathRole,
1046+ ButtonsRole,
1047+ SwitchesRole,
1048+ RelativeAxisRole,
1049+ AbsoluteAxisRole,
1050+ TypesRole
1051+ };
1052+
1053+ explicit QDeclarativeInputDeviceModel(QObject *parent = 0);
1054+ virtual ~QDeclarativeInputDeviceModel();
1055+
1056+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
1057+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
1058+
1059+ void setDeviceFilter(QInputDevice::InputType filter);
1060+ QInputDevice::InputType deviceFilter();
1061+
1062+ Q_INVOKABLE int indexOf(const QString &devicePath) const;
1063+
1064+ Q_INVOKABLE QInputDevice *get(int index) const;
1065+ QHash<int, QByteArray> roleNames() const;
1066+
1067+Q_SIGNALS:
1068+ void deviceAdded(const QString &devicePath);
1069+ void deviceRemoved(const QString &devicePath);
1070+ void deviceFilterChanged(const QInputDevice::InputType filter);
1071+ void countChanged();
1072+
1073+public Q_SLOTS:
1074+ void updateDeviceList();
1075+private:
1076+ QInputDeviceManager *deviceInfo;
1077+ QVector<QInputDevice *> inputDevices;
1078+ QInputDevice::InputType currentFilter;
1079+
1080+private Q_SLOTS:
1081+ void addedDevice(const QString &);
1082+ void removedDevice(const QString &path);
1083+
1084+};
1085+
1086+#endif // QDECLARATIVEINPUTDEVICEMODEL_H
1087
1088=== added file 'src/plugin/file-qml-plugin/InputInfo/qinputinfo.cpp'
1089--- src/plugin/file-qml-plugin/InputInfo/qinputinfo.cpp 1970-01-01 00:00:00 +0000
1090+++ src/plugin/file-qml-plugin/InputInfo/qinputinfo.cpp 2016-02-03 14:19:17 +0000
1091@@ -0,0 +1,270 @@
1092+/****************************************************************************
1093+**
1094+** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies).
1095+** Contact: http://www.qt-project.org/legal
1096+**
1097+** This file is part of the QtSystems module of the Qt Toolkit.
1098+**
1099+** $QT_BEGIN_LICENSE:LGPL$
1100+** Commercial License Usage
1101+** Licensees holding valid commercial Qt licenses may use this file in
1102+** accordance with the commercial license agreement provided with the
1103+** Software or, alternatively, in accordance with the terms contained in
1104+** a written agreement between you and Digia. For licensing terms and
1105+** conditions see http://qt.digia.com/licensing. For further information
1106+** use the contact form at http://qt.digia.com/contact-us.
1107+**
1108+** GNU Lesser General Public License Usage
1109+** Alternatively, this file may be used under the terms of the GNU Lesser
1110+** General Public License version 2.1 as published by the Free Software
1111+** Foundation and appearing in the file LICENSE.LGPL included in the
1112+** packaging of this file. Please review the following information to
1113+** ensure the GNU Lesser General Public License version 2.1 requirements
1114+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
1115+**
1116+** In addition, as a special exception, Digia gives you certain additional
1117+** rights. These rights are described in the Digia Qt LGPL Exception
1118+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
1119+**
1120+** GNU General Public License Usage
1121+** Alternatively, this file may be used under the terms of the GNU
1122+** General Public License version 3.0 as published by the Free Software
1123+** Foundation and appearing in the file LICENSE.GPL included in the
1124+** packaging of this file. Please review the following information to
1125+** ensure the GNU General Public License version 3.0 requirements will be
1126+** met: http://www.gnu.org/copyleft/gpl.html.
1127+**
1128+**
1129+** $QT_END_LICENSE$
1130+**
1131+****************************************************************************/
1132+
1133+#include "qinputinfo.h"
1134+
1135+#if defined(UNITY_MOCKS)
1136+#include "qinputdeviceinfo_mock_p.h"
1137+#elif defined(Q_OS_LINUX)
1138+#include "linux/qinputdeviceinfo_linux_p.h"
1139+#endif
1140+
1141+Q_GLOBAL_STATIC(QInputDeviceManagerPrivate, inputDeviceManagerPrivate)
1142+
1143+QT_BEGIN_NAMESPACE
1144+
1145+QInputDeviceManagerPrivate * QInputDeviceManagerPrivate::instance()
1146+{
1147+ QInputDeviceManagerPrivate *priv = inputDeviceManagerPrivate();
1148+ return priv;
1149+}
1150+
1151+QInputDevicePrivate::QInputDevicePrivate(QObject *parent) :
1152+ QObject(parent),
1153+ type(QInputDevice::Unknown)
1154+{
1155+}
1156+
1157+QInputDevice::QInputDevice(QObject *parent) :
1158+ QObject(parent),
1159+ d_ptr(new QInputDevicePrivate(this))
1160+{
1161+}
1162+
1163+/*
1164+ * Returns the name of this input device.
1165+ */
1166+QString QInputDevice::name() const
1167+{
1168+ return d_ptr->name;
1169+}
1170+
1171+/*
1172+ * Sets the name of this input device to \b name.
1173+ */
1174+void QInputDevice::setName(const QString &name)
1175+{
1176+ d_ptr->name = name;
1177+}
1178+
1179+/*
1180+ * Returns the device path of this device.
1181+ */
1182+QString QInputDevice::devicePath() const
1183+{
1184+ return d_ptr->devicePath;
1185+}
1186+
1187+/*
1188+ * Sets the device ppath of this device to /b path.
1189+ */
1190+void QInputDevice::setDevicePath(const QString &path)
1191+{
1192+ d_ptr->devicePath = path;
1193+}
1194+
1195+/*
1196+ * Returns the number of buttons this device has.
1197+ */
1198+QList <int> QInputDevice::buttons() const
1199+{
1200+ return d_ptr->buttons;
1201+}
1202+
1203+/*
1204+ * Adds a button
1205+ */
1206+void QInputDevice::addButton(int buttonCode)
1207+{
1208+ d_ptr->buttons.append(buttonCode);
1209+}
1210+
1211+/*
1212+ * Returns the number of switch of this device.
1213+ */
1214+QList <int> QInputDevice::switches() const
1215+{
1216+ return d_ptr->switches;
1217+}
1218+
1219+/*
1220+ * Adds a switch
1221+ */
1222+void QInputDevice::addSwitch(int switchCode)
1223+{
1224+ d_ptr->switches.append(switchCode);
1225+}
1226+
1227+/*
1228+ * Returns a list of the relative axis of this device
1229+ */
1230+QList <int> QInputDevice::relativeAxis() const
1231+{
1232+ return d_ptr->relativeAxis;
1233+}
1234+
1235+/*
1236+ */
1237+void QInputDevice::addRelativeAxis(int axisCode)
1238+{
1239+ d_ptr->relativeAxis.append(axisCode);
1240+}
1241+
1242+/*
1243+ * Returns a list of the absolute axis of this device
1244+ */
1245+QList <int> QInputDevice::absoluteAxis() const
1246+{
1247+ return d_ptr->absoluteAxis;
1248+}
1249+
1250+/*
1251+ */
1252+void QInputDevice::addAbsoluteAxis(int axisCode)
1253+{
1254+ d_ptr->absoluteAxis.append(axisCode);
1255+}
1256+
1257+/*
1258+ * Returns a QInputDevice::InputTypeFlags of all the types of types.
1259+ */
1260+QInputDevice::InputTypeFlags QInputDevice::type() const
1261+{
1262+ return d_ptr->type;
1263+}
1264+
1265+/*
1266+ */
1267+void QInputDevice::setType(QInputDevice::InputTypeFlags type) //? setTypes?
1268+{
1269+ d_ptr->type = type;
1270+}
1271+
1272+QInputDeviceManager::QInputDeviceManager(QObject *parent) :
1273+ QObject(parent),
1274+ d_ptr(inputDeviceManagerPrivate)
1275+{
1276+ connect(d_ptr, &QInputDeviceManagerPrivate::deviceAdded,this,&QInputDeviceManager::addedDevice);
1277+ connect(d_ptr, &QInputDeviceManagerPrivate::deviceRemoved,this,&QInputDeviceManager::deviceRemoved);
1278+
1279+ connect(d_ptr,SIGNAL(ready()),this,SIGNAL(ready()));
1280+}
1281+
1282+/*
1283+ * Returns a QMap of known input devices.
1284+ */
1285+QMap <QString, QInputDevice *> QInputDeviceManager::deviceMap()
1286+{
1287+ return d_ptr->deviceMap;
1288+}
1289+
1290+/*
1291+ */
1292+void QInputDeviceManager::addedDevice(const QString & devicePath)
1293+{
1294+ Q_EMIT deviceAdded(devicePath);
1295+}
1296+
1297+/*
1298+ * Returns a QVector of InputDevices of type filter
1299+ * */
1300+QVector <QInputDevice *> QInputDeviceManager::deviceListOfType(QInputDevice::InputType filter)
1301+{
1302+ QVector <QInputDevice *> dList;
1303+ QMapIterator<QString, QInputDevice *> i(d_ptr->deviceMap);
1304+ while (i.hasNext()) {
1305+ i.next();
1306+ if (i.value()->type().testFlag(filter) || filter == QInputDevice::Unknown) {
1307+ dList.append(i.value());
1308+ }
1309+ }
1310+ return dList;
1311+}
1312+
1313+/*
1314+ * Returns the number of input devices with the currently set QInputDevice::InputType filter.
1315+ * If no device filter has been set, returns number of all available input devices.
1316+ * If filter has not been set, returns all available input devices
1317+ */
1318+int QInputDeviceManager::deviceCount() const
1319+{
1320+ return deviceCount(static_cast< QInputDevice::InputType >(d_ptr->currentFilter));
1321+}
1322+
1323+/*
1324+ * Returns the number of input devices of the type filter.
1325+ */
1326+int QInputDeviceManager::deviceCount(const QInputDevice::InputType filter) const
1327+{
1328+ int dList = 0;
1329+ QMapIterator<QString, QInputDevice *> i(d_ptr->deviceMap);
1330+ while (i.hasNext()) {
1331+ i.next();
1332+// qDebug() << i.value()->name() << i.value()->devicePath();
1333+// qDebug() << i.value()->type() << i.value()->type().testFlag(filter);
1334+
1335+ if (i.value()->type().testFlag(filter)) {
1336+ dList++;
1337+ }
1338+ }
1339+ return dList;
1340+}
1341+
1342+/*
1343+ * Returns the currently set device filter.
1344+ * */
1345+QInputDevice::InputType QInputDeviceManager::deviceFilter()
1346+{
1347+ return d_ptr->currentFilter;
1348+}
1349+
1350+/*
1351+ * Sets the current input device filter to filter.
1352+ * */
1353+void QInputDeviceManager::setDeviceFilter(QInputDevice::InputType filter)
1354+{
1355+ if (filter != d_ptr->currentFilter) {
1356+ d_ptr->currentFilter = filter;
1357+ Q_EMIT deviceFilterChanged(filter);
1358+ }
1359+}
1360+
1361+QT_END_NAMESPACE
1362
1363=== added file 'src/plugin/file-qml-plugin/InputInfo/qinputinfo.h'
1364--- src/plugin/file-qml-plugin/InputInfo/qinputinfo.h 1970-01-01 00:00:00 +0000
1365+++ src/plugin/file-qml-plugin/InputInfo/qinputinfo.h 2016-02-03 14:19:17 +0000
1366@@ -0,0 +1,143 @@
1367+/****************************************************************************
1368+**
1369+** Copyright (C) 2014 Canonical, Ltd. and/or its subsidiary(-ies).
1370+** Contact: http://www.qt-project.org/legal
1371+**
1372+** This file is part of the QtSystems module of the Qt Toolkit.
1373+**
1374+** $QT_BEGIN_LICENSE:LGPL$
1375+** Commercial License Usage
1376+** Licensees holding valid commercial Qt licenses may use this file in
1377+** accordance with the commercial license agreement provided with the
1378+** Software or, alternatively, in accordance with the terms contained in
1379+** a written agreement between you and Digia. For licensing terms and
1380+** conditions see http://qt.digia.com/licensing. For further information
1381+** use the contact form at http://qt.digia.com/contact-us.
1382+**
1383+** GNU Lesser General Public License Usage
1384+** Alternatively, this file may be used under the terms of the GNU Lesser
1385+** General Public License version 2.1 as published by the Free Software
1386+** Foundation and appearing in the file LICENSE.LGPL included in the
1387+** packaging of this file. Please review the following information to
1388+** ensure the GNU Lesser General Public License version 2.1 requirements
1389+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
1390+**
1391+** In addition, as a special exception, Digia gives you certain additional
1392+** rights. These rights are described in the Digia Qt LGPL Exception
1393+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
1394+**
1395+** GNU General Public License Usage
1396+** Alternatively, this file may be used under the terms of the GNU
1397+** General Public License version 3.0 as published by the Free Software
1398+** Foundation and appearing in the file LICENSE.GPL included in the
1399+** packaging of this file. Please review the following information to
1400+** ensure the GNU General Public License version 3.0 requirements will be
1401+** met: http://www.gnu.org/copyleft/gpl.html.
1402+**
1403+**
1404+** $QT_END_LICENSE$
1405+**
1406+****************************************************************************/
1407+
1408+#ifndef QINPUTINFO_H
1409+#define QINPUTINFO_H
1410+
1411+#include <QObject>
1412+#include <QVector>
1413+#include <QMap>
1414+#include <QSocketNotifier>
1415+#include <QDebug>
1416+
1417+class QInputDeviceManagerPrivate;
1418+class QInputDevicePrivate;
1419+class QInputDevice;
1420+
1421+class QInputDeviceManager;
1422+
1423+class QInputDevice : public QObject
1424+{
1425+ Q_OBJECT
1426+ Q_ENUMS(InputType)
1427+ Q_FLAGS(InputType InputTypeFlags)
1428+ friend class QInputDeviceManagerPrivate;
1429+
1430+public:
1431+
1432+ enum InputType {
1433+ Unknown = 0,
1434+ Button = 1,
1435+ Mouse = 2,
1436+ TouchPad = 4,
1437+ TouchScreen = 8,
1438+ Keyboard = 16,
1439+ Switch = 32
1440+ };
1441+ Q_ENUMS(InputType)
1442+ Q_DECLARE_FLAGS(InputTypeFlags, InputType)
1443+
1444+ explicit QInputDevice(QObject *parent = 0);
1445+ QString name() const;
1446+ QString devicePath() const;
1447+ QList <int> buttons() const; //keys event code
1448+ QList <int> switches() const;
1449+ QList <int> relativeAxis() const;
1450+ QList <int> absoluteAxis() const;
1451+ QInputDevice::InputTypeFlags type() const;
1452+
1453+private:
1454+
1455+ QInputDevicePrivate *d_ptr;
1456+ void setName(const QString &);
1457+ void setDevicePath(const QString &);
1458+ void addButton(int);
1459+ void addSwitch(int);
1460+ void addRelativeAxis(int);
1461+ void addAbsoluteAxis(int);
1462+ void setType(QInputDevice::InputTypeFlags flags);
1463+
1464+};
1465+
1466+Q_DECLARE_METATYPE(QInputDevice::InputType)
1467+Q_DECLARE_METATYPE(QInputDevice::InputTypeFlags)
1468+
1469+class QInputDeviceManagerPrivate;
1470+
1471+class QInputDeviceManager : public QObject
1472+{
1473+ Q_OBJECT
1474+ Q_PROPERTY(int deviceCount READ deviceCount NOTIFY deviceCountChanged)
1475+ Q_PROPERTY(QInputDevice::InputType deviceFilter READ deviceFilter WRITE setDeviceFilter NOTIFY deviceFilterChanged)
1476+public:
1477+
1478+ explicit QInputDeviceManager(QObject *parent = 0);
1479+
1480+ int deviceCount() const;
1481+ int deviceCount(const QInputDevice::InputType filter) const;
1482+
1483+ void setDeviceFilter(QInputDevice::InputType filter);
1484+ QInputDevice::InputType deviceFilter();
1485+
1486+ QMap <QString, QInputDevice *> deviceMap();
1487+ Q_INVOKABLE QVector <QInputDevice *> deviceListOfType(QInputDevice::InputType filter);
1488+
1489+Q_SIGNALS:
1490+
1491+ void deviceAdded(const QString & devicePath);
1492+ void deviceRemoved(const QString & devicePath);
1493+
1494+ void ready();
1495+ void deviceCountChanged(int count);
1496+ void deviceFilterChanged(const QInputDevice::InputType filter);
1497+
1498+public Q_SLOTS:
1499+ void addedDevice(const QString & devicePath);
1500+
1501+private:
1502+ Q_DISABLE_COPY(QInputDeviceManager)
1503+#if !defined(QT_SIMULATOR)
1504+ QInputDeviceManagerPrivate *const d_ptr;
1505+ Q_DECLARE_PRIVATE(QInputDeviceManager)
1506+#endif
1507+};
1508+
1509+#endif // QINPUTINFO_H
1510
1511=== added file 'src/plugin/file-qml-plugin/InputInfo/qmldir'
1512--- src/plugin/file-qml-plugin/InputInfo/qmldir 1970-01-01 00:00:00 +0000
1513+++ src/plugin/file-qml-plugin/InputInfo/qmldir 2016-02-03 14:19:17 +0000
1514@@ -0,0 +1,3 @@
1515+module Unity.InputInfo
1516+plugin InputInfo
1517+typeinfo InputInfo.qmltypes
1518
1519=== modified file 'src/plugin/file-qml-plugin/backend.cpp'
1520--- src/plugin/file-qml-plugin/backend.cpp 2015-09-19 15:40:22 +0000
1521+++ src/plugin/file-qml-plugin/backend.cpp 2016-02-03 14:19:17 +0000
1522@@ -21,27 +21,38 @@
1523 #include "backend.h"
1524 #include "documentmodel.h"
1525 #include "docviewerfile.h"
1526-#include "docviewerutils.h"
1527-
1528-static QObject *registerDocviewerUtils (QQmlEngine *engine, QJSEngine *scriptEngine)
1529-{
1530- Q_UNUSED(engine)
1531- Q_UNUSED(scriptEngine)
1532-
1533- DocviewerUtils *ch = new DocviewerUtils();
1534- return ch;
1535+#include "fileutils.h"
1536+#include "ubuntuconvergenceutils.h"
1537+
1538+static QObject *registerFileUtils (QQmlEngine *engine, QJSEngine *scriptEngine)
1539+{
1540+ Q_UNUSED(engine)
1541+ Q_UNUSED(scriptEngine)
1542+
1543+ DocviewerFileUtils *f = new DocviewerFileUtils();
1544+ return f;
1545+}
1546+
1547+static QObject *registerConvergenceUtils (QQmlEngine *engine, QJSEngine *scriptEngine)
1548+{
1549+ Q_UNUSED(engine)
1550+ Q_UNUSED(scriptEngine)
1551+
1552+ UbuntuConvergenceUtils *c = new UbuntuConvergenceUtils();
1553+ return c;
1554 }
1555
1556 void BackendPlugin::registerTypes(const char *uri)
1557 {
1558 Q_ASSERT(uri == QLatin1String("DocumentViewer"));
1559-
1560+
1561 //@uri DocumentViewer
1562
1563 qmlRegisterType<DocumentModel>(uri, 1, 0, "DocumentsModel");
1564 qmlRegisterType<DocviewerFile>(uri, 1, 0, "File");
1565
1566- qmlRegisterSingletonType<DocviewerUtils>(uri, 1, 0, "DocumentViewer", registerDocviewerUtils);
1567+ qmlRegisterSingletonType<DocviewerFileUtils>(uri, 1, 0, "FileUtils", registerFileUtils);
1568+ qmlRegisterSingletonType<UbuntuConvergenceUtils>(uri, 1, 0, "ConvergenceUtils", registerConvergenceUtils);
1569 }
1570
1571 void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
1572
1573=== modified file 'src/plugin/file-qml-plugin/documentmodel.cpp'
1574--- src/plugin/file-qml-plugin/documentmodel.cpp 2015-09-19 15:40:22 +0000
1575+++ src/plugin/file-qml-plugin/documentmodel.cpp 2016-02-03 14:19:17 +0000
1576@@ -17,7 +17,7 @@
1577
1578 #include "documentmodel.h"
1579 #include "fswatcher.h"
1580-#include "docviewerutils.h"
1581+#include "fileutils.h"
1582
1583 #include <QStandardPaths>
1584 #include <QDir>
1585@@ -115,7 +115,7 @@
1586
1587 bool DocumentModel::isFileSupported(const QString &path)
1588 {
1589- return DocviewerUtils::isFileSupported(path);
1590+ return DocviewerFileUtils::isFileSupported(path);
1591 }
1592
1593 QHash<int, QByteArray> DocumentModel::roleNames() const
1594
1595=== removed file 'src/plugin/file-qml-plugin/docviewerutils.cpp'
1596--- src/plugin/file-qml-plugin/docviewerutils.cpp 2015-12-27 12:10:06 +0000
1597+++ src/plugin/file-qml-plugin/docviewerutils.cpp 1970-01-01 00:00:00 +0000
1598@@ -1,184 +0,0 @@
1599-/*
1600- Copyright (C) 2015 Canonical, Ltd.
1601-
1602- This program is free software: you can redistribute it and/or modify
1603- it under the terms of the GNU General Public License 3 as published by
1604- the Free Software Foundation.
1605-
1606- This program is distributed in the hope that it will be useful,
1607- but WITHOUT ANY WARRANTY; without even the implied warranty of
1608- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1609- GNU General Public License for more details.
1610-
1611- You should have received a copy of the GNU General Public License
1612- along with this program. If not, see http://www.gnu.org/licenses/.
1613-*/
1614-
1615-#include "docviewerutils.h"
1616-
1617-#include <QFileInfo>
1618-#include <QDir>
1619-#include <QMimeDatabase>
1620-#include <QStandardPaths>
1621-#include <QDirIterator>
1622-#include <QDateTime>
1623-#include <QtGui/QGuiApplication>
1624-
1625-bool DocviewerUtils::desktopMode() const
1626-{
1627- // Assume that platformName (QtUbuntu) with ubuntu
1628- // in name means it's running on device
1629- // TODO: replace this check with SDK call for formfactor
1630- QString platform = QGuiApplication::platformName();
1631- return !((platform == "ubuntu") || (platform == "ubuntumirclient"));
1632-}
1633-
1634-bool DocviewerUtils::exists(const QString &path)
1635-{
1636- QFileInfo fi(path);
1637-
1638- if (fi.isFile())
1639- return fi.exists();
1640-
1641- // else
1642- return QDir(path).exists();
1643-}
1644-
1645-bool DocviewerUtils::copy(const QString &source, const QString &destination)
1646-{
1647- return QFile::copy(source, destination);
1648-}
1649-
1650-bool DocviewerUtils::isFileSupported(const QString &path)
1651-{
1652- QMimeDatabase mdb;
1653- const QString mimetype = mdb.mimeTypeForFile(path).name();
1654-
1655- return mimetype.startsWith("text/")
1656- || mimetype == "application/pdf"
1657- || mimetype.startsWith("application/vnd.oasis.opendocument")
1658- || mimetype == "application/msword"
1659- || mimetype == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
1660- || mimetype == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1661- || mimetype == "application/vnd.openxmlformats-officedocument.presentationml.presentation"
1662- || mimetype == "application/vnd.ms-excel"
1663- || mimetype == "application/vnd.ms-powerpoint";
1664-}
1665-
1666-QString DocviewerUtils::getXdgDocumentsLocation()
1667-{
1668- return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
1669-}
1670-
1671-QString DocviewerUtils::buildDestinationPath(const QString &destinationDir, const QString &sourcePath)
1672-{
1673- QFileInfo fi(sourcePath);
1674-
1675- /*
1676- We don't support formats that use a double extension
1677- (e.g. tar.gz), so we can safely use completeBaseName() and
1678- suffix() functions, in order to properly detect the name of
1679- the document even when there's a dot in the middle of the name.
1680- */
1681- QString suffix = fi.suffix();
1682- QString filenameWithoutSuffix = fi.completeBaseName();
1683-
1684- QMimeDatabase mdb;
1685- QMimeType mt = mdb.mimeTypeForFile(sourcePath);
1686-
1687- // If the filename doesn't have an extension add one from the
1688- // detected mimetype
1689- if (suffix.isEmpty())
1690- suffix = mt.preferredSuffix();
1691-
1692- QString dir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + QDir::separator();
1693- QString destination = QString("%1.%2").arg(dir + filenameWithoutSuffix, suffix);
1694-
1695- // If there's already a file of this name, reformat it to
1696- // "filename (copy x).png" where x is a number, incremented until we find an
1697- // available filename.
1698- if (QFile::exists(destination)) {
1699- /*
1700- TRANSLATORS: This string is used for renaming a copied file,
1701- when a file with the same name already exists in user's
1702- Documents folder.
1703-
1704- e.g. "Manual_Aquaris_E4.5_ubuntu_EN.pdf" will become
1705- "Manual_Aquaris_E4.5_ubuntu_EN (copy 2).pdf"
1706-
1707- where "2" is given by the argument "%1"
1708- */
1709- QString reformattedSuffix = QString(tr("copy %1"));
1710-
1711- // Check if the file has already a "copy" suffix
1712- // If so, remove it since we will update it later.
1713- QRegExp rx(" \\(" + reformattedSuffix.arg(QString("\\d+")) + "\\)");
1714- int reformattedSuffixPos = filenameWithoutSuffix.lastIndexOf(rx);
1715-
1716- if (reformattedSuffixPos != -1)
1717- filenameWithoutSuffix.truncate(reformattedSuffixPos);
1718-
1719- // Add the right "copy" suffix.
1720- int append = 1;
1721- while (QFile::exists(destination)) {
1722- destination = QString("%1 (%2).%3").arg(
1723- dir + filenameWithoutSuffix,
1724- reformattedSuffix.arg(QString::number(append)),
1725- suffix);
1726- append++;
1727- }
1728- }
1729-
1730- return destination;
1731-}
1732-
1733-// Return the path of the file, if found in the storageLocation paths,
1734-// otherwise return an empty string.
1735-// Used for prevent importing of a second copy of a file through ContentHub.
1736-QString DocviewerUtils::checkIfFileAlreadyImported(const QString &filePath, const QStringList &storageLocationList)
1737-{
1738- QFileInfo fi(filePath);
1739- QStringList files;
1740-
1741- // Get the list of all the files in the watched folders
1742- Q_FOREACH(const QString &storageLocation, storageLocationList) {
1743- QDirIterator dir(storageLocation, QDir::Files | QDir::NoDotAndDotDot | QDir::Readable,
1744- QDirIterator::Subdirectories);
1745-
1746- while (dir.hasNext())
1747- {
1748- dir.next();
1749- files.append(dir.filePath());
1750- }
1751- }
1752-
1753- // Check if there's a file with the same name in the list
1754- Q_FOREACH(const QString &file, files) {
1755- if (file.endsWith(fi.fileName())) {
1756- // Seems there could be already the same file in the watched
1757- // folders. Check also size and lastModified date.
1758- QFileInfo fileToCheck(file);
1759-
1760- if (fi.size() == fileToCheck.size() &&
1761- fi.lastModified() == fileToCheck.lastModified())
1762- return file;
1763- }
1764- }
1765-
1766- return QString();
1767-}
1768-
1769-QString DocviewerUtils::getFileBaseNameFromPath(const QString &filePath)
1770-{
1771- return QFileInfo(filePath).completeBaseName();
1772-}
1773-
1774-QString DocviewerUtils::getFileNameFromPath(const QString &filePath)
1775-{
1776- return QFileInfo(filePath).fileName();
1777-}
1778-
1779-QString DocviewerUtils::getCanonicalPath(const QString &filePath)
1780-{
1781- return QFileInfo(filePath).canonicalPath();
1782-}
1783
1784=== removed file 'src/plugin/file-qml-plugin/docviewerutils.h'
1785--- src/plugin/file-qml-plugin/docviewerutils.h 2015-12-27 12:10:06 +0000
1786+++ src/plugin/file-qml-plugin/docviewerutils.h 1970-01-01 00:00:00 +0000
1787@@ -1,45 +0,0 @@
1788-/*
1789- Copyright (C) 2015 Canonical, Ltd.
1790-
1791- This program is free software: you can redistribute it and/or modify
1792- it under the terms of the GNU General Public License 3 as published by
1793- the Free Software Foundation.
1794-
1795- This program is distributed in the hope that it will be useful,
1796- but WITHOUT ANY WARRANTY; without even the implied warranty of
1797- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1798- GNU General Public License for more details.
1799-
1800- You should have received a copy of the GNU General Public License
1801- along with this program. If not, see http://www.gnu.org/licenses/.
1802-*/
1803-
1804-#ifndef DOCVIEWERUTILS_H
1805-#define DOCVIEWERUTILS_H
1806-
1807-#include <QObject>
1808-
1809-class DocviewerUtils : public QObject
1810-{
1811- Q_OBJECT
1812- Q_PROPERTY(bool desktopMode READ desktopMode CONSTANT)
1813-
1814-public:
1815- bool desktopMode() const;
1816-
1817- Q_INVOKABLE static bool exists(const QString &path);
1818- Q_INVOKABLE static bool copy(const QString &source, const QString &destination);
1819-
1820- Q_INVOKABLE static bool isFileSupported(const QString &path);
1821- Q_INVOKABLE static QString getXdgDocumentsLocation();
1822-
1823- Q_INVOKABLE static QString buildDestinationPath(const QString &destinationDir, const QString &sourcePath);
1824-
1825- Q_INVOKABLE static QString checkIfFileAlreadyImported(const QString &filePath, const QStringList &storageLocationList);
1826-
1827- Q_INVOKABLE static QString getFileBaseNameFromPath(const QString &filePath);
1828- Q_INVOKABLE static QString getFileNameFromPath(const QString &filePath);
1829- Q_INVOKABLE static QString getCanonicalPath(const QString &filePath);
1830-};
1831-
1832-#endif // DOCVIEWERUTILS_H
1833
1834=== added file 'src/plugin/file-qml-plugin/fileutils.cpp'
1835--- src/plugin/file-qml-plugin/fileutils.cpp 1970-01-01 00:00:00 +0000
1836+++ src/plugin/file-qml-plugin/fileutils.cpp 2016-02-03 14:19:17 +0000
1837@@ -0,0 +1,174 @@
1838+/*
1839+ Copyright (C) 2015 Canonical, Ltd.
1840+
1841+ This program is free software: you can redistribute it and/or modify
1842+ it under the terms of the GNU General Public License 3 as published by
1843+ the Free Software Foundation.
1844+
1845+ This program is distributed in the hope that it will be useful,
1846+ but WITHOUT ANY WARRANTY; without even the implied warranty of
1847+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1848+ GNU General Public License for more details.
1849+
1850+ You should have received a copy of the GNU General Public License
1851+ along with this program. If not, see http://www.gnu.org/licenses/.
1852+*/
1853+
1854+#include "fileutils.h"
1855+
1856+#include <QFileInfo>
1857+#include <QDir>
1858+#include <QMimeDatabase>
1859+#include <QStandardPaths>
1860+#include <QDirIterator>
1861+#include <QDateTime>
1862+
1863+bool DocviewerFileUtils::exists(const QString &path)
1864+{
1865+ QFileInfo fi(path);
1866+
1867+ if (fi.isFile())
1868+ return fi.exists();
1869+
1870+ // else
1871+ return QDir(path).exists();
1872+}
1873+
1874+bool DocviewerFileUtils::copy(const QString &source, const QString &destination)
1875+{
1876+ return QFile::copy(source, destination);
1877+}
1878+
1879+bool DocviewerFileUtils::isFileSupported(const QString &path)
1880+{
1881+ QMimeDatabase mdb;
1882+ const QString mimetype = mdb.mimeTypeForFile(path).name();
1883+
1884+ return mimetype.startsWith("text/")
1885+ || mimetype == "application/pdf"
1886+ || mimetype.startsWith("application/vnd.oasis.opendocument")
1887+ || mimetype == "application/msword"
1888+ || mimetype == "application/vnd.openxmlformats-officedocument.wordprocessingml.document"
1889+ || mimetype == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
1890+ || mimetype == "application/vnd.openxmlformats-officedocument.presentationml.presentation"
1891+ || mimetype == "application/vnd.ms-excel"
1892+ || mimetype == "application/vnd.ms-powerpoint";
1893+}
1894+
1895+QString DocviewerFileUtils::getXdgDocumentsLocation()
1896+{
1897+ return QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
1898+}
1899+
1900+QString DocviewerFileUtils::buildDestinationPath(const QString &destinationDir, const QString &sourcePath)
1901+{
1902+ QFileInfo fi(sourcePath);
1903+
1904+ /*
1905+ We don't support formats that use a double extension
1906+ (e.g. tar.gz), so we can safely use completeBaseName() and
1907+ suffix() functions, in order to properly detect the name of
1908+ the document even when there's a dot in the middle of the name.
1909+ */
1910+ QString suffix = fi.suffix();
1911+ QString filenameWithoutSuffix = fi.completeBaseName();
1912+
1913+ QMimeDatabase mdb;
1914+ QMimeType mt = mdb.mimeTypeForFile(sourcePath);
1915+
1916+ // If the filename doesn't have an extension add one from the
1917+ // detected mimetype
1918+ if (suffix.isEmpty())
1919+ suffix = mt.preferredSuffix();
1920+
1921+ QString dir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + QDir::separator();
1922+ QString destination = QString("%1.%2").arg(dir + filenameWithoutSuffix, suffix);
1923+
1924+ // If there's already a file of this name, reformat it to
1925+ // "filename (copy x).png" where x is a number, incremented until we find an
1926+ // available filename.
1927+ if (QFile::exists(destination)) {
1928+ /*
1929+ TRANSLATORS: This string is used for renaming a copied file,
1930+ when a file with the same name already exists in user's
1931+ Documents folder.
1932+
1933+ e.g. "Manual_Aquaris_E4.5_ubuntu_EN.pdf" will become
1934+ "Manual_Aquaris_E4.5_ubuntu_EN (copy 2).pdf"
1935+
1936+ where "2" is given by the argument "%1"
1937+ */
1938+ QString reformattedSuffix = QString(tr("copy %1"));
1939+
1940+ // Check if the file has already a "copy" suffix
1941+ // If so, remove it since we will update it later.
1942+ QRegExp rx(" \\(" + reformattedSuffix.arg(QString("\\d+")) + "\\)");
1943+ int reformattedSuffixPos = filenameWithoutSuffix.lastIndexOf(rx);
1944+
1945+ if (reformattedSuffixPos != -1)
1946+ filenameWithoutSuffix.truncate(reformattedSuffixPos);
1947+
1948+ // Add the right "copy" suffix.
1949+ int append = 1;
1950+ while (QFile::exists(destination)) {
1951+ destination = QString("%1 (%2).%3").arg(
1952+ dir + filenameWithoutSuffix,
1953+ reformattedSuffix.arg(QString::number(append)),
1954+ suffix);
1955+ append++;
1956+ }
1957+ }
1958+
1959+ return destination;
1960+}
1961+
1962+// Return the path of the file, if found in the storageLocation paths,
1963+// otherwise return an empty string.
1964+// Used for prevent importing of a second copy of a file through ContentHub.
1965+QString DocviewerFileUtils::checkIfFileAlreadyImported(const QString &filePath, const QStringList &storageLocationList)
1966+{
1967+ QFileInfo fi(filePath);
1968+ QStringList files;
1969+
1970+ // Get the list of all the files in the watched folders
1971+ Q_FOREACH(const QString &storageLocation, storageLocationList) {
1972+ QDirIterator dir(storageLocation, QDir::Files | QDir::NoDotAndDotDot | QDir::Readable,
1973+ QDirIterator::Subdirectories);
1974+
1975+ while (dir.hasNext())
1976+ {
1977+ dir.next();
1978+ files.append(dir.filePath());
1979+ }
1980+ }
1981+
1982+ // Check if there's a file with the same name in the list
1983+ Q_FOREACH(const QString &file, files) {
1984+ if (file.endsWith(fi.fileName())) {
1985+ // Seems there could be already the same file in the watched
1986+ // folders. Check also size and lastModified date.
1987+ QFileInfo fileToCheck(file);
1988+
1989+ if (fi.size() == fileToCheck.size() &&
1990+ fi.lastModified() == fileToCheck.lastModified())
1991+ return file;
1992+ }
1993+ }
1994+
1995+ return QString();
1996+}
1997+
1998+QString DocviewerFileUtils::getFileBaseNameFromPath(const QString &filePath)
1999+{
2000+ return QFileInfo(filePath).completeBaseName();
2001+}
2002+
2003+QString DocviewerFileUtils::getFileNameFromPath(const QString &filePath)
2004+{
2005+ return QFileInfo(filePath).fileName();
2006+}
2007+
2008+QString DocviewerFileUtils::getCanonicalPath(const QString &filePath)
2009+{
2010+ return QFileInfo(filePath).canonicalPath();
2011+}
2012
2013=== added file 'src/plugin/file-qml-plugin/fileutils.h'
2014--- src/plugin/file-qml-plugin/fileutils.h 1970-01-01 00:00:00 +0000
2015+++ src/plugin/file-qml-plugin/fileutils.h 2016-02-03 14:19:17 +0000
2016@@ -0,0 +1,42 @@
2017+/*
2018+ Copyright (C) 2015 Canonical, Ltd.
2019+
2020+ This program is free software: you can redistribute it and/or modify
2021+ it under the terms of the GNU General Public License 3 as published by
2022+ the Free Software Foundation.
2023+
2024+ This program is distributed in the hope that it will be useful,
2025+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2026+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2027+ GNU General Public License for more details.
2028+
2029+ You should have received a copy of the GNU General Public License
2030+ along with this program. If not, see http://www.gnu.org/licenses/.
2031+*/
2032+
2033+#ifndef DOCVIEWER_FILEUTILS_H
2034+#define DOCVIEWER_FILEUTILS_H
2035+
2036+#include <QObject>
2037+
2038+class DocviewerFileUtils : public QObject
2039+{
2040+ Q_OBJECT
2041+
2042+public:
2043+ Q_INVOKABLE static bool exists(const QString &path);
2044+ Q_INVOKABLE static bool copy(const QString &source, const QString &destination);
2045+
2046+ Q_INVOKABLE static bool isFileSupported(const QString &path);
2047+ Q_INVOKABLE static QString getXdgDocumentsLocation();
2048+
2049+ Q_INVOKABLE static QString buildDestinationPath(const QString &destinationDir, const QString &sourcePath);
2050+
2051+ Q_INVOKABLE static QString checkIfFileAlreadyImported(const QString &filePath, const QStringList &storageLocationList);
2052+
2053+ Q_INVOKABLE static QString getFileBaseNameFromPath(const QString &filePath);
2054+ Q_INVOKABLE static QString getFileNameFromPath(const QString &filePath);
2055+ Q_INVOKABLE static QString getCanonicalPath(const QString &filePath);
2056+};
2057+
2058+#endif // DOCVIEWER_FILEUTILS_H
2059
2060=== added file 'src/plugin/file-qml-plugin/ubuntuconvergenceutils.cpp'
2061--- src/plugin/file-qml-plugin/ubuntuconvergenceutils.cpp 1970-01-01 00:00:00 +0000
2062+++ src/plugin/file-qml-plugin/ubuntuconvergenceutils.cpp 2016-02-03 14:19:17 +0000
2063@@ -0,0 +1,82 @@
2064+/*
2065+ Copyright (C) 2015 Stefano Verzegnassi
2066+
2067+ This program is free software: you can redistribute it and/or modify
2068+ it under the terms of the GNU General Public License 3 as published by
2069+ the Free Software Foundation.
2070+
2071+ This program is distributed in the hope that it will be useful,
2072+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2073+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2074+ GNU General Public License for more details.
2075+
2076+ You should have received a copy of the GNU General Public License
2077+ along with this program. If not, see http://www.gnu.org/licenses/.
2078+*/
2079+
2080+#include "ubuntuconvergenceutils.h"
2081+#include "InputInfo/qinputinfo.h"
2082+
2083+#include <QtGui/QGuiApplication>
2084+
2085+bool isUnity8Env()
2086+{
2087+ // Assume that platformName (QtUbuntu) with ubuntu
2088+ // in name means it's running on device
2089+ QString platform = QGuiApplication::platformName();
2090+ return (platform == "ubuntu") || (platform == "ubuntumirclient");
2091+}
2092+
2093+UbuntuConvergenceUtils::UbuntuConvergenceUtils(QObject *parent) :
2094+ QObject(parent),
2095+ m_desktopMode(false),
2096+ m_mouseAttached(false),
2097+ m_inputDevicesWatcher(new QInputDeviceManager())
2098+{
2099+ // Initialize signals when the watcher is ready.
2100+ // QInputDeviceManager() emits deviceAdded() signal multiple times during its
2101+ // initializations.
2102+ connect(m_inputDevicesWatcher, &QInputDeviceManager::ready,
2103+ this, &UbuntuConvergenceUtils::init);
2104+}
2105+
2106+void UbuntuConvergenceUtils::init()
2107+{
2108+ // Connect signals
2109+ connect(m_inputDevicesWatcher, SIGNAL(deviceAdded(QString)), this, SLOT(checkPointersCount()));
2110+ connect(m_inputDevicesWatcher, SIGNAL(deviceRemoved(QString)), this, SLOT(checkPointersCount()));
2111+
2112+ checkPointersCount();
2113+}
2114+
2115+void UbuntuConvergenceUtils::checkPointersCount()
2116+{
2117+ int mouseCount = m_inputDevicesWatcher->deviceCount(QInputDevice::Mouse);
2118+ int touchPadCount = m_inputDevicesWatcher->deviceCount(QInputDevice::TouchPad);
2119+
2120+ setMouseAttached(mouseCount || touchPadCount);
2121+ setDesktopMode(isUnity8Env() || m_mouseAttached);
2122+}
2123+
2124+void UbuntuConvergenceUtils::setDesktopMode(bool desktopMode)
2125+{
2126+ if (m_desktopMode == desktopMode)
2127+ return;
2128+
2129+ m_desktopMode = desktopMode;
2130+ Q_EMIT desktopModeChanged();
2131+}
2132+
2133+void UbuntuConvergenceUtils::setMouseAttached(bool mouseAttached)
2134+{
2135+ if (m_mouseAttached == mouseAttached)
2136+ return;
2137+
2138+ m_mouseAttached = mouseAttached;
2139+ Q_EMIT mouseAttachedChanged();
2140+}
2141+
2142+UbuntuConvergenceUtils::~UbuntuConvergenceUtils()
2143+{
2144+ delete m_inputDevicesWatcher;
2145+}
2146
2147=== added file 'src/plugin/file-qml-plugin/ubuntuconvergenceutils.h'
2148--- src/plugin/file-qml-plugin/ubuntuconvergenceutils.h 1970-01-01 00:00:00 +0000
2149+++ src/plugin/file-qml-plugin/ubuntuconvergenceutils.h 2016-02-03 14:19:17 +0000
2150@@ -0,0 +1,56 @@
2151+/*
2152+ Copyright (C) 2015 Stefano Verzegnassi
2153+
2154+ This program is free software: you can redistribute it and/or modify
2155+ it under the terms of the GNU General Public License 3 as published by
2156+ the Free Software Foundation.
2157+
2158+ This program is distributed in the hope that it will be useful,
2159+ but WITHOUT ANY WARRANTY; without even the implied warranty of
2160+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2161+ GNU General Public License for more details.
2162+
2163+ You should have received a copy of the GNU General Public License
2164+ along with this program. If not, see http://www.gnu.org/licenses/.
2165+*/
2166+
2167+#ifndef DOCVIEWER_CONVERGENCEUTILS_H
2168+#define DOCVIEWER_CONVERGENCEUTILS_H
2169+
2170+#include <QObject>
2171+
2172+class QInputDeviceManager;
2173+
2174+class UbuntuConvergenceUtils : public QObject
2175+{
2176+ Q_OBJECT
2177+ Q_PROPERTY(bool desktopMode READ desktopMode NOTIFY desktopModeChanged)
2178+ Q_PROPERTY(bool mouseAttached READ mouseAttached NOTIFY mouseAttachedChanged)
2179+
2180+public:
2181+ UbuntuConvergenceUtils(QObject *parent = 0);
2182+ ~UbuntuConvergenceUtils();
2183+
2184+ bool desktopMode() const { return m_desktopMode; }
2185+ bool mouseAttached() const { return m_mouseAttached; }
2186+
2187+Q_SIGNALS:
2188+ void desktopModeChanged();
2189+ void mouseAttachedChanged();
2190+
2191+private slots:
2192+ void checkPointersCount();
2193+ void init();
2194+
2195+private:
2196+ bool m_desktopMode;
2197+ bool m_mouseAttached;
2198+
2199+private:
2200+ QInputDeviceManager* m_inputDevicesWatcher;
2201+
2202+ void setDesktopMode(bool desktopMode);
2203+ void setMouseAttached(bool mouseAttached);
2204+};
2205+
2206+#endif // DOCVIEWER_CONVERGENCEUTILS_H

Subscribers

People subscribed via source and target branches