Merge lp:~carlos-mazieri/ubuntu-filemanager-app/model into lp:ubuntu-filemanager-app
- model
- Merge into trunk
Status: | Rejected |
---|---|
Rejected by: | Michael Hall |
Proposed branch: | lp:~carlos-mazieri/ubuntu-filemanager-app/model |
Merge into: | lp:ubuntu-filemanager-app |
Diff against target: |
48088 lines (+47602/-0) 94 files modified
folderlistmodel/README (+6/-0) folderlistmodel/dirmodel.cpp (+1005/-0) folderlistmodel/dirmodel.h (+328/-0) folderlistmodel/filesystemaction.cpp (+1389/-0) folderlistmodel/filesystemaction.h (+212/-0) folderlistmodel/folderlistmodel.pri (+26/-0) folderlistmodel/folderlistmodel.pro (+39/-0) folderlistmodel/iorequest.cpp (+36/-0) folderlistmodel/iorequest.h (+51/-0) folderlistmodel/iorequestworker.cpp (+94/-0) folderlistmodel/iorequestworker.h (+61/-0) folderlistmodel/ioworkerthread.cpp (+64/-0) folderlistmodel/ioworkerthread.h (+52/-0) folderlistmodel/plugin.cpp (+53/-0) folderlistmodel/plugin.h (+84/-0) folderlistmodel/qmldir (+1/-0) nemo-folderlistmodel/dirmodel.cpp (+385/-0) nemo-folderlistmodel/dirmodel.h (+124/-0) nemo-folderlistmodel/folderlistmodel.pro (+16/-0) nemo-folderlistmodel/iorequest.cpp (+36/-0) nemo-folderlistmodel/iorequest.h (+51/-0) nemo-folderlistmodel/iorequestworker.cpp (+92/-0) nemo-folderlistmodel/iorequestworker.h (+61/-0) nemo-folderlistmodel/ioworkerthread.cpp (+64/-0) nemo-folderlistmodel/ioworkerthread.h (+52/-0) nemo-folderlistmodel/plugin.cpp (+53/-0) nemo-folderlistmodel/plugin.h (+82/-0) nemo-folderlistmodel/qmldir (+1/-0) test_folderlistmodel/regression/media_asx.h (+21/-0) test_folderlistmodel/regression/media_xspf.h (+135/-0) test_folderlistmodel/regression/mimetypes/LICENSE.LGPL (+504/-0) test_folderlistmodel/regression/mimetypes/TODO.txt (+8/-0) test_folderlistmodel/regression/mimetypes/include/QtMimeTypes/QMimeDatabase (+1/-0) test_folderlistmodel/regression/mimetypes/include/QtMimeTypes/QMimeMagicRule (+1/-0) test_folderlistmodel/regression/mimetypes/include/QtMimeTypes/QMimeType (+1/-0) test_folderlistmodel/regression/mimetypes/include/QtMimeTypes/QtMimeTypes.pro (+17/-0) test_folderlistmodel/regression/mimetypes/include/QtMimeTypes/qmimedatabase.h (+1/-0) test_folderlistmodel/regression/mimetypes/include/QtMimeTypes/qmimemagicrule.h (+1/-0) test_folderlistmodel/regression/mimetypes/include/QtMimeTypes/qmimetype.h (+1/-0) test_folderlistmodel/regression/mimetypes/include/include.pro (+4/-0) test_folderlistmodel/regression/mimetypes/mimetypes-nolibs.pri (+11/-0) test_folderlistmodel/regression/mimetypes/mimetypes-src.pri (+26/-0) test_folderlistmodel/regression/mimetypes/qtmimetypes.pro (+23/-0) test_folderlistmodel/regression/mimetypes/src/imports/imports.pro (+3/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/mimetypes.cpp (+69/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/mimetypes.pro (+43/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/plugins.qmltypes (+59/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/qdeclarativemimedatabase.cpp (+320/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/qdeclarativemimedatabase_p.h (+98/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/qdeclarativemimetype.cpp (+683/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/qdeclarativemimetype_p.h (+155/-0) test_folderlistmodel/regression/mimetypes/src/imports/mimetypes/qmldir (+1/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/inqt5/qstandardpaths.cpp (+275/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/inqt5/qstandardpaths.h (+106/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/inqt5/qstandardpaths_mac.cpp (+173/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/inqt5/qstandardpaths_unix.cpp (+258/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/inqt5/qstandardpaths_win.cpp (+218/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/mime/packages/freedesktop.org.xml (+31966/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/mimetypes.pro (+72/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/mimetypes.qrc (+5/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmime_global.h (+32/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimedatabase.cpp (+615/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimedatabase.h (+114/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimedatabase_p.h (+89/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimeglobpattern.cpp (+240/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimeglobpattern_p.h (+146/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimemagicrule.cpp (+387/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimemagicrule_p.h (+89/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimemagicrulematcher.cpp (+107/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimemagicrulematcher_p.h (+78/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimeprovider.cpp (+835/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimeprovider_p.h (+165/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimetype.cpp (+482/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimetype.h (+120/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimetype_p.h (+114/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimetypeparser.cpp (+341/-0) test_folderlistmodel/regression/mimetypes/src/mimetypes/qmimetypeparser_p.h (+118/-0) test_folderlistmodel/regression/mimetypes/src/src.pro (+3/-0) test_folderlistmodel/regression/regression_folderlilstmodel.pro (+30/-0) test_folderlistmodel/regression/sound_7200_amr.h (+87/-0) test_folderlistmodel/regression/sound_mp3.h (+700/-0) test_folderlistmodel/regression/tempfiles.cpp (+177/-0) test_folderlistmodel/regression/tempfiles.h (+90/-0) test_folderlistmodel/regression/testonly_pdf.h (+641/-0) test_folderlistmodel/regression/tst_folderlistmodel.cpp (+1304/-0) test_folderlistmodel/results/DesktopQt4.74.txt (+47/-0) test_folderlistmodel/results/DesktopQt5.0.txt (+53/-0) test_folderlistmodel/results/NemoEmulatorQ8.43.txt (+36/-0) test_folderlistmodel/results/openFiles.Readme.txt (+7/-0) test_folderlistmodel/simpleUI/main.cpp (+32/-0) test_folderlistmodel/simpleUI/simplelist.cpp (+256/-0) test_folderlistmodel/simpleUI/simplelist.h (+72/-0) test_folderlistmodel/simpleUI/simplelist.ui (+183/-0) test_folderlistmodel/simpleUI/simpleui.pro (+35/-0) |
To merge this branch: | bzr merge lp:~carlos-mazieri/ubuntu-filemanager-app/model |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Phone Apps Jenkins Bot | continuous-integration | Needs Fixing | |
Arto Jalkanen | Disapprove | ||
Review via email: mp+166863@code.launchpad.net |
Commit message
Fixes bug #1180956.
Description of the change
It contains the fix for bug #1180956.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
Arto Jalkanen (ajalkane) wrote : | # |
Hi,
you've committed to the wrong branch. This is for the QML application. The correct branch for plugin changes are in lp:ubuntu-filemanager-app/plugin
- 21. By Carlos Jose Mazieri
-
fixed refresh view signals when a pate operation is made and items already exist.
In this case as the existent item is removed both signals: "removed" and "added" items are sent.
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote : | # |
FAILED: Continuous integration, rev:21
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Unmerged revisions
- 66. By Carlos Jose Mazieri
-
remade C++ UI
- 65. By Carlos Jose Mazieri
-
added moveToTrash, removeFromTrash, restoreFromTrash and emptyTrash facilities.
Test View remade to use selection. - 64. By Carlos Jose Mazieri
-
Preparation for Move/Restore to/from Trash and Undo Actions:
* Some information from Action data structure were moved into ActionEntry data structure.
* Actions used to have "targetPath" saying all items (ActionEntry items) were copied/moved into a unique path.
Now having ActionEntry more indenpendent allows to move/copy items to different paths inside an Action.
This is required for Restore items from Trash. - 63. By Carlos Jose Mazieri
-
Redesign:
* Created Location class which represents a URL supported in the File Manager
- DiskLocation represents any url/path like file:/// or normal /
- TrashLocation represents any url/path like trash:///
- There will be a SmbLocation for samba/cifs network sharing
* Browsing items (IOReuest/IOWorkerThread) moved into the Location
* External File system watcher handling was moved into DiskLocation class
* Navigation into child folders and up to parent folder were delegated to the Location
* Created LocationsFactory class which keeps the supported Locations, it provides a URL
parser that sets the current Location.
Trash:
* implemented browsing: missing carry orignal item properties
* implemented a specific External File system watcher for trash
* missing Move/Restore to/from Trash (NOT YET IMPLEMENTED)OBS:
* due to current File Manager UI typing method both: "file:" and "trash:" are supported.
Preview Diff
1 | === added directory 'folderlistmodel' | |||
2 | === added file 'folderlistmodel/README' | |||
3 | --- folderlistmodel/README 1970-01-01 00:00:00 +0000 | |||
4 | +++ folderlistmodel/README 2013-06-01 17:20:36 +0000 | |||
5 | @@ -0,0 +1,6 @@ | |||
6 | 1 | Building and installing | ||
7 | 2 | ======================= | ||
8 | 3 | |||
9 | 4 | qmake && make | ||
10 | 5 | sudo make install | ||
11 | 6 | |||
12 | 0 | 7 | ||
13 | === added file 'folderlistmodel/dirmodel.cpp' | |||
14 | --- folderlistmodel/dirmodel.cpp 1970-01-01 00:00:00 +0000 | |||
15 | +++ folderlistmodel/dirmodel.cpp 2013-06-01 17:20:36 +0000 | |||
16 | @@ -0,0 +1,1005 @@ | |||
17 | 1 | /* | ||
18 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
19 | 3 | * | ||
20 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
21 | 5 | * | ||
22 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
23 | 7 | * modification, are permitted provided that the following conditions are | ||
24 | 8 | * met: | ||
25 | 9 | * * Redistributions of source code must retain the above copyright | ||
26 | 10 | * notice, this list of conditions and the following disclaimer. | ||
27 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
28 | 12 | * notice, this list of conditions and the following disclaimer in | ||
29 | 13 | * the documentation and/or other materials provided with the | ||
30 | 14 | * distribution. | ||
31 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
32 | 16 | * may be used to endorse or promote products derived from this | ||
33 | 17 | * software without specific prior written permission. | ||
34 | 18 | * | ||
35 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
36 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
37 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
38 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
39 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
40 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
41 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
42 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
43 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
44 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
45 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
46 | 30 | */ | ||
47 | 31 | |||
48 | 32 | #include <errno.h> | ||
49 | 33 | #include <string.h> | ||
50 | 34 | #include "dirmodel.h" | ||
51 | 35 | #include "ioworkerthread.h" | ||
52 | 36 | #include "filesystemaction.h" | ||
53 | 37 | |||
54 | 38 | #include <QDirIterator> | ||
55 | 39 | #include <QDir> | ||
56 | 40 | #include <QDebug> | ||
57 | 41 | #include <QDateTime> | ||
58 | 42 | #include <QFileIconProvider> | ||
59 | 43 | #include <QUrl> | ||
60 | 44 | #include <QDesktopServices> | ||
61 | 45 | |||
62 | 46 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) || QT_VERSION >= 0x050000 | ||
63 | 47 | # include <QMimeType> | ||
64 | 48 | # include <QMimeDatabase> | ||
65 | 49 | #endif | ||
66 | 50 | |||
67 | 51 | #define IS_VALID_ROW(row) (row >=0 && row < mDirectoryContents.count()) | ||
68 | 52 | #define WARN_ROW_OUT_OF_RANGE(row) qWarning() << Q_FUNC_INFO << "row" << row << "Out of bounds access" | ||
69 | 53 | |||
70 | 54 | |||
71 | 55 | Q_GLOBAL_STATIC(IOWorkerThread, ioWorkerThread) | ||
72 | 56 | |||
73 | 57 | namespace { | ||
74 | 58 | QHash<QByteArray, int> roleMapping; | ||
75 | 59 | } | ||
76 | 60 | |||
77 | 61 | |||
78 | 62 | |||
79 | 63 | |||
80 | 64 | static bool fileCompareExists(const QFileInfo &a, const QFileInfo &b) | ||
81 | 65 | { | ||
82 | 66 | if (a.isDir() && !b.isDir()) | ||
83 | 67 | return true; | ||
84 | 68 | |||
85 | 69 | if (b.isDir() && !a.isDir()) | ||
86 | 70 | return false; | ||
87 | 71 | |||
88 | 72 | bool ret = QString::localeAwareCompare(a.absoluteFilePath(), b.absoluteFilePath()) < 0; | ||
89 | 73 | #if DEBUG_MESSAGES | ||
90 | 74 | qDebug() << Q_FUNC_INFO << ret << a.absoluteFilePath() << b.absoluteFilePath(); | ||
91 | 75 | #endif | ||
92 | 76 | return ret; | ||
93 | 77 | } | ||
94 | 78 | |||
95 | 79 | static bool fileCompareAscending(const QFileInfo &a, const QFileInfo &b) | ||
96 | 80 | { | ||
97 | 81 | if (a.isDir() && !b.isDir()) | ||
98 | 82 | return true; | ||
99 | 83 | |||
100 | 84 | if (b.isDir() && !a.isDir()) | ||
101 | 85 | return false; | ||
102 | 86 | |||
103 | 87 | return QString::localeAwareCompare(a.fileName(), b.fileName()) < 0; | ||
104 | 88 | } | ||
105 | 89 | |||
106 | 90 | |||
107 | 91 | static bool fileCompareDescending(const QFileInfo &a, const QFileInfo &b) | ||
108 | 92 | { | ||
109 | 93 | if (a.isDir() && !b.isDir()) | ||
110 | 94 | return true; | ||
111 | 95 | |||
112 | 96 | if (b.isDir() && !a.isDir()) | ||
113 | 97 | return false; | ||
114 | 98 | |||
115 | 99 | return QString::localeAwareCompare(a.fileName(), b.fileName()) > 0; | ||
116 | 100 | } | ||
117 | 101 | |||
118 | 102 | static bool dateCompareDescending(const QFileInfo &a, const QFileInfo &b) | ||
119 | 103 | { | ||
120 | 104 | if (a.isDir() && !b.isDir()) | ||
121 | 105 | return true; | ||
122 | 106 | |||
123 | 107 | if (b.isDir() && !a.isDir()) | ||
124 | 108 | return false; | ||
125 | 109 | |||
126 | 110 | return a.lastModified() > b.lastModified(); | ||
127 | 111 | } | ||
128 | 112 | |||
129 | 113 | static bool dateCompareAscending(const QFileInfo &a, const QFileInfo &b) | ||
130 | 114 | { | ||
131 | 115 | if (a.isDir() && !b.isDir()) | ||
132 | 116 | return true; | ||
133 | 117 | |||
134 | 118 | if (b.isDir() && !a.isDir()) | ||
135 | 119 | return false; | ||
136 | 120 | |||
137 | 121 | return a.lastModified() < b.lastModified(); | ||
138 | 122 | } | ||
139 | 123 | |||
140 | 124 | /*! | ||
141 | 125 | * Sort was originally done in \ref onItemsAdded() and that code is now in \ref addItem(), | ||
142 | 126 | * the reason to keep doing sort and do not let QDir does it is that when adding new items | ||
143 | 127 | * by \ref mkdir() or \paste() it is not necessary to call refresh() to load the entire directory | ||
144 | 128 | * to organize it items again. New items order/position are organized by \ref addItem() | ||
145 | 129 | * | ||
146 | 130 | */ | ||
147 | 131 | static CompareFunction availableCompareFunctions[2][2] = | ||
148 | 132 | { | ||
149 | 133 | {fileCompareAscending, fileCompareDescending} | ||
150 | 134 | ,{dateCompareAscending, dateCompareDescending} | ||
151 | 135 | }; | ||
152 | 136 | |||
153 | 137 | |||
154 | 138 | |||
155 | 139 | |||
156 | 140 | class DirListWorker : public IORequest | ||
157 | 141 | { | ||
158 | 142 | Q_OBJECT | ||
159 | 143 | public: | ||
160 | 144 | DirListWorker(const QString &pathName, QDir::Filter filter) | ||
161 | 145 | : mPathName(pathName) | ||
162 | 146 | , mFilter(filter) | ||
163 | 147 | { } | ||
164 | 148 | |||
165 | 149 | void run() | ||
166 | 150 | { | ||
167 | 151 | #if DEBUG_MESSAGES | ||
168 | 152 | qDebug() << Q_FUNC_INFO << "Running on: " << QThread::currentThreadId(); | ||
169 | 153 | #endif | ||
170 | 154 | |||
171 | 155 | QDir tmpDir = QDir(mPathName, QString(), QDir::NoSort, mFilter); | ||
172 | 156 | QDirIterator it(tmpDir); | ||
173 | 157 | QVector<QFileInfo> directoryContents; | ||
174 | 158 | |||
175 | 159 | while (it.hasNext()) { | ||
176 | 160 | it.next(); | ||
177 | 161 | |||
178 | 162 | directoryContents.append(it.fileInfo()); | ||
179 | 163 | if (directoryContents.count() >= 50) { | ||
180 | 164 | emit itemsAdded(directoryContents); | ||
181 | 165 | |||
182 | 166 | // clear() would force a deallocation, micro-optimization | ||
183 | 167 | directoryContents.erase(directoryContents.begin(), directoryContents.end()); | ||
184 | 168 | } | ||
185 | 169 | } | ||
186 | 170 | |||
187 | 171 | // last batch | ||
188 | 172 | emit itemsAdded(directoryContents); | ||
189 | 173 | emit workerFinished(); | ||
190 | 174 | } | ||
191 | 175 | |||
192 | 176 | signals: | ||
193 | 177 | void itemsAdded(const QVector<QFileInfo> &files); | ||
194 | 178 | void workerFinished(); | ||
195 | 179 | |||
196 | 180 | private: | ||
197 | 181 | QString mPathName; | ||
198 | 182 | QDir::Filter mFilter; | ||
199 | 183 | }; | ||
200 | 184 | |||
201 | 185 | DirModel::DirModel(QObject *parent) | ||
202 | 186 | : QAbstractListModel(parent) | ||
203 | 187 | , mShowDirectories(true) | ||
204 | 188 | , mAwaitingResults(false) | ||
205 | 189 | , mShowHiddenFiles(false) | ||
206 | 190 | , mSortBy(SortByName) | ||
207 | 191 | , mSortOrder(SortAscending) | ||
208 | 192 | , mCompareFunction(0) | ||
209 | 193 | , m_fsAction(new FileSystemAction(this) ) | ||
210 | 194 | { | ||
211 | 195 | mNameFilters = QStringList() << "*"; | ||
212 | 196 | |||
213 | 197 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | ||
214 | 198 | // There's no setRoleNames in Qt5. | ||
215 | 199 | setRoleNames(buildRoleNames()); | ||
216 | 200 | #else | ||
217 | 201 | // In Qt5, the roleNames() is virtual and will work just fine. | ||
218 | 202 | #endif | ||
219 | 203 | |||
220 | 204 | connect(m_fsAction, SIGNAL(progress(int,int,int)), | ||
221 | 205 | this, SIGNAL(progress(int,int,int))); | ||
222 | 206 | |||
223 | 207 | connect(m_fsAction, SIGNAL(added(QFileInfo)), | ||
224 | 208 | this, SLOT(onItemAdded(QFileInfo))); | ||
225 | 209 | |||
226 | 210 | connect(m_fsAction, SIGNAL(added(QString)), | ||
227 | 211 | this, SLOT(onItemAdded(QString))); | ||
228 | 212 | |||
229 | 213 | connect(m_fsAction, SIGNAL(removed(QFileInfo)), | ||
230 | 214 | this, SLOT(onItemRemoved(QFileInfo))); | ||
231 | 215 | |||
232 | 216 | connect(m_fsAction, SIGNAL(removed(QString)), | ||
233 | 217 | this, SLOT(onItemRemoved(QString))); | ||
234 | 218 | |||
235 | 219 | connect(m_fsAction, SIGNAL(error(QString,QString)), | ||
236 | 220 | this, SIGNAL(error(QString,QString))); | ||
237 | 221 | |||
238 | 222 | connect(this, SIGNAL(pathChanged(QString)), | ||
239 | 223 | m_fsAction, SLOT(pathChanged(QString))); | ||
240 | 224 | |||
241 | 225 | connect(m_fsAction, SIGNAL(clipboardChanged()), | ||
242 | 226 | this, SIGNAL(clipboardChanged())); | ||
243 | 227 | |||
244 | 228 | setCompareAndReorder(); | ||
245 | 229 | } | ||
246 | 230 | |||
247 | 231 | DirModel::~DirModel() | ||
248 | 232 | { | ||
249 | 233 | } | ||
250 | 234 | |||
251 | 235 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
252 | 236 | // roleNames has changed between Qt4 and Qt5. In Qt5 it is a virtual | ||
253 | 237 | // function and setRoleNames should not be used. | ||
254 | 238 | QHash<int, QByteArray> DirModel::roleNames() const | ||
255 | 239 | { | ||
256 | 240 | static QHash<int, QByteArray> roles; | ||
257 | 241 | if (roles.isEmpty()) { | ||
258 | 242 | roles = buildRoleNames(); | ||
259 | 243 | } | ||
260 | 244 | |||
261 | 245 | return roles; | ||
262 | 246 | } | ||
263 | 247 | #endif | ||
264 | 248 | |||
265 | 249 | QHash<int, QByteArray> DirModel::buildRoleNames() const | ||
266 | 250 | { | ||
267 | 251 | QHash<int, QByteArray> roles; | ||
268 | 252 | roles.insert(FileNameRole, QByteArray("fileName")); | ||
269 | 253 | roles.insert(CreationDateRole, QByteArray("creationDate")); | ||
270 | 254 | roles.insert(ModifiedDateRole, QByteArray("modifiedDate")); | ||
271 | 255 | roles.insert(FileSizeRole, QByteArray("fileSize")); | ||
272 | 256 | roles.insert(IconSourceRole, QByteArray("iconSource")); | ||
273 | 257 | roles.insert(FilePathRole, QByteArray("filePath")); | ||
274 | 258 | roles.insert(IsDirRole, QByteArray("isDir")); | ||
275 | 259 | roles.insert(IsFileRole, QByteArray("isFile")); | ||
276 | 260 | roles.insert(IsReadableRole, QByteArray("isReadable")); | ||
277 | 261 | roles.insert(IsWritableRole, QByteArray("isWritable")); | ||
278 | 262 | roles.insert(IsExecutableRole, QByteArray("isExecutable")); | ||
279 | 263 | |||
280 | 264 | // populate reverse mapping | ||
281 | 265 | if (roleMapping.isEmpty()) { | ||
282 | 266 | QHash<int, QByteArray>::ConstIterator it = roles.constBegin(); | ||
283 | 267 | for (;it != roles.constEnd(); ++it) | ||
284 | 268 | roleMapping.insert(it.value(), it.key()); | ||
285 | 269 | |||
286 | 270 | // make sure we cover all roles | ||
287 | 271 | // Q_ASSERT(roles.count() == IsFileRole - FileNameRole); | ||
288 | 272 | } | ||
289 | 273 | |||
290 | 274 | return roles; | ||
291 | 275 | } | ||
292 | 276 | |||
293 | 277 | QVariant DirModel::data(int row, const QByteArray &stringRole) const | ||
294 | 278 | { | ||
295 | 279 | QHash<QByteArray, int>::ConstIterator it = roleMapping.constFind(stringRole); | ||
296 | 280 | |||
297 | 281 | if (it == roleMapping.constEnd()) | ||
298 | 282 | return QVariant(); | ||
299 | 283 | |||
300 | 284 | return data(index(row, 0), *it); | ||
301 | 285 | } | ||
302 | 286 | |||
303 | 287 | QVariant DirModel::data(const QModelIndex &index, int role) const | ||
304 | 288 | { | ||
305 | 289 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) | ||
306 | 290 | if (!index.isValid() || (role != Qt::DisplayRole && role != Qt::DecorationRole) ) | ||
307 | 291 | { | ||
308 | 292 | return QVariant(); | ||
309 | 293 | } | ||
310 | 294 | if (role == Qt::DecorationRole) | ||
311 | 295 | { | ||
312 | 296 | if (index.column() == 0) | ||
313 | 297 | { | ||
314 | 298 | QMimeDatabase database; | ||
315 | 299 | QIcon icon; | ||
316 | 300 | QMimeType mime = database.mimeTypeForFile(mDirectoryContents.at(index.row())); | ||
317 | 301 | if (mime.isValid()) { | ||
318 | 302 | icon = QIcon::fromTheme(mime.iconName()); | ||
319 | 303 | } | ||
320 | 304 | if (icon.isNull()) { | ||
321 | 305 | icon = QFileIconProvider().icon(mDirectoryContents.at(index.row())); | ||
322 | 306 | } | ||
323 | 307 | return icon; | ||
324 | 308 | } | ||
325 | 309 | return QVariant(); | ||
326 | 310 | } | ||
327 | 311 | role = FileNameRole + index.column(); | ||
328 | 312 | #else | ||
329 | 313 | if (role < FileNameRole || role > IsExecutableRole) { | ||
330 | 314 | qWarning() << Q_FUNC_INFO << "Got an out of range role: " << role; | ||
331 | 315 | return QVariant(); | ||
332 | 316 | } | ||
333 | 317 | |||
334 | 318 | if (index.row() < 0 || index.row() >= mDirectoryContents.count()) { | ||
335 | 319 | qWarning() << "Attempted to access out of range row: " << index.row(); | ||
336 | 320 | return QVariant(); | ||
337 | 321 | } | ||
338 | 322 | |||
339 | 323 | if (index.column() != 0) | ||
340 | 324 | return QVariant(); | ||
341 | 325 | #endif | ||
342 | 326 | |||
343 | 327 | const QFileInfo &fi = mDirectoryContents.at(index.row()); | ||
344 | 328 | |||
345 | 329 | switch (role) { | ||
346 | 330 | case FileNameRole: | ||
347 | 331 | return fi.fileName(); | ||
348 | 332 | case CreationDateRole: | ||
349 | 333 | return fi.created(); | ||
350 | 334 | case ModifiedDateRole: | ||
351 | 335 | return fi.lastModified(); | ||
352 | 336 | case FileSizeRole: { | ||
353 | 337 | if (fi.isDir()) | ||
354 | 338 | { | ||
355 | 339 | return dirItems(fi); | ||
356 | 340 | } | ||
357 | 341 | return fileSize(fi.size()); | ||
358 | 342 | } | ||
359 | 343 | case IconSourceRole: { | ||
360 | 344 | const QString &fileName = fi.fileName(); | ||
361 | 345 | |||
362 | 346 | if (fi.isDir()) | ||
363 | 347 | return QLatin1String("image://theme/icon-m-common-directory"); | ||
364 | 348 | |||
365 | 349 | if (fileName.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive) || | ||
366 | 350 | fileName.endsWith(QLatin1String(".png"), Qt::CaseInsensitive)) { | ||
367 | 351 | return QLatin1String("image://nemoThumbnail/") + fi.filePath(); | ||
368 | 352 | } | ||
369 | 353 | |||
370 | 354 | return "image://theme/icon-m-content-document"; | ||
371 | 355 | } | ||
372 | 356 | case FilePathRole: | ||
373 | 357 | return fi.filePath(); | ||
374 | 358 | case IsDirRole: | ||
375 | 359 | return fi.isDir(); | ||
376 | 360 | case IsFileRole: | ||
377 | 361 | return !fi.isDir(); | ||
378 | 362 | case IsReadableRole: | ||
379 | 363 | return fi.isReadable(); | ||
380 | 364 | case IsWritableRole: | ||
381 | 365 | return fi.isWritable(); | ||
382 | 366 | case IsExecutableRole: | ||
383 | 367 | return fi.isExecutable(); | ||
384 | 368 | default: | ||
385 | 369 | #if !defined(REGRESSION_TEST_FOLDERLISTMODEL) | ||
386 | 370 | // this should not happen, ever | ||
387 | 371 | Q_ASSERT(false); | ||
388 | 372 | qWarning() << Q_FUNC_INFO << "Got an unknown role: " << role; | ||
389 | 373 | #endif | ||
390 | 374 | return QVariant(); | ||
391 | 375 | } | ||
392 | 376 | } | ||
393 | 377 | |||
394 | 378 | void DirModel::setPath(const QString &pathName) | ||
395 | 379 | { | ||
396 | 380 | if (pathName.isEmpty()) | ||
397 | 381 | return; | ||
398 | 382 | |||
399 | 383 | if (mAwaitingResults) { | ||
400 | 384 | // TODO: handle the case where pathName != our current path, cancel old | ||
401 | 385 | // request, start a new one | ||
402 | 386 | qDebug() << Q_FUNC_INFO << "Ignoring path change request, request already running"; | ||
403 | 387 | return; | ||
404 | 388 | } | ||
405 | 389 | |||
406 | 390 | mAwaitingResults = true; | ||
407 | 391 | emit awaitingResultsChanged(); | ||
408 | 392 | #if DEBUG_MESSAGES | ||
409 | 393 | qDebug() << Q_FUNC_INFO << "Changing to " << pathName << " on " << QThread::currentThreadId(); | ||
410 | 394 | #endif | ||
411 | 395 | beginResetModel(); | ||
412 | 396 | mDirectoryContents.clear(); | ||
413 | 397 | endResetModel(); | ||
414 | 398 | |||
415 | 399 | QDir::Filter dirFilter = currentDirFilter(); | ||
416 | 400 | // TODO: we need to set a spinner active before we start getting results from DirListWorker | ||
417 | 401 | DirListWorker *dlw = new DirListWorker(pathName, dirFilter); | ||
418 | 402 | connect(dlw, SIGNAL(itemsAdded(QVector<QFileInfo>)), SLOT(onItemsAdded(QVector<QFileInfo>))); | ||
419 | 403 | connect(dlw, SIGNAL(workerFinished()), SLOT(onResultsFetched())); | ||
420 | 404 | ioWorkerThread()->addRequest(dlw); | ||
421 | 405 | |||
422 | 406 | mCurrentDir = pathName; | ||
423 | 407 | emit pathChanged(pathName); | ||
424 | 408 | } | ||
425 | 409 | |||
426 | 410 | |||
427 | 411 | void DirModel::onResultsFetched() { | ||
428 | 412 | if (mAwaitingResults) { | ||
429 | 413 | #if DEBUG_MESSAGES | ||
430 | 414 | qDebug() << Q_FUNC_INFO << "No longer awaiting results"; | ||
431 | 415 | #endif | ||
432 | 416 | mAwaitingResults = false; | ||
433 | 417 | emit awaitingResultsChanged(); | ||
434 | 418 | } | ||
435 | 419 | } | ||
436 | 420 | |||
437 | 421 | void DirModel::onItemsAdded(const QVector<QFileInfo> &newFiles) | ||
438 | 422 | { | ||
439 | 423 | #if DEBUG_MESSAGES | ||
440 | 424 | qDebug() << Q_FUNC_INFO << "Got new files: " << newFiles.count(); | ||
441 | 425 | #endif | ||
442 | 426 | |||
443 | 427 | foreach (const QFileInfo &fi, newFiles) { | ||
444 | 428 | |||
445 | 429 | bool doAdd = true; | ||
446 | 430 | foreach (const QString &nameFilter, mNameFilters) { | ||
447 | 431 | // TODO: using QRegExp for wildcard matching is slow | ||
448 | 432 | QRegExp re(nameFilter, Qt::CaseInsensitive, QRegExp::Wildcard); | ||
449 | 433 | if (!re.exactMatch(fi.fileName())) { | ||
450 | 434 | doAdd = false; | ||
451 | 435 | break; | ||
452 | 436 | } | ||
453 | 437 | } | ||
454 | 438 | |||
455 | 439 | if (!doAdd) | ||
456 | 440 | continue; | ||
457 | 441 | |||
458 | 442 | addItem(fi); | ||
459 | 443 | } | ||
460 | 444 | } | ||
461 | 445 | |||
462 | 446 | void DirModel::rm(const QStringList &paths) | ||
463 | 447 | { | ||
464 | 448 | m_fsAction->remove(paths); | ||
465 | 449 | } | ||
466 | 450 | |||
467 | 451 | bool DirModel::rename(int row, const QString &newName) | ||
468 | 452 | { | ||
469 | 453 | #if DEBUG_MESSAGES | ||
470 | 454 | qDebug() << Q_FUNC_INFO << "Renaming " << row << " to " << newName; | ||
471 | 455 | #endif | ||
472 | 456 | |||
473 | 457 | if (!IS_VALID_ROW(row)) { | ||
474 | 458 | WARN_ROW_OUT_OF_RANGE(row); | ||
475 | 459 | return false; | ||
476 | 460 | } | ||
477 | 461 | |||
478 | 462 | const QFileInfo &fi = mDirectoryContents.at(row); | ||
479 | 463 | QString newFullFilename(fi.absolutePath() + QDir::separator() + newName); | ||
480 | 464 | |||
481 | 465 | //QFile::rename() works for File and Dir | ||
482 | 466 | QFile f(fi.absoluteFilePath()); | ||
483 | 467 | bool retval = f.rename(newFullFilename); | ||
484 | 468 | if (!retval) | ||
485 | 469 | { | ||
486 | 470 | qDebug() << Q_FUNC_INFO << "Rename returned error code: " << f.error() << f.errorString(); | ||
487 | 471 | emit(QObject::tr("Rename error"), f.errorString()); | ||
488 | 472 | } | ||
489 | 473 | else | ||
490 | 474 | { | ||
491 | 475 | mDirectoryContents[row] = QFileInfo(newFullFilename); | ||
492 | 476 | QModelIndex idx = createIndex(row,0); | ||
493 | 477 | emit dataChanged(idx, idx); | ||
494 | 478 | } | ||
495 | 479 | return retval; | ||
496 | 480 | } | ||
497 | 481 | |||
498 | 482 | void DirModel::mkdir(const QString &newDir) | ||
499 | 483 | { | ||
500 | 484 | QDir dir(mCurrentDir); | ||
501 | 485 | bool retval = dir.mkdir(newDir); | ||
502 | 486 | if (!retval) { | ||
503 | 487 | const char *errorStr = strerror(errno); | ||
504 | 488 | qDebug() << Q_FUNC_INFO << "Error creating new directory: " << errno << " (" << errorStr << ")"; | ||
505 | 489 | emit error(QObject::tr("Error creating new folder"), errorStr); | ||
506 | 490 | } else { | ||
507 | 491 | onItemAdded(dir.filePath(newDir)); | ||
508 | 492 | } | ||
509 | 493 | } | ||
510 | 494 | |||
511 | 495 | bool DirModel::showDirectories() const | ||
512 | 496 | { | ||
513 | 497 | return mShowDirectories; | ||
514 | 498 | } | ||
515 | 499 | |||
516 | 500 | void DirModel::setShowDirectories(bool showDirectories) | ||
517 | 501 | { | ||
518 | 502 | mShowDirectories = showDirectories; | ||
519 | 503 | refresh(); | ||
520 | 504 | emit showDirectoriesChanged(); | ||
521 | 505 | } | ||
522 | 506 | |||
523 | 507 | QStringList DirModel::nameFilters() const | ||
524 | 508 | { | ||
525 | 509 | return mNameFilters; | ||
526 | 510 | } | ||
527 | 511 | |||
528 | 512 | void DirModel::setNameFilters(const QStringList &nameFilters) | ||
529 | 513 | { | ||
530 | 514 | mNameFilters = nameFilters; | ||
531 | 515 | refresh(); | ||
532 | 516 | emit nameFiltersChanged(); | ||
533 | 517 | } | ||
534 | 518 | |||
535 | 519 | bool DirModel::awaitingResults() const | ||
536 | 520 | { | ||
537 | 521 | return mAwaitingResults; | ||
538 | 522 | } | ||
539 | 523 | |||
540 | 524 | |||
541 | 525 | QString DirModel::parentPath() const | ||
542 | 526 | { | ||
543 | 527 | QDir dir(mCurrentDir); | ||
544 | 528 | if (dir.isRoot()) { | ||
545 | 529 | qDebug() << Q_FUNC_INFO << "already at root"; | ||
546 | 530 | return mCurrentDir; | ||
547 | 531 | } | ||
548 | 532 | |||
549 | 533 | bool success = dir.cdUp(); | ||
550 | 534 | if (!success) { | ||
551 | 535 | qWarning() << Q_FUNC_INFO << "Failed to to go to parent of " << mCurrentDir; | ||
552 | 536 | return mCurrentDir; | ||
553 | 537 | } | ||
554 | 538 | qDebug() << Q_FUNC_INFO << "returning" << dir.absolutePath(); | ||
555 | 539 | return dir.absolutePath(); | ||
556 | 540 | } | ||
557 | 541 | |||
558 | 542 | QString DirModel::homePath() const | ||
559 | 543 | { | ||
560 | 544 | return QDir::homePath(); | ||
561 | 545 | } | ||
562 | 546 | |||
563 | 547 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) | ||
564 | 548 | QVariant DirModel::headerData(int section, Qt::Orientation orientation, int role) const | ||
565 | 549 | { | ||
566 | 550 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) | ||
567 | 551 | { | ||
568 | 552 | QVariant ret; | ||
569 | 553 | QHash<int, QByteArray> roles = this->roleNames(); | ||
570 | 554 | section += FileNameRole; | ||
571 | 555 | if (roles.contains(section)) | ||
572 | 556 | { | ||
573 | 557 | QString header= QString(roles.value(section)); | ||
574 | 558 | ret = header; | ||
575 | 559 | } | ||
576 | 560 | return ret; | ||
577 | 561 | } | ||
578 | 562 | return QAbstractItemModel::headerData(section, orientation, role); | ||
579 | 563 | } | ||
580 | 564 | #endif | ||
581 | 565 | |||
582 | 566 | |||
583 | 567 | void DirModel::goHome() | ||
584 | 568 | { | ||
585 | 569 | setPath(QDir::homePath()); | ||
586 | 570 | } | ||
587 | 571 | |||
588 | 572 | |||
589 | 573 | bool DirModel::cdUp() | ||
590 | 574 | { | ||
591 | 575 | int ret = false; | ||
592 | 576 | if (!mCurrentDir.isEmpty()) // we are in any dir | ||
593 | 577 | { | ||
594 | 578 | QDir current(mCurrentDir); | ||
595 | 579 | if (current.cdUp()) | ||
596 | 580 | { | ||
597 | 581 | setPath(current.absolutePath()); | ||
598 | 582 | ret = true; | ||
599 | 583 | } | ||
600 | 584 | } | ||
601 | 585 | return ret; | ||
602 | 586 | } | ||
603 | 587 | |||
604 | 588 | |||
605 | 589 | void DirModel::removeIndex(int row) | ||
606 | 590 | { | ||
607 | 591 | if (IS_VALID_ROW(row)) | ||
608 | 592 | { | ||
609 | 593 | const QFileInfo &fi = mDirectoryContents.at(row); | ||
610 | 594 | QStringList list(fi.absoluteFilePath()); | ||
611 | 595 | this->rm(list); | ||
612 | 596 | } | ||
613 | 597 | else | ||
614 | 598 | { | ||
615 | 599 | WARN_ROW_OUT_OF_RANGE(row); | ||
616 | 600 | } | ||
617 | 601 | } | ||
618 | 602 | |||
619 | 603 | void DirModel::removePaths(const QStringList& items) | ||
620 | 604 | { | ||
621 | 605 | this->rm(items); | ||
622 | 606 | } | ||
623 | 607 | |||
624 | 608 | void DirModel::copyIndex(int row) | ||
625 | 609 | { | ||
626 | 610 | if (IS_VALID_ROW(row)) | ||
627 | 611 | { | ||
628 | 612 | const QFileInfo &fi = mDirectoryContents.at(row); | ||
629 | 613 | QStringList list(fi.absoluteFilePath()); | ||
630 | 614 | this->copyPaths(list); | ||
631 | 615 | } | ||
632 | 616 | else | ||
633 | 617 | { | ||
634 | 618 | WARN_ROW_OUT_OF_RANGE(row); | ||
635 | 619 | } | ||
636 | 620 | } | ||
637 | 621 | |||
638 | 622 | void DirModel::copyPaths(const QStringList &items) | ||
639 | 623 | { | ||
640 | 624 | m_fsAction->copy(items); | ||
641 | 625 | } | ||
642 | 626 | |||
643 | 627 | |||
644 | 628 | void DirModel::cutIndex(int row) | ||
645 | 629 | { | ||
646 | 630 | if (IS_VALID_ROW(row)) | ||
647 | 631 | { | ||
648 | 632 | const QFileInfo &fi = mDirectoryContents.at(row); | ||
649 | 633 | QStringList list(fi.absoluteFilePath()); | ||
650 | 634 | m_fsAction->cut(list); | ||
651 | 635 | } | ||
652 | 636 | else | ||
653 | 637 | { | ||
654 | 638 | WARN_ROW_OUT_OF_RANGE(row); | ||
655 | 639 | } | ||
656 | 640 | } | ||
657 | 641 | |||
658 | 642 | |||
659 | 643 | void DirModel::cutPaths(const QStringList &items) | ||
660 | 644 | { | ||
661 | 645 | m_fsAction->cut(items); | ||
662 | 646 | } | ||
663 | 647 | |||
664 | 648 | |||
665 | 649 | void DirModel::paste() | ||
666 | 650 | { | ||
667 | 651 | m_fsAction->paste(); | ||
668 | 652 | } | ||
669 | 653 | |||
670 | 654 | |||
671 | 655 | bool DirModel::cdIntoIndex(int row) | ||
672 | 656 | { | ||
673 | 657 | bool ret = false; | ||
674 | 658 | if (IS_VALID_ROW(row)) | ||
675 | 659 | { | ||
676 | 660 | ret = cdInto(mDirectoryContents.at(row)); | ||
677 | 661 | } | ||
678 | 662 | else | ||
679 | 663 | { | ||
680 | 664 | WARN_ROW_OUT_OF_RANGE(row); | ||
681 | 665 | } | ||
682 | 666 | return ret; | ||
683 | 667 | } | ||
684 | 668 | |||
685 | 669 | |||
686 | 670 | bool DirModel::cdIntoPath(const QString &filename) | ||
687 | 671 | { | ||
688 | 672 | QFileInfo fi(filename); | ||
689 | 673 | if (fi.isRelative()) | ||
690 | 674 | { | ||
691 | 675 | fi.setFile(mCurrentDir, filename); | ||
692 | 676 | } | ||
693 | 677 | return cdInto(fi); | ||
694 | 678 | } | ||
695 | 679 | |||
696 | 680 | |||
697 | 681 | bool DirModel::cdInto(const QFileInfo &fi) | ||
698 | 682 | { | ||
699 | 683 | bool ret = false; | ||
700 | 684 | if (fi.exists() && fi.isDir() && fi.isReadable()) | ||
701 | 685 | { | ||
702 | 686 | QDir childDir(mCurrentDir); | ||
703 | 687 | if ( childDir.cd(fi.fileName()) ) | ||
704 | 688 | { | ||
705 | 689 | setPath(childDir.absolutePath()); | ||
706 | 690 | ret = true; | ||
707 | 691 | } | ||
708 | 692 | } | ||
709 | 693 | return ret; | ||
710 | 694 | } | ||
711 | 695 | |||
712 | 696 | /*! | ||
713 | 697 | * \brief DirModel::onItemRemoved() | ||
714 | 698 | * \param pathname full pathname of removed file | ||
715 | 699 | */ | ||
716 | 700 | void DirModel::onItemRemoved(const QString &pathname) | ||
717 | 701 | { | ||
718 | 702 | QFileInfo info(pathname); | ||
719 | 703 | onItemRemoved(info); | ||
720 | 704 | } | ||
721 | 705 | |||
722 | 706 | |||
723 | 707 | void DirModel::onItemRemoved(const QFileInfo &fi) | ||
724 | 708 | { | ||
725 | 709 | int row = rowOfItem(fi); | ||
726 | 710 | if (row >= 0) | ||
727 | 711 | { | ||
728 | 712 | beginRemoveRows(QModelIndex(), row, row); | ||
729 | 713 | mDirectoryContents.remove(row,1); | ||
730 | 714 | endRemoveRows(); | ||
731 | 715 | } | ||
732 | 716 | } | ||
733 | 717 | |||
734 | 718 | /*! | ||
735 | 719 | * \brief DirModel::onItemAdded() | ||
736 | 720 | * \param pathname full pathname of the added file | ||
737 | 721 | */ | ||
738 | 722 | void DirModel::onItemAdded(const QString &pathname) | ||
739 | 723 | { | ||
740 | 724 | QFileInfo info(pathname); | ||
741 | 725 | onItemAdded(info); | ||
742 | 726 | } | ||
743 | 727 | |||
744 | 728 | |||
745 | 729 | void DirModel::onItemAdded(const QFileInfo &fi) | ||
746 | 730 | { | ||
747 | 731 | int newRow = addItem(fi); | ||
748 | 732 | emit insertedRow(newRow); | ||
749 | 733 | } | ||
750 | 734 | |||
751 | 735 | /*! | ||
752 | 736 | * \brief DirModel::addItem() adds an item into the model | ||
753 | 737 | * This code was moved from onItemsAdded(const QVector<QFileInfo> &newFiles), | ||
754 | 738 | * the reason is: this code now is used for \ref mkdir() and for \ref paste() operations | ||
755 | 739 | * that inserts new items | ||
756 | 740 | * \param fi | ||
757 | 741 | * \return the index where it was inserted, it can be used in the view | ||
758 | 742 | * \sa insertedRow() | ||
759 | 743 | */ | ||
760 | 744 | int DirModel::addItem(const QFileInfo &fi) | ||
761 | 745 | { | ||
762 | 746 | QVector<QFileInfo>::Iterator it = qLowerBound(mDirectoryContents.begin(), | ||
763 | 747 | mDirectoryContents.end(), | ||
764 | 748 | fi, | ||
765 | 749 | mCompareFunction); | ||
766 | 750 | int idx = mDirectoryContents.count(); | ||
767 | 751 | |||
768 | 752 | if (it == mDirectoryContents.end()) { | ||
769 | 753 | beginInsertRows(QModelIndex(), mDirectoryContents.count(), mDirectoryContents.count()); | ||
770 | 754 | mDirectoryContents.append(fi); | ||
771 | 755 | endInsertRows(); | ||
772 | 756 | } else { | ||
773 | 757 | idx = it - mDirectoryContents.begin(); | ||
774 | 758 | beginInsertRows(QModelIndex(), idx, idx); | ||
775 | 759 | mDirectoryContents.insert(it, fi); | ||
776 | 760 | endInsertRows(); | ||
777 | 761 | } | ||
778 | 762 | return idx; | ||
779 | 763 | } | ||
780 | 764 | |||
781 | 765 | |||
782 | 766 | |||
783 | 767 | void DirModel::cancelAction() | ||
784 | 768 | { | ||
785 | 769 | m_fsAction->cancel(); | ||
786 | 770 | } | ||
787 | 771 | |||
788 | 772 | |||
789 | 773 | QString DirModel::fileSize(qint64 size) const | ||
790 | 774 | { | ||
791 | 775 | struct UnitSizes | ||
792 | 776 | { | ||
793 | 777 | qint64 bytes; | ||
794 | 778 | const char *name; | ||
795 | 779 | }; | ||
796 | 780 | |||
797 | 781 | static UnitSizes m_unitBytes[5] = | ||
798 | 782 | { | ||
799 | 783 | { 1, "Bytes" } | ||
800 | 784 | ,{1024, "KB"} | ||
801 | 785 | // got it from http://wiki.answers.com/Q/How_many_bytes_are_in_a_megabyte | ||
802 | 786 | ,{1000 * 1000, "MB"} | ||
803 | 787 | ,{1000 * m_unitBytes[2].bytes, "GB"} | ||
804 | 788 | ,{1000 * m_unitBytes[3].bytes, "TB"} | ||
805 | 789 | }; | ||
806 | 790 | |||
807 | 791 | QString ret; | ||
808 | 792 | int unit = sizeof(m_unitBytes)/sizeof(m_unitBytes[0]); | ||
809 | 793 | while( unit-- > 1 && size < m_unitBytes[unit].bytes ); | ||
810 | 794 | if (unit > 0 ) | ||
811 | 795 | { | ||
812 | 796 | ret.sprintf("%0.1f %s", (float)size/m_unitBytes[unit].bytes, | ||
813 | 797 | m_unitBytes[unit].name); | ||
814 | 798 | } | ||
815 | 799 | else | ||
816 | 800 | { | ||
817 | 801 | ret.sprintf("%ld %s", (long int)size, m_unitBytes[0].name); | ||
818 | 802 | } | ||
819 | 803 | return ret; | ||
820 | 804 | } | ||
821 | 805 | |||
822 | 806 | |||
823 | 807 | |||
824 | 808 | bool DirModel::getShowHiddenFiles() const | ||
825 | 809 | { | ||
826 | 810 | return mShowHiddenFiles; | ||
827 | 811 | } | ||
828 | 812 | |||
829 | 813 | |||
830 | 814 | void DirModel::setShowHiddenFiles(bool show) | ||
831 | 815 | { | ||
832 | 816 | if (show != mShowHiddenFiles) | ||
833 | 817 | { | ||
834 | 818 | mShowHiddenFiles = show; | ||
835 | 819 | refresh(); | ||
836 | 820 | emit showHiddenFilesChanged(); | ||
837 | 821 | } | ||
838 | 822 | } | ||
839 | 823 | |||
840 | 824 | |||
841 | 825 | void DirModel::toggleShowDirectories() | ||
842 | 826 | { | ||
843 | 827 | setShowDirectories(!mShowDirectories); | ||
844 | 828 | } | ||
845 | 829 | |||
846 | 830 | |||
847 | 831 | void DirModel::toggleShowHiddenFiles() | ||
848 | 832 | { | ||
849 | 833 | setShowHiddenFiles(!mShowHiddenFiles); | ||
850 | 834 | } | ||
851 | 835 | |||
852 | 836 | |||
853 | 837 | DirModel::SortBy | ||
854 | 838 | DirModel::getSortBy() const | ||
855 | 839 | { | ||
856 | 840 | return mSortBy; | ||
857 | 841 | } | ||
858 | 842 | |||
859 | 843 | |||
860 | 844 | void DirModel::setSortBy(SortBy field) | ||
861 | 845 | { | ||
862 | 846 | if (field != mSortBy) | ||
863 | 847 | { | ||
864 | 848 | mSortBy = field; | ||
865 | 849 | setCompareAndReorder(); | ||
866 | 850 | emit sortByChanged(); | ||
867 | 851 | } | ||
868 | 852 | } | ||
869 | 853 | |||
870 | 854 | |||
871 | 855 | DirModel::SortOrder | ||
872 | 856 | DirModel::getSortOrder() const | ||
873 | 857 | { | ||
874 | 858 | return mSortOrder; | ||
875 | 859 | } | ||
876 | 860 | |||
877 | 861 | void DirModel::setSortOrder(SortOrder order) | ||
878 | 862 | { | ||
879 | 863 | if ( order != mSortOrder ) | ||
880 | 864 | { | ||
881 | 865 | mSortOrder = order; | ||
882 | 866 | setCompareAndReorder(); | ||
883 | 867 | emit sortOrderChanged(); | ||
884 | 868 | } | ||
885 | 869 | } | ||
886 | 870 | |||
887 | 871 | |||
888 | 872 | void DirModel::toggleSortOrder() | ||
889 | 873 | { | ||
890 | 874 | SortOrder order = static_cast<SortOrder> (mSortOrder ^ 1); | ||
891 | 875 | setSortOrder(order); | ||
892 | 876 | } | ||
893 | 877 | |||
894 | 878 | |||
895 | 879 | void DirModel::toggleSortBy() | ||
896 | 880 | { | ||
897 | 881 | SortBy by = static_cast<SortBy> (mSortBy ^ 1); | ||
898 | 882 | setSortBy(by); | ||
899 | 883 | } | ||
900 | 884 | |||
901 | 885 | /*! | ||
902 | 886 | * \brief DirModel::setCompareAndReorder() called when SortOrder or SortBy change | ||
903 | 887 | * | ||
904 | 888 | * It does not reload items from disk, just reorganize items from \a mDirectoryContents array | ||
905 | 889 | */ | ||
906 | 890 | void DirModel::setCompareAndReorder() | ||
907 | 891 | { | ||
908 | 892 | mCompareFunction = availableCompareFunctions[mSortBy][mSortOrder]; | ||
909 | 893 | if (mDirectoryContents.count() > 0 && !mAwaitingResults ) | ||
910 | 894 | { | ||
911 | 895 | QVector<QFileInfo> tmpDirectoryContents = mDirectoryContents; | ||
912 | 896 | beginResetModel(); | ||
913 | 897 | mDirectoryContents.clear(); | ||
914 | 898 | endResetModel(); | ||
915 | 899 | for(int counter=0; counter < tmpDirectoryContents.count(); counter++) | ||
916 | 900 | { | ||
917 | 901 | addItem(tmpDirectoryContents.at(counter)); | ||
918 | 902 | } | ||
919 | 903 | } | ||
920 | 904 | } | ||
921 | 905 | |||
922 | 906 | |||
923 | 907 | int DirModel::getClipboardUrlsCounter() const | ||
924 | 908 | { | ||
925 | 909 | return m_fsAction->clipboardLocalUrlsConunter(); | ||
926 | 910 | } | ||
927 | 911 | |||
928 | 912 | |||
929 | 913 | int DirModel::rowOfItem(const QFileInfo& fi) | ||
930 | 914 | { | ||
931 | 915 | QVector<QFileInfo>::Iterator it = qBinaryFind(mDirectoryContents.begin(), | ||
932 | 916 | mDirectoryContents.end(), | ||
933 | 917 | fi, | ||
934 | 918 | fileCompareExists); | ||
935 | 919 | int row; | ||
936 | 920 | if (it == mDirectoryContents.end()) | ||
937 | 921 | { | ||
938 | 922 | row = -1; | ||
939 | 923 | } | ||
940 | 924 | else | ||
941 | 925 | { | ||
942 | 926 | row = it - mDirectoryContents.begin(); | ||
943 | 927 | } | ||
944 | 928 | return row; | ||
945 | 929 | } | ||
946 | 930 | |||
947 | 931 | |||
948 | 932 | QDir::Filter DirModel::currentDirFilter() const | ||
949 | 933 | { | ||
950 | 934 | int filter = QDir::AllEntries | QDir::NoDotAndDotDot ; | ||
951 | 935 | if (!mShowDirectories) | ||
952 | 936 | { | ||
953 | 937 | filter &= ~QDir::AllDirs; | ||
954 | 938 | filter &= ~QDir::Dirs; | ||
955 | 939 | } | ||
956 | 940 | if (mShowHiddenFiles) | ||
957 | 941 | { | ||
958 | 942 | filter |= QDir::Hidden; | ||
959 | 943 | } | ||
960 | 944 | QDir::Filter dirFilter = static_cast<QDir::Filter>(filter); | ||
961 | 945 | return dirFilter; | ||
962 | 946 | } | ||
963 | 947 | |||
964 | 948 | QString DirModel::dirItems(const QFileInfo& fi) const | ||
965 | 949 | { | ||
966 | 950 | int counter = 0; | ||
967 | 951 | QDir d(fi.absoluteFilePath(), QString(), QDir::NoSort, currentDirFilter()); | ||
968 | 952 | counter = d.count(); | ||
969 | 953 | if (counter < 0) | ||
970 | 954 | { | ||
971 | 955 | counter = 0; | ||
972 | 956 | } | ||
973 | 957 | QString ret (QString::number(counter) + QLatin1Char(' ')); | ||
974 | 958 | ret += QObject::tr("items"); | ||
975 | 959 | return ret; | ||
976 | 960 | } | ||
977 | 961 | |||
978 | 962 | |||
979 | 963 | bool DirModel::openIndex(int row) | ||
980 | 964 | { | ||
981 | 965 | bool ret = false; | ||
982 | 966 | if (IS_VALID_ROW(row)) | ||
983 | 967 | { | ||
984 | 968 | ret = openItem(mDirectoryContents.at(row)); | ||
985 | 969 | } | ||
986 | 970 | else | ||
987 | 971 | { | ||
988 | 972 | WARN_ROW_OUT_OF_RANGE(row); | ||
989 | 973 | } | ||
990 | 974 | return ret; | ||
991 | 975 | } | ||
992 | 976 | |||
993 | 977 | bool DirModel::openPath(const QString &filename) | ||
994 | 978 | { | ||
995 | 979 | QFileInfo fi(filename); | ||
996 | 980 | if (fi.isRelative()) | ||
997 | 981 | { | ||
998 | 982 | fi.setFile(mCurrentDir, filename); | ||
999 | 983 | } | ||
1000 | 984 | return openItem(fi); | ||
1001 | 985 | } | ||
1002 | 986 | |||
1003 | 987 | bool DirModel::openItem(const QFileInfo &fi) | ||
1004 | 988 | { | ||
1005 | 989 | bool ret = false; | ||
1006 | 990 | if (fi.exists()) | ||
1007 | 991 | { | ||
1008 | 992 | if (fi.isDir()) | ||
1009 | 993 | { | ||
1010 | 994 | ret = cdInto(fi); | ||
1011 | 995 | } | ||
1012 | 996 | else | ||
1013 | 997 | { | ||
1014 | 998 | ret = QDesktopServices::openUrl(QUrl::fromLocalFile(fi.absoluteFilePath())); | ||
1015 | 999 | } | ||
1016 | 1000 | } | ||
1017 | 1001 | return ret; | ||
1018 | 1002 | } | ||
1019 | 1003 | |||
1020 | 1004 | // for dirlistworker | ||
1021 | 1005 | #include "dirmodel.moc" | ||
1022 | 0 | 1006 | ||
1023 | === added file 'folderlistmodel/dirmodel.h' | |||
1024 | --- folderlistmodel/dirmodel.h 1970-01-01 00:00:00 +0000 | |||
1025 | +++ folderlistmodel/dirmodel.h 2013-06-01 17:20:36 +0000 | |||
1026 | @@ -0,0 +1,328 @@ | |||
1027 | 1 | /* | ||
1028 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
1029 | 3 | * | ||
1030 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
1031 | 5 | * | ||
1032 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
1033 | 7 | * modification, are permitted provided that the following conditions are | ||
1034 | 8 | * met: | ||
1035 | 9 | * * Redistributions of source code must retain the above copyright | ||
1036 | 10 | * notice, this list of conditions and the following disclaimer. | ||
1037 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
1038 | 12 | * notice, this list of conditions and the following disclaimer in | ||
1039 | 13 | * the documentation and/or other materials provided with the | ||
1040 | 14 | * distribution. | ||
1041 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
1042 | 16 | * may be used to endorse or promote products derived from this | ||
1043 | 17 | * software without specific prior written permission. | ||
1044 | 18 | * | ||
1045 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
1046 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
1047 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
1048 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
1049 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
1050 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
1051 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
1052 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
1053 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
1054 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
1055 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
1056 | 30 | */ | ||
1057 | 31 | |||
1058 | 32 | #ifndef DIRMODEL_H | ||
1059 | 33 | #define DIRMODEL_H | ||
1060 | 34 | |||
1061 | 35 | #include <QAbstractListModel> | ||
1062 | 36 | #include <QFileInfo> | ||
1063 | 37 | #include <QVector> | ||
1064 | 38 | #include <QStringList> | ||
1065 | 39 | #include <QDir> | ||
1066 | 40 | |||
1067 | 41 | #include "iorequest.h" | ||
1068 | 42 | |||
1069 | 43 | class FileSystemAction; | ||
1070 | 44 | typedef bool (*CompareFunction)(const QFileInfo &a, const QFileInfo &b); | ||
1071 | 45 | |||
1072 | 46 | class DirModel : public QAbstractListModel | ||
1073 | 47 | { | ||
1074 | 48 | Q_OBJECT | ||
1075 | 49 | public: | ||
1076 | 50 | enum Roles { | ||
1077 | 51 | FileNameRole = Qt::UserRole, | ||
1078 | 52 | CreationDateRole, | ||
1079 | 53 | ModifiedDateRole, | ||
1080 | 54 | FileSizeRole, | ||
1081 | 55 | IconSourceRole, | ||
1082 | 56 | FilePathRole, | ||
1083 | 57 | IsDirRole, | ||
1084 | 58 | IsFileRole, | ||
1085 | 59 | IsReadableRole, | ||
1086 | 60 | IsWritableRole, | ||
1087 | 61 | IsExecutableRole | ||
1088 | 62 | }; | ||
1089 | 63 | |||
1090 | 64 | public: | ||
1091 | 65 | explicit DirModel(QObject *parent = 0); | ||
1092 | 66 | ~DirModel(); | ||
1093 | 67 | |||
1094 | 68 | int rowCount(const QModelIndex &index = QModelIndex()) const | ||
1095 | 69 | { | ||
1096 | 70 | if (index.parent() != QModelIndex()) | ||
1097 | 71 | return 0; | ||
1098 | 72 | return mDirectoryContents.count(); | ||
1099 | 73 | } | ||
1100 | 74 | |||
1101 | 75 | // TODO: this won't be safe if the model can change under the holder of the row | ||
1102 | 76 | Q_INVOKABLE QVariant data(int row, const QByteArray &stringRole) const; | ||
1103 | 77 | |||
1104 | 78 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; | ||
1105 | 79 | |||
1106 | 80 | Q_INVOKABLE void refresh() | ||
1107 | 81 | { | ||
1108 | 82 | // just some syntactical sugar really | ||
1109 | 83 | setPath(path()); | ||
1110 | 84 | } | ||
1111 | 85 | |||
1112 | 86 | Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged) | ||
1113 | 87 | inline QString path() const { return mCurrentDir; } | ||
1114 | 88 | void setPath(const QString &pathName); | ||
1115 | 89 | |||
1116 | 90 | Q_PROPERTY(bool awaitingResults READ awaitingResults NOTIFY awaitingResultsChanged) | ||
1117 | 91 | bool awaitingResults() const; | ||
1118 | 92 | |||
1119 | 93 | Q_INVOKABLE void rm(const QStringList &paths); | ||
1120 | 94 | |||
1121 | 95 | Q_INVOKABLE bool rename(int row, const QString &newName); | ||
1122 | 96 | |||
1123 | 97 | Q_INVOKABLE void mkdir(const QString &newdir); | ||
1124 | 98 | |||
1125 | 99 | Q_PROPERTY(bool showDirectories READ showDirectories WRITE setShowDirectories NOTIFY showDirectoriesChanged) | ||
1126 | 100 | bool showDirectories() const; | ||
1127 | 101 | |||
1128 | 102 | Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) | ||
1129 | 103 | QStringList nameFilters() const; | ||
1130 | 104 | void setNameFilters(const QStringList &nameFilters); | ||
1131 | 105 | |||
1132 | 106 | public slots: | ||
1133 | 107 | void onItemsAdded(const QVector<QFileInfo> &newFiles); | ||
1134 | 108 | void onResultsFetched(); | ||
1135 | 109 | |||
1136 | 110 | signals: | ||
1137 | 111 | void awaitingResultsChanged(); | ||
1138 | 112 | void nameFiltersChanged(); | ||
1139 | 113 | void showDirectoriesChanged(); | ||
1140 | 114 | void pathChanged(const QString& newPath); | ||
1141 | 115 | void error(const QString &errorTitle, const QString &errorMessage); | ||
1142 | 116 | |||
1143 | 117 | private: | ||
1144 | 118 | QHash<int, QByteArray> buildRoleNames() const; | ||
1145 | 119 | #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) | ||
1146 | 120 | // In Qt5, the roleNames() is virtual and will work just fine. On qt4 setRoleNames must be used with buildRoleNames. | ||
1147 | 121 | QHash<int, QByteArray> roleNames() const; | ||
1148 | 122 | #endif | ||
1149 | 123 | |||
1150 | 124 | QStringList mNameFilters; | ||
1151 | 125 | bool mShowDirectories; | ||
1152 | 126 | bool mAwaitingResults; | ||
1153 | 127 | QString mCurrentDir; | ||
1154 | 128 | QVector<QFileInfo> mDirectoryContents; | ||
1155 | 129 | |||
1156 | 130 | public: | ||
1157 | 131 | //[0] new stuff Ubuntu File Manager | ||
1158 | 132 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) | ||
1159 | 133 | //make this work with tables | ||
1160 | 134 | virtual int columnCount(const QModelIndex &) const | ||
1161 | 135 | { | ||
1162 | 136 | return IsExecutableRole - FileNameRole + 1; | ||
1163 | 137 | } | ||
1164 | 138 | virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const; | ||
1165 | 139 | #endif | ||
1166 | 140 | |||
1167 | 141 | Q_PROPERTY(QString parentPath READ parentPath NOTIFY pathChanged) | ||
1168 | 142 | QString parentPath() const; | ||
1169 | 143 | |||
1170 | 144 | Q_PROPERTY(bool showHiddenFiles READ getShowHiddenFiles WRITE setShowHiddenFiles NOTIFY showHiddenFilesChanged) | ||
1171 | 145 | bool getShowHiddenFiles() const; | ||
1172 | 146 | |||
1173 | 147 | Q_ENUMS(SortBy) | ||
1174 | 148 | enum SortBy | ||
1175 | 149 | { | ||
1176 | 150 | SortByName, | ||
1177 | 151 | SortByDate | ||
1178 | 152 | }; | ||
1179 | 153 | Q_PROPERTY(SortBy sortBy READ getSortBy WRITE setSortBy NOTIFY sortByChanged) | ||
1180 | 154 | SortBy getSortBy() const; | ||
1181 | 155 | |||
1182 | 156 | Q_ENUMS(SortOrder) | ||
1183 | 157 | enum SortOrder | ||
1184 | 158 | { | ||
1185 | 159 | SortAscending = Qt::AscendingOrder, | ||
1186 | 160 | SortDescending = Qt::DescendingOrder | ||
1187 | 161 | }; | ||
1188 | 162 | Q_PROPERTY(SortOrder sortOrder READ getSortOrder WRITE setSortOrder NOTIFY sortOrderChanged) | ||
1189 | 163 | SortOrder getSortOrder() const; | ||
1190 | 164 | |||
1191 | 165 | Q_PROPERTY(int clipboardUrlsCounter READ getClipboardUrlsCounter NOTIFY clipboardChanged) | ||
1192 | 166 | int getClipboardUrlsCounter() const; | ||
1193 | 167 | |||
1194 | 168 | Q_INVOKABLE QString homePath() const; | ||
1195 | 169 | |||
1196 | 170 | /*! | ||
1197 | 171 | * \brief Tries to make the directory pointed by row as the current to be browsed | ||
1198 | 172 | * \return true if row points to a directory and the directory is readble, false otherwise | ||
1199 | 173 | */ | ||
1200 | 174 | Q_INVOKABLE bool cdIntoIndex(int row); | ||
1201 | 175 | |||
1202 | 176 | Q_INVOKABLE bool cdIntoPath(const QString& filename); | ||
1203 | 177 | /*! | ||
1204 | 178 | * \brief copyIndex() puts the item pointed by \a row (dir or file) into the clipboard | ||
1205 | 179 | * \param row points to the item file or directory | ||
1206 | 180 | */ | ||
1207 | 181 | Q_INVOKABLE void copyIndex(int row); | ||
1208 | 182 | |||
1209 | 183 | /*! | ||
1210 | 184 | * \brief copyPaths(const QStringList& urls) several items (dirs or files) into the clipboard | ||
1211 | 185 | * \param items fullpathnames or names only | ||
1212 | 186 | */ | ||
1213 | 187 | Q_INVOKABLE void copyPaths(const QStringList& items); | ||
1214 | 188 | |||
1215 | 189 | /*! | ||
1216 | 190 | * \brief cutIndex() puts the item into the clipboard as \ref copy(), | ||
1217 | 191 | * mark the item to be removed after \ref paste() | ||
1218 | 192 | * \param row points to the item file or directory | ||
1219 | 193 | */ | ||
1220 | 194 | Q_INVOKABLE void cutIndex(int row); | ||
1221 | 195 | |||
1222 | 196 | /*! | ||
1223 | 197 | * \brief cut() puts several items (dirs or files) into the clipboard as \ref copy(), | ||
1224 | 198 | * mark the item to be removed after \ref paste() | ||
1225 | 199 | * \param items fullpathnames or names only | ||
1226 | 200 | */ | ||
1227 | 201 | Q_INVOKABLE void cutPaths(const QStringList& items); | ||
1228 | 202 | |||
1229 | 203 | /*! | ||
1230 | 204 | * \brief removeIndex(); remove a item file or directory | ||
1231 | 205 | * | ||
1232 | 206 | * I gets the item indicated by \row and calls \ref rm() | ||
1233 | 207 | * | ||
1234 | 208 | * \param row points to the item to b e removed | ||
1235 | 209 | * \return true if it was possible to remove the item | ||
1236 | 210 | */ | ||
1237 | 211 | Q_INVOKABLE void removeIndex(int row); | ||
1238 | 212 | |||
1239 | 213 | /*! | ||
1240 | 214 | * Just calls \ref rm() | ||
1241 | 215 | */ | ||
1242 | 216 | Q_INVOKABLE void removePaths(const QStringList& items); | ||
1243 | 217 | |||
1244 | 218 | /*! | ||
1245 | 219 | * Tries to open a file using a suitable application, if the index points to a directory | ||
1246 | 220 | * it goes into it using \ref cdIntoIndex() or \ref cdIntoPath() | ||
1247 | 221 | * | ||
1248 | 222 | * \note Qt uses Qt QDesktopServices::openUrl() | ||
1249 | 223 | */ | ||
1250 | 224 | |||
1251 | 225 | Q_INVOKABLE bool openIndex(int row); | ||
1252 | 226 | /*! | ||
1253 | 227 | * Same as \ref openIndex() but using a file name instead of index | ||
1254 | 228 | * | ||
1255 | 229 | * \sa \ref cdIntoPath() | ||
1256 | 230 | */ | ||
1257 | 231 | Q_INVOKABLE bool openPath(const QString& filename); | ||
1258 | 232 | |||
1259 | 233 | public slots: | ||
1260 | 234 | /*! | ||
1261 | 235 | * \brief goHome() goes to user home dir | ||
1262 | 236 | * Go to user home dir, we may have a tab for places or something like that | ||
1263 | 237 | */ | ||
1264 | 238 | void goHome(); | ||
1265 | 239 | |||
1266 | 240 | /*! | ||
1267 | 241 | * \brief cdUp() sets the parent directory as current directory | ||
1268 | 242 | * | ||
1269 | 243 | * It can work as a back function if there is no user input path | ||
1270 | 244 | * \return true if it was possible to change to parent dir, otherwise false | ||
1271 | 245 | */ | ||
1272 | 246 | bool cdUp(); | ||
1273 | 247 | |||
1274 | 248 | /*! | ||
1275 | 249 | * \brief paste() copy item(s) from \ref copy() and \ref paste() into the current directory | ||
1276 | 250 | * | ||
1277 | 251 | * If the operation was \ref cut(), then remove the original item | ||
1278 | 252 | */ | ||
1279 | 253 | void paste(); | ||
1280 | 254 | |||
1281 | 255 | /*! | ||
1282 | 256 | * \brief cancelAction() any copy/cut/remove can be cancelled | ||
1283 | 257 | */ | ||
1284 | 258 | void cancelAction(); | ||
1285 | 259 | |||
1286 | 260 | void setShowDirectories(bool showDirectories); | ||
1287 | 261 | void setShowHiddenFiles(bool show); | ||
1288 | 262 | void setSortBy(SortBy field); | ||
1289 | 263 | void setSortOrder(SortOrder order); | ||
1290 | 264 | |||
1291 | 265 | void toggleShowDirectories(); | ||
1292 | 266 | void toggleShowHiddenFiles(); | ||
1293 | 267 | void toggleSortOrder(); | ||
1294 | 268 | void toggleSortBy(); | ||
1295 | 269 | |||
1296 | 270 | signals: | ||
1297 | 271 | /*! | ||
1298 | 272 | * \brief insertedItem() | ||
1299 | 273 | * | ||
1300 | 274 | * It happens when a new file is inserted in an existent view, | ||
1301 | 275 | * for example from \ref mkdir() or \ref paste() | ||
1302 | 276 | * | ||
1303 | 277 | * It can be used to make the new row visible to the user doing a scroll to | ||
1304 | 278 | */ | ||
1305 | 279 | void insertedRow(int row); | ||
1306 | 280 | /*! | ||
1307 | 281 | * \brief progress() | ||
1308 | 282 | * Sends status about recursive and multi-items remove/move/copy | ||
1309 | 283 | * | ||
1310 | 284 | * \param curItem current item being handled | ||
1311 | 285 | * \param totalItems total of items including recursive directories content | ||
1312 | 286 | * \param percent a percent done | ||
1313 | 287 | */ | ||
1314 | 288 | void progress(int curItem, int totalItems, int percent); | ||
1315 | 289 | |||
1316 | 290 | void showHiddenFilesChanged(); | ||
1317 | 291 | void sortByChanged(); | ||
1318 | 292 | void sortOrderChanged(); | ||
1319 | 293 | |||
1320 | 294 | void clipboardChanged(); | ||
1321 | 295 | |||
1322 | 296 | private slots: | ||
1323 | 297 | void onItemRemoved(const QString&); | ||
1324 | 298 | void onItemRemoved(const QFileInfo&); | ||
1325 | 299 | void onItemAdded(const QString&); | ||
1326 | 300 | void onItemAdded(const QFileInfo&); | ||
1327 | 301 | |||
1328 | 302 | private: | ||
1329 | 303 | int addItem(const QFileInfo& fi); | ||
1330 | 304 | void setCompareAndReorder(); | ||
1331 | 305 | int rowOfItem(const QFileInfo& fi); | ||
1332 | 306 | QDir::Filter currentDirFilter() const; | ||
1333 | 307 | QString dirItems(const QFileInfo& fi) const; | ||
1334 | 308 | bool cdInto(const QFileInfo& fi); | ||
1335 | 309 | bool openItem(const QFileInfo& fi); | ||
1336 | 310 | |||
1337 | 311 | private: | ||
1338 | 312 | bool mShowHiddenFiles; | ||
1339 | 313 | SortBy mSortBy; | ||
1340 | 314 | SortOrder mSortOrder; | ||
1341 | 315 | CompareFunction mCompareFunction; | ||
1342 | 316 | |||
1343 | 317 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) //used in Unit/Regression tests | ||
1344 | 318 | public: | ||
1345 | 319 | #else | ||
1346 | 320 | private: | ||
1347 | 321 | #endif | ||
1348 | 322 | FileSystemAction * m_fsAction; //!< it does file system recursive remove/copy/move | ||
1349 | 323 | QString fileSize(qint64 size) const; | ||
1350 | 324 | //[0] | ||
1351 | 325 | }; | ||
1352 | 326 | |||
1353 | 327 | |||
1354 | 328 | #endif // DIRMODEL_H | ||
1355 | 0 | 329 | ||
1356 | === added file 'folderlistmodel/filesystemaction.cpp' | |||
1357 | --- folderlistmodel/filesystemaction.cpp 1970-01-01 00:00:00 +0000 | |||
1358 | +++ folderlistmodel/filesystemaction.cpp 2013-06-01 17:20:36 +0000 | |||
1359 | @@ -0,0 +1,1389 @@ | |||
1360 | 1 | /************************************************************************** | ||
1361 | 2 | * | ||
1362 | 3 | * Copyright 2013 Canonical Ltd. | ||
1363 | 4 | * Copyright 2013 Carlos J Mazieri <carlos.mazieri@gmail.com> | ||
1364 | 5 | * | ||
1365 | 6 | * You may use this file under the terms of the BSD license as follows: | ||
1366 | 7 | * | ||
1367 | 8 | * "Redistribution and use in source and binary forms, with or without | ||
1368 | 9 | * modification, are permitted provided that the following conditions are | ||
1369 | 10 | * met: | ||
1370 | 11 | * * Redistributions of source code must retain the above copyright | ||
1371 | 12 | * notice, this list of conditions and the following disclaimer. | ||
1372 | 13 | * * Redistributions in binary form must reproduce the above copyright | ||
1373 | 14 | * notice, this list of conditions and the following disclaimer in | ||
1374 | 15 | * the documentation and/or other materials provided with the | ||
1375 | 16 | * distribution. | ||
1376 | 17 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
1377 | 18 | * may be used to endorse or promote products derived from this | ||
1378 | 19 | * software without specific prior written permission. | ||
1379 | 20 | * | ||
1380 | 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
1381 | 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
1382 | 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
1383 | 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
1384 | 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
1385 | 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
1386 | 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
1387 | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
1388 | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
1389 | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
1390 | 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
1391 | 32 | * | ||
1392 | 33 | * File: filesystemaction.cpp | ||
1393 | 34 | * Date: 3/13/2013 | ||
1394 | 35 | */ | ||
1395 | 36 | |||
1396 | 37 | #include "filesystemaction.h" | ||
1397 | 38 | #include <sys/statvfs.h> | ||
1398 | 39 | #include <errno.h> | ||
1399 | 40 | |||
1400 | 41 | #include <QDirIterator> | ||
1401 | 42 | #include <QDebug> | ||
1402 | 43 | #include <QTimer> | ||
1403 | 44 | #include <QMimeData> | ||
1404 | 45 | #include <QClipboard> | ||
1405 | 46 | #include <QApplication> | ||
1406 | 47 | #include <QUrl> | ||
1407 | 48 | #include <QFileInfo> | ||
1408 | 49 | #include <QDir> | ||
1409 | 50 | #include <QThread> | ||
1410 | 51 | #include <QTemporaryFile> | ||
1411 | 52 | |||
1412 | 53 | #define STEP_FILES 5 // number of the files to work on a step, when this number is reached a signal is emitted | ||
1413 | 54 | |||
1414 | 55 | #define SHOULD_EMIT_PROGRESS_SIGNAL(action) (1) | ||
1415 | 56 | |||
1416 | 57 | #define COMMON_SIZE_ITEM 120 | ||
1417 | 58 | |||
1418 | 59 | RemoveNotifier FileSystemAction::m_removeNotifier; | ||
1419 | 60 | |||
1420 | 61 | static QLatin1String GNOME_COPIED_MIME_TYPE ("x-special/gnome-copied-files"); | ||
1421 | 62 | static QLatin1String KDE_CUT_MIME_TYPE ("application/x-kde-cutselection"); | ||
1422 | 63 | |||
1423 | 64 | |||
1424 | 65 | |||
1425 | 66 | class DirModelMimeData : public QMimeData | ||
1426 | 67 | { | ||
1427 | 68 | public: | ||
1428 | 69 | enum ClipBoardDataOwner | ||
1429 | 70 | { | ||
1430 | 71 | Nobody, // might have failed | ||
1431 | 72 | Application, | ||
1432 | 73 | MySelf | ||
1433 | 74 | }; | ||
1434 | 75 | |||
1435 | 76 | explicit DirModelMimeData(); | ||
1436 | 77 | ~DirModelMimeData(); | ||
1437 | 78 | virtual QStringList formats() const { return m_formats; } | ||
1438 | 79 | virtual bool hasFormat ( const QString & mimeType ) const; | ||
1439 | 80 | public: | ||
1440 | 81 | ClipBoardDataOwner setIntoClipboard(const QStringList& files, | ||
1441 | 82 | const QString &path, | ||
1442 | 83 | ClipboardOperation operation); | ||
1443 | 84 | const QMimeData *clipboardMimeData(); | ||
1444 | 85 | QStringList localUrls(ClipboardOperation& operation); | ||
1445 | 86 | private: | ||
1446 | 87 | static QList<QUrl> gnomeUrls(const QMimeData *mime, ClipboardOperation& operation); | ||
1447 | 88 | ClipboardOperation clipBoardOperation(); | ||
1448 | 89 | bool fillClipboard(const QStringList& files, const QString &path, ClipboardOperation operation); | ||
1449 | 90 | private: | ||
1450 | 91 | QStringList m_formats; | ||
1451 | 92 | const QMimeData * m_appMime; | ||
1452 | 93 | QByteArray gnomeData; | ||
1453 | 94 | QList<QUrl> urls; | ||
1454 | 95 | static DirModelMimeData* m_globalMimeData; //!< some mobile devices do not use X, they may not have clipboard | ||
1455 | 96 | static int instances; | ||
1456 | 97 | }; | ||
1457 | 98 | |||
1458 | 99 | |||
1459 | 100 | int DirModelMimeData::instances = 0; | ||
1460 | 101 | DirModelMimeData* DirModelMimeData::m_globalMimeData = 0; | ||
1461 | 102 | |||
1462 | 103 | void FileSystemAction::CopyFile::clear() | ||
1463 | 104 | { | ||
1464 | 105 | bytesWritten = 0; | ||
1465 | 106 | if (source) delete source; | ||
1466 | 107 | if (target) delete target; | ||
1467 | 108 | source = 0; | ||
1468 | 109 | target = 0; | ||
1469 | 110 | } | ||
1470 | 111 | |||
1471 | 112 | bool DirModelMimeData::hasFormat ( const QString & mimeType ) const | ||
1472 | 113 | { | ||
1473 | 114 | bool ret = false; | ||
1474 | 115 | if ( mimeType == KDE_CUT_MIME_TYPE ) | ||
1475 | 116 | { | ||
1476 | 117 | ret = true; | ||
1477 | 118 | } | ||
1478 | 119 | else | ||
1479 | 120 | { | ||
1480 | 121 | ret = m_formats.contains(mimeType); | ||
1481 | 122 | } | ||
1482 | 123 | return ret; | ||
1483 | 124 | } | ||
1484 | 125 | |||
1485 | 126 | //=============================================================================================== | ||
1486 | 127 | /*! | ||
1487 | 128 | * \brief DirModelMimeData::DirModelMimeData | ||
1488 | 129 | */ | ||
1489 | 130 | DirModelMimeData::DirModelMimeData() : | ||
1490 | 131 | QMimeData() | ||
1491 | 132 | , m_appMime(0) | ||
1492 | 133 | { | ||
1493 | 134 | m_formats.append("text/uri-list"); | ||
1494 | 135 | m_formats.append(GNOME_COPIED_MIME_TYPE); | ||
1495 | 136 | m_formats.append("text/plain"); | ||
1496 | 137 | m_formats.append("COMPOUND_TEXT"); | ||
1497 | 138 | m_formats.append("TARGETS"); | ||
1498 | 139 | m_formats.append("MULTIPLE"); | ||
1499 | 140 | m_formats.append("TIMESTAMP"); | ||
1500 | 141 | m_formats.append("SAVE_TARGETS"); | ||
1501 | 142 | |||
1502 | 143 | ++instances; | ||
1503 | 144 | #if DEBUG_MESSAGES | ||
1504 | 145 | qDebug() << Q_FUNC_INFO << this << "instances" << instances; | ||
1505 | 146 | #endif | ||
1506 | 147 | } | ||
1507 | 148 | |||
1508 | 149 | |||
1509 | 150 | |||
1510 | 151 | |||
1511 | 152 | DirModelMimeData::~DirModelMimeData() | ||
1512 | 153 | { | ||
1513 | 154 | --instances; | ||
1514 | 155 | #if DEBUG_MESSAGES | ||
1515 | 156 | qDebug() << Q_FUNC_INFO << this << "instances" << instances | ||
1516 | 157 | << "m_globalMimeData" << m_globalMimeData; | ||
1517 | 158 | #endif | ||
1518 | 159 | if (instances == 1 && m_globalMimeData) | ||
1519 | 160 | { | ||
1520 | 161 | DirModelMimeData * tmp = m_globalMimeData; | ||
1521 | 162 | m_globalMimeData = 0; | ||
1522 | 163 | delete tmp; | ||
1523 | 164 | } | ||
1524 | 165 | } | ||
1525 | 166 | |||
1526 | 167 | //=============================================================================================== | ||
1527 | 168 | /*! | ||
1528 | 169 | * \brief DirModelMimeData::gnomeUrls | ||
1529 | 170 | * \param mime | ||
1530 | 171 | * \param operation | ||
1531 | 172 | * \return | ||
1532 | 173 | */ | ||
1533 | 174 | QList<QUrl> | ||
1534 | 175 | DirModelMimeData::gnomeUrls(const QMimeData * mime, | ||
1535 | 176 | ClipboardOperation& operation) | ||
1536 | 177 | { | ||
1537 | 178 | QList<QUrl> urls; | ||
1538 | 179 | if (mime->hasFormat(GNOME_COPIED_MIME_TYPE)) | ||
1539 | 180 | { | ||
1540 | 181 | QByteArray bytes = mime->data(GNOME_COPIED_MIME_TYPE); | ||
1541 | 182 | QList<QString> d = QString(bytes).split(QLatin1String("\r\n"), | ||
1542 | 183 | QString::SkipEmptyParts); | ||
1543 | 184 | for (int counter= 0; counter < d.count(); counter++) | ||
1544 | 185 | { | ||
1545 | 186 | if (counter==0) | ||
1546 | 187 | { | ||
1547 | 188 | QStringList couple = d.at(0).split(QLatin1Char('\n')); | ||
1548 | 189 | urls.append(couple[1]); | ||
1549 | 190 | if (couple[0] == QLatin1String("cut")) { | ||
1550 | 191 | operation = ClipboardCut; | ||
1551 | 192 | } | ||
1552 | 193 | else { | ||
1553 | 194 | operation = ClipboardCopy; | ||
1554 | 195 | } | ||
1555 | 196 | } | ||
1556 | 197 | else { | ||
1557 | 198 | urls.append(d.at(counter)); | ||
1558 | 199 | } | ||
1559 | 200 | } | ||
1560 | 201 | } | ||
1561 | 202 | return urls; | ||
1562 | 203 | } | ||
1563 | 204 | |||
1564 | 205 | //=============================================================================================== | ||
1565 | 206 | /*! | ||
1566 | 207 | * \brief DirModelMimeData::clipBoardOperation() | ||
1567 | 208 | * \param mime | ||
1568 | 209 | * \return | ||
1569 | 210 | */ | ||
1570 | 211 | ClipboardOperation DirModelMimeData::clipBoardOperation() | ||
1571 | 212 | { | ||
1572 | 213 | ClipboardOperation op = ClipboardCopy; | ||
1573 | 214 | m_appMime = clipboardMimeData(); | ||
1574 | 215 | if (m_appMime) | ||
1575 | 216 | { | ||
1576 | 217 | //first check for GNOME clipboard format, op comes with Copy/Cut | ||
1577 | 218 | if (gnomeUrls(m_appMime, op).count() == 0) | ||
1578 | 219 | { // there is no gnome format, tries KDE format | ||
1579 | 220 | QStringList formats = m_appMime->formats(); | ||
1580 | 221 | int f = formats.count(); | ||
1581 | 222 | while(f--) | ||
1582 | 223 | { | ||
1583 | 224 | const QString &mi = formats.at(f); | ||
1584 | 225 | if(mi.startsWith(QLatin1String("application/x-kde")) ) | ||
1585 | 226 | { | ||
1586 | 227 | if (mi.contains(QLatin1String("cut"))) | ||
1587 | 228 | { | ||
1588 | 229 | op = ClipboardCut; | ||
1589 | 230 | break; | ||
1590 | 231 | } | ||
1591 | 232 | } | ||
1592 | 233 | } | ||
1593 | 234 | } | ||
1594 | 235 | } | ||
1595 | 236 | return op; | ||
1596 | 237 | } | ||
1597 | 238 | |||
1598 | 239 | |||
1599 | 240 | //=============================================================================================== | ||
1600 | 241 | /*! | ||
1601 | 242 | * \brief DirModelMimeData::setIntoClipboard | ||
1602 | 243 | * | ||
1603 | 244 | * Try to put data in the global cliboard | ||
1604 | 245 | * | ||
1605 | 246 | * \note: | ||
1606 | 247 | * On mobile devices clipboard might not work, in this case a local Clipboard is simulated | ||
1607 | 248 | * | ||
1608 | 249 | * \param files | ||
1609 | 250 | * \param path | ||
1610 | 251 | * \param isCut | ||
1611 | 252 | * \return who is owner of clipboard data | ||
1612 | 253 | */ | ||
1613 | 254 | DirModelMimeData::ClipBoardDataOwner | ||
1614 | 255 | DirModelMimeData::setIntoClipboard(const QStringList &files, const QString& path, ClipboardOperation operation) | ||
1615 | 256 | { | ||
1616 | 257 | DirModelMimeData::ClipBoardDataOwner ret = Nobody; | ||
1617 | 258 | QClipboard *clipboard = QApplication::clipboard(); | ||
1618 | 259 | if (clipboard) | ||
1619 | 260 | { | ||
1620 | 261 | ret = Application; | ||
1621 | 262 | DirModelMimeData *mime = m_globalMimeData ? m_globalMimeData | ||
1622 | 263 | : new DirModelMimeData(); | ||
1623 | 264 | if (mime->fillClipboard(files, path, operation)) | ||
1624 | 265 | { | ||
1625 | 266 | clipboard->setMimeData(mime); | ||
1626 | 267 | const QMimeData *data = clipboard->mimeData(); | ||
1627 | 268 | //it looks like some mobile devices does not have X | ||
1628 | 269 | //in this case we simulate our own clipboard | ||
1629 | 270 | if (!data && !m_globalMimeData) | ||
1630 | 271 | { | ||
1631 | 272 | m_globalMimeData = mime; | ||
1632 | 273 | } | ||
1633 | 274 | #if DEBUG_MESSAGES | ||
1634 | 275 | qDebug() << Q_FUNC_INFO << "mime" << mime << "clipboard->mimeData()" << data | ||
1635 | 276 | << "m_ownClipboardMimeData" << m_globalMimeData; | ||
1636 | 277 | #endif | ||
1637 | 278 | } | ||
1638 | 279 | else | ||
1639 | 280 | if (m_globalMimeData != mime) | ||
1640 | 281 | { | ||
1641 | 282 | delete mime; | ||
1642 | 283 | } | ||
1643 | 284 | //check if it is necessary to send notification about Clipboard changed | ||
1644 | 285 | if (m_globalMimeData) | ||
1645 | 286 | { | ||
1646 | 287 | ret = MySelf; | ||
1647 | 288 | } | ||
1648 | 289 | } | ||
1649 | 290 | return ret; | ||
1650 | 291 | } | ||
1651 | 292 | |||
1652 | 293 | |||
1653 | 294 | bool DirModelMimeData::fillClipboard(const QStringList& files, const QString &path, ClipboardOperation operation) | ||
1654 | 295 | { | ||
1655 | 296 | bool ret = false; | ||
1656 | 297 | int index = m_formats.indexOf(KDE_CUT_MIME_TYPE); | ||
1657 | 298 | if (index != -1 && operation != ClipboardCut) | ||
1658 | 299 | { | ||
1659 | 300 | m_formats.removeAt(index); | ||
1660 | 301 | } | ||
1661 | 302 | else | ||
1662 | 303 | if (operation == ClipboardCut) | ||
1663 | 304 | { | ||
1664 | 305 | m_formats.append(KDE_CUT_MIME_TYPE); | ||
1665 | 306 | } | ||
1666 | 307 | |||
1667 | 308 | urls.clear(); | ||
1668 | 309 | QFileInfo fi; | ||
1669 | 310 | gnomeData.clear(); | ||
1670 | 311 | gnomeData += operation == ClipboardCut ? | ||
1671 | 312 | QLatin1String("cut\n") : | ||
1672 | 313 | QLatin1String("copy\n"); | ||
1673 | 314 | for(int counter = 0; counter < files.count(); counter++) | ||
1674 | 315 | { | ||
1675 | 316 | const QString& item = files.at(counter); | ||
1676 | 317 | fi.setFile(item); | ||
1677 | 318 | if (!fi.isAbsolute()) | ||
1678 | 319 | { | ||
1679 | 320 | fi.setFile(path + QDir::separator() + item); | ||
1680 | 321 | } | ||
1681 | 322 | if (fi.exists()) | ||
1682 | 323 | { | ||
1683 | 324 | QUrl item = QUrl::fromLocalFile(fi.absoluteFilePath()); | ||
1684 | 325 | urls.append(item); | ||
1685 | 326 | gnomeData += item.toEncoded() + QLatin1String("\r\n"); | ||
1686 | 327 | } | ||
1687 | 328 | else | ||
1688 | 329 | { | ||
1689 | 330 | // emit error( QObject::tr("Item does not exist"), item); | ||
1690 | 331 | urls.clear(); | ||
1691 | 332 | break; | ||
1692 | 333 | } | ||
1693 | 334 | } | ||
1694 | 335 | if (urls.count() > 0) | ||
1695 | 336 | { | ||
1696 | 337 | setData(GNOME_COPIED_MIME_TYPE, gnomeData); | ||
1697 | 338 | setUrls(urls); | ||
1698 | 339 | ret = true; | ||
1699 | 340 | } | ||
1700 | 341 | return ret; | ||
1701 | 342 | } | ||
1702 | 343 | |||
1703 | 344 | //=============================================================================================== | ||
1704 | 345 | /*! | ||
1705 | 346 | * \brief DirModelMimeData::clipboardMimeData | ||
1706 | 347 | * \return | ||
1707 | 348 | */ | ||
1708 | 349 | const QMimeData *DirModelMimeData::clipboardMimeData() | ||
1709 | 350 | { | ||
1710 | 351 | const QMimeData *ret = 0; | ||
1711 | 352 | QClipboard *clipboard = QApplication::clipboard(); | ||
1712 | 353 | if (m_globalMimeData) | ||
1713 | 354 | { | ||
1714 | 355 | ret = m_globalMimeData; | ||
1715 | 356 | } | ||
1716 | 357 | else | ||
1717 | 358 | if (clipboard) | ||
1718 | 359 | { | ||
1719 | 360 | ret = clipboard->mimeData(); | ||
1720 | 361 | } | ||
1721 | 362 | #if DEBUG_MESSAGES | ||
1722 | 363 | qDebug() << Q_FUNC_INFO << "clipboard" << clipboard | ||
1723 | 364 | << "m_ownClipboardMimeData" << m_globalMimeData | ||
1724 | 365 | << "clipboard->mimeData()" << ret; | ||
1725 | 366 | #endif | ||
1726 | 367 | return ret; | ||
1727 | 368 | } | ||
1728 | 369 | |||
1729 | 370 | //=============================================================================================== | ||
1730 | 371 | /*! | ||
1731 | 372 | * \brief DirModelMimeData::localUrls | ||
1732 | 373 | * \return | ||
1733 | 374 | */ | ||
1734 | 375 | QStringList | ||
1735 | 376 | DirModelMimeData::localUrls(ClipboardOperation& operation) | ||
1736 | 377 | { | ||
1737 | 378 | m_appMime = clipboardMimeData(); | ||
1738 | 379 | QStringList paths; | ||
1739 | 380 | //it may have external urls | ||
1740 | 381 | if (m_appMime) | ||
1741 | 382 | { | ||
1742 | 383 | QList<QUrl> urls; | ||
1743 | 384 | if (m_appMime->hasUrls()) | ||
1744 | 385 | { | ||
1745 | 386 | urls = m_appMime->urls(); | ||
1746 | 387 | operation = clipBoardOperation(); | ||
1747 | 388 | } | ||
1748 | 389 | else | ||
1749 | 390 | { | ||
1750 | 391 | urls = gnomeUrls(m_appMime, operation); | ||
1751 | 392 | } | ||
1752 | 393 | for (int counter=0; counter < urls.count(); counter++) | ||
1753 | 394 | { | ||
1754 | 395 | if (urls.at(counter).toString().startsWith(QLatin1String("file://"))) | ||
1755 | 396 | { | ||
1756 | 397 | paths.append(urls.at(counter).toLocalFile()); | ||
1757 | 398 | } | ||
1758 | 399 | } | ||
1759 | 400 | } | ||
1760 | 401 | #if DEBUG_MESSAGES | ||
1761 | 402 | qDebug() << Q_FUNC_INFO << paths; | ||
1762 | 403 | #endif | ||
1763 | 404 | return paths; | ||
1764 | 405 | } | ||
1765 | 406 | |||
1766 | 407 | /*! | ||
1767 | 408 | * \brief RemoveNotifier::RemoveNotifier | ||
1768 | 409 | * \param parent | ||
1769 | 410 | */ | ||
1770 | 411 | RemoveNotifier::RemoveNotifier(QObject *parent) : | ||
1771 | 412 | QObject(parent) | ||
1772 | 413 | { | ||
1773 | 414 | } | ||
1774 | 415 | |||
1775 | 416 | //=============================================================================================== | ||
1776 | 417 | /*! | ||
1777 | 418 | * \brief RemoveNotifier::notifyRemoved | ||
1778 | 419 | * \param fi | ||
1779 | 420 | */ | ||
1780 | 421 | void RemoveNotifier::notifyRemoved(const QFileInfo &fi) | ||
1781 | 422 | { | ||
1782 | 423 | #if DEBUG_MESSAGES | ||
1783 | 424 | qDebug() << Q_FUNC_INFO << "emit removed(QFileInfo)" << fi.absoluteFilePath(); | ||
1784 | 425 | #endif | ||
1785 | 426 | emit removed(fi); | ||
1786 | 427 | } | ||
1787 | 428 | |||
1788 | 429 | //=============================================================================================== | ||
1789 | 430 | /*! | ||
1790 | 431 | * \brief RemoveNotifier::notifyRemoved | ||
1791 | 432 | * \param item | ||
1792 | 433 | */ | ||
1793 | 434 | void RemoveNotifier::notifyRemoved(const QString &item) | ||
1794 | 435 | { | ||
1795 | 436 | #if DEBUG_MESSAGES | ||
1796 | 437 | qDebug() << Q_FUNC_INFO << "emit removed(QString)" << item; | ||
1797 | 438 | #endif | ||
1798 | 439 | emit removed(item); | ||
1799 | 440 | } | ||
1800 | 441 | |||
1801 | 442 | |||
1802 | 443 | //=============================================================================================== | ||
1803 | 444 | /*! | ||
1804 | 445 | * \brief FileSystemAction::FileSystemAction | ||
1805 | 446 | * \param parent | ||
1806 | 447 | */ | ||
1807 | 448 | FileSystemAction::FileSystemAction(QObject *parent) : | ||
1808 | 449 | QObject(parent) | ||
1809 | 450 | , m_curAction(0) | ||
1810 | 451 | , m_cancelCurrentAction(false) | ||
1811 | 452 | , m_busy(false) | ||
1812 | 453 | , m_mimeData ( new DirModelMimeData() ) | ||
1813 | 454 | , m_clipboardModifiedByOther(false) | ||
1814 | 455 | { | ||
1815 | 456 | //as m_removeNotifier is static it will send signals to all instances of | ||
1816 | 457 | //the model | ||
1817 | 458 | connect(&m_removeNotifier, SIGNAL(removed(QFileInfo)), | ||
1818 | 459 | this, SIGNAL(removed(QFileInfo))); | ||
1819 | 460 | |||
1820 | 461 | connect(&m_removeNotifier, SIGNAL(removed(QString)), | ||
1821 | 462 | this, SIGNAL(removed(QString))); | ||
1822 | 463 | |||
1823 | 464 | QClipboard *clipboard = QApplication::clipboard(); | ||
1824 | 465 | |||
1825 | 466 | connect(clipboard, SIGNAL(dataChanged()), this, SIGNAL(clipboardChanged())); | ||
1826 | 467 | connect(clipboard, SIGNAL(dataChanged()), this, SLOT(clipboardHasChanged())); | ||
1827 | 468 | } | ||
1828 | 469 | |||
1829 | 470 | //=============================================================================================== | ||
1830 | 471 | /*! | ||
1831 | 472 | * \brief FileSystemAction::~FileSystemAction | ||
1832 | 473 | */ | ||
1833 | 474 | FileSystemAction::~FileSystemAction() | ||
1834 | 475 | { | ||
1835 | 476 | delete m_mimeData; | ||
1836 | 477 | } | ||
1837 | 478 | |||
1838 | 479 | //=============================================================================================== | ||
1839 | 480 | /*! | ||
1840 | 481 | * \brief FileSystemAction::remove | ||
1841 | 482 | * \param paths | ||
1842 | 483 | */ | ||
1843 | 484 | void FileSystemAction::remove(const QStringList &paths) | ||
1844 | 485 | { | ||
1845 | 486 | createAndProcessAction(ActionRemove, paths, NoClipboard); | ||
1846 | 487 | } | ||
1847 | 488 | |||
1848 | 489 | //=============================================================================================== | ||
1849 | 490 | /*! | ||
1850 | 491 | * \brief FileSystemAction::createAction | ||
1851 | 492 | * \param type | ||
1852 | 493 | * \param origBase | ||
1853 | 494 | * \return | ||
1854 | 495 | */ | ||
1855 | 496 | FileSystemAction::Action* FileSystemAction::createAction(ActionType type, int origBase) | ||
1856 | 497 | { | ||
1857 | 498 | Action * action = new Action(); | ||
1858 | 499 | action->type = type; | ||
1859 | 500 | action->baseOrigSize = origBase; | ||
1860 | 501 | action->targetPath = m_path; | ||
1861 | 502 | action->totalItems = 0; | ||
1862 | 503 | action->currItem = 0; | ||
1863 | 504 | action->currEntry = 0; | ||
1864 | 505 | action->totalBytes = 0; | ||
1865 | 506 | action->bytesWritten = 0; | ||
1866 | 507 | action->done = false; | ||
1867 | 508 | |||
1868 | 509 | return action; | ||
1869 | 510 | } | ||
1870 | 511 | |||
1871 | 512 | //=============================================================================================== | ||
1872 | 513 | /*! | ||
1873 | 514 | * \brief FileSystemAction::addEntry | ||
1874 | 515 | * \param action | ||
1875 | 516 | * \param pathname | ||
1876 | 517 | */ | ||
1877 | 518 | void FileSystemAction::addEntry(Action* action, const QString& pathname) | ||
1878 | 519 | { | ||
1879 | 520 | #if DEBUG_MESSAGES | ||
1880 | 521 | qDebug() << Q_FUNC_INFO << pathname; | ||
1881 | 522 | #endif | ||
1882 | 523 | QFileInfo info(pathname); | ||
1883 | 524 | if (!info.isAbsolute()) | ||
1884 | 525 | { | ||
1885 | 526 | info.setFile(action->targetPath, pathname); | ||
1886 | 527 | } | ||
1887 | 528 | if (!info.exists()) | ||
1888 | 529 | { | ||
1889 | 530 | emit error(QObject::tr("File or Directory does not exist"), | ||
1890 | 531 | pathname + QObject::tr(" does not exist") | ||
1891 | 532 | ); | ||
1892 | 533 | return; | ||
1893 | 534 | } | ||
1894 | 535 | ActionEntry * entry = new ActionEntry(); | ||
1895 | 536 | QFileInfo item; | ||
1896 | 537 | //ActionMove will perform a rename, so no Directory expanding is necessary | ||
1897 | 538 | if (action->type != ActionMove && info.isDir() && !info.isSymLink()) | ||
1898 | 539 | { | ||
1899 | 540 | QDirIterator it(info.absoluteFilePath(), | ||
1900 | 541 | QDir::AllEntries | QDir::System | | ||
1901 | 542 | QDir::NoDotAndDotDot | QDir::Hidden, | ||
1902 | 543 | QDirIterator::Subdirectories); | ||
1903 | 544 | while (it.hasNext() && !it.next().isEmpty()) | ||
1904 | 545 | { | ||
1905 | 546 | item = it.fileInfo(); | ||
1906 | 547 | entry->reversedOrder.prepend(it.fileInfo()); | ||
1907 | 548 | if (item.isFile() && !item.isDir() && !item.isSymLink()) | ||
1908 | 549 | { | ||
1909 | 550 | action->totalBytes += item.size(); | ||
1910 | 551 | } | ||
1911 | 552 | else | ||
1912 | 553 | { | ||
1913 | 554 | action->totalBytes += COMMON_SIZE_ITEM; | ||
1914 | 555 | } | ||
1915 | 556 | } | ||
1916 | 557 | } | ||
1917 | 558 | //this is the item being handled | ||
1918 | 559 | entry->reversedOrder.append(info); | ||
1919 | 560 | |||
1920 | 561 | // verify if the destination item already exists | ||
1921 | 562 | if (action->type == ActionCopy || action->type == ActionMove || | ||
1922 | 563 | action->type == ActionHardMoveCopy) | ||
1923 | 564 | { | ||
1924 | 565 | QFileInfo destination(targetFom(info.absoluteFilePath())); | ||
1925 | 566 | entry->alreadyExists = destination.exists(); | ||
1926 | 567 | } | ||
1927 | 568 | |||
1928 | 569 | action->totalItems += entry->reversedOrder.count(); | ||
1929 | 570 | if (info.isFile() && !info.isDir() && !info.isSymLink()) | ||
1930 | 571 | { | ||
1931 | 572 | action->totalBytes += info.size(); | ||
1932 | 573 | } | ||
1933 | 574 | else | ||
1934 | 575 | { | ||
1935 | 576 | action->totalBytes += COMMON_SIZE_ITEM; | ||
1936 | 577 | } | ||
1937 | 578 | action->entries.append(entry); | ||
1938 | 579 | } | ||
1939 | 580 | |||
1940 | 581 | //=============================================================================================== | ||
1941 | 582 | /*! | ||
1942 | 583 | * \brief FileSystemAction::processAction | ||
1943 | 584 | */ | ||
1944 | 585 | void FileSystemAction::processAction() | ||
1945 | 586 | { | ||
1946 | 587 | if (m_curAction) | ||
1947 | 588 | { | ||
1948 | 589 | //it will be ActionHardMoveRemove only when switched from ActionHardMoveCopy | ||
1949 | 590 | //in this case the move is done in two steps COPY and REMOVE | ||
1950 | 591 | if (m_curAction->type != ActionHardMoveCopy) | ||
1951 | 592 | { | ||
1952 | 593 | delete m_curAction; | ||
1953 | 594 | m_curAction = 0; | ||
1954 | 595 | } | ||
1955 | 596 | } | ||
1956 | 597 | if (!m_curAction && m_queuedActions.count()) | ||
1957 | 598 | { | ||
1958 | 599 | m_curAction = m_queuedActions.at(0); | ||
1959 | 600 | m_queuedActions.remove(0,1); | ||
1960 | 601 | } | ||
1961 | 602 | if (m_curAction) | ||
1962 | 603 | { | ||
1963 | 604 | m_busy = true; | ||
1964 | 605 | m_cancelCurrentAction = false; | ||
1965 | 606 | m_errorMsg.clear(); | ||
1966 | 607 | m_errorTitle.clear(); | ||
1967 | 608 | scheduleSlot(SLOT(processActionEntry())); | ||
1968 | 609 | if (SHOULD_EMIT_PROGRESS_SIGNAL(m_curAction)) | ||
1969 | 610 | { | ||
1970 | 611 | emit progress(0,m_curAction->totalItems, 0); | ||
1971 | 612 | } | ||
1972 | 613 | } | ||
1973 | 614 | else | ||
1974 | 615 | { | ||
1975 | 616 | m_busy = false; | ||
1976 | 617 | } | ||
1977 | 618 | } | ||
1978 | 619 | |||
1979 | 620 | |||
1980 | 621 | //=============================================================================================== | ||
1981 | 622 | /*! | ||
1982 | 623 | * \brief FileSystemAction::processActionEntry | ||
1983 | 624 | */ | ||
1984 | 625 | void FileSystemAction::processActionEntry() | ||
1985 | 626 | { | ||
1986 | 627 | #if DEBUG_MESSAGES | ||
1987 | 628 | qDebug() << Q_FUNC_INFO; | ||
1988 | 629 | #endif | ||
1989 | 630 | |||
1990 | 631 | ActionEntry * curEntry = static_cast<ActionEntry*> | ||
1991 | 632 | ( m_curAction->entries.at(m_curAction->currEntry) ); | ||
1992 | 633 | |||
1993 | 634 | #if defined(SIMULATE_LONG_ACTION) | ||
1994 | 635 | { | ||
1995 | 636 | unsigned int delay = SIMULATE_LONG_ACTION; | ||
1996 | 637 | if (delay == 1) | ||
1997 | 638 | { | ||
1998 | 639 | delay = 100; //each (10 * STEP_FILES) files will waits a second | ||
1999 | 640 | QThread::currentThread()->wait(delay); | ||
2000 | 641 | } | ||
2001 | 642 | } | ||
2002 | 643 | #endif | ||
2003 | 644 | if (!m_cancelCurrentAction) | ||
2004 | 645 | { | ||
2005 | 646 | switch(m_curAction->type) | ||
2006 | 647 | { | ||
2007 | 648 | case ActionRemove: | ||
2008 | 649 | case ActionHardMoveRemove: | ||
2009 | 650 | removeEntry(curEntry); | ||
2010 | 651 | endActionEntry(); | ||
2011 | 652 | break; | ||
2012 | 653 | case ActionCopy: | ||
2013 | 654 | case ActionHardMoveCopy: | ||
2014 | 655 | processCopyEntry(); // specially: this is a slot | ||
2015 | 656 | break; | ||
2016 | 657 | case ActionMove: | ||
2017 | 658 | moveEntry(curEntry); | ||
2018 | 659 | endActionEntry(); | ||
2019 | 660 | break; | ||
2020 | 661 | } | ||
2021 | 662 | } | ||
2022 | 663 | } | ||
2023 | 664 | |||
2024 | 665 | //=============================================================================================== | ||
2025 | 666 | /*! | ||
2026 | 667 | * \brief FileSystemAction::endActionEntry | ||
2027 | 668 | */ | ||
2028 | 669 | void FileSystemAction::endActionEntry() | ||
2029 | 670 | { | ||
2030 | 671 | #if DEBUG_MESSAGES | ||
2031 | 672 | qDebug() << Q_FUNC_INFO; | ||
2032 | 673 | #endif | ||
2033 | 674 | ActionEntry * curEntry = static_cast<ActionEntry*> | ||
2034 | 675 | ( m_curAction->entries.at(m_curAction->currEntry) ); | ||
2035 | 676 | |||
2036 | 677 | // first of all check for any error or a cancel issued by the user | ||
2037 | 678 | if (m_cancelCurrentAction) | ||
2038 | 679 | { | ||
2039 | 680 | if (!m_errorTitle.isEmpty()) | ||
2040 | 681 | { | ||
2041 | 682 | emit error(m_errorTitle, m_errorMsg); | ||
2042 | 683 | } | ||
2043 | 684 | //it may have other actions to do | ||
2044 | 685 | scheduleSlot(SLOT(processAction())); | ||
2045 | 686 | return; | ||
2046 | 687 | } | ||
2047 | 688 | // check if the current entry has finished | ||
2048 | 689 | // if so Views need to receive the notification about that | ||
2049 | 690 | if (curEntry->currItem == curEntry->reversedOrder.count()) | ||
2050 | 691 | { | ||
2051 | 692 | const QFileInfo & mainItem = curEntry->reversedOrder.at(curEntry->currItem -1); | ||
2052 | 693 | if (m_curAction->type == ActionRemove || m_curAction->type == ActionMove || | ||
2053 | 694 | m_curAction->type == ActionHardMoveRemove) | ||
2054 | 695 | { | ||
2055 | 696 | m_removeNotifier.notifyRemoved(mainItem); // notify all instances | ||
2056 | 697 | } | ||
2057 | 698 | if (m_curAction->type == ActionCopy || m_curAction->type == ActionMove || | ||
2058 | 699 | m_curAction->type == ActionHardMoveCopy) | ||
2059 | 700 | { | ||
2060 | 701 | QString addedItem = targetFom(mainItem.absoluteFilePath()); | ||
2061 | 702 | if (curEntry->alreadyExists) | ||
2062 | 703 | { | ||
2063 | 704 | m_removeNotifier.notifyRemoved(addedItem); | ||
2064 | 705 | } | ||
2065 | 706 | emit added(addedItem); | ||
2066 | 707 | } | ||
2067 | 708 | m_curAction->currEntry++; | ||
2068 | 709 | //check if is doing a hard move and the copy part has finished | ||
2069 | 710 | //if so switch the action to remove | ||
2070 | 711 | if (m_curAction->type == ActionHardMoveCopy && | ||
2071 | 712 | m_curAction->currEntry == m_curAction->entries.count() ) | ||
2072 | 713 | { | ||
2073 | 714 | m_curAction->type = ActionHardMoveRemove; | ||
2074 | 715 | m_curAction->currEntry = 0; | ||
2075 | 716 | int entryCounter = m_curAction->entries.count(); | ||
2076 | 717 | ActionEntry * entry; | ||
2077 | 718 | while (entryCounter--) | ||
2078 | 719 | { | ||
2079 | 720 | entry = m_curAction->entries.at(entryCounter); | ||
2080 | 721 | entry->currItem = 0; | ||
2081 | 722 | entry->currStep = 0; | ||
2082 | 723 | } | ||
2083 | 724 | } | ||
2084 | 725 | } | ||
2085 | 726 | if (curEntry->currStep == STEP_FILES) | ||
2086 | 727 | { | ||
2087 | 728 | curEntry->currStep = 0; | ||
2088 | 729 | } | ||
2089 | 730 | |||
2090 | 731 | int percent = notifyProgress(); | ||
2091 | 732 | //Check if the current action has finished or cancelled | ||
2092 | 733 | if (m_cancelCurrentAction || | ||
2093 | 734 | m_curAction->currEntry == m_curAction->entries.count()) | ||
2094 | 735 | { | ||
2095 | 736 | if (!m_cancelCurrentAction) | ||
2096 | 737 | { | ||
2097 | 738 | endCurrentAction(); | ||
2098 | 739 | if (percent < 100) | ||
2099 | 740 | { | ||
2100 | 741 | notifyProgress(100); | ||
2101 | 742 | } | ||
2102 | 743 | } | ||
2103 | 744 | //it may have other actions to do | ||
2104 | 745 | scheduleSlot(SLOT(processAction())); | ||
2105 | 746 | } | ||
2106 | 747 | else | ||
2107 | 748 | { | ||
2108 | 749 | //keep working on current Action maybe more entries | ||
2109 | 750 | scheduleSlot(SLOT(processActionEntry())); | ||
2110 | 751 | } | ||
2111 | 752 | } | ||
2112 | 753 | |||
2113 | 754 | //=============================================================================================== | ||
2114 | 755 | /*! | ||
2115 | 756 | * \brief FileSystemAction::cancel | ||
2116 | 757 | */ | ||
2117 | 758 | void FileSystemAction::cancel() | ||
2118 | 759 | { | ||
2119 | 760 | m_cancelCurrentAction = true; | ||
2120 | 761 | } | ||
2121 | 762 | |||
2122 | 763 | //=============================================================================================== | ||
2123 | 764 | /*! | ||
2124 | 765 | * \brief FileSystemAction::removeEntry | ||
2125 | 766 | * \param entry | ||
2126 | 767 | */ | ||
2127 | 768 | void FileSystemAction::removeEntry(ActionEntry *entry) | ||
2128 | 769 | { | ||
2129 | 770 | QDir dir; | ||
2130 | 771 | //do one step at least | ||
2131 | 772 | for(; !m_cancelCurrentAction && | ||
2132 | 773 | entry->currStep < STEP_FILES && | ||
2133 | 774 | m_curAction->currItem < m_curAction->totalItems && | ||
2134 | 775 | entry->currItem < entry->reversedOrder.count() | ||
2135 | 776 | ; entry->currStep++, m_curAction->currItem++, entry->currItem++ | ||
2136 | 777 | ) | ||
2137 | 778 | |||
2138 | 779 | { | ||
2139 | 780 | const QFileInfo &fi = entry->reversedOrder.at(entry->currItem); | ||
2140 | 781 | if (fi.isDir() && !fi.isSymLink()) | ||
2141 | 782 | { | ||
2142 | 783 | m_cancelCurrentAction = !dir.rmdir(fi.absoluteFilePath()); | ||
2143 | 784 | } | ||
2144 | 785 | else | ||
2145 | 786 | { | ||
2146 | 787 | m_cancelCurrentAction = !QFile::remove(fi.absoluteFilePath()); | ||
2147 | 788 | } | ||
2148 | 789 | #if DEBUG_REMOVE | ||
2149 | 790 | qDebug() << "remove ret=" << !m_cancelCurrentAction << fi.absoluteFilePath(); | ||
2150 | 791 | #endif | ||
2151 | 792 | if (m_cancelCurrentAction) | ||
2152 | 793 | { | ||
2153 | 794 | m_errorTitle = QObject::tr("Could not remove the item ") + | ||
2154 | 795 | fi.absoluteFilePath(); | ||
2155 | 796 | m_errorMsg = ::strerror(errno); | ||
2156 | 797 | } | ||
2157 | 798 | } | ||
2158 | 799 | } | ||
2159 | 800 | |||
2160 | 801 | //=============================================================================================== | ||
2161 | 802 | /*! | ||
2162 | 803 | * \brief FileSystemAction::copyEntry | ||
2163 | 804 | * \param entry | ||
2164 | 805 | */ | ||
2165 | 806 | void FileSystemAction::processCopyEntry() | ||
2166 | 807 | { | ||
2167 | 808 | #if DEBUG_MESSAGES | ||
2168 | 809 | qDebug() << Q_FUNC_INFO; | ||
2169 | 810 | #endif | ||
2170 | 811 | |||
2171 | 812 | ActionEntry * entry = static_cast<ActionEntry*> | ||
2172 | 813 | ( m_curAction->entries.at(m_curAction->currEntry) ); | ||
2173 | 814 | |||
2174 | 815 | /* | ||
2175 | 816 | * This flag will be true when processCopySingleFile() has put any slot in the execution queue | ||
2176 | 817 | * it will work to stop the loop. | ||
2177 | 818 | * Later processCopyEntry() will be called again to continue working | ||
2178 | 819 | */ | ||
2179 | 820 | bool scheduleAnySlot = false; | ||
2180 | 821 | |||
2181 | 822 | for(; !m_cancelCurrentAction && !scheduleAnySlot && | ||
2182 | 823 | entry->currStep < STEP_FILES && | ||
2183 | 824 | m_curAction->currItem < m_curAction->totalItems && | ||
2184 | 825 | entry->currItem < entry->reversedOrder.count() | ||
2185 | 826 | ; entry->currStep++, entry->currItem++ | ||
2186 | 827 | ) | ||
2187 | 828 | |||
2188 | 829 | { | ||
2189 | 830 | const QFileInfo &fi = entry->reversedOrder.at(entry->currItem); | ||
2190 | 831 | QString orig = fi.absoluteFilePath(); | ||
2191 | 832 | QString target = targetFom(orig); | ||
2192 | 833 | QString path(target); | ||
2193 | 834 | // do this here to allow progress send right item number, copySingleFile will emit progress() | ||
2194 | 835 | m_curAction->currItem++; | ||
2195 | 836 | |||
2196 | 837 | if (fi.isFile() || fi.isSymLink()) | ||
2197 | 838 | { | ||
2198 | 839 | QFileInfo t(target); | ||
2199 | 840 | path = t.path(); | ||
2200 | 841 | } | ||
2201 | 842 | QDir d(path); | ||
2202 | 843 | if (!d.exists() && !d.mkpath(path)) | ||
2203 | 844 | { | ||
2204 | 845 | m_cancelCurrentAction = true; | ||
2205 | 846 | m_errorTitle = QObject::tr("Could not create the directory"); | ||
2206 | 847 | m_errorMsg = path; | ||
2207 | 848 | } | ||
2208 | 849 | else | ||
2209 | 850 | if (fi.isSymLink()) | ||
2210 | 851 | { | ||
2211 | 852 | m_cancelCurrentAction = ! copySymLink(target,fi); | ||
2212 | 853 | if (m_cancelCurrentAction) | ||
2213 | 854 | { | ||
2214 | 855 | m_errorTitle = QObject::tr("Could not create link to"); | ||
2215 | 856 | m_errorMsg = target; | ||
2216 | 857 | } | ||
2217 | 858 | m_curAction->bytesWritten += COMMON_SIZE_ITEM; | ||
2218 | 859 | } | ||
2219 | 860 | else | ||
2220 | 861 | if (fi.isDir()) | ||
2221 | 862 | { | ||
2222 | 863 | m_cancelCurrentAction = ! | ||
2223 | 864 | QFile(target).setPermissions(fi.permissions()); | ||
2224 | 865 | if (m_cancelCurrentAction) | ||
2225 | 866 | { | ||
2226 | 867 | m_errorTitle = QObject::tr("Could not set permissions to dir"); | ||
2227 | 868 | m_errorMsg = target; | ||
2228 | 869 | } | ||
2229 | 870 | m_curAction->bytesWritten += COMMON_SIZE_ITEM; | ||
2230 | 871 | } | ||
2231 | 872 | else | ||
2232 | 873 | if (fi.isFile()) | ||
2233 | 874 | { | ||
2234 | 875 | m_curAction->copyFile.clear(); | ||
2235 | 876 | m_curAction->copyFile.source = new QFile(orig); | ||
2236 | 877 | if (!m_curAction->copyFile.source->open(QFile::ReadOnly)) | ||
2237 | 878 | { | ||
2238 | 879 | m_cancelCurrentAction = true; | ||
2239 | 880 | m_errorTitle = QObject::tr("Could not open file"); | ||
2240 | 881 | m_errorMsg = orig; | ||
2241 | 882 | } | ||
2242 | 883 | m_curAction->copyFile.target = new QTemporaryFile(); | ||
2243 | 884 | if (! m_curAction->copyFile.target->open()) | ||
2244 | 885 | { | ||
2245 | 886 | m_cancelCurrentAction = true; | ||
2246 | 887 | m_errorTitle = QObject::tr("Could not create temporary file"); | ||
2247 | 888 | m_errorMsg = m_curAction->copyFile.target->fileName(); | ||
2248 | 889 | } | ||
2249 | 890 | m_curAction->copyFile.targetName = target; | ||
2250 | 891 | scheduleAnySlot = processCopySingleFile(); | ||
2251 | 892 | } | ||
2252 | 893 | }//for | ||
2253 | 894 | |||
2254 | 895 | //no copy going on | ||
2255 | 896 | if (!scheduleAnySlot) | ||
2256 | 897 | { | ||
2257 | 898 | endActionEntry(); | ||
2258 | 899 | } | ||
2259 | 900 | } | ||
2260 | 901 | |||
2261 | 902 | //=============================================================================================== | ||
2262 | 903 | /*! | ||
2263 | 904 | * \brief FileSystemAction::moveEntry | ||
2264 | 905 | * \param entry | ||
2265 | 906 | */ | ||
2266 | 907 | void FileSystemAction::moveEntry(ActionEntry *entry) | ||
2267 | 908 | { | ||
2268 | 909 | QFile file; | ||
2269 | 910 | |||
2270 | 911 | for(; !m_cancelCurrentAction && | ||
2271 | 912 | entry->currStep < STEP_FILES && | ||
2272 | 913 | m_curAction->currItem < m_curAction->totalItems && | ||
2273 | 914 | entry->currItem < entry->reversedOrder.count() | ||
2274 | 915 | ; entry->currStep++, m_curAction->currItem++, entry->currItem++ | ||
2275 | 916 | ) | ||
2276 | 917 | |||
2277 | 918 | { | ||
2278 | 919 | const QFileInfo &fi = entry->reversedOrder.at(entry->currItem); | ||
2279 | 920 | file.setFileName(fi.absoluteFilePath()); | ||
2280 | 921 | QString target = targetFom(fi.absoluteFilePath()); | ||
2281 | 922 | if (!file.rename(target)) | ||
2282 | 923 | { | ||
2283 | 924 | m_cancelCurrentAction = true; | ||
2284 | 925 | m_errorTitle = QObject::tr("Could not move the directory/file ") + target; | ||
2285 | 926 | m_errorMsg = ::strerror(errno); | ||
2286 | 927 | } | ||
2287 | 928 | }//for | ||
2288 | 929 | } | ||
2289 | 930 | |||
2290 | 931 | //=============================================================================================== | ||
2291 | 932 | /*! | ||
2292 | 933 | * \brief FileSystemAction::pathChanged | ||
2293 | 934 | * \param path | ||
2294 | 935 | */ | ||
2295 | 936 | void FileSystemAction::pathChanged(const QString &path) | ||
2296 | 937 | { | ||
2297 | 938 | m_path = path; | ||
2298 | 939 | } | ||
2299 | 940 | |||
2300 | 941 | //=============================================================================================== | ||
2301 | 942 | /*! | ||
2302 | 943 | * \brief FileSystemAction::copy | ||
2303 | 944 | * \param pathnames | ||
2304 | 945 | */ | ||
2305 | 946 | void FileSystemAction::copy(const QStringList &pathnames) | ||
2306 | 947 | { | ||
2307 | 948 | #if DEBUG_MESSAGES | ||
2308 | 949 | qDebug() << Q_FUNC_INFO << pathnames; | ||
2309 | 950 | #endif | ||
2310 | 951 | DirModelMimeData::ClipBoardDataOwner owner = | ||
2311 | 952 | m_mimeData->setIntoClipboard(pathnames, m_path, ClipboardCopy); | ||
2312 | 953 | if (owner == DirModelMimeData::MySelf ) | ||
2313 | 954 | { | ||
2314 | 955 | emit clipboardChanged(); | ||
2315 | 956 | } | ||
2316 | 957 | } | ||
2317 | 958 | |||
2318 | 959 | //=============================================================================================== | ||
2319 | 960 | /*! | ||
2320 | 961 | * \brief FileSystemAction::cut | ||
2321 | 962 | * \param pathnames | ||
2322 | 963 | */ | ||
2323 | 964 | void FileSystemAction::cut(const QStringList &pathnames) | ||
2324 | 965 | { | ||
2325 | 966 | #if DEBUG_MESSAGES | ||
2326 | 967 | qDebug() << Q_FUNC_INFO << pathnames; | ||
2327 | 968 | #endif | ||
2328 | 969 | DirModelMimeData::ClipBoardDataOwner owner = | ||
2329 | 970 | m_mimeData->setIntoClipboard(pathnames, m_path, ClipboardCut); | ||
2330 | 971 | if (owner == DirModelMimeData::MySelf ) | ||
2331 | 972 | { | ||
2332 | 973 | emit clipboardChanged(); | ||
2333 | 974 | } | ||
2334 | 975 | } | ||
2335 | 976 | |||
2336 | 977 | //=============================================================================================== | ||
2337 | 978 | /*! | ||
2338 | 979 | * \brief FileSystemAction::paste | ||
2339 | 980 | */ | ||
2340 | 981 | void FileSystemAction::paste() | ||
2341 | 982 | { | ||
2342 | 983 | ClipboardOperation operation; | ||
2343 | 984 | QStringList paths = m_mimeData->localUrls(operation); | ||
2344 | 985 | #if DEBUG_MESSAGES | ||
2345 | 986 | qDebug() << Q_FUNC_INFO << paths; | ||
2346 | 987 | #endif | ||
2347 | 988 | if (paths.count()) | ||
2348 | 989 | { | ||
2349 | 990 | if (QFileInfo(m_path).absoluteFilePath() == QFileInfo(paths.at(0)).absolutePath()) | ||
2350 | 991 | { | ||
2351 | 992 | emit error(tr("Cannot paste"), | ||
2352 | 993 | tr("origin and destination folder are the same")); | ||
2353 | 994 | return; | ||
2354 | 995 | } | ||
2355 | 996 | ActionType actionType = ActionCopy; // start with Copy and check for Cut | ||
2356 | 997 | if (operation == ClipboardCut) | ||
2357 | 998 | { | ||
2358 | 999 | //so far it always returns true since on Linux it is possible to rename | ||
2359 | 1000 | // between different file systems | ||
2360 | 1001 | if ( moveUsingSameFileSystem(paths.at(0)) ) { | ||
2361 | 1002 | actionType = ActionMove; | ||
2362 | 1003 | } else { | ||
2363 | 1004 | actionType = ActionHardMoveCopy; // first step | ||
2364 | 1005 | } | ||
2365 | 1006 | } | ||
2366 | 1007 | createAndProcessAction(actionType, paths, operation); | ||
2367 | 1008 | } | ||
2368 | 1009 | } | ||
2369 | 1010 | |||
2370 | 1011 | //=============================================================================================== | ||
2371 | 1012 | /*! | ||
2372 | 1013 | * \brief FileSystemAction::createAndProcessAction | ||
2373 | 1014 | * \param actionType | ||
2374 | 1015 | * \param paths | ||
2375 | 1016 | * \param operation | ||
2376 | 1017 | */ | ||
2377 | 1018 | void FileSystemAction::createAndProcessAction(ActionType actionType, const QStringList& paths, ClipboardOperation operation) | ||
2378 | 1019 | { | ||
2379 | 1020 | #if DEBUG_MESSAGES | ||
2380 | 1021 | qDebug() << Q_FUNC_INFO << paths; | ||
2381 | 1022 | #endif | ||
2382 | 1023 | Action *myAction = 0; | ||
2383 | 1024 | int origPathLen = 0; | ||
2384 | 1025 | myAction = createAction(actionType, origPathLen); | ||
2385 | 1026 | myAction->operation = operation; | ||
2386 | 1027 | myAction->origPath = QFileInfo(paths.at(0)).absolutePath(); | ||
2387 | 1028 | myAction->baseOrigSize = myAction->origPath.length(); | ||
2388 | 1029 | Action * saveAction = m_curAction; | ||
2389 | 1030 | m_curAction = myAction; | ||
2390 | 1031 | for (int counter=0; counter < paths.count(); counter++) | ||
2391 | 1032 | { | ||
2392 | 1033 | //targetFom() uses m_curAction and is called inside addEntry() | ||
2393 | 1034 | addEntry(myAction, paths.at(counter)); | ||
2394 | 1035 | } | ||
2395 | 1036 | m_curAction = saveAction; | ||
2396 | 1037 | if (actionType == ActionHardMoveCopy) | ||
2397 | 1038 | { | ||
2398 | 1039 | myAction->totalItems *= 2; //duplicate this | ||
2399 | 1040 | myAction->totalBytes *= 2; | ||
2400 | 1041 | } | ||
2401 | 1042 | if (operation == ClipboardCut) | ||
2402 | 1043 | { | ||
2403 | 1044 | //this must still be false when cut finishes to change the clipboard to the target | ||
2404 | 1045 | m_clipboardModifiedByOther = false; | ||
2405 | 1046 | } | ||
2406 | 1047 | m_queuedActions.append(myAction); | ||
2407 | 1048 | if (!m_busy) | ||
2408 | 1049 | { | ||
2409 | 1050 | processAction(); | ||
2410 | 1051 | } | ||
2411 | 1052 | } | ||
2412 | 1053 | |||
2413 | 1054 | //=============================================================================================== | ||
2414 | 1055 | /*! | ||
2415 | 1056 | * \brief FileSystemAction::targetFom() makes a destination full pathname from \a origItem | ||
2416 | 1057 | * \param origItem full pathname from a item intended to be copied or moved into current path | ||
2417 | 1058 | * \return full pathname of target | ||
2418 | 1059 | */ | ||
2419 | 1060 | QString FileSystemAction::targetFom(const QString& origItem) | ||
2420 | 1061 | { | ||
2421 | 1062 | QString target(m_curAction->targetPath + origItem.mid(m_curAction->baseOrigSize)); | ||
2422 | 1063 | return target; | ||
2423 | 1064 | } | ||
2424 | 1065 | |||
2425 | 1066 | //=============================================================================================== | ||
2426 | 1067 | /*! | ||
2427 | 1068 | * \brief FileSystemAction::moveUsingSameFileSystem() Checks if the item being moved to | ||
2428 | 1069 | * current m_path belongs to the same File System | ||
2429 | 1070 | * | ||
2430 | 1071 | * \param itemToMovePathname first item being moved from a paste operation | ||
2431 | 1072 | * | ||
2432 | 1073 | * \return true if the item being moved to the current m_path belongs to the same file system as m_path | ||
2433 | 1074 | */ | ||
2434 | 1075 | bool FileSystemAction::moveUsingSameFileSystem(const QString& itemToMovePathname) | ||
2435 | 1076 | { | ||
2436 | 1077 | #if 0 //disabled since on Linux it looks like renaming between different file systems works | ||
2437 | 1078 | unsigned long targetFsId = 0xffff; | ||
2438 | 1079 | unsigned long originFsId = 0xfffe; | ||
2439 | 1080 | struct statvfs vfs; | ||
2440 | 1081 | |||
2441 | 1082 | if ( ::statvfs(m_path.toLatin1().constData(), &vfs) == 0 ) | ||
2442 | 1083 | { | ||
2443 | 1084 | targetFsId = vfs.f_fsid; | ||
2444 | 1085 | } | ||
2445 | 1086 | if ( ::statvfs(itemToMovePathname.toLatin1().constData(), &vfs) == 0) | ||
2446 | 1087 | { | ||
2447 | 1088 | originFsId = vfs.f_fsid; | ||
2448 | 1089 | } | ||
2449 | 1090 | return targetFsId == originFsId; | ||
2450 | 1091 | #else | ||
2451 | 1092 | Q_UNUSED(itemToMovePathname); | ||
2452 | 1093 | return true; | ||
2453 | 1094 | #endif | ||
2454 | 1095 | } | ||
2455 | 1096 | |||
2456 | 1097 | //======================================================= | ||
2457 | 1098 | /*! | ||
2458 | 1099 | * \brief FileSystemAction::clipboardLocalUrlsConunter | ||
2459 | 1100 | * \return | ||
2460 | 1101 | */ | ||
2461 | 1102 | int FileSystemAction::clipboardLocalUrlsConunter() | ||
2462 | 1103 | { | ||
2463 | 1104 | ClipboardOperation operation; | ||
2464 | 1105 | return m_mimeData->localUrls(operation).count(); | ||
2465 | 1106 | } | ||
2466 | 1107 | |||
2467 | 1108 | //================================================================================ | ||
2468 | 1109 | /*! | ||
2469 | 1110 | * \brief FileSystemAction::endCurrentAction() finishes an Action | ||
2470 | 1111 | * | ||
2471 | 1112 | * If a Paste was made from a Cut operation, items pasted become avaialable in the clipboard | ||
2472 | 1113 | * as from Copy source operation, so items can be now Pasted again, but with no source removal | ||
2473 | 1114 | * | ||
2474 | 1115 | * It checks for \a m_clipboardModifiedByOther that idenftifies if the clipboard was modified during the | ||
2475 | 1116 | * operation maybe by another application. | ||
2476 | 1117 | */ | ||
2477 | 1118 | void FileSystemAction::endCurrentAction() | ||
2478 | 1119 | { | ||
2479 | 1120 | if ( m_curAction->origPath != m_curAction->targetPath && | ||
2480 | 1121 | m_curAction->operation == ClipboardCut && | ||
2481 | 1122 | !m_clipboardModifiedByOther ) | ||
2482 | 1123 | { | ||
2483 | 1124 | QStringList items; | ||
2484 | 1125 | const ActionEntry *entry; | ||
2485 | 1126 | int last; | ||
2486 | 1127 | for(int e = 0; e < m_curAction->entries.count(); e++) | ||
2487 | 1128 | { | ||
2488 | 1129 | entry = m_curAction->entries.at(e); | ||
2489 | 1130 | last = entry->reversedOrder.count() -1; | ||
2490 | 1131 | QString item(targetFom(entry->reversedOrder.at(last).absoluteFilePath())); | ||
2491 | 1132 | items.append(item); | ||
2492 | 1133 | } | ||
2493 | 1134 | if (items.count()) | ||
2494 | 1135 | { | ||
2495 | 1136 | QString targetPath = m_curAction->targetPath; | ||
2496 | 1137 | //it is not necessary to handle own clipboard here | ||
2497 | 1138 | m_mimeData->setIntoClipboard(items, targetPath, ClipboardCopy); | ||
2498 | 1139 | } | ||
2499 | 1140 | } | ||
2500 | 1141 | } | ||
2501 | 1142 | |||
2502 | 1143 | //================================================================================ | ||
2503 | 1144 | /*! | ||
2504 | 1145 | * \brief FileSystemAction::copySingleFile() do a single file copy | ||
2505 | 1146 | * | ||
2506 | 1147 | * Several write operations are required to copy big files, each operation writes (STEP_FILES * 4k) bytes. | ||
2507 | 1148 | * After a write operation if more operations are required to copy the whole file, | ||
2508 | 1149 | * a progress() signal is emitted and a new write operation is scheduled to happen in the next loop interaction. | ||
2509 | 1150 | * | ||
2510 | 1151 | * \return true if scheduled to another slot either processCopyEntry() or itself; false if not. | ||
2511 | 1152 | */ | ||
2512 | 1153 | bool FileSystemAction::processCopySingleFile() | ||
2513 | 1154 | { | ||
2514 | 1155 | #if DEBUG_MESSAGES | ||
2515 | 1156 | qDebug() << Q_FUNC_INFO; | ||
2516 | 1157 | #endif | ||
2517 | 1158 | char block[4096]; | ||
2518 | 1159 | int step = 0; | ||
2519 | 1160 | bool copySingleFileDone = false; | ||
2520 | 1161 | bool scheduleAnySlot = true; | ||
2521 | 1162 | int startBytes = m_curAction->copyFile.bytesWritten; | ||
2522 | 1163 | |||
2523 | 1164 | while( m_curAction->copyFile.source && | ||
2524 | 1165 | !m_curAction->copyFile.source->atEnd() && | ||
2525 | 1166 | !m_cancelCurrentAction && | ||
2526 | 1167 | m_curAction->copyFile.bytesWritten < m_curAction->copyFile.source->size() && | ||
2527 | 1168 | step++ < STEP_FILES | ||
2528 | 1169 | ) | ||
2529 | 1170 | { | ||
2530 | 1171 | qint64 in = m_curAction->copyFile.source->read(block, sizeof(block)); | ||
2531 | 1172 | if (in > 0) | ||
2532 | 1173 | { | ||
2533 | 1174 | if(in != m_curAction->copyFile.target->write(block, in)) | ||
2534 | 1175 | { | ||
2535 | 1176 | m_curAction->copyFile.source->close(); | ||
2536 | 1177 | m_curAction->copyFile.target->close(); | ||
2537 | 1178 | m_cancelCurrentAction = true; | ||
2538 | 1179 | m_errorTitle = QObject::tr("Write error in ") | ||
2539 | 1180 | + m_curAction->copyFile.targetName, | ||
2540 | 1181 | m_errorMsg = ::strerror(errno); | ||
2541 | 1182 | break; | ||
2542 | 1183 | } | ||
2543 | 1184 | m_curAction->bytesWritten += in; | ||
2544 | 1185 | m_curAction->copyFile.bytesWritten += in; | ||
2545 | 1186 | } | ||
2546 | 1187 | else | ||
2547 | 1188 | if (in < 0) | ||
2548 | 1189 | { | ||
2549 | 1190 | m_cancelCurrentAction = true; | ||
2550 | 1191 | m_errorTitle = QObject::tr("Read error in ") | ||
2551 | 1192 | + m_curAction->copyFile.source->fileName(); | ||
2552 | 1193 | m_errorMsg = ::strerror(errno); | ||
2553 | 1194 | break; | ||
2554 | 1195 | } | ||
2555 | 1196 | }// end write loop | ||
2556 | 1197 | |||
2557 | 1198 | // write loop finished, the copy might be finished | ||
2558 | 1199 | if (!m_cancelCurrentAction | ||
2559 | 1200 | && m_curAction->copyFile.source | ||
2560 | 1201 | && m_curAction->copyFile.bytesWritten == m_curAction->copyFile.source->size() | ||
2561 | 1202 | && m_curAction->copyFile.source->isOpen() | ||
2562 | 1203 | ) | ||
2563 | 1204 | { | ||
2564 | 1205 | m_curAction->copyFile.source->close(); | ||
2565 | 1206 | m_curAction->copyFile.target->close(); | ||
2566 | 1207 | m_curAction->copyFile.target->setAutoRemove(false); | ||
2567 | 1208 | m_cancelCurrentAction = !m_curAction->copyFile.target->setPermissions( | ||
2568 | 1209 | m_curAction->copyFile.source->permissions()); | ||
2569 | 1210 | if (m_cancelCurrentAction) | ||
2570 | 1211 | { | ||
2571 | 1212 | m_errorTitle = QObject::tr("Set permissions error in ") | ||
2572 | 1213 | + m_curAction->copyFile.targetName, | ||
2573 | 1214 | m_errorMsg = ::strerror(errno); | ||
2574 | 1215 | } | ||
2575 | 1216 | else | ||
2576 | 1217 | { | ||
2577 | 1218 | QFile testExistTarget(m_curAction->copyFile.targetName); | ||
2578 | 1219 | if (testExistTarget.exists()) | ||
2579 | 1220 | { | ||
2580 | 1221 | if ((m_cancelCurrentAction = ! testExistTarget.remove())) | ||
2581 | 1222 | { | ||
2582 | 1223 | m_errorTitle = QObject::tr("Could not remove original file ") | ||
2583 | 1224 | + m_curAction->copyFile.targetName, | ||
2584 | 1225 | m_errorMsg = ::strerror(errno); | ||
2585 | 1226 | } | ||
2586 | 1227 | } | ||
2587 | 1228 | if (!m_cancelCurrentAction) | ||
2588 | 1229 | { | ||
2589 | 1230 | m_cancelCurrentAction = ! m_curAction->copyFile.target-> | ||
2590 | 1231 | rename(m_curAction->copyFile.targetName); | ||
2591 | 1232 | if (m_cancelCurrentAction) | ||
2592 | 1233 | { | ||
2593 | 1234 | m_errorTitle = QObject::tr("Rename error: renaming to ") | ||
2594 | 1235 | + m_curAction->copyFile.targetName, | ||
2595 | 1236 | m_errorMsg = ::strerror(errno); | ||
2596 | 1237 | } | ||
2597 | 1238 | else | ||
2598 | 1239 | { | ||
2599 | 1240 | copySingleFileDone = true; | ||
2600 | 1241 | } | ||
2601 | 1242 | } | ||
2602 | 1243 | } | ||
2603 | 1244 | } | ||
2604 | 1245 | |||
2605 | 1246 | if (m_cancelCurrentAction) | ||
2606 | 1247 | { | ||
2607 | 1248 | if (m_curAction->copyFile.target) | ||
2608 | 1249 | { | ||
2609 | 1250 | m_curAction->copyFile.target->setAutoRemove(true); | ||
2610 | 1251 | } | ||
2611 | 1252 | m_curAction->copyFile.clear(); | ||
2612 | 1253 | endActionEntry(); | ||
2613 | 1254 | } | ||
2614 | 1255 | else | ||
2615 | 1256 | { | ||
2616 | 1257 | notifyProgress(); | ||
2617 | 1258 | if (copySingleFileDone) | ||
2618 | 1259 | { | ||
2619 | 1260 | m_curAction->copyFile.clear(); | ||
2620 | 1261 | //whem the whole copy could be done just in one call | ||
2621 | 1262 | //do not schedule to call copyEntry() | ||
2622 | 1263 | if (startBytes > 0) | ||
2623 | 1264 | { | ||
2624 | 1265 | //the whole took more than one call to copySingleFile() | ||
2625 | 1266 | scheduleSlot(SLOT(processCopyEntry())); | ||
2626 | 1267 | } | ||
2627 | 1268 | else | ||
2628 | 1269 | { //return normally to entry loop | ||
2629 | 1270 | scheduleAnySlot = false; | ||
2630 | 1271 | } | ||
2631 | 1272 | } | ||
2632 | 1273 | else | ||
2633 | 1274 | { | ||
2634 | 1275 | scheduleSlot(SLOT(processCopySingleFile())); | ||
2635 | 1276 | } | ||
2636 | 1277 | } | ||
2637 | 1278 | |||
2638 | 1279 | return scheduleAnySlot; | ||
2639 | 1280 | } | ||
2640 | 1281 | |||
2641 | 1282 | |||
2642 | 1283 | //================================================================================ | ||
2643 | 1284 | /*! | ||
2644 | 1285 | * \brief FileSystemAction::percentWorkDone() Compute the percent of work done | ||
2645 | 1286 | * | ||
2646 | 1287 | * Copy operations are based on bytes written while remove/move operations are based on items number | ||
2647 | 1288 | * | ||
2648 | 1289 | * \return the percent of work done | ||
2649 | 1290 | */ | ||
2650 | 1291 | int FileSystemAction::percentWorkDone() | ||
2651 | 1292 | { | ||
2652 | 1293 | int percent = 0; | ||
2653 | 1294 | if (m_curAction->type != ActionCopy && m_curAction->type != ActionHardMoveCopy) | ||
2654 | 1295 | { | ||
2655 | 1296 | percent = (m_curAction->currItem * 100) / m_curAction->totalItems; | ||
2656 | 1297 | } | ||
2657 | 1298 | else | ||
2658 | 1299 | { | ||
2659 | 1300 | percent = (m_curAction->bytesWritten * 100) / m_curAction->totalBytes ; | ||
2660 | 1301 | } | ||
2661 | 1302 | if (percent > 100) | ||
2662 | 1303 | { | ||
2663 | 1304 | percent = 100; | ||
2664 | 1305 | } | ||
2665 | 1306 | return percent; | ||
2666 | 1307 | } | ||
2667 | 1308 | |||
2668 | 1309 | |||
2669 | 1310 | //================================================================================ | ||
2670 | 1311 | /*! | ||
2671 | 1312 | * \brief FileSystemAction::notifyProgress() Notify the progress signal | ||
2672 | 1313 | * | ||
2673 | 1314 | * \return the percent of work done | ||
2674 | 1315 | */ | ||
2675 | 1316 | int FileSystemAction::notifyProgress(int forcePercent) | ||
2676 | 1317 | { | ||
2677 | 1318 | int percent = forcePercent > 0 ? forcePercent : percentWorkDone(); | ||
2678 | 1319 | if (percent == 0) | ||
2679 | 1320 | { | ||
2680 | 1321 | percent = 1; | ||
2681 | 1322 | } | ||
2682 | 1323 | if (SHOULD_EMIT_PROGRESS_SIGNAL(m_curAction) && !m_curAction->done) | ||
2683 | 1324 | { | ||
2684 | 1325 | if (m_curAction->type == ActionHardMoveCopy || | ||
2685 | 1326 | m_curAction->type ==ActionHardMoveRemove) | ||
2686 | 1327 | { | ||
2687 | 1328 | emit progress(m_curAction->currItem/2, m_curAction->totalItems/2, percent); | ||
2688 | 1329 | } | ||
2689 | 1330 | else | ||
2690 | 1331 | { | ||
2691 | 1332 | emit progress(m_curAction->currItem, m_curAction->totalItems, percent); | ||
2692 | 1333 | } | ||
2693 | 1334 | if (percent == 100 && m_curAction->currItem == m_curAction->totalItems) | ||
2694 | 1335 | { | ||
2695 | 1336 | m_curAction->done = true; | ||
2696 | 1337 | } | ||
2697 | 1338 | } | ||
2698 | 1339 | return percent; | ||
2699 | 1340 | } | ||
2700 | 1341 | |||
2701 | 1342 | //================================================================================ | ||
2702 | 1343 | /*! | ||
2703 | 1344 | * \brief FileSystemAction::copySymLink() creates the \a target as a link according to \a orig | ||
2704 | 1345 | * \param target full pathname of the file to be created | ||
2705 | 1346 | * \param orig original file, it carries the link that \a target will point to | ||
2706 | 1347 | * \return true if it could create, else if not | ||
2707 | 1348 | */ | ||
2708 | 1349 | bool FileSystemAction::copySymLink(const QString &target, const QFileInfo &orig) | ||
2709 | 1350 | { | ||
2710 | 1351 | QString link(orig.symLinkTarget()); | ||
2711 | 1352 | QFileInfo linkFile(link); | ||
2712 | 1353 | if (linkFile.isAbsolute() && linkFile.absolutePath() == orig.absolutePath()) | ||
2713 | 1354 | { | ||
2714 | 1355 | link = linkFile.fileName(); | ||
2715 | 1356 | } | ||
2716 | 1357 | #if QT_VERSION <= 0x040704 | ||
2717 | 1358 | QString current = QDir::currentPath(); | ||
2718 | 1359 | QDir::setCurrent(linkFile.absolutePath()); | ||
2719 | 1360 | bool ret = QFile::link(link, target); | ||
2720 | 1361 | QDir::setCurrent(current); | ||
2721 | 1362 | #else | ||
2722 | 1363 | bool ret = QFile::link(link, target); | ||
2723 | 1364 | #endif | ||
2724 | 1365 | #if DEBUG_MESSAGES | ||
2725 | 1366 | qDebug() << "FileSystemAction::copySymLink" << ret << target << link; | ||
2726 | 1367 | #endif | ||
2727 | 1368 | return ret; | ||
2728 | 1369 | } | ||
2729 | 1370 | |||
2730 | 1371 | //================================================================================ | ||
2731 | 1372 | void FileSystemAction::scheduleSlot(const char *slot) | ||
2732 | 1373 | { | ||
2733 | 1374 | #if DEBUG_MESSAGES | ||
2734 | 1375 | qDebug() << "FileSystemAction::scheduleSlot()" << slot; | ||
2735 | 1376 | #endif | ||
2736 | 1377 | QTimer::singleShot(0, this, slot); | ||
2737 | 1378 | } | ||
2738 | 1379 | |||
2739 | 1380 | //================================================================================ | ||
2740 | 1381 | /*! | ||
2741 | 1382 | * \brief FileSystemAction::clipboardHasChanged() used to identify if the clipboard changed during a Cut operation | ||
2742 | 1383 | * | ||
2743 | 1384 | * \sa \ref endCurrentAction() | ||
2744 | 1385 | */ | ||
2745 | 1386 | void FileSystemAction::clipboardHasChanged() | ||
2746 | 1387 | { | ||
2747 | 1388 | m_clipboardModifiedByOther = true; | ||
2748 | 1389 | } | ||
2749 | 0 | 1390 | ||
2750 | === added file 'folderlistmodel/filesystemaction.h' | |||
2751 | --- folderlistmodel/filesystemaction.h 1970-01-01 00:00:00 +0000 | |||
2752 | +++ folderlistmodel/filesystemaction.h 2013-06-01 17:20:36 +0000 | |||
2753 | @@ -0,0 +1,212 @@ | |||
2754 | 1 | /************************************************************************** | ||
2755 | 2 | * | ||
2756 | 3 | * Copyright 2013 Canonical Ltd. | ||
2757 | 4 | * Copyright 2013 Carlos J Mazieri <carlos.mazieri@gmail.com> | ||
2758 | 5 | * | ||
2759 | 6 | * You may use this file under the terms of the BSD license as follows: | ||
2760 | 7 | * | ||
2761 | 8 | * "Redistribution and use in source and binary forms, with or without | ||
2762 | 9 | * modification, are permitted provided that the following conditions are | ||
2763 | 10 | * met: | ||
2764 | 11 | * * Redistributions of source code must retain the above copyright | ||
2765 | 12 | * notice, this list of conditions and the following disclaimer. | ||
2766 | 13 | * * Redistributions in binary form must reproduce the above copyright | ||
2767 | 14 | * notice, this list of conditions and the following disclaimer in | ||
2768 | 15 | * the documentation and/or other materials provided with the | ||
2769 | 16 | * distribution. | ||
2770 | 17 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
2771 | 18 | * may be used to endorse or promote products derived from this | ||
2772 | 19 | * software without specific prior written permission. | ||
2773 | 20 | * | ||
2774 | 21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
2775 | 22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
2776 | 23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
2777 | 24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
2778 | 25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
2779 | 26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
2780 | 27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
2781 | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
2782 | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
2783 | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
2784 | 31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
2785 | 32 | * | ||
2786 | 33 | * File: filesystemaction.h | ||
2787 | 34 | * Date: 3/13/2013 | ||
2788 | 35 | */ | ||
2789 | 36 | |||
2790 | 37 | #ifndef FILESYSTEMACTION_H | ||
2791 | 38 | #define FILESYSTEMACTION_H | ||
2792 | 39 | |||
2793 | 40 | |||
2794 | 41 | #include <QObject> | ||
2795 | 42 | #include <QFileInfo> | ||
2796 | 43 | #include <QVector> | ||
2797 | 44 | |||
2798 | 45 | class DirModelMimeData; | ||
2799 | 46 | class RemoveNotifier; | ||
2800 | 47 | class QFile; | ||
2801 | 48 | class QTemporaryFile; | ||
2802 | 49 | |||
2803 | 50 | enum ClipboardOperation | ||
2804 | 51 | { | ||
2805 | 52 | NoClipboard, ClipboardCopy, ClipboardCut | ||
2806 | 53 | }; | ||
2807 | 54 | |||
2808 | 55 | /*! | ||
2809 | 56 | * \brief The FileSystemAction class | ||
2810 | 57 | * | ||
2811 | 58 | * | ||
2812 | 59 | */ | ||
2813 | 60 | class FileSystemAction : public QObject | ||
2814 | 61 | { | ||
2815 | 62 | Q_OBJECT | ||
2816 | 63 | public: | ||
2817 | 64 | explicit FileSystemAction(QObject *parent = 0); | ||
2818 | 65 | ~FileSystemAction(); | ||
2819 | 66 | public slots: | ||
2820 | 67 | void cancel(); | ||
2821 | 68 | void remove(const QStringList & filePaths); | ||
2822 | 69 | int clipboardLocalUrlsConunter(); | ||
2823 | 70 | |||
2824 | 71 | signals: | ||
2825 | 72 | void error(const QString& errorTitle, const QString &errorMessage); | ||
2826 | 73 | void removed(const QString& item); //must be sent to all Model instances | ||
2827 | 74 | void removed(const QFileInfo&); | ||
2828 | 75 | void added(const QString& ); | ||
2829 | 76 | void added(const QFileInfo& ); | ||
2830 | 77 | void progress(int curItem, int totalItems, int percent); | ||
2831 | 78 | void clipboardChanged(); | ||
2832 | 79 | |||
2833 | 80 | public slots: | ||
2834 | 81 | void pathChanged(const QString& path); | ||
2835 | 82 | void paste(); | ||
2836 | 83 | void cut(const QStringList& ); | ||
2837 | 84 | void copy(const QStringList&); | ||
2838 | 85 | |||
2839 | 86 | private slots: | ||
2840 | 87 | void processAction(); | ||
2841 | 88 | void processActionEntry(); | ||
2842 | 89 | void processCopyEntry(); | ||
2843 | 90 | bool processCopySingleFile(); | ||
2844 | 91 | void clipboardHasChanged(); | ||
2845 | 92 | |||
2846 | 93 | #if defined(REGRESSION_TEST_FOLDERLISTMODEL) //used in Unit/Regression tests | ||
2847 | 94 | public: | ||
2848 | 95 | #else | ||
2849 | 96 | private: | ||
2850 | 97 | #endif | ||
2851 | 98 | enum ActionType | ||
2852 | 99 | { | ||
2853 | 100 | ActionRemove, | ||
2854 | 101 | ActionCopy, | ||
2855 | 102 | ActionMove, | ||
2856 | 103 | ActionHardMoveCopy, | ||
2857 | 104 | ActionHardMoveRemove | ||
2858 | 105 | }; | ||
2859 | 106 | void createAndProcessAction(ActionType actionType, const QStringList& paths, | ||
2860 | 107 | ClipboardOperation operation=NoClipboard); | ||
2861 | 108 | |||
2862 | 109 | private: | ||
2863 | 110 | |||
2864 | 111 | struct CopyFile | ||
2865 | 112 | { | ||
2866 | 113 | public: | ||
2867 | 114 | CopyFile() : bytesWritten(0), source(0), target(0) {} | ||
2868 | 115 | ~CopyFile() { clear(); } | ||
2869 | 116 | void clear(); | ||
2870 | 117 | |||
2871 | 118 | qint64 bytesWritten; // set 0 when reach bytesToNotify, notify progress | ||
2872 | 119 | QFile * source; | ||
2873 | 120 | QTemporaryFile * target; | ||
2874 | 121 | QString targetName; | ||
2875 | 122 | }; | ||
2876 | 123 | |||
2877 | 124 | /*! | ||
2878 | 125 | An ActionEntry represents a high level item as a File or a Directory which an Action is required | ||
2879 | 126 | |||
2880 | 127 | For directories \a reversedOrder keeps all children | ||
2881 | 128 | */ | ||
2882 | 129 | struct ActionEntry | ||
2883 | 130 | { | ||
2884 | 131 | public: | ||
2885 | 132 | ActionEntry(): currStep(0),currItem(0),alreadyExists(false), newName(0) {} | ||
2886 | 133 | ~ActionEntry() | ||
2887 | 134 | { | ||
2888 | 135 | reversedOrder.clear(); | ||
2889 | 136 | if (newName) { delete newName; } | ||
2890 | 137 | } | ||
2891 | 138 | QList<QFileInfo> reversedOrder; //!< last item must be the item from the list | ||
2892 | 139 | int currStep; | ||
2893 | 140 | int currItem; | ||
2894 | 141 | bool alreadyExists; | ||
2895 | 142 | QString * newName; //TODO: allow to rename an existent file when it already exists | ||
2896 | 143 | }; | ||
2897 | 144 | |||
2898 | 145 | struct Action | ||
2899 | 146 | { | ||
2900 | 147 | public: | ||
2901 | 148 | ~Action() {qDeleteAll(entries); entries.clear(); copyFile.clear();} | ||
2902 | 149 | ActionType type; | ||
2903 | 150 | QList<ActionEntry*> entries; | ||
2904 | 151 | int totalItems; | ||
2905 | 152 | int currItem; | ||
2906 | 153 | int baseOrigSize; | ||
2907 | 154 | QString origPath; | ||
2908 | 155 | QString targetPath; | ||
2909 | 156 | quint64 totalBytes; | ||
2910 | 157 | quint64 bytesWritten; | ||
2911 | 158 | int currEntry; | ||
2912 | 159 | ClipboardOperation operation; | ||
2913 | 160 | CopyFile copyFile; | ||
2914 | 161 | bool done; | ||
2915 | 162 | }; | ||
2916 | 163 | |||
2917 | 164 | QVector<Action*> m_queuedActions; //!< work always at item 0, after finishing taking item 0 out | ||
2918 | 165 | Action * m_curAction; | ||
2919 | 166 | bool m_cancelCurrentAction; | ||
2920 | 167 | bool m_busy; | ||
2921 | 168 | static RemoveNotifier m_removeNotifier; | ||
2922 | 169 | QString m_path; | ||
2923 | 170 | DirModelMimeData * m_mimeData; | ||
2924 | 171 | QString m_errorTitle; | ||
2925 | 172 | QString m_errorMsg; | ||
2926 | 173 | bool m_clipboardModifiedByOther; | ||
2927 | 174 | |||
2928 | 175 | private: | ||
2929 | 176 | Action * createAction(ActionType, int origBase = 0); | ||
2930 | 177 | void addEntry(Action* action, const QString &pathname); | ||
2931 | 178 | void removeEntry(ActionEntry *); | ||
2932 | 179 | void moveEntry(ActionEntry *entry); | ||
2933 | 180 | bool moveUsingSameFileSystem(const QString& itemToMovePathname); | ||
2934 | 181 | QString targetFom(const QString& origItem); | ||
2935 | 182 | void endCurrentAction(); | ||
2936 | 183 | int percentWorkDone(); | ||
2937 | 184 | int notifyProgress(int forcePercent = 0); | ||
2938 | 185 | void endActionEntry(); | ||
2939 | 186 | bool copySymLink(const QString& target, const QFileInfo& orig); | ||
2940 | 187 | void scheduleSlot(const char *slot); | ||
2941 | 188 | }; | ||
2942 | 189 | |||
2943 | 190 | |||
2944 | 191 | /*! | ||
2945 | 192 | * \brief The RemoveNotifier is a utility class for \ref FileSystemAction to send | ||
2946 | 193 | * notifications about removed files/dir | ||
2947 | 194 | * | ||
2948 | 195 | * This class must have a unique instance to notify all instances of \ref FileSystemAction and \ref DirModel | ||
2949 | 196 | */ | ||
2950 | 197 | class RemoveNotifier : public QObject | ||
2951 | 198 | { | ||
2952 | 199 | Q_OBJECT | ||
2953 | 200 | |||
2954 | 201 | friend class FileSystemAction; | ||
2955 | 202 | private: | ||
2956 | 203 | explicit RemoveNotifier(QObject *parent = 0); | ||
2957 | 204 | void notifyRemoved(const QString& item); | ||
2958 | 205 | void notifyRemoved(const QFileInfo& fi); | ||
2959 | 206 | |||
2960 | 207 | signals: | ||
2961 | 208 | void removed(const QString& item); | ||
2962 | 209 | void removed(const QFileInfo&); | ||
2963 | 210 | }; | ||
2964 | 211 | |||
2965 | 212 | #endif // FILESYSTEMACTION_H | ||
2966 | 0 | 213 | ||
2967 | === added file 'folderlistmodel/folderlistmodel.pri' | |||
2968 | --- folderlistmodel/folderlistmodel.pri 1970-01-01 00:00:00 +0000 | |||
2969 | +++ folderlistmodel/folderlistmodel.pri 2013-06-01 17:20:36 +0000 | |||
2970 | @@ -0,0 +1,26 @@ | |||
2971 | 1 | SOURCES += $$PWD/dirmodel.cpp \ | ||
2972 | 2 | $$PWD/iorequest.cpp \ | ||
2973 | 3 | $$PWD/iorequestworker.cpp \ | ||
2974 | 4 | $$PWD/ioworkerthread.cpp \ | ||
2975 | 5 | $$PWD/filesystemaction.cpp \ | ||
2976 | 6 | |||
2977 | 7 | |||
2978 | 8 | |||
2979 | 9 | |||
2980 | 10 | HEADERS += $$PWD/dirmodel.h \ | ||
2981 | 11 | $$PWD/iorequest.h \ | ||
2982 | 12 | $$PWD/iorequestworker.h \ | ||
2983 | 13 | $$PWD/ioworkerthread.h \ | ||
2984 | 14 | $$PWD/filesystemaction.h \ | ||
2985 | 15 | |||
2986 | 16 | |||
2987 | 17 | |||
2988 | 18 | INCLUDEPATH += $$PWD | ||
2989 | 19 | |||
2990 | 20 | greaterThan(QT_MAJOR_VERSION, 4) { | ||
2991 | 21 | QT += qml | ||
2992 | 22 | } | ||
2993 | 23 | else { | ||
2994 | 24 | QT += declarative | ||
2995 | 25 | } | ||
2996 | 26 | |||
2997 | 0 | 27 | ||
2998 | === added file 'folderlistmodel/folderlistmodel.pro' | |||
2999 | --- folderlistmodel/folderlistmodel.pro 1970-01-01 00:00:00 +0000 | |||
3000 | +++ folderlistmodel/folderlistmodel.pro 2013-06-01 17:20:36 +0000 | |||
3001 | @@ -0,0 +1,39 @@ | |||
3002 | 1 | TARGET = nemofolderlistmodel | ||
3003 | 2 | |||
3004 | 3 | PLUGIN_IMPORT_PATH = org/nemomobile/folderlistmodel | ||
3005 | 4 | PLUGIN_URI = org.nemomobile.folderlistmodel | ||
3006 | 5 | |||
3007 | 6 | # plugin.h and plugin.cpp use URI from PLUGIN_URI instead of hard coded | ||
3008 | 7 | DEFINES += PLUGIN_URI=$$PLUGIN_URI | ||
3009 | 8 | |||
3010 | 9 | #core: sources + headers, separated here to use in regression test project | ||
3011 | 10 | include (folderlistmodel.pri) | ||
3012 | 11 | |||
3013 | 12 | # Input | ||
3014 | 13 | SOURCES += plugin.cpp | ||
3015 | 14 | HEADERS += plugin.h | ||
3016 | 15 | |||
3017 | 16 | ## QApplication::clipboard() needs gui | ||
3018 | 17 | QT += gui | ||
3019 | 18 | greaterThan(QT_MAJOR_VERSION, 4): QT += widgets | ||
3020 | 19 | |||
3021 | 20 | exists(../plugin.pri) { | ||
3022 | 21 | include(../plugin.pri) | ||
3023 | 22 | } | ||
3024 | 23 | else { | ||
3025 | 24 | TEMPLATE = lib | ||
3026 | 25 | CONFIG += qt plugin hide_symbols | ||
3027 | 26 | greaterThan(QT_MAJOR_VERSION, 4) { | ||
3028 | 27 | QT += qml | ||
3029 | 28 | } | ||
3030 | 29 | else { | ||
3031 | 30 | QT += declarative | ||
3032 | 31 | } | ||
3033 | 32 | target.path = $$[QT_INSTALL_QML]/$$PLUGIN_IMPORT_PATH | ||
3034 | 33 | INSTALLS += target | ||
3035 | 34 | qmldir.files += $$PWD/qmldir | ||
3036 | 35 | qmldir.path += $$[QT_INSTALL_QML]/$$$$PLUGIN_IMPORT_PATH | ||
3037 | 36 | INSTALLS += qmldir | ||
3038 | 37 | } | ||
3039 | 38 | |||
3040 | 39 | |||
3041 | 0 | 40 | ||
3042 | === added file 'folderlistmodel/iorequest.cpp' | |||
3043 | --- folderlistmodel/iorequest.cpp 1970-01-01 00:00:00 +0000 | |||
3044 | +++ folderlistmodel/iorequest.cpp 2013-06-01 17:20:36 +0000 | |||
3045 | @@ -0,0 +1,36 @@ | |||
3046 | 1 | /* | ||
3047 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3048 | 3 | * | ||
3049 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3050 | 5 | * | ||
3051 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3052 | 7 | * modification, are permitted provided that the following conditions are | ||
3053 | 8 | * met: | ||
3054 | 9 | * * Redistributions of source code must retain the above copyright | ||
3055 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3056 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3057 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3058 | 13 | * the documentation and/or other materials provided with the | ||
3059 | 14 | * distribution. | ||
3060 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3061 | 16 | * may be used to endorse or promote products derived from this | ||
3062 | 17 | * software without specific prior written permission. | ||
3063 | 18 | * | ||
3064 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3065 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3066 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3067 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3068 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3069 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3070 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3071 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3072 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3073 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3074 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3075 | 30 | */ | ||
3076 | 31 | |||
3077 | 32 | #include "iorequest.h" | ||
3078 | 33 | |||
3079 | 34 | IORequest::IORequest() : QObject() | ||
3080 | 35 | { | ||
3081 | 36 | } | ||
3082 | 0 | 37 | ||
3083 | === added file 'folderlistmodel/iorequest.h' | |||
3084 | --- folderlistmodel/iorequest.h 1970-01-01 00:00:00 +0000 | |||
3085 | +++ folderlistmodel/iorequest.h 2013-06-01 17:20:36 +0000 | |||
3086 | @@ -0,0 +1,51 @@ | |||
3087 | 1 | /* | ||
3088 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3089 | 3 | * | ||
3090 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3091 | 5 | * | ||
3092 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3093 | 7 | * modification, are permitted provided that the following conditions are | ||
3094 | 8 | * met: | ||
3095 | 9 | * * Redistributions of source code must retain the above copyright | ||
3096 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3097 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3098 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3099 | 13 | * the documentation and/or other materials provided with the | ||
3100 | 14 | * distribution. | ||
3101 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3102 | 16 | * may be used to endorse or promote products derived from this | ||
3103 | 17 | * software without specific prior written permission. | ||
3104 | 18 | * | ||
3105 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3106 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3107 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3108 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3109 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3110 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3111 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3112 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3113 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3114 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3115 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3116 | 30 | */ | ||
3117 | 31 | |||
3118 | 32 | #ifndef IOREQUEST_H | ||
3119 | 33 | #define IOREQUEST_H | ||
3120 | 34 | |||
3121 | 35 | #include <QObject> | ||
3122 | 36 | |||
3123 | 37 | class IORequest : public QObject | ||
3124 | 38 | { | ||
3125 | 39 | Q_OBJECT | ||
3126 | 40 | public: | ||
3127 | 41 | explicit IORequest(); | ||
3128 | 42 | |||
3129 | 43 | public: | ||
3130 | 44 | virtual void run() = 0; | ||
3131 | 45 | |||
3132 | 46 | private: | ||
3133 | 47 | // hide this because IORequest should *NOT* be parented directly | ||
3134 | 48 | using QObject::setParent; | ||
3135 | 49 | }; | ||
3136 | 50 | |||
3137 | 51 | #endif // IOREQUEST_H | ||
3138 | 0 | 52 | ||
3139 | === added file 'folderlistmodel/iorequestworker.cpp' | |||
3140 | --- folderlistmodel/iorequestworker.cpp 1970-01-01 00:00:00 +0000 | |||
3141 | +++ folderlistmodel/iorequestworker.cpp 2013-06-01 17:20:36 +0000 | |||
3142 | @@ -0,0 +1,94 @@ | |||
3143 | 1 | /* | ||
3144 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3145 | 3 | * | ||
3146 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3147 | 5 | * | ||
3148 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3149 | 7 | * modification, are permitted provided that the following conditions are | ||
3150 | 8 | * met: | ||
3151 | 9 | * * Redistributions of source code must retain the above copyright | ||
3152 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3153 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3154 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3155 | 13 | * the documentation and/or other materials provided with the | ||
3156 | 14 | * distribution. | ||
3157 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3158 | 16 | * may be used to endorse or promote products derived from this | ||
3159 | 17 | * software without specific prior written permission. | ||
3160 | 18 | * | ||
3161 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3162 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3163 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3164 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3165 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3166 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3167 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3168 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3169 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3170 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3171 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3172 | 30 | */ | ||
3173 | 31 | |||
3174 | 32 | #include "iorequestworker.h" | ||
3175 | 33 | #include "iorequest.h" | ||
3176 | 34 | |||
3177 | 35 | #include <QMutexLocker> | ||
3178 | 36 | #include <QDebug> | ||
3179 | 37 | |||
3180 | 38 | /*! | ||
3181 | 39 | Lives on an IOWorkerThread. | ||
3182 | 40 | |||
3183 | 41 | Responsible for running IORequest jobs on the thread instance, and | ||
3184 | 42 | disposing of their resources once they are done. | ||
3185 | 43 | */ | ||
3186 | 44 | IORequestWorker::IORequestWorker() | ||
3187 | 45 | : QThread() | ||
3188 | 46 | , mTimeToQuit(false) | ||
3189 | 47 | { | ||
3190 | 48 | } | ||
3191 | 49 | |||
3192 | 50 | void IORequestWorker::addRequest(IORequest *request) | ||
3193 | 51 | { | ||
3194 | 52 | request->moveToThread(this); | ||
3195 | 53 | |||
3196 | 54 | // TODO: queue requests so we run the most important one first | ||
3197 | 55 | QMutexLocker lock(&mMutex); | ||
3198 | 56 | mRequests.append(request); | ||
3199 | 57 | |||
3200 | 58 | // wake run() | ||
3201 | 59 | mWaitCondition.wakeOne(); | ||
3202 | 60 | } | ||
3203 | 61 | |||
3204 | 62 | void IORequestWorker::run() | ||
3205 | 63 | { | ||
3206 | 64 | forever { | ||
3207 | 65 | QMutexLocker lock(&mMutex); | ||
3208 | 66 | |||
3209 | 67 | if (mTimeToQuit) | ||
3210 | 68 | return; | ||
3211 | 69 | |||
3212 | 70 | if (mRequests.empty()) | ||
3213 | 71 | mWaitCondition.wait(&mMutex); | ||
3214 | 72 | |||
3215 | 73 | while (!mRequests.isEmpty()) { | ||
3216 | 74 | IORequest *request = mRequests.takeFirst(); | ||
3217 | 75 | |||
3218 | 76 | lock.unlock(); | ||
3219 | 77 | |||
3220 | 78 | request->run(); | ||
3221 | 79 | request->deleteLater(); | ||
3222 | 80 | |||
3223 | 81 | lock.relock(); | ||
3224 | 82 | } | ||
3225 | 83 | } | ||
3226 | 84 | } | ||
3227 | 85 | |||
3228 | 86 | void IORequestWorker::exit() | ||
3229 | 87 | { | ||
3230 | 88 | #if DEBUG_MESSAGES | ||
3231 | 89 | qDebug() << Q_FUNC_INFO << "Quitting"; | ||
3232 | 90 | #endif | ||
3233 | 91 | QMutexLocker lock(&mMutex); | ||
3234 | 92 | mTimeToQuit = true; | ||
3235 | 93 | mWaitCondition.wakeOne(); | ||
3236 | 94 | } | ||
3237 | 0 | 95 | ||
3238 | === added file 'folderlistmodel/iorequestworker.h' | |||
3239 | --- folderlistmodel/iorequestworker.h 1970-01-01 00:00:00 +0000 | |||
3240 | +++ folderlistmodel/iorequestworker.h 2013-06-01 17:20:36 +0000 | |||
3241 | @@ -0,0 +1,61 @@ | |||
3242 | 1 | /* | ||
3243 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3244 | 3 | * | ||
3245 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3246 | 5 | * | ||
3247 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3248 | 7 | * modification, are permitted provided that the following conditions are | ||
3249 | 8 | * met: | ||
3250 | 9 | * * Redistributions of source code must retain the above copyright | ||
3251 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3252 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3253 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3254 | 13 | * the documentation and/or other materials provided with the | ||
3255 | 14 | * distribution. | ||
3256 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3257 | 16 | * may be used to endorse or promote products derived from this | ||
3258 | 17 | * software without specific prior written permission. | ||
3259 | 18 | * | ||
3260 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3261 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3262 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3263 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3264 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3265 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3266 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3267 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3268 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3269 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3270 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3271 | 30 | */ | ||
3272 | 31 | |||
3273 | 32 | #ifndef IOREQUESTWORKER_H | ||
3274 | 33 | #define IOREQUESTWORKER_H | ||
3275 | 34 | |||
3276 | 35 | #include <QObject> | ||
3277 | 36 | #include <QThread> | ||
3278 | 37 | #include <QMutex> | ||
3279 | 38 | #include <QWaitCondition> | ||
3280 | 39 | |||
3281 | 40 | #include "iorequest.h" | ||
3282 | 41 | |||
3283 | 42 | class IORequestWorker : public QThread | ||
3284 | 43 | { | ||
3285 | 44 | Q_OBJECT | ||
3286 | 45 | public: | ||
3287 | 46 | explicit IORequestWorker(); | ||
3288 | 47 | |||
3289 | 48 | void addRequest(IORequest *request); | ||
3290 | 49 | |||
3291 | 50 | void run(); | ||
3292 | 51 | |||
3293 | 52 | void exit(); | ||
3294 | 53 | |||
3295 | 54 | private: | ||
3296 | 55 | QMutex mMutex; | ||
3297 | 56 | QWaitCondition mWaitCondition; | ||
3298 | 57 | QList<IORequest *> mRequests; | ||
3299 | 58 | bool mTimeToQuit; | ||
3300 | 59 | }; | ||
3301 | 60 | |||
3302 | 61 | #endif // IOREQUESTWORKER_H | ||
3303 | 0 | 62 | ||
3304 | === added file 'folderlistmodel/ioworkerthread.cpp' | |||
3305 | --- folderlistmodel/ioworkerthread.cpp 1970-01-01 00:00:00 +0000 | |||
3306 | +++ folderlistmodel/ioworkerthread.cpp 2013-06-01 17:20:36 +0000 | |||
3307 | @@ -0,0 +1,64 @@ | |||
3308 | 1 | /* | ||
3309 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3310 | 3 | * | ||
3311 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3312 | 5 | * | ||
3313 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3314 | 7 | * modification, are permitted provided that the following conditions are | ||
3315 | 8 | * met: | ||
3316 | 9 | * * Redistributions of source code must retain the above copyright | ||
3317 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3318 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3319 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3320 | 13 | * the documentation and/or other materials provided with the | ||
3321 | 14 | * distribution. | ||
3322 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3323 | 16 | * may be used to endorse or promote products derived from this | ||
3324 | 17 | * software without specific prior written permission. | ||
3325 | 18 | * | ||
3326 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3327 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3328 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3329 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3330 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3331 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3332 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3333 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3334 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3335 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3336 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3337 | 30 | */ | ||
3338 | 31 | |||
3339 | 32 | #include "ioworkerthread.h" | ||
3340 | 33 | |||
3341 | 34 | |||
3342 | 35 | /*! | ||
3343 | 36 | Hosts a thread, lives on the main thread. | ||
3344 | 37 | |||
3345 | 38 | Responsible for relaying interaction between the main thread and an IOWorkerThread. | ||
3346 | 39 | */ | ||
3347 | 40 | IOWorkerThread::IOWorkerThread(QObject *parent) : | ||
3348 | 41 | QObject(parent) | ||
3349 | 42 | { | ||
3350 | 43 | mWorker.start(QThread::IdlePriority); | ||
3351 | 44 | } | ||
3352 | 45 | |||
3353 | 46 | /*! | ||
3354 | 47 | Destroys an IOWorkerThread instance. | ||
3355 | 48 | */ | ||
3356 | 49 | IOWorkerThread::~IOWorkerThread() | ||
3357 | 50 | { | ||
3358 | 51 | mWorker.exit(); | ||
3359 | 52 | mWorker.wait(); | ||
3360 | 53 | } | ||
3361 | 54 | |||
3362 | 55 | /*! | ||
3363 | 56 | Attempts an asynchronous attempt to start a \a request. | ||
3364 | 57 | |||
3365 | 58 | If the request may be run, it is queued, and true is returned, otherwise, false. | ||
3366 | 59 | */ | ||
3367 | 60 | bool IOWorkerThread::addRequest(IORequest *request) | ||
3368 | 61 | { | ||
3369 | 62 | mWorker.addRequest(request); | ||
3370 | 63 | return true; | ||
3371 | 64 | } | ||
3372 | 0 | 65 | ||
3373 | === added file 'folderlistmodel/ioworkerthread.h' | |||
3374 | --- folderlistmodel/ioworkerthread.h 1970-01-01 00:00:00 +0000 | |||
3375 | +++ folderlistmodel/ioworkerthread.h 2013-06-01 17:20:36 +0000 | |||
3376 | @@ -0,0 +1,52 @@ | |||
3377 | 1 | /* | ||
3378 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3379 | 3 | * | ||
3380 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3381 | 5 | * | ||
3382 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3383 | 7 | * modification, are permitted provided that the following conditions are | ||
3384 | 8 | * met: | ||
3385 | 9 | * * Redistributions of source code must retain the above copyright | ||
3386 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3387 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3388 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3389 | 13 | * the documentation and/or other materials provided with the | ||
3390 | 14 | * distribution. | ||
3391 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3392 | 16 | * may be used to endorse or promote products derived from this | ||
3393 | 17 | * software without specific prior written permission. | ||
3394 | 18 | * | ||
3395 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3396 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3397 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3398 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3399 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3400 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3401 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3402 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3403 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3404 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3405 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3406 | 30 | */ | ||
3407 | 31 | |||
3408 | 32 | #ifndef IOWORKERTHREAD_H | ||
3409 | 33 | #define IOWORKERTHREAD_H | ||
3410 | 34 | |||
3411 | 35 | #include <QObject> | ||
3412 | 36 | #include <QThread> | ||
3413 | 37 | |||
3414 | 38 | #include "iorequestworker.h" | ||
3415 | 39 | |||
3416 | 40 | class IOWorkerThread : public QObject | ||
3417 | 41 | { | ||
3418 | 42 | Q_OBJECT | ||
3419 | 43 | public: | ||
3420 | 44 | explicit IOWorkerThread(QObject *parent = 0); | ||
3421 | 45 | virtual ~IOWorkerThread(); | ||
3422 | 46 | bool addRequest(IORequest *request); | ||
3423 | 47 | |||
3424 | 48 | private: | ||
3425 | 49 | IORequestWorker mWorker; | ||
3426 | 50 | }; | ||
3427 | 51 | |||
3428 | 52 | #endif // IOWORKERTHREAD_H | ||
3429 | 0 | 53 | ||
3430 | === added file 'folderlistmodel/plugin.cpp' | |||
3431 | --- folderlistmodel/plugin.cpp 1970-01-01 00:00:00 +0000 | |||
3432 | +++ folderlistmodel/plugin.cpp 2013-06-01 17:20:36 +0000 | |||
3433 | @@ -0,0 +1,53 @@ | |||
3434 | 1 | /* | ||
3435 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3436 | 3 | * | ||
3437 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3438 | 5 | * | ||
3439 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3440 | 7 | * modification, are permitted provided that the following conditions are | ||
3441 | 8 | * met: | ||
3442 | 9 | * * Redistributions of source code must retain the above copyright | ||
3443 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3444 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3445 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3446 | 13 | * the documentation and/or other materials provided with the | ||
3447 | 14 | * distribution. | ||
3448 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3449 | 16 | * may be used to endorse or promote products derived from this | ||
3450 | 17 | * software without specific prior written permission. | ||
3451 | 18 | * | ||
3452 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3453 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3454 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3455 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3456 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3457 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3458 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3459 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3460 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3461 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3462 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3463 | 30 | */ | ||
3464 | 31 | |||
3465 | 32 | #include <QVector> | ||
3466 | 33 | #include <QFileInfo> | ||
3467 | 34 | |||
3468 | 35 | #include "plugin.h" | ||
3469 | 36 | |||
3470 | 37 | NemoFolderListModelPlugin::NemoFolderListModelPlugin() { } | ||
3471 | 38 | |||
3472 | 39 | NemoFolderListModelPlugin::~NemoFolderListModelPlugin() { } | ||
3473 | 40 | |||
3474 | 41 | void NemoFolderListModelPlugin::initializeEngine(QmlEngine *engine, const char *uri) | ||
3475 | 42 | { | ||
3476 | 43 | Q_UNUSED(engine) | ||
3477 | 44 | Q_ASSERT(uri == QLatin1String(QUOTES(PLUGIN_URI))); | ||
3478 | 45 | } | ||
3479 | 46 | |||
3480 | 47 | void NemoFolderListModelPlugin::registerTypes(const char *uri) | ||
3481 | 48 | { | ||
3482 | 49 | Q_ASSERT(uri == QLatin1String(QUOTES(PLUGIN_URI))); | ||
3483 | 50 | qRegisterMetaType<QVector<QFileInfo> >(); | ||
3484 | 51 | qmlRegisterType<DirModel>(uri, 1, 0, "FolderListModel"); | ||
3485 | 52 | } | ||
3486 | 53 | |||
3487 | 0 | 54 | ||
3488 | === added file 'folderlistmodel/plugin.h' | |||
3489 | --- folderlistmodel/plugin.h 1970-01-01 00:00:00 +0000 | |||
3490 | +++ folderlistmodel/plugin.h 2013-06-01 17:20:36 +0000 | |||
3491 | @@ -0,0 +1,84 @@ | |||
3492 | 1 | /* | ||
3493 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3494 | 3 | * | ||
3495 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3496 | 5 | * | ||
3497 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3498 | 7 | * modification, are permitted provided that the following conditions are | ||
3499 | 8 | * met: | ||
3500 | 9 | * * Redistributions of source code must retain the above copyright | ||
3501 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3502 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3503 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3504 | 13 | * the documentation and/or other materials provided with the | ||
3505 | 14 | * distribution. | ||
3506 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3507 | 16 | * may be used to endorse or promote products derived from this | ||
3508 | 17 | * software without specific prior written permission. | ||
3509 | 18 | * | ||
3510 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3511 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3512 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3513 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3514 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3515 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3516 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3517 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3518 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3519 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3520 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3521 | 30 | */ | ||
3522 | 31 | |||
3523 | 32 | #ifndef NEMO_QML_PLUGINS_FOLDERLISTMODEL | ||
3524 | 33 | #define NEMO_QML_PLUGINS_FOLDERLISTMODEL | ||
3525 | 34 | |||
3526 | 35 | #include <QtGlobal> | ||
3527 | 36 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | ||
3528 | 37 | #include <QtDeclarative> | ||
3529 | 38 | #include <QDeclarativeEngine> | ||
3530 | 39 | #include <QDeclarativeExtensionPlugin> | ||
3531 | 40 | #include <QVector> | ||
3532 | 41 | #include <QFileInfo> | ||
3533 | 42 | |||
3534 | 43 | #define PLUGIN_CLASS_EXPORT | ||
3535 | 44 | #define PLUGIN_CLASS_EXTERNAL_EXPORT Q_EXPORT_PLUGIN2(nemofolderlistmodel, NemoFolderListModelPlugin); | ||
3536 | 45 | #define PLUGIN_CLASS_EXTEND | ||
3537 | 46 | typedef QDeclarativeExtensionPlugin QmlPluginParent; | ||
3538 | 47 | typedef QDeclarativeEngine QmlEngine; | ||
3539 | 48 | Q_DECLARE_METATYPE(QVector<QFileInfo>) | ||
3540 | 49 | |||
3541 | 50 | #else | ||
3542 | 51 | #include <QQmlComponent> | ||
3543 | 52 | #include <QQmlEngine> | ||
3544 | 53 | #include <QQmlContext> | ||
3545 | 54 | #include <QQmlExtensionPlugin> | ||
3546 | 55 | |||
3547 | 56 | #define PLUGIN_CLASS_EXPORT Q_DECL_EXPORT | ||
3548 | 57 | #define PLUGIN_CLASS_EXTERNAL_EXPORT | ||
3549 | 58 | #define PLUGIN_CLASS_EXTEND \ | ||
3550 | 59 | Q_OBJECT \ | ||
3551 | 60 | Q_PLUGIN_METADATA(IID "org.nemomobile.folderlistmodel") | ||
3552 | 61 | typedef QQmlExtensionPlugin QmlPluginParent; | ||
3553 | 62 | typedef QQmlEngine QmlEngine; | ||
3554 | 63 | #endif | ||
3555 | 64 | |||
3556 | 65 | #include "dirmodel.h" | ||
3557 | 66 | |||
3558 | 67 | #define QUOTES(x) #x | ||
3559 | 68 | |||
3560 | 69 | |||
3561 | 70 | class PLUGIN_CLASS_EXPORT NemoFolderListModelPlugin : public QmlPluginParent | ||
3562 | 71 | { | ||
3563 | 72 | PLUGIN_CLASS_EXTEND | ||
3564 | 73 | |||
3565 | 74 | public: | ||
3566 | 75 | NemoFolderListModelPlugin(); | ||
3567 | 76 | virtual ~NemoFolderListModelPlugin(); | ||
3568 | 77 | |||
3569 | 78 | void initializeEngine(QmlEngine *engine, const char *uri); | ||
3570 | 79 | void registerTypes(const char *uri); | ||
3571 | 80 | }; | ||
3572 | 81 | |||
3573 | 82 | PLUGIN_CLASS_EXTERNAL_EXPORT | ||
3574 | 83 | |||
3575 | 84 | #endif // NEMO_QML_PLUGINS_FOLDERLISTMODEL | ||
3576 | 0 | 85 | ||
3577 | === added file 'folderlistmodel/qmldir' | |||
3578 | --- folderlistmodel/qmldir 1970-01-01 00:00:00 +0000 | |||
3579 | +++ folderlistmodel/qmldir 2013-06-01 17:20:36 +0000 | |||
3580 | @@ -0,0 +1,1 @@ | |||
3581 | 1 | plugin nemofolderlistmodel | ||
3582 | 0 | 2 | ||
3583 | === added directory 'nemo-folderlistmodel' | |||
3584 | === added file 'nemo-folderlistmodel/dirmodel.cpp' | |||
3585 | --- nemo-folderlistmodel/dirmodel.cpp 1970-01-01 00:00:00 +0000 | |||
3586 | +++ nemo-folderlistmodel/dirmodel.cpp 2013-06-01 17:20:36 +0000 | |||
3587 | @@ -0,0 +1,385 @@ | |||
3588 | 1 | /* | ||
3589 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3590 | 3 | * | ||
3591 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3592 | 5 | * | ||
3593 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3594 | 7 | * modification, are permitted provided that the following conditions are | ||
3595 | 8 | * met: | ||
3596 | 9 | * * Redistributions of source code must retain the above copyright | ||
3597 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3598 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3599 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3600 | 13 | * the documentation and/or other materials provided with the | ||
3601 | 14 | * distribution. | ||
3602 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3603 | 16 | * may be used to endorse or promote products derived from this | ||
3604 | 17 | * software without specific prior written permission. | ||
3605 | 18 | * | ||
3606 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3607 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3608 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3609 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
3610 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
3611 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
3612 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
3613 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
3614 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
3615 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
3616 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
3617 | 30 | */ | ||
3618 | 31 | |||
3619 | 32 | #include <QDirIterator> | ||
3620 | 33 | #include <QDir> | ||
3621 | 34 | #include <QDebug> | ||
3622 | 35 | #include <QDateTime> | ||
3623 | 36 | #include <QUrl> | ||
3624 | 37 | |||
3625 | 38 | #include <errno.h> | ||
3626 | 39 | #include <string.h> | ||
3627 | 40 | |||
3628 | 41 | #include "dirmodel.h" | ||
3629 | 42 | #include "ioworkerthread.h" | ||
3630 | 43 | |||
3631 | 44 | Q_GLOBAL_STATIC(IOWorkerThread, ioWorkerThread); | ||
3632 | 45 | |||
3633 | 46 | class DirListWorker : public IORequest | ||
3634 | 47 | { | ||
3635 | 48 | Q_OBJECT | ||
3636 | 49 | public: | ||
3637 | 50 | DirListWorker(const QString &pathName) | ||
3638 | 51 | : mPathName(pathName) | ||
3639 | 52 | { } | ||
3640 | 53 | |||
3641 | 54 | void run() | ||
3642 | 55 | { | ||
3643 | 56 | qDebug() << Q_FUNC_INFO << "Running on: " << QThread::currentThreadId(); | ||
3644 | 57 | |||
3645 | 58 | QDir tmpDir = QDir(mPathName); | ||
3646 | 59 | QDirIterator it(tmpDir); | ||
3647 | 60 | QVector<QFileInfo> directoryContents; | ||
3648 | 61 | |||
3649 | 62 | while (it.hasNext()) { | ||
3650 | 63 | it.next(); | ||
3651 | 64 | |||
3652 | 65 | // skip hidden files | ||
3653 | 66 | if (it.fileName()[0] == QLatin1Char('.')) | ||
3654 | 67 | continue; | ||
3655 | 68 | |||
3656 | 69 | directoryContents.append(it.fileInfo()); | ||
3657 | 70 | if (directoryContents.count() >= 50) { | ||
3658 | 71 | emit itemsAdded(directoryContents); | ||
3659 | 72 | |||
3660 | 73 | // clear() would force a deallocation, micro-optimisation | ||
3661 | 74 | directoryContents.erase(directoryContents.begin(), directoryContents.end()); | ||
3662 | 75 | } | ||
3663 | 76 | } | ||
3664 | 77 | |||
3665 | 78 | // last batch | ||
3666 | 79 | emit itemsAdded(directoryContents); | ||
3667 | 80 | |||
3668 | 81 | //std::sort(directoryContents.begin(), directoryContents.end(), DirModel::fileCompare); | ||
3669 | 82 | } | ||
3670 | 83 | |||
3671 | 84 | signals: | ||
3672 | 85 | void itemsAdded(const QVector<QFileInfo> &files); | ||
3673 | 86 | |||
3674 | 87 | private: | ||
3675 | 88 | QString mPathName; | ||
3676 | 89 | }; | ||
3677 | 90 | |||
3678 | 91 | DirModel::DirModel(QObject *parent) | ||
3679 | 92 | : QAbstractListModel(parent) | ||
3680 | 93 | , mAwaitingResults(false) | ||
3681 | 94 | , mShowDirectories(true) | ||
3682 | 95 | { | ||
3683 | 96 | mNameFilters = QStringList() << "*"; | ||
3684 | 97 | |||
3685 | 98 | QHash<int, QByteArray> roles = roleNames(); | ||
3686 | 99 | roles.insert(FileNameRole, QByteArray("fileName")); | ||
3687 | 100 | roles.insert(CreationDateRole, QByteArray("creationDate")); | ||
3688 | 101 | roles.insert(ModifiedDateRole, QByteArray("modifiedDate")); | ||
3689 | 102 | roles.insert(FileSizeRole, QByteArray("fileSize")); | ||
3690 | 103 | roles.insert(IconSourceRole, QByteArray("iconSource")); | ||
3691 | 104 | roles.insert(FilePathRole, QByteArray("filePath")); | ||
3692 | 105 | roles.insert(IsDirRole, QByteArray("isDir")); | ||
3693 | 106 | roles.insert(IsFileRole, QByteArray("isFile")); | ||
3694 | 107 | roles.insert(IsReadableRole, QByteArray("isReadable")); | ||
3695 | 108 | roles.insert(IsWritableRole, QByteArray("isWritable")); | ||
3696 | 109 | roles.insert(IsExecutableRole, QByteArray("isExecutable")); | ||
3697 | 110 | setRoleNames(roles); | ||
3698 | 111 | |||
3699 | 112 | // populate reverse mapping | ||
3700 | 113 | QHash<int, QByteArray>::ConstIterator it = roles.constBegin(); | ||
3701 | 114 | for (;it != roles.constEnd(); ++it) | ||
3702 | 115 | mRoleMapping.insert(it.value(), it.key()); | ||
3703 | 116 | |||
3704 | 117 | // make sure we cover all roles | ||
3705 | 118 | // Q_ASSERT(roles.count() == IsFileRole - FileNameRole); | ||
3706 | 119 | } | ||
3707 | 120 | |||
3708 | 121 | QVariant DirModel::data(int row, const QByteArray &stringRole) const | ||
3709 | 122 | { | ||
3710 | 123 | QHash<QByteArray, int>::ConstIterator it = mRoleMapping.constFind(stringRole); | ||
3711 | 124 | |||
3712 | 125 | if (it == mRoleMapping.constEnd()) | ||
3713 | 126 | return QVariant(); | ||
3714 | 127 | |||
3715 | 128 | return data(index(row, 0), *it); | ||
3716 | 129 | } | ||
3717 | 130 | |||
3718 | 131 | QVariant DirModel::data(const QModelIndex &index, int role) const | ||
3719 | 132 | { | ||
3720 | 133 | if (role < FileNameRole || role > IsExecutableRole) { | ||
3721 | 134 | qWarning() << Q_FUNC_INFO << "Got an out of range role: " << role; | ||
3722 | 135 | return QVariant(); | ||
3723 | 136 | } | ||
3724 | 137 | |||
3725 | 138 | if (index.row() < 0 || index.row() >= mDirectoryContents.count()) { | ||
3726 | 139 | qWarning() << "Attempted to access out of range row: " << index.row(); | ||
3727 | 140 | return QVariant(); | ||
3728 | 141 | } | ||
3729 | 142 | |||
3730 | 143 | if (index.column() != 0) | ||
3731 | 144 | return QVariant(); | ||
3732 | 145 | |||
3733 | 146 | const QFileInfo &fi = mDirectoryContents.at(index.row()); | ||
3734 | 147 | |||
3735 | 148 | switch (role) { | ||
3736 | 149 | case FileNameRole: | ||
3737 | 150 | return fi.fileName(); | ||
3738 | 151 | case CreationDateRole: | ||
3739 | 152 | return fi.created(); | ||
3740 | 153 | case ModifiedDateRole: | ||
3741 | 154 | return fi.lastModified(); | ||
3742 | 155 | case FileSizeRole: { | ||
3743 | 156 | qint64 kb = fi.size() / 1024; | ||
3744 | 157 | if (kb < 1) | ||
3745 | 158 | return QString::number(fi.size()) + " bytes"; | ||
3746 | 159 | else if (kb < 1024) | ||
3747 | 160 | return QString::number(kb) + " kb"; | ||
3748 | 161 | |||
3749 | 162 | kb /= 1024; | ||
3750 | 163 | return QString::number(kb) + "mb"; | ||
3751 | 164 | } | ||
3752 | 165 | case IconSourceRole: { | ||
3753 | 166 | const QString &fileName = fi.fileName(); | ||
3754 | 167 | |||
3755 | 168 | if (fi.isDir()) | ||
3756 | 169 | return "image://theme/icon-m-common-directory"; | ||
3757 | 170 | |||
3758 | 171 | if (fileName.endsWith(".jpg", Qt::CaseInsensitive) || | ||
3759 | 172 | fileName.endsWith(".png", Qt::CaseInsensitive)) { | ||
3760 | 173 | return "image://nemoThumbnail/" + fi.filePath(); | ||
3761 | 174 | } | ||
3762 | 175 | |||
3763 | 176 | return "image://theme/icon-m-content-document"; | ||
3764 | 177 | } | ||
3765 | 178 | case FilePathRole: | ||
3766 | 179 | return fi.filePath(); | ||
3767 | 180 | case IsDirRole: | ||
3768 | 181 | return fi.isDir(); | ||
3769 | 182 | case IsFileRole: | ||
3770 | 183 | return !fi.isDir(); | ||
3771 | 184 | case IsReadableRole: | ||
3772 | 185 | return fi.isReadable(); | ||
3773 | 186 | case IsWritableRole: | ||
3774 | 187 | return fi.isWritable(); | ||
3775 | 188 | case IsExecutableRole: | ||
3776 | 189 | return fi.isExecutable(); | ||
3777 | 190 | default: | ||
3778 | 191 | // this should not happen, ever | ||
3779 | 192 | Q_ASSERT(false); | ||
3780 | 193 | qWarning() << Q_FUNC_INFO << "Got an unknown role: " << role; | ||
3781 | 194 | return QVariant(); | ||
3782 | 195 | } | ||
3783 | 196 | } | ||
3784 | 197 | |||
3785 | 198 | void DirModel::setPath(const QString &pathName) | ||
3786 | 199 | { | ||
3787 | 200 | if (pathName.isEmpty()) | ||
3788 | 201 | return; | ||
3789 | 202 | |||
3790 | 203 | if (mAwaitingResults) { | ||
3791 | 204 | // TODO: handle the case where pathName != our current path, cancel old | ||
3792 | 205 | // request, start a new one | ||
3793 | 206 | qDebug() << Q_FUNC_INFO << "Ignoring path change request, request already running"; | ||
3794 | 207 | return; | ||
3795 | 208 | } | ||
3796 | 209 | |||
3797 | 210 | mAwaitingResults = true; | ||
3798 | 211 | emit awaitingResultsChanged(); | ||
3799 | 212 | qDebug() << Q_FUNC_INFO << "Changing to " << pathName << " on " << QThread::currentThreadId(); | ||
3800 | 213 | |||
3801 | 214 | beginResetModel(); | ||
3802 | 215 | mDirectoryContents.clear(); | ||
3803 | 216 | endResetModel(); | ||
3804 | 217 | |||
3805 | 218 | // TODO: we need to set a spinner active before we start getting results from DirListWorker | ||
3806 | 219 | DirListWorker *dlw = new DirListWorker(pathName); | ||
3807 | 220 | connect(dlw, SIGNAL(itemsAdded(QVector<QFileInfo>)), SLOT(onItemsAdded(QVector<QFileInfo>))); | ||
3808 | 221 | ioWorkerThread()->addRequest(dlw); | ||
3809 | 222 | |||
3810 | 223 | mCurrentDir = pathName; | ||
3811 | 224 | emit pathChanged(); | ||
3812 | 225 | } | ||
3813 | 226 | |||
3814 | 227 | static bool fileCompare(const QFileInfo &a, const QFileInfo &b) | ||
3815 | 228 | { | ||
3816 | 229 | if (a.isDir() && !b.isDir()) | ||
3817 | 230 | return true; | ||
3818 | 231 | |||
3819 | 232 | if (b.isDir() && !a.isDir()) | ||
3820 | 233 | return false; | ||
3821 | 234 | |||
3822 | 235 | return QString::localeAwareCompare(a.fileName(), b.fileName()) < 0; | ||
3823 | 236 | } | ||
3824 | 237 | |||
3825 | 238 | void DirModel::onItemsAdded(const QVector<QFileInfo> &newFiles) | ||
3826 | 239 | { | ||
3827 | 240 | qDebug() << Q_FUNC_INFO << "Got new files: " << newFiles.count(); | ||
3828 | 241 | |||
3829 | 242 | if (mAwaitingResults) { | ||
3830 | 243 | qDebug() << Q_FUNC_INFO << "No longer awaiting results"; | ||
3831 | 244 | mAwaitingResults = false; | ||
3832 | 245 | emit awaitingResultsChanged(); | ||
3833 | 246 | } | ||
3834 | 247 | |||
3835 | 248 | foreach (const QFileInfo &fi, newFiles) { | ||
3836 | 249 | if (!mShowDirectories && fi.isDir()) | ||
3837 | 250 | continue; | ||
3838 | 251 | |||
3839 | 252 | bool doAdd = true; | ||
3840 | 253 | foreach (const QString &nameFilter, mNameFilters) { | ||
3841 | 254 | // TODO: using QRegExp for wildcard matching is slow | ||
3842 | 255 | QRegExp re(nameFilter, Qt::CaseInsensitive, QRegExp::Wildcard); | ||
3843 | 256 | if (!re.exactMatch(fi.fileName())) { | ||
3844 | 257 | doAdd = false; | ||
3845 | 258 | break; | ||
3846 | 259 | } | ||
3847 | 260 | } | ||
3848 | 261 | |||
3849 | 262 | if (!doAdd) | ||
3850 | 263 | continue; | ||
3851 | 264 | |||
3852 | 265 | QVector<QFileInfo>::Iterator it = qLowerBound(mDirectoryContents.begin(), | ||
3853 | 266 | mDirectoryContents.end(), | ||
3854 | 267 | fi, | ||
3855 | 268 | fileCompare); | ||
3856 | 269 | |||
3857 | 270 | if (it == mDirectoryContents.end()) { | ||
3858 | 271 | beginInsertRows(QModelIndex(), mDirectoryContents.count(), mDirectoryContents.count()); | ||
3859 | 272 | mDirectoryContents.append(fi); | ||
3860 | 273 | endInsertRows(); | ||
3861 | 274 | } else { | ||
3862 | 275 | int idx = it - mDirectoryContents.begin(); | ||
3863 | 276 | beginInsertRows(QModelIndex(), idx, idx); | ||
3864 | 277 | mDirectoryContents.insert(it, fi); | ||
3865 | 278 | endInsertRows(); | ||
3866 | 279 | } | ||
3867 | 280 | } | ||
3868 | 281 | } | ||
3869 | 282 | |||
3870 | 283 | void DirModel::rm(const QStringList &paths) | ||
3871 | 284 | { | ||
3872 | 285 | // TODO: handle directory deletions? | ||
3873 | 286 | bool error = false; | ||
3874 | 287 | |||
3875 | 288 | foreach (const QString &path, paths) { | ||
3876 | 289 | error |= QFile::remove(path); | ||
3877 | 290 | |||
3878 | 291 | if (error) { | ||
3879 | 292 | qWarning() << Q_FUNC_INFO << "Failed to remove " << path; | ||
3880 | 293 | error = false; | ||
3881 | 294 | } | ||
3882 | 295 | } | ||
3883 | 296 | |||
3884 | 297 | // TODO: just remove removed items; don't reload the entire model | ||
3885 | 298 | refresh(); | ||
3886 | 299 | } | ||
3887 | 300 | |||
3888 | 301 | bool DirModel::rename(int row, const QString &newName) | ||
3889 | 302 | { | ||
3890 | 303 | qDebug() << Q_FUNC_INFO << "Renaming " << row << " to " << newName; | ||
3891 | 304 | Q_ASSERT(row >= 0 && row < mDirectoryContents.count()); | ||
3892 | 305 | if (row < 0 || row >= mDirectoryContents.count()) { | ||
3893 | 306 | qWarning() << Q_FUNC_INFO << "Out of bounds access"; | ||
3894 | 307 | return false; | ||
3895 | 308 | } | ||
3896 | 309 | |||
3897 | 310 | const QFileInfo &fi = mDirectoryContents.at(row); | ||
3898 | 311 | |||
3899 | 312 | if (!fi.isDir()) { | ||
3900 | 313 | QFile f(fi.absoluteFilePath()); | ||
3901 | 314 | bool retval = f.rename(fi.absolutePath() + QDir::separator() + newName); | ||
3902 | 315 | |||
3903 | 316 | if (!retval) | ||
3904 | 317 | qDebug() << Q_FUNC_INFO << "Rename returned error code: " << f.error() << f.errorString(); | ||
3905 | 318 | else | ||
3906 | 319 | refresh(); | ||
3907 | 320 | // TODO: just change the affected item... ^^ | ||
3908 | 321 | |||
3909 | 322 | return retval; | ||
3910 | 323 | } else { | ||
3911 | 324 | QDir d(fi.absoluteFilePath()); | ||
3912 | 325 | bool retval = d.rename(fi.absoluteFilePath(), fi.absolutePath() + QDir::separator() + newName); | ||
3913 | 326 | |||
3914 | 327 | // QDir has no way to detect what went wrong. woohoo! | ||
3915 | 328 | |||
3916 | 329 | // TODO: just change the affected item... | ||
3917 | 330 | refresh(); | ||
3918 | 331 | |||
3919 | 332 | return retval; | ||
3920 | 333 | } | ||
3921 | 334 | |||
3922 | 335 | // unreachable (we hope) | ||
3923 | 336 | Q_ASSERT(false); | ||
3924 | 337 | return false; | ||
3925 | 338 | } | ||
3926 | 339 | |||
3927 | 340 | void DirModel::mkdir(const QString &newDir) | ||
3928 | 341 | { | ||
3929 | 342 | qDebug() << Q_FUNC_INFO << "Creating new folder " << newDir << " to " << mCurrentDir; | ||
3930 | 343 | |||
3931 | 344 | QDir dir(mCurrentDir); | ||
3932 | 345 | bool retval = dir.mkdir(newDir); | ||
3933 | 346 | if (!retval) { | ||
3934 | 347 | const char *errorStr = strerror(errno); | ||
3935 | 348 | qDebug() << Q_FUNC_INFO << "Error creating new directory: " << errno << " (" << errorStr << ")"; | ||
3936 | 349 | emit error("Error creating new folder", errorStr); | ||
3937 | 350 | } else { | ||
3938 | 351 | refresh(); | ||
3939 | 352 | } | ||
3940 | 353 | } | ||
3941 | 354 | |||
3942 | 355 | bool DirModel::showDirectories() const | ||
3943 | 356 | { | ||
3944 | 357 | return mShowDirectories; | ||
3945 | 358 | } | ||
3946 | 359 | |||
3947 | 360 | void DirModel::setShowDirectories(bool showDirectories) | ||
3948 | 361 | { | ||
3949 | 362 | mShowDirectories = showDirectories; | ||
3950 | 363 | refresh(); | ||
3951 | 364 | emit showDirectoriesChanged(); | ||
3952 | 365 | } | ||
3953 | 366 | |||
3954 | 367 | QStringList DirModel::nameFilters() const | ||
3955 | 368 | { | ||
3956 | 369 | return mNameFilters; | ||
3957 | 370 | } | ||
3958 | 371 | |||
3959 | 372 | void DirModel::setNameFilters(const QStringList &nameFilters) | ||
3960 | 373 | { | ||
3961 | 374 | mNameFilters = nameFilters; | ||
3962 | 375 | refresh(); | ||
3963 | 376 | emit nameFiltersChanged(); | ||
3964 | 377 | } | ||
3965 | 378 | |||
3966 | 379 | bool DirModel::awaitingResults() const | ||
3967 | 380 | { | ||
3968 | 381 | return mAwaitingResults; | ||
3969 | 382 | } | ||
3970 | 383 | |||
3971 | 384 | // for dirlistworker | ||
3972 | 385 | #include "dirmodel.moc" | ||
3973 | 0 | 386 | ||
3974 | === added file 'nemo-folderlistmodel/dirmodel.h' | |||
3975 | --- nemo-folderlistmodel/dirmodel.h 1970-01-01 00:00:00 +0000 | |||
3976 | +++ nemo-folderlistmodel/dirmodel.h 2013-06-01 17:20:36 +0000 | |||
3977 | @@ -0,0 +1,124 @@ | |||
3978 | 1 | /* | ||
3979 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
3980 | 3 | * | ||
3981 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
3982 | 5 | * | ||
3983 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
3984 | 7 | * modification, are permitted provided that the following conditions are | ||
3985 | 8 | * met: | ||
3986 | 9 | * * Redistributions of source code must retain the above copyright | ||
3987 | 10 | * notice, this list of conditions and the following disclaimer. | ||
3988 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
3989 | 12 | * notice, this list of conditions and the following disclaimer in | ||
3990 | 13 | * the documentation and/or other materials provided with the | ||
3991 | 14 | * distribution. | ||
3992 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
3993 | 16 | * may be used to endorse or promote products derived from this | ||
3994 | 17 | * software without specific prior written permission. | ||
3995 | 18 | * | ||
3996 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
3997 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
3998 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
3999 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4000 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4001 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4002 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4003 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4004 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4005 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4006 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4007 | 30 | */ | ||
4008 | 31 | |||
4009 | 32 | #ifndef DIRMODEL_H | ||
4010 | 33 | #define DIRMODEL_H | ||
4011 | 34 | |||
4012 | 35 | #include <QAbstractListModel> | ||
4013 | 36 | #include <QFileInfo> | ||
4014 | 37 | #include <QVector> | ||
4015 | 38 | #include <QStringList> | ||
4016 | 39 | |||
4017 | 40 | #include "iorequest.h" | ||
4018 | 41 | |||
4019 | 42 | class DirModel : public QAbstractListModel | ||
4020 | 43 | { | ||
4021 | 44 | Q_OBJECT | ||
4022 | 45 | |||
4023 | 46 | enum Roles { | ||
4024 | 47 | FileNameRole = Qt::UserRole, | ||
4025 | 48 | CreationDateRole, | ||
4026 | 49 | ModifiedDateRole, | ||
4027 | 50 | FileSizeRole, | ||
4028 | 51 | IconSourceRole, | ||
4029 | 52 | FilePathRole, | ||
4030 | 53 | IsDirRole, | ||
4031 | 54 | IsFileRole, | ||
4032 | 55 | IsReadableRole, | ||
4033 | 56 | IsWritableRole, | ||
4034 | 57 | IsExecutableRole | ||
4035 | 58 | }; | ||
4036 | 59 | |||
4037 | 60 | public: | ||
4038 | 61 | DirModel(QObject *parent = 0); | ||
4039 | 62 | |||
4040 | 63 | int rowCount(const QModelIndex &index) const | ||
4041 | 64 | { | ||
4042 | 65 | if (index.parent() != QModelIndex()) | ||
4043 | 66 | return 0; | ||
4044 | 67 | |||
4045 | 68 | return mDirectoryContents.count(); | ||
4046 | 69 | } | ||
4047 | 70 | |||
4048 | 71 | // TODO: this won't be safe if the model can change under the holder of the row | ||
4049 | 72 | Q_INVOKABLE QVariant data(int row, const QByteArray &stringRole) const; | ||
4050 | 73 | |||
4051 | 74 | QVariant data(const QModelIndex &index, int role) const; | ||
4052 | 75 | |||
4053 | 76 | Q_INVOKABLE void refresh() | ||
4054 | 77 | { | ||
4055 | 78 | // just some syntactical sugar really | ||
4056 | 79 | setPath(path()); | ||
4057 | 80 | } | ||
4058 | 81 | |||
4059 | 82 | Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged); | ||
4060 | 83 | inline QString path() const { return mCurrentDir; } | ||
4061 | 84 | |||
4062 | 85 | Q_PROPERTY(bool awaitingResults READ awaitingResults NOTIFY awaitingResultsChanged); | ||
4063 | 86 | bool awaitingResults() const; | ||
4064 | 87 | |||
4065 | 88 | void setPath(const QString &pathName); | ||
4066 | 89 | |||
4067 | 90 | Q_INVOKABLE void rm(const QStringList &paths); | ||
4068 | 91 | |||
4069 | 92 | Q_INVOKABLE bool rename(int row, const QString &newName); | ||
4070 | 93 | |||
4071 | 94 | Q_INVOKABLE void mkdir(const QString &newdir); | ||
4072 | 95 | |||
4073 | 96 | Q_PROPERTY(bool showDirectories READ showDirectories WRITE setShowDirectories NOTIFY showDirectoriesChanged) | ||
4074 | 97 | bool showDirectories() const; | ||
4075 | 98 | void setShowDirectories(bool showDirectories); | ||
4076 | 99 | |||
4077 | 100 | Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) | ||
4078 | 101 | QStringList nameFilters() const; | ||
4079 | 102 | void setNameFilters(const QStringList &nameFilters); | ||
4080 | 103 | |||
4081 | 104 | public slots: | ||
4082 | 105 | void onItemsAdded(const QVector<QFileInfo> &newFiles); | ||
4083 | 106 | |||
4084 | 107 | signals: | ||
4085 | 108 | void awaitingResultsChanged(); | ||
4086 | 109 | void nameFiltersChanged(); | ||
4087 | 110 | void showDirectoriesChanged(); | ||
4088 | 111 | void pathChanged(); | ||
4089 | 112 | void error(const QString &errorTitle, const QString &errorMessage); | ||
4090 | 113 | |||
4091 | 114 | private: | ||
4092 | 115 | QStringList mNameFilters; | ||
4093 | 116 | bool mShowDirectories; | ||
4094 | 117 | bool mAwaitingResults; | ||
4095 | 118 | QString mCurrentDir; | ||
4096 | 119 | QVector<QFileInfo> mDirectoryContents; | ||
4097 | 120 | QHash<QByteArray, int> mRoleMapping; | ||
4098 | 121 | }; | ||
4099 | 122 | |||
4100 | 123 | |||
4101 | 124 | #endif // DIRMODEL_H | ||
4102 | 0 | 125 | ||
4103 | === added file 'nemo-folderlistmodel/folderlistmodel.pro' | |||
4104 | --- nemo-folderlistmodel/folderlistmodel.pro 1970-01-01 00:00:00 +0000 | |||
4105 | +++ nemo-folderlistmodel/folderlistmodel.pro 2013-06-01 17:20:36 +0000 | |||
4106 | @@ -0,0 +1,16 @@ | |||
4107 | 1 | TARGET = nemofolderlistmodel | ||
4108 | 2 | PLUGIN_IMPORT_PATH = org/nemomobile/folderlistmodel | ||
4109 | 3 | |||
4110 | 4 | SOURCES += plugin.cpp \ | ||
4111 | 5 | dirmodel.cpp \ | ||
4112 | 6 | iorequest.cpp \ | ||
4113 | 7 | iorequestworker.cpp \ | ||
4114 | 8 | ioworkerthread.cpp | ||
4115 | 9 | |||
4116 | 10 | HEADERS += plugin.h \ | ||
4117 | 11 | dirmodel.h \ | ||
4118 | 12 | iorequest.h \ | ||
4119 | 13 | iorequestworker.h \ | ||
4120 | 14 | ioworkerthread.h | ||
4121 | 15 | |||
4122 | 16 | include(../plugin.pri) | ||
4123 | 0 | 17 | ||
4124 | === added file 'nemo-folderlistmodel/iorequest.cpp' | |||
4125 | --- nemo-folderlistmodel/iorequest.cpp 1970-01-01 00:00:00 +0000 | |||
4126 | +++ nemo-folderlistmodel/iorequest.cpp 2013-06-01 17:20:36 +0000 | |||
4127 | @@ -0,0 +1,36 @@ | |||
4128 | 1 | /* | ||
4129 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4130 | 3 | * | ||
4131 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4132 | 5 | * | ||
4133 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4134 | 7 | * modification, are permitted provided that the following conditions are | ||
4135 | 8 | * met: | ||
4136 | 9 | * * Redistributions of source code must retain the above copyright | ||
4137 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4138 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4139 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4140 | 13 | * the documentation and/or other materials provided with the | ||
4141 | 14 | * distribution. | ||
4142 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4143 | 16 | * may be used to endorse or promote products derived from this | ||
4144 | 17 | * software without specific prior written permission. | ||
4145 | 18 | * | ||
4146 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4147 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4148 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4149 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4150 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4151 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4152 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4153 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4154 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4155 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4156 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4157 | 30 | */ | ||
4158 | 31 | |||
4159 | 32 | #include "iorequest.h" | ||
4160 | 33 | |||
4161 | 34 | IORequest::IORequest() : QObject() | ||
4162 | 35 | { | ||
4163 | 36 | } | ||
4164 | 0 | 37 | ||
4165 | === added file 'nemo-folderlistmodel/iorequest.h' | |||
4166 | --- nemo-folderlistmodel/iorequest.h 1970-01-01 00:00:00 +0000 | |||
4167 | +++ nemo-folderlistmodel/iorequest.h 2013-06-01 17:20:36 +0000 | |||
4168 | @@ -0,0 +1,51 @@ | |||
4169 | 1 | /* | ||
4170 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4171 | 3 | * | ||
4172 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4173 | 5 | * | ||
4174 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4175 | 7 | * modification, are permitted provided that the following conditions are | ||
4176 | 8 | * met: | ||
4177 | 9 | * * Redistributions of source code must retain the above copyright | ||
4178 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4179 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4180 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4181 | 13 | * the documentation and/or other materials provided with the | ||
4182 | 14 | * distribution. | ||
4183 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4184 | 16 | * may be used to endorse or promote products derived from this | ||
4185 | 17 | * software without specific prior written permission. | ||
4186 | 18 | * | ||
4187 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4188 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4189 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4190 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4191 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4192 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4193 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4194 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4195 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4196 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4197 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4198 | 30 | */ | ||
4199 | 31 | |||
4200 | 32 | #ifndef IOREQUEST_H | ||
4201 | 33 | #define IOREQUEST_H | ||
4202 | 34 | |||
4203 | 35 | #include <QObject> | ||
4204 | 36 | |||
4205 | 37 | class IORequest : public QObject | ||
4206 | 38 | { | ||
4207 | 39 | Q_OBJECT | ||
4208 | 40 | public: | ||
4209 | 41 | explicit IORequest(); | ||
4210 | 42 | |||
4211 | 43 | public: | ||
4212 | 44 | virtual void run() = 0; | ||
4213 | 45 | |||
4214 | 46 | private: | ||
4215 | 47 | // hide this because IORequest should *NOT* be parented directly | ||
4216 | 48 | using QObject::setParent; | ||
4217 | 49 | }; | ||
4218 | 50 | |||
4219 | 51 | #endif // IOREQUEST_H | ||
4220 | 0 | 52 | ||
4221 | === added file 'nemo-folderlistmodel/iorequestworker.cpp' | |||
4222 | --- nemo-folderlistmodel/iorequestworker.cpp 1970-01-01 00:00:00 +0000 | |||
4223 | +++ nemo-folderlistmodel/iorequestworker.cpp 2013-06-01 17:20:36 +0000 | |||
4224 | @@ -0,0 +1,92 @@ | |||
4225 | 1 | /* | ||
4226 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4227 | 3 | * | ||
4228 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4229 | 5 | * | ||
4230 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4231 | 7 | * modification, are permitted provided that the following conditions are | ||
4232 | 8 | * met: | ||
4233 | 9 | * * Redistributions of source code must retain the above copyright | ||
4234 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4235 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4236 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4237 | 13 | * the documentation and/or other materials provided with the | ||
4238 | 14 | * distribution. | ||
4239 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4240 | 16 | * may be used to endorse or promote products derived from this | ||
4241 | 17 | * software without specific prior written permission. | ||
4242 | 18 | * | ||
4243 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4244 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4245 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4246 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4247 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4248 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4249 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4250 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4251 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4252 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4253 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4254 | 30 | */ | ||
4255 | 31 | |||
4256 | 32 | #include <QMutexLocker> | ||
4257 | 33 | #include <QDebug> | ||
4258 | 34 | |||
4259 | 35 | #include "iorequestworker.h" | ||
4260 | 36 | #include "iorequest.h" | ||
4261 | 37 | |||
4262 | 38 | /*! | ||
4263 | 39 | Lives on an IOWorkerThread. | ||
4264 | 40 | |||
4265 | 41 | Responsible for running IORequest jobs on the thread instance, and | ||
4266 | 42 | disposing of their resources once they are done. | ||
4267 | 43 | */ | ||
4268 | 44 | IORequestWorker::IORequestWorker() | ||
4269 | 45 | : QThread() | ||
4270 | 46 | , mTimeToQuit(false) | ||
4271 | 47 | { | ||
4272 | 48 | } | ||
4273 | 49 | |||
4274 | 50 | void IORequestWorker::addRequest(IORequest *request) | ||
4275 | 51 | { | ||
4276 | 52 | request->moveToThread(this); | ||
4277 | 53 | |||
4278 | 54 | // TODO: queue requests so we run the most important one first | ||
4279 | 55 | QMutexLocker lock(&mMutex); | ||
4280 | 56 | mRequests.append(request); | ||
4281 | 57 | |||
4282 | 58 | // wake run() | ||
4283 | 59 | mWaitCondition.wakeOne(); | ||
4284 | 60 | } | ||
4285 | 61 | |||
4286 | 62 | void IORequestWorker::run() | ||
4287 | 63 | { | ||
4288 | 64 | forever { | ||
4289 | 65 | QMutexLocker lock(&mMutex); | ||
4290 | 66 | |||
4291 | 67 | if (mTimeToQuit) | ||
4292 | 68 | return; | ||
4293 | 69 | |||
4294 | 70 | if (mRequests.empty()) | ||
4295 | 71 | mWaitCondition.wait(&mMutex); | ||
4296 | 72 | |||
4297 | 73 | while (!mRequests.isEmpty()) { | ||
4298 | 74 | IORequest *request = mRequests.takeFirst(); | ||
4299 | 75 | |||
4300 | 76 | lock.unlock(); | ||
4301 | 77 | |||
4302 | 78 | request->run(); | ||
4303 | 79 | request->deleteLater(); | ||
4304 | 80 | |||
4305 | 81 | lock.relock(); | ||
4306 | 82 | } | ||
4307 | 83 | } | ||
4308 | 84 | } | ||
4309 | 85 | |||
4310 | 86 | void IORequestWorker::exit() | ||
4311 | 87 | { | ||
4312 | 88 | qDebug() << Q_FUNC_INFO << "Quitting"; | ||
4313 | 89 | QMutexLocker lock(&mMutex); | ||
4314 | 90 | mTimeToQuit = true; | ||
4315 | 91 | mWaitCondition.wakeOne(); | ||
4316 | 92 | } | ||
4317 | 0 | 93 | ||
4318 | === added file 'nemo-folderlistmodel/iorequestworker.h' | |||
4319 | --- nemo-folderlistmodel/iorequestworker.h 1970-01-01 00:00:00 +0000 | |||
4320 | +++ nemo-folderlistmodel/iorequestworker.h 2013-06-01 17:20:36 +0000 | |||
4321 | @@ -0,0 +1,61 @@ | |||
4322 | 1 | /* | ||
4323 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4324 | 3 | * | ||
4325 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4326 | 5 | * | ||
4327 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4328 | 7 | * modification, are permitted provided that the following conditions are | ||
4329 | 8 | * met: | ||
4330 | 9 | * * Redistributions of source code must retain the above copyright | ||
4331 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4332 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4333 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4334 | 13 | * the documentation and/or other materials provided with the | ||
4335 | 14 | * distribution. | ||
4336 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4337 | 16 | * may be used to endorse or promote products derived from this | ||
4338 | 17 | * software without specific prior written permission. | ||
4339 | 18 | * | ||
4340 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4341 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4342 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4343 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4344 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4345 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4346 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4347 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4348 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4349 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4350 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4351 | 30 | */ | ||
4352 | 31 | |||
4353 | 32 | #ifndef IOREQUESTWORKER_H | ||
4354 | 33 | #define IOREQUESTWORKER_H | ||
4355 | 34 | |||
4356 | 35 | #include <QObject> | ||
4357 | 36 | #include <QThread> | ||
4358 | 37 | #include <QMutex> | ||
4359 | 38 | #include <QWaitCondition> | ||
4360 | 39 | |||
4361 | 40 | #include "iorequest.h" | ||
4362 | 41 | |||
4363 | 42 | class IORequestWorker : public QThread | ||
4364 | 43 | { | ||
4365 | 44 | Q_OBJECT | ||
4366 | 45 | public: | ||
4367 | 46 | explicit IORequestWorker(); | ||
4368 | 47 | |||
4369 | 48 | void addRequest(IORequest *request); | ||
4370 | 49 | |||
4371 | 50 | void run(); | ||
4372 | 51 | |||
4373 | 52 | void exit(); | ||
4374 | 53 | |||
4375 | 54 | private: | ||
4376 | 55 | QMutex mMutex; | ||
4377 | 56 | QWaitCondition mWaitCondition; | ||
4378 | 57 | QList<IORequest *> mRequests; | ||
4379 | 58 | bool mTimeToQuit; | ||
4380 | 59 | }; | ||
4381 | 60 | |||
4382 | 61 | #endif // IOREQUESTWORKER_H | ||
4383 | 0 | 62 | ||
4384 | === added file 'nemo-folderlistmodel/ioworkerthread.cpp' | |||
4385 | --- nemo-folderlistmodel/ioworkerthread.cpp 1970-01-01 00:00:00 +0000 | |||
4386 | +++ nemo-folderlistmodel/ioworkerthread.cpp 2013-06-01 17:20:36 +0000 | |||
4387 | @@ -0,0 +1,64 @@ | |||
4388 | 1 | /* | ||
4389 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4390 | 3 | * | ||
4391 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4392 | 5 | * | ||
4393 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4394 | 7 | * modification, are permitted provided that the following conditions are | ||
4395 | 8 | * met: | ||
4396 | 9 | * * Redistributions of source code must retain the above copyright | ||
4397 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4398 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4399 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4400 | 13 | * the documentation and/or other materials provided with the | ||
4401 | 14 | * distribution. | ||
4402 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4403 | 16 | * may be used to endorse or promote products derived from this | ||
4404 | 17 | * software without specific prior written permission. | ||
4405 | 18 | * | ||
4406 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4407 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4408 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4409 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4410 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4411 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4412 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4413 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4414 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4415 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4416 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4417 | 30 | */ | ||
4418 | 31 | |||
4419 | 32 | #include "ioworkerthread.h" | ||
4420 | 33 | |||
4421 | 34 | |||
4422 | 35 | /*! | ||
4423 | 36 | Hosts a thread, lives on the main thread. | ||
4424 | 37 | |||
4425 | 38 | Responsible for relaying interaction between the main thread and an IOWorkerThread. | ||
4426 | 39 | */ | ||
4427 | 40 | IOWorkerThread::IOWorkerThread(QObject *parent) : | ||
4428 | 41 | QObject(parent) | ||
4429 | 42 | { | ||
4430 | 43 | mWorker.start(QThread::IdlePriority); | ||
4431 | 44 | } | ||
4432 | 45 | |||
4433 | 46 | /*! | ||
4434 | 47 | Destroys an IOWorkerThread instance. | ||
4435 | 48 | */ | ||
4436 | 49 | IOWorkerThread::~IOWorkerThread() | ||
4437 | 50 | { | ||
4438 | 51 | mWorker.exit(); | ||
4439 | 52 | mWorker.wait(); | ||
4440 | 53 | } | ||
4441 | 54 | |||
4442 | 55 | /*! | ||
4443 | 56 | Attempts an asynchronous attempt to start a \a request. | ||
4444 | 57 | |||
4445 | 58 | If the request may be run, it is queued, and true is returned, otherwise, false. | ||
4446 | 59 | */ | ||
4447 | 60 | bool IOWorkerThread::addRequest(IORequest *request) | ||
4448 | 61 | { | ||
4449 | 62 | mWorker.addRequest(request); | ||
4450 | 63 | return true; | ||
4451 | 64 | } | ||
4452 | 0 | 65 | ||
4453 | === added file 'nemo-folderlistmodel/ioworkerthread.h' | |||
4454 | --- nemo-folderlistmodel/ioworkerthread.h 1970-01-01 00:00:00 +0000 | |||
4455 | +++ nemo-folderlistmodel/ioworkerthread.h 2013-06-01 17:20:36 +0000 | |||
4456 | @@ -0,0 +1,52 @@ | |||
4457 | 1 | /* | ||
4458 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4459 | 3 | * | ||
4460 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4461 | 5 | * | ||
4462 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4463 | 7 | * modification, are permitted provided that the following conditions are | ||
4464 | 8 | * met: | ||
4465 | 9 | * * Redistributions of source code must retain the above copyright | ||
4466 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4467 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4468 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4469 | 13 | * the documentation and/or other materials provided with the | ||
4470 | 14 | * distribution. | ||
4471 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4472 | 16 | * may be used to endorse or promote products derived from this | ||
4473 | 17 | * software without specific prior written permission. | ||
4474 | 18 | * | ||
4475 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4476 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4477 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4478 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4479 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4480 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4481 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4482 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4483 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4484 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4485 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4486 | 30 | */ | ||
4487 | 31 | |||
4488 | 32 | #ifndef IOWORKERTHREAD_H | ||
4489 | 33 | #define IOWORKERTHREAD_H | ||
4490 | 34 | |||
4491 | 35 | #include <QObject> | ||
4492 | 36 | #include <QThread> | ||
4493 | 37 | |||
4494 | 38 | #include "iorequestworker.h" | ||
4495 | 39 | |||
4496 | 40 | class IOWorkerThread : public QObject | ||
4497 | 41 | { | ||
4498 | 42 | Q_OBJECT | ||
4499 | 43 | public: | ||
4500 | 44 | explicit IOWorkerThread(QObject *parent = 0); | ||
4501 | 45 | virtual ~IOWorkerThread(); | ||
4502 | 46 | bool addRequest(IORequest *request); | ||
4503 | 47 | |||
4504 | 48 | private: | ||
4505 | 49 | IORequestWorker mWorker; | ||
4506 | 50 | }; | ||
4507 | 51 | |||
4508 | 52 | #endif // IOWORKERTHREAD_H | ||
4509 | 0 | 53 | ||
4510 | === added file 'nemo-folderlistmodel/plugin.cpp' | |||
4511 | --- nemo-folderlistmodel/plugin.cpp 1970-01-01 00:00:00 +0000 | |||
4512 | +++ nemo-folderlistmodel/plugin.cpp 2013-06-01 17:20:36 +0000 | |||
4513 | @@ -0,0 +1,53 @@ | |||
4514 | 1 | /* | ||
4515 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4516 | 3 | * | ||
4517 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4518 | 5 | * | ||
4519 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4520 | 7 | * modification, are permitted provided that the following conditions are | ||
4521 | 8 | * met: | ||
4522 | 9 | * * Redistributions of source code must retain the above copyright | ||
4523 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4524 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4525 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4526 | 13 | * the documentation and/or other materials provided with the | ||
4527 | 14 | * distribution. | ||
4528 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4529 | 16 | * may be used to endorse or promote products derived from this | ||
4530 | 17 | * software without specific prior written permission. | ||
4531 | 18 | * | ||
4532 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4533 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4534 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4535 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4536 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4537 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4538 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4539 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4540 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4541 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4542 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4543 | 30 | */ | ||
4544 | 31 | |||
4545 | 32 | #include <QVector> | ||
4546 | 33 | #include <QFileInfo> | ||
4547 | 34 | |||
4548 | 35 | #include "plugin.h" | ||
4549 | 36 | |||
4550 | 37 | NemoFolderListModelPlugin::NemoFolderListModelPlugin() { } | ||
4551 | 38 | |||
4552 | 39 | NemoFolderListModelPlugin::~NemoFolderListModelPlugin() { } | ||
4553 | 40 | |||
4554 | 41 | void NemoFolderListModelPlugin::initializeEngine(QmlEngine *engine, const char *uri) | ||
4555 | 42 | { | ||
4556 | 43 | Q_UNUSED(engine) | ||
4557 | 44 | Q_ASSERT(uri == QLatin1String("org.nemomobile.folderlistmodel")); | ||
4558 | 45 | } | ||
4559 | 46 | |||
4560 | 47 | void NemoFolderListModelPlugin::registerTypes(const char *uri) | ||
4561 | 48 | { | ||
4562 | 49 | Q_ASSERT(uri == QLatin1String("org.nemomobile.folderlistmodel")); | ||
4563 | 50 | qRegisterMetaType<QVector<QFileInfo> >(); | ||
4564 | 51 | qmlRegisterType<DirModel>(uri, 1, 0, "FolderListModel"); | ||
4565 | 52 | } | ||
4566 | 53 | |||
4567 | 0 | 54 | ||
4568 | === added file 'nemo-folderlistmodel/plugin.h' | |||
4569 | --- nemo-folderlistmodel/plugin.h 1970-01-01 00:00:00 +0000 | |||
4570 | +++ nemo-folderlistmodel/plugin.h 2013-06-01 17:20:36 +0000 | |||
4571 | @@ -0,0 +1,82 @@ | |||
4572 | 1 | /* | ||
4573 | 2 | * Copyright (C) 2012 Robin Burchell <robin+nemo@viroteck.net> | ||
4574 | 3 | * | ||
4575 | 4 | * You may use this file under the terms of the BSD license as follows: | ||
4576 | 5 | * | ||
4577 | 6 | * "Redistribution and use in source and binary forms, with or without | ||
4578 | 7 | * modification, are permitted provided that the following conditions are | ||
4579 | 8 | * met: | ||
4580 | 9 | * * Redistributions of source code must retain the above copyright | ||
4581 | 10 | * notice, this list of conditions and the following disclaimer. | ||
4582 | 11 | * * Redistributions in binary form must reproduce the above copyright | ||
4583 | 12 | * notice, this list of conditions and the following disclaimer in | ||
4584 | 13 | * the documentation and/or other materials provided with the | ||
4585 | 14 | * distribution. | ||
4586 | 15 | * * Neither the name of Nemo Mobile nor the names of its contributors | ||
4587 | 16 | * may be used to endorse or promote products derived from this | ||
4588 | 17 | * software without specific prior written permission. | ||
4589 | 18 | * | ||
4590 | 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
4591 | 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
4592 | 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
4593 | 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
4594 | 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
4595 | 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
4596 | 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
4597 | 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
4598 | 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
4599 | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
4600 | 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." | ||
4601 | 30 | */ | ||
4602 | 31 | |||
4603 | 32 | #ifndef NEMO_QML_PLUGINS_FOLDERLISTMODEL | ||
4604 | 33 | #define NEMO_QML_PLUGINS_FOLDERLISTMODEL | ||
4605 | 34 | |||
4606 | 35 | #include <QtGlobal> | ||
4607 | 36 | |||
4608 | 37 | #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) | ||
4609 | 38 | #include <QtDeclarative> | ||
4610 | 39 | #include <QDeclarativeEngine> | ||
4611 | 40 | #include <QDeclarativeExtensionPlugin> | ||
4612 | 41 | #include <QVector> | ||
4613 | 42 | #include <QFileInfo> | ||
4614 | 43 | |||
4615 | 44 | #define PLUGIN_CLASS_EXPORT | ||
4616 | 45 | #define PLUGIN_CLASS_EXTERNAL_EXPORT Q_EXPORT_PLUGIN2(nemofolderlistmodel, NemoFolderListModelPlugin); | ||
4617 | 46 | #define PLUGIN_CLASS_EXTEND | ||
4618 | 47 | typedef QDeclarativeExtensionPlugin QmlPluginParent; | ||
4619 | 48 | typedef QDeclarativeEngine QmlEngine; | ||
4620 | 49 | Q_DECLARE_METATYPE(QVector<QFileInfo>) | ||
4621 | 50 | |||
4622 | 51 | #else | ||
4623 | 52 | #include <QQmlComponent> | ||
4624 | 53 | #include <QQmlEngine> | ||
4625 | 54 | #include <QQmlContext> | ||
4626 | 55 | #include <QQmlExtensionPlugin> | ||
4627 | 56 | |||
4628 | 57 | #define PLUGIN_CLASS_EXPORT Q_DECL_EXPORT | ||
4629 | 58 | #define PLUGIN_CLASS_EXTERNAL_EXPORT | ||
4630 | 59 | #define PLUGIN_CLASS_EXTEND \ | ||
4631 | 60 | Q_OBJECT \ | ||
4632 | 61 | Q_PLUGIN_METADATA(IID "org.nemomobile.folderlistmodel") | ||
4633 | 62 | typedef QQmlExtensionPlugin QmlPluginParent; | ||
4634 | 63 | typedef QQmlEngine QmlEngine; | ||
4635 | 64 | #endif | ||
4636 | 65 | |||
4637 | 66 | #include "dirmodel.h" | ||
4638 | 67 | |||
4639 | 68 | class PLUGIN_CLASS_EXPORT NemoFolderListModelPlugin : public QmlPluginParent | ||
4640 | 69 | { | ||
4641 | 70 | PLUGIN_CLASS_EXTEND | ||
4642 | 71 | |||
4643 | 72 | public: | ||
4644 | 73 | NemoFolderListModelPlugin(); | ||
4645 | 74 | virtual ~NemoFolderListModelPlugin(); | ||
4646 | 75 | |||
4647 | 76 | void initializeEngine(QmlEngine *engine, const char *uri); | ||
4648 | 77 | void registerTypes(const char *uri); | ||
4649 | 78 | }; | ||
4650 | 79 | |||
4651 | 80 | PLUGIN_CLASS_EXTERNAL_EXPORT | ||
4652 | 81 | |||
4653 | 82 | #endif // NEMO_QML_PLUGINS_FOLDERLISTMODEL | ||
4654 | 0 | 83 | ||
4655 | === added file 'nemo-folderlistmodel/qmldir' | |||
4656 | --- nemo-folderlistmodel/qmldir 1970-01-01 00:00:00 +0000 | |||
4657 | +++ nemo-folderlistmodel/qmldir 2013-06-01 17:20:36 +0000 | |||
4658 | @@ -0,0 +1,1 @@ | |||
4659 | 1 | plugin nemofolderlistmodel | ||
4660 | 0 | 2 | ||
4661 | === added directory 'test_folderlistmodel' | |||
4662 | === added directory 'test_folderlistmodel/regression' | |||
4663 | === added file 'test_folderlistmodel/regression/media_asx.h' | |||
4664 | --- test_folderlistmodel/regression/media_asx.h 1970-01-01 00:00:00 +0000 | |||
4665 | +++ test_folderlistmodel/regression/media_asx.h 2013-06-01 17:20:36 +0000 | |||
4666 | @@ -0,0 +1,21 @@ | |||
4667 | 1 | const unsigned char media_asx[] = { | ||
4668 | 2 | 0x3c, 0x61, 0x73, 0x78, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, | ||
4669 | 3 | 0x3d, 0x22, 0x33, 0x2e, 0x30, 0x22, 0x3e, 0x0d, 0x0a, 0x3c, 0x65, 0x6e, | ||
4670 | 4 | 0x74, 0x72, 0x79, 0x3e, 0x0d, 0x0a, 0x3c, 0x72, 0x65, 0x66, 0x20, 0x68, | ||
4671 | 5 | 0x72, 0x65, 0x66, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, | ||
4672 | 6 | 0x72, 0x65, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x61, 0x62, 0x61, 0x63, 0x61, | ||
4673 | 7 | 0x73, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x61, 0x74, 0x65, 0x77, | ||
4674 | 8 | 0x61, 0x79, 0x2f, 0x67, 0x65, 0x74, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x2e, | ||
4675 | 9 | 0x61, 0x73, 0x70, 0x3f, 0x73, 0x63, 0x3d, 0x77, 0x74, 0x72, 0x78, 0x2d, | ||
4676 | 10 | 0x66, 0x6d, 0x22, 0x20, 0x2f, 0x3e, 0x0d, 0x0a, 0x3c, 0x2f, 0x65, 0x6e, | ||
4677 | 11 | 0x74, 0x72, 0x79, 0x3e, 0x0d, 0x0a, 0x3c, 0x65, 0x6e, 0x74, 0x72, 0x79, | ||
4678 | 12 | 0x3e, 0x0d, 0x0a, 0x3c, 0x72, 0x65, 0x66, 0x20, 0x68, 0x72, 0x65, 0x66, | ||
4679 | 13 | 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x6d, 0x65, 0x64, | ||
4680 | 14 | 0x69, 0x61, 0x2e, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x61, 0x64, 0x73, | ||
4681 | 15 | 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x64, | ||
4682 | 16 | 0x61, 0x74, 0x61, 0x2f, 0x72, 0x65, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x61, | ||
4683 | 17 | 0x73, 0x78, 0x2f, 0x57, 0x54, 0x52, 0x58, 0x2e, 0x61, 0x73, 0x78, 0x22, | ||
4684 | 18 | 0x20, 0x2f, 0x3e, 0x0d, 0x0a, 0x3c, 0x2f, 0x65, 0x6e, 0x74, 0x72, 0x79, | ||
4685 | 19 | 0x3e, 0x0d, 0x0a, 0x3c, 0x2f, 0x61, 0x73, 0x78, 0x3e, 0x0d, 0x0a | ||
4686 | 20 | }; | ||
4687 | 21 | qint64 media_asx_len = 215; | ||
4688 | 0 | 22 | ||
4689 | === added file 'test_folderlistmodel/regression/media_xspf.h' | |||
4690 | --- test_folderlistmodel/regression/media_xspf.h 1970-01-01 00:00:00 +0000 | |||
4691 | +++ test_folderlistmodel/regression/media_xspf.h 2013-06-01 17:20:36 +0000 | |||
4692 | @@ -0,0 +1,135 @@ | |||
4693 | 1 | const unsigned char media_xspf[] = { | ||
4694 | 2 | 0x3c, 0x3f, 0x78, 0x6d, 0x6c, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, | ||
4695 | 3 | 0x6e, 0x3d, 0x22, 0x31, 0x2e, 0x30, 0x22, 0x20, 0x65, 0x6e, 0x63, 0x6f, | ||
4696 | 4 | 0x64, 0x69, 0x6e, 0x67, 0x3d, 0x22, 0x55, 0x54, 0x46, 0x2d, 0x38, 0x22, | ||
4697 | 5 | 0x3f, 0x3e, 0x0a, 0x3c, 0x70, 0x6c, 0x61, 0x79, 0x6c, 0x69, 0x73, 0x74, | ||
4698 | 6 | 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x31, 0x22, | ||
4699 | 7 | 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, | ||
4700 | 8 | 0x3a, 0x2f, 0x2f, 0x78, 0x73, 0x70, 0x66, 0x2e, 0x6f, 0x72, 0x67, 0x2f, | ||
4701 | 9 | 0x6e, 0x73, 0x2f, 0x30, 0x2f, 0x22, 0x20, 0x78, 0x6d, 0x6c, 0x6e, 0x73, | ||
4702 | 10 | 0x3a, 0x76, 0x6c, 0x63, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, | ||
4703 | 11 | 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, | ||
4704 | 12 | 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x76, 0x6c, 0x63, 0x2f, 0x70, 0x6c, | ||
4705 | 13 | 0x61, 0x79, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x6e, 0x73, 0x2f, 0x30, 0x2f, | ||
4706 | 14 | 0x22, 0x3e, 0x0a, 0x09, 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x4c, | ||
4707 | 15 | 0x69, 0x73, 0x74, 0x61, 0x20, 0x64, 0x65, 0x20, 0x72, 0x65, 0x70, 0x72, | ||
4708 | 16 | 0x6f, 0x64, 0x75, 0xc3, 0xa7, 0xc3, 0xa3, 0x6f, 0x3c, 0x2f, 0x74, 0x69, | ||
4709 | 17 | 0x74, 0x6c, 0x65, 0x3e, 0x0a, 0x09, 0x3c, 0x74, 0x72, 0x61, 0x63, 0x6b, | ||
4710 | 18 | 0x4c, 0x69, 0x73, 0x74, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4711 | 19 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x74, | ||
4712 | 20 | 0x72, 0x61, 0x63, 0x6b, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4713 | 21 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4714 | 22 | 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x4c, 0x69, 0x61, 0x6e, 0xc3, | ||
4715 | 23 | 0xa7, 0x61, 0x2f, 0x45, 0x41, 0x45, 0x20, 0x70, 0x61, 0x72, 0x61, 0x20, | ||
4716 | 24 | 0x61, 0x20, 0x53, 0x6f, 0x63, 0x69, 0x65, 0x64, 0x61, 0x64, 0x65, 0x3c, | ||
4717 | 25 | 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, | ||
4718 | 26 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4719 | 27 | 0x20, 0x20, 0x3c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, | ||
4720 | 28 | 0x66, 0x69, 0x6c, 0x65, 0x3a, 0x2f, 0x2f, 0x2f, 0x6d, 0x6e, 0x74, 0x2f, | ||
4721 | 29 | 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x2f, 0x61, 0x75, 0x6c, 0x61, 0x73, | ||
4722 | 30 | 0x2f, 0x45, 0x41, 0x45, 0x2f, 0x31, 0x31, 0x35, 0x25, 0x32, 0x30, 0x50, | ||
4723 | 31 | 0x72, 0x6f, 0x70, 0x61, 0x67, 0x61, 0x63, 0x61, 0x6f, 0x5f, 0x64, 0x6f, | ||
4724 | 32 | 0x5f, 0x45, 0x73, 0x70, 0x69, 0x72, 0x69, 0x74, 0x69, 0x73, 0x6d, 0x6f, | ||
4725 | 33 | 0x2f, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x73, 0x2f, 0x4f, 0x25, 0x32, 0x30, | ||
4726 | 34 | 0x71, 0x75, 0x65, 0x25, 0x32, 0x30, 0x65, 0x25, 0x32, 0x30, 0x61, 0x25, | ||
4727 | 35 | 0x32, 0x30, 0x45, 0x41, 0x45, 0x25, 0x32, 0x30, 0x31, 0x2e, 0x6d, 0x70, | ||
4728 | 36 | 0x34, 0x3c, 0x2f, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, | ||
4729 | 37 | 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4730 | 38 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4731 | 39 | 0x20, 0x3c, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, | ||
4732 | 40 | 0x61, 0x70, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3d, | ||
4733 | 41 | 0x22, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, | ||
4734 | 42 | 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, | ||
4735 | 43 | 0x2f, 0x76, 0x6c, 0x63, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x6c, 0x69, 0x73, | ||
4736 | 44 | 0x74, 0x2f, 0x30, 0x22, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4737 | 45 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4738 | 46 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4739 | 47 | 0x20, 0x20, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x69, 0x64, 0x3e, 0x30, 0x3c, | ||
4740 | 48 | 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x69, 0x64, 0x3e, 0x0a, 0x20, 0x20, 0x20, | ||
4741 | 49 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4742 | 50 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x76, | ||
4743 | 51 | 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x73, 0x74, | ||
4744 | 52 | 0x61, 0x72, 0x74, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x34, 0x35, 0x3c, | ||
4745 | 53 | 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, | ||
4746 | 54 | 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4747 | 55 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4748 | 56 | 0x20, 0x20, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, | ||
4749 | 57 | 0x6e, 0x3e, 0x73, 0x74, 0x6f, 0x70, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x3d, | ||
4750 | 58 | 0x36, 0x39, 0x3c, 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, | ||
4751 | 59 | 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4752 | 60 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4753 | 61 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, | ||
4754 | 62 | 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, | ||
4755 | 63 | 0x65, 0x65, 0x6e, 0x3c, 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, | ||
4756 | 64 | 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4757 | 65 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4758 | 66 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x6f, | ||
4759 | 67 | 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, | ||
4760 | 68 | 0x3d, 0x35, 0x30, 0x30, 0x3c, 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, | ||
4761 | 69 | 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4762 | 70 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4763 | 71 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x2f, 0x65, 0x78, 0x74, 0x65, | ||
4764 | 72 | 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4765 | 73 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, | ||
4766 | 74 | 0x2f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x74, | ||
4767 | 75 | 0x72, 0x61, 0x63, 0x6b, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4768 | 76 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4769 | 77 | 0x3c, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x3e, 0x48, 0x69, 0x73, 0x74, 0x6f, | ||
4770 | 78 | 0x72, 0x69, 0x61, 0x20, 0x64, 0x6f, 0x20, 0x45, 0x73, 0x70, 0x69, 0x72, | ||
4771 | 79 | 0x69, 0x74, 0x69, 0x73, 0x6d, 0x6f, 0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, | ||
4772 | 80 | 0x65, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4773 | 81 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x6c, 0x6f, | ||
4774 | 82 | 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x66, 0x69, 0x6c, 0x65, 0x3a, | ||
4775 | 83 | 0x2f, 0x2f, 0x2f, 0x6d, 0x6e, 0x74, 0x2f, 0x62, 0x61, 0x63, 0x6b, 0x75, | ||
4776 | 84 | 0x70, 0x2f, 0x61, 0x75, 0x6c, 0x61, 0x73, 0x2f, 0x45, 0x41, 0x45, 0x2f, | ||
4777 | 85 | 0x31, 0x31, 0x35, 0x25, 0x32, 0x30, 0x50, 0x72, 0x6f, 0x70, 0x61, 0x67, | ||
4778 | 86 | 0x61, 0x63, 0x61, 0x6f, 0x5f, 0x64, 0x6f, 0x5f, 0x45, 0x73, 0x70, 0x69, | ||
4779 | 87 | 0x72, 0x69, 0x74, 0x69, 0x73, 0x6d, 0x6f, 0x2f, 0x76, 0x69, 0x64, 0x65, | ||
4780 | 88 | 0x6f, 0x73, 0x2f, 0x4f, 0x25, 0x32, 0x30, 0x71, 0x75, 0x65, 0x25, 0x32, | ||
4781 | 89 | 0x30, 0x65, 0x25, 0x32, 0x30, 0x61, 0x25, 0x32, 0x30, 0x45, 0x41, 0x45, | ||
4782 | 90 | 0x25, 0x32, 0x30, 0x31, 0x2e, 0x6d, 0x70, 0x34, 0x3c, 0x2f, 0x6c, 0x6f, | ||
4783 | 91 | 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x3c, | ||
4784 | 92 | 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x70, | ||
4785 | 93 | 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x68, | ||
4786 | 94 | 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, | ||
4787 | 95 | 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x76, | ||
4788 | 96 | 0x6c, 0x63, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x6c, 0x69, 0x73, 0x74, 0x2f, | ||
4789 | 97 | 0x30, 0x22, 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x09, 0x3c, 0x76, 0x6c, 0x63, | ||
4790 | 98 | 0x3a, 0x69, 0x64, 0x3e, 0x31, 0x3c, 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x69, | ||
4791 | 99 | 0x64, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4792 | 100 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4793 | 101 | 0x20, 0x20, 0x20, 0x20, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, | ||
4794 | 102 | 0x69, 0x6f, 0x6e, 0x3e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x2d, 0x74, 0x69, | ||
4795 | 103 | 0x6d, 0x65, 0x3d, 0x31, 0x39, 0x37, 0x3c, 0x2f, 0x76, 0x6c, 0x63, 0x3a, | ||
4796 | 104 | 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x20, 0x20, 0x20, 0x20, | ||
4797 | 105 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4798 | 106 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3c, 0x76, 0x6c, | ||
4799 | 107 | 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x73, 0x74, 0x6f, | ||
4800 | 108 | 0x70, 0x2d, 0x74, 0x69, 0x6d, 0x65, 0x3d, 0x32, 0x36, 0x37, 0x3c, 0x2f, | ||
4801 | 109 | 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, | ||
4802 | 110 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4803 | 111 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4804 | 112 | 0x20, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, | ||
4805 | 113 | 0x3e, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65, 0x6e, 0x3c, | ||
4806 | 114 | 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x3e, | ||
4807 | 115 | 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4808 | 116 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, | ||
4809 | 117 | 0x20, 0x20, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, | ||
4810 | 118 | 0x6e, 0x3e, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x3d, 0x35, 0x30, 0x30, | ||
4811 | 119 | 0x3c, 0x2f, 0x76, 0x6c, 0x63, 0x3a, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, | ||
4812 | 120 | 0x3e, 0x0a, 0x09, 0x09, 0x09, 0x3c, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, | ||
4813 | 121 | 0x73, 0x69, 0x6f, 0x6e, 0x3e, 0x0a, 0x09, 0x09, 0x3c, 0x2f, 0x74, 0x72, | ||
4814 | 122 | 0x61, 0x63, 0x6b, 0x3e, 0x0a, 0x09, 0x3c, 0x2f, 0x74, 0x72, 0x61, 0x63, | ||
4815 | 123 | 0x6b, 0x4c, 0x69, 0x73, 0x74, 0x3e, 0x0a, 0x09, 0x3c, 0x65, 0x78, 0x74, | ||
4816 | 124 | 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x70, 0x70, 0x6c, 0x69, | ||
4817 | 125 | 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3d, 0x22, 0x68, 0x74, 0x74, 0x70, | ||
4818 | 126 | 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, | ||
4819 | 127 | 0x6c, 0x61, 0x6e, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x76, 0x6c, 0x63, 0x2f, | ||
4820 | 128 | 0x70, 0x6c, 0x61, 0x79, 0x6c, 0x69, 0x73, 0x74, 0x2f, 0x30, 0x22, 0x3e, | ||
4821 | 129 | 0x0a, 0x09, 0x09, 0x09, 0x3c, 0x76, 0x6c, 0x63, 0x3a, 0x69, 0x74, 0x65, | ||
4822 | 130 | 0x6d, 0x20, 0x74, 0x69, 0x64, 0x3d, 0x22, 0x30, 0x22, 0x20, 0x2f, 0x3e, | ||
4823 | 131 | 0x0a, 0x09, 0x3c, 0x2f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, | ||
4824 | 132 | 0x6e, 0x3e, 0x0a, 0x3c, 0x2f, 0x70, 0x6c, 0x61, 0x79, 0x6c, 0x69, 0x73, | ||
4825 | 133 | 0x74, 0x3e, 0x0a | ||
4826 | 134 | }; | ||
4827 | 135 | qint64 media_xspf_len = 1575; | ||
4828 | 0 | 136 | ||
4829 | === added directory 'test_folderlistmodel/regression/mimetypes' | |||
4830 | === added file 'test_folderlistmodel/regression/mimetypes/LICENSE.LGPL' | |||
4831 | --- test_folderlistmodel/regression/mimetypes/LICENSE.LGPL 1970-01-01 00:00:00 +0000 | |||
4832 | +++ test_folderlistmodel/regression/mimetypes/LICENSE.LGPL 2013-06-01 17:20:36 +0000 | |||
4833 | @@ -0,0 +1,504 @@ | |||
4834 | 1 | GNU LESSER GENERAL PUBLIC LICENSE | ||
4835 | 2 | Version 2.1, February 1999 | ||
4836 | 3 | |||
4837 | 4 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. | ||
4838 | 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
4839 | 6 | Everyone is permitted to copy and distribute verbatim copies | ||
4840 | 7 | of this license document, but changing it is not allowed. | ||
4841 | 8 | |||
4842 | 9 | [This is the first released version of the Lesser GPL. It also counts | ||
4843 | 10 | as the successor of the GNU Library Public License, version 2, hence | ||
4844 | 11 | the version number 2.1.] | ||
4845 | 12 | |||
4846 | 13 | Preamble | ||
4847 | 14 | |||
4848 | 15 | The licenses for most software are designed to take away your | ||
4849 | 16 | freedom to share and change it. By contrast, the GNU General Public | ||
4850 | 17 | Licenses are intended to guarantee your freedom to share and change | ||
4851 | 18 | free software--to make sure the software is free for all its users. | ||
4852 | 19 | |||
4853 | 20 | This license, the Lesser General Public License, applies to some | ||
4854 | 21 | specially designated software packages--typically libraries--of the | ||
4855 | 22 | Free Software Foundation and other authors who decide to use it. You | ||
4856 | 23 | can use it too, but we suggest you first think carefully about whether | ||
4857 | 24 | this license or the ordinary General Public License is the better | ||
4858 | 25 | strategy to use in any particular case, based on the explanations below. | ||
4859 | 26 | |||
4860 | 27 | When we speak of free software, we are referring to freedom of use, | ||
4861 | 28 | not price. Our General Public Licenses are designed to make sure that | ||
4862 | 29 | you have the freedom to distribute copies of free software (and charge | ||
4863 | 30 | for this service if you wish); that you receive source code or can get | ||
4864 | 31 | it if you want it; that you can change the software and use pieces of | ||
4865 | 32 | it in new free programs; and that you are informed that you can do | ||
4866 | 33 | these things. | ||
4867 | 34 | |||
4868 | 35 | To protect your rights, we need to make restrictions that forbid | ||
4869 | 36 | distributors to deny you these rights or to ask you to surrender these | ||
4870 | 37 | rights. These restrictions translate to certain responsibilities for | ||
4871 | 38 | you if you distribute copies of the library or if you modify it. | ||
4872 | 39 | |||
4873 | 40 | For example, if you distribute copies of the library, whether gratis | ||
4874 | 41 | or for a fee, you must give the recipients all the rights that we gave | ||
4875 | 42 | you. You must make sure that they, too, receive or can get the source | ||
4876 | 43 | code. If you link other code with the library, you must provide | ||
4877 | 44 | complete object files to the recipients, so that they can relink them | ||
4878 | 45 | with the library after making changes to the library and recompiling | ||
4879 | 46 | it. And you must show them these terms so they know their rights. | ||
4880 | 47 | |||
4881 | 48 | We protect your rights with a two-step method: (1) we copyright the | ||
4882 | 49 | library, and (2) we offer you this license, which gives you legal | ||
4883 | 50 | permission to copy, distribute and/or modify the library. | ||
4884 | 51 | |||
4885 | 52 | To protect each distributor, we want to make it very clear that | ||
4886 | 53 | there is no warranty for the free library. Also, if the library is | ||
4887 | 54 | modified by someone else and passed on, the recipients should know | ||
4888 | 55 | that what they have is not the original version, so that the original | ||
4889 | 56 | author's reputation will not be affected by problems that might be | ||
4890 | 57 | introduced by others. | ||
4891 | 58 | |||
4892 | 0 | 59 | ||
4893 | 60 | Finally, software patents pose a constant threat to the existence of | ||
4894 | 61 | any free program. We wish to make sure that a company cannot | ||
4895 | 62 | effectively restrict the users of a free program by obtaining a | ||
4896 | 63 | restrictive license from a patent holder. Therefore, we insist that | ||
4897 | 64 | any patent license obtained for a version of the library must be | ||
4898 | 65 | consistent with the full freedom of use specified in this license. | ||
4899 | 66 | |||
4900 | 67 | Most GNU software, including some libraries, is covered by the | ||
4901 | 68 | ordinary GNU General Public License. This license, the GNU Lesser | ||
4902 | 69 | General Public License, applies to certain designated libraries, and | ||
4903 | 70 | is quite different from the ordinary General Public License. We use | ||
4904 | 71 | this license for certain libraries in order to permit linking those | ||
4905 | 72 | libraries into non-free programs. | ||
4906 | 73 | |||
4907 | 74 | When a program is linked with a library, whether statically or using | ||
4908 | 75 | a shared library, the combination of the two is legally speaking a | ||
4909 | 76 | combined work, a derivative of the original library. The ordinary | ||
4910 | 77 | General Public License therefore permits such linking only if the | ||
4911 | 78 | entire combination fits its criteria of freedom. The Lesser General | ||
4912 | 79 | Public License permits more lax criteria for linking other code with | ||
4913 | 80 | the library. | ||
4914 | 81 | |||
4915 | 82 | We call this license the "Lesser" General Public License because it | ||
4916 | 83 | does Less to protect the user's freedom than the ordinary General | ||
4917 | 84 | Public License. It also provides other free software developers Less | ||
4918 | 85 | of an advantage over competing non-free programs. These disadvantages | ||
4919 | 86 | are the reason we use the ordinary General Public License for many | ||
4920 | 87 | libraries. However, the Lesser license provides advantages in certain | ||
4921 | 88 | special circumstances. | ||
4922 | 89 | |||
4923 | 90 | For example, on rare occasions, there may be a special need to | ||
4924 | 91 | encourage the widest possible use of a certain library, so that it becomes | ||
4925 | 92 | a de-facto standard. To achieve this, non-free programs must be | ||
4926 | 93 | allowed to use the library. A more frequent case is that a free | ||
4927 | 94 | library does the same job as widely used non-free libraries. In this | ||
4928 | 95 | case, there is little to gain by limiting the free library to free | ||
4929 | 96 | software only, so we use the Lesser General Public License. | ||
4930 | 97 | |||
4931 | 98 | In other cases, permission to use a particular library in non-free | ||
4932 | 99 | programs enables a greater number of people to use a large body of | ||
4933 | 100 | free software. For example, permission to use the GNU C Library in | ||
4934 | 101 | non-free programs enables many more people to use the whole GNU | ||
4935 | 102 | operating system, as well as its variant, the GNU/Linux operating | ||
4936 | 103 | system. | ||
4937 | 104 | |||
4938 | 105 | Although the Lesser General Public License is Less protective of the | ||
4939 | 106 | users' freedom, it does ensure that the user of a program that is | ||
4940 | 107 | linked with the Library has the freedom and the wherewithal to run | ||
4941 | 108 | that program using a modified version of the Library. | ||
4942 | 109 | |||
4943 | 110 | The precise terms and conditions for copying, distribution and | ||
4944 | 111 | modification follow. Pay close attention to the difference between a | ||
4945 | 112 | "work based on the library" and a "work that uses the library". The | ||
4946 | 113 | former contains code derived from the library, whereas the latter must | ||
4947 | 114 | be combined with the library in order to run. | ||
4948 | 115 | |||
4949 | 1 | 116 | ||
4950 | 117 | GNU LESSER GENERAL PUBLIC LICENSE | ||
4951 | 118 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | ||
4952 | 119 | |||
4953 | 120 | 0. This License Agreement applies to any software library or other | ||
4954 | 121 | program which contains a notice placed by the copyright holder or | ||
4955 | 122 | other authorized party saying it may be distributed under the terms of | ||
4956 | 123 | this Lesser General Public License (also called "this License"). | ||
4957 | 124 | Each licensee is addressed as "you". | ||
4958 | 125 | |||
4959 | 126 | A "library" means a collection of software functions and/or data | ||
4960 | 127 | prepared so as to be conveniently linked with application programs | ||
4961 | 128 | (which use some of those functions and data) to form executables. | ||
4962 | 129 | |||
4963 | 130 | The "Library", below, refers to any such software library or work | ||
4964 | 131 | which has been distributed under these terms. A "work based on the | ||
4965 | 132 | Library" means either the Library or any derivative work under | ||
4966 | 133 | copyright law: that is to say, a work containing the Library or a | ||
4967 | 134 | portion of it, either verbatim or with modifications and/or translated | ||
4968 | 135 | straightforwardly into another language. (Hereinafter, translation is | ||
4969 | 136 | included without limitation in the term "modification".) | ||
4970 | 137 | |||
4971 | 138 | "Source code" for a work means the preferred form of the work for | ||
4972 | 139 | making modifications to it. For a library, complete source code means | ||
4973 | 140 | all the source code for all modules it contains, plus any associated | ||
4974 | 141 | interface definition files, plus the scripts used to control compilation | ||
4975 | 142 | and installation of the library. | ||
4976 | 143 | |||
4977 | 144 | Activities other than copying, distribution and modification are not | ||
4978 | 145 | covered by this License; they are outside its scope. The act of | ||
4979 | 146 | running a program using the Library is not restricted, and output from | ||
4980 | 147 | such a program is covered only if its contents constitute a work based | ||
4981 | 148 | on the Library (independent of the use of the Library in a tool for | ||
4982 | 149 | writing it). Whether that is true depends on what the Library does | ||
4983 | 150 | and what the program that uses the Library does. | ||
4984 | 151 | |||
4985 | 152 | 1. You may copy and distribute verbatim copies of the Library's | ||
4986 | 153 | complete source code as you receive it, in any medium, provided that | ||
4987 | 154 | you conspicuously and appropriately publish on each copy an | ||
4988 | 155 | appropriate copyright notice and disclaimer of warranty; keep intact | ||
4989 | 156 | all the notices that refer to this License and to the absence of any | ||
4990 | 157 | warranty; and distribute a copy of this License along with the | ||
4991 | 158 | Library. | ||
4992 | 159 | |||
4993 | 160 | You may charge a fee for the physical act of transferring a copy, | ||
4994 | 161 | and you may at your option offer warranty protection in exchange for a | ||
4995 | 162 | fee. | ||
4996 | 163 | |||
4997 | 2 | 164 | ||
4998 | 165 | 2. You may modify your copy or copies of the Library or any portion | ||
4999 | 166 | of it, thus forming a work based on the Library, and copy and | ||
5000 | 167 | distribute such modifications or work under the terms of Section 1 |
FAILED: Continuous integration, rev:20 /code.launchpad .net/~carlos- mazieri/ ubuntu- filemanager- app/model/ +merge/ 166863/ +edit-commit- message
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https:/
http:// 91.189. 93.125: 8080/job/ ubuntu- filemanager- app-ci/ 5/ 91.189. 93.125: 8080/job/ ubuntu- filemanager- app-quantal- amd64-ci/ 2 91.189. 93.125: 8080/job/ ubuntu- filemanager- app-raring- amd64-ci/ 5
Executed test runs:
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: 91.189. 93.125: 8080/job/ ubuntu- filemanager- app-ci/ 5/rebuild
http://