Merge lp:~carlos-mazieri/ubuntu-filemanager-app/model into lp:ubuntu-filemanager-app/plugin

Proposed by Carlos Jose Mazieri
Status: Merged
Approved by: Carlos Jose Mazieri
Approved revision: 54
Merged at revision: 44
Proposed branch: lp:~carlos-mazieri/ubuntu-filemanager-app/model
Merge into: lp:ubuntu-filemanager-app/plugin
Diff against target: 1905 lines (+968/-547)
10 files modified
folderlistmodel/clipboard.cpp (+495/-0)
folderlistmodel/clipboard.h (+132/-0)
folderlistmodel/dirmodel.cpp (+37/-8)
folderlistmodel/dirmodel.h (+2/-0)
folderlistmodel/filesystemaction.cpp (+85/-507)
folderlistmodel/filesystemaction.h (+15/-20)
folderlistmodel/fmutil.cpp (+132/-0)
folderlistmodel/fmutil.h (+46/-0)
folderlistmodel/folderlistmodel.pri (+6/-2)
test_folderlistmodel/regression/tst_folderlistmodel.cpp (+18/-10)
To merge this branch: bzr merge lp:~carlos-mazieri/ubuntu-filemanager-app/model
Reviewer Review Type Date Requested Status
Carlos Jose Mazieri Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+203786@code.launchpad.net

Commit message

separated Clipboard stuff into a new file
created FMUtil class

Description of the change

separated Clipboard stuff into a new file
created FMUtil class

To post a comment you must log in.
Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Carlos Jose Mazieri (carlos-mazieri) wrote :

I wish someone else could review my work.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added file 'folderlistmodel/clipboard.cpp'
2--- folderlistmodel/clipboard.cpp 1970-01-01 00:00:00 +0000
3+++ folderlistmodel/clipboard.cpp 2014-01-29 16:33:58 +0000
4@@ -0,0 +1,495 @@
5+/**************************************************************************
6+ *
7+ * Copyright 2014 Canonical Ltd.
8+ * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
9+ *
10+ * You may use this file under the terms of the BSD license as follows:
11+ *
12+ * "Redistribution and use in source and binary forms, with or without
13+ * modification, are permitted provided that the following conditions are
14+ * met:
15+ * * Redistributions of source code must retain the above copyright
16+ * notice, this list of conditions and the following disclaimer.
17+ * * Redistributions in binary form must reproduce the above copyright
18+ * notice, this list of conditions and the following disclaimer in
19+ * the documentation and/or other materials provided with the
20+ * distribution.
21+ * * Neither the name of Nemo Mobile nor the names of its contributors
22+ * may be used to endorse or promote products derived from this
23+ * software without specific prior written permission.
24+ *
25+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36+ *
37+ * File: clipboard.cpp
38+ * Date: 1/22/2014
39+ */
40+
41+#include "clipboard.h"
42+
43+#include <QClipboard>
44+#include <QApplication>
45+#include <QDir>
46+#include <QFileInfo>
47+#include <QDebug>
48+
49+static QLatin1String GNOME_COPIED_MIME_TYPE ("x-special/gnome-copied-files");
50+static QLatin1String KDE_CUT_MIME_TYPE ("application/x-kde-cutselection");
51+
52+
53+int DirModelMimeData::m_instances = 0;
54+DirModelMimeData* DirModelMimeData::m_globalMimeData = 0;
55+
56+
57+bool DirModelMimeData::hasFormat ( const QString & mimeType ) const
58+{
59+ bool ret = false;
60+ if ( mimeType == KDE_CUT_MIME_TYPE )
61+ {
62+ ret = true;
63+ }
64+ else
65+ {
66+ ret = m_formats.contains(mimeType);
67+ }
68+ return ret;
69+}
70+
71+//===============================================================================================
72+/*!
73+ * \brief DirModelMimeData::DirModelMimeData
74+ */
75+DirModelMimeData::DirModelMimeData() :
76+ QMimeData()
77+ , m_appMime(0)
78+{
79+ m_formats.append("text/uri-list");
80+ m_formats.append(GNOME_COPIED_MIME_TYPE);
81+ m_formats.append("text/plain");
82+ m_formats.append("COMPOUND_TEXT");
83+ m_formats.append("TARGETS");
84+ m_formats.append("MULTIPLE");
85+ m_formats.append("TIMESTAMP");
86+ m_formats.append("SAVE_TARGETS");
87+
88+ ++m_instances;
89+#if DEBUG_MESSAGES
90+ qDebug() << Q_FUNC_INFO << this << "instances" << m_instances;
91+#endif
92+}
93+
94+
95+
96+
97+DirModelMimeData::~DirModelMimeData()
98+{
99+ --m_instances;
100+#if DEBUG_MESSAGES
101+ qDebug() << Q_FUNC_INFO << this << "instances" << m_instances
102+ << "m_globalMimeData" << m_globalMimeData;
103+#endif
104+ if (m_instances == 1 && m_globalMimeData)
105+ {
106+ DirModelMimeData * tmp = m_globalMimeData;
107+ m_globalMimeData = 0;
108+ delete tmp;
109+ }
110+}
111+
112+//===============================================================================================
113+/*!
114+ * \brief DirModelMimeData::gnomeUrls
115+ * \param mime
116+ * \param operation
117+ * \return
118+ */
119+QList<QUrl>
120+DirModelMimeData::gnomeUrls(const QMimeData * mime,
121+ ClipboardOperation& operation)
122+{
123+ QList<QUrl> urls;
124+ if (mime->hasFormat(GNOME_COPIED_MIME_TYPE))
125+ {
126+ QByteArray bytes = mime->data(GNOME_COPIED_MIME_TYPE);
127+ QList<QString> d = QString(bytes).split(QLatin1String("\n"),
128+ QString::SkipEmptyParts);
129+ operation = ClipboardCopy;
130+ if (d.count() > 0)
131+ {
132+ if (d.at(0).trimmed().startsWith(QLatin1String("cut")))
133+ {
134+ operation = ClipboardCut;
135+ }
136+ for (int counter= 1; counter < d.count(); counter++)
137+ {
138+ urls.append(d.at(counter).trimmed());
139+ }
140+ }
141+ }
142+ return urls;
143+}
144+
145+//===============================================================================================
146+/*!
147+ * \brief DirModelMimeData::clipBoardOperation()
148+ * \param mime
149+ * \return
150+ */
151+ClipboardOperation DirModelMimeData::clipBoardOperation()
152+{
153+ ClipboardOperation op = ClipboardCopy;
154+ m_appMime = clipboardMimeData();
155+ if (m_appMime)
156+ {
157+ //first check for GNOME clipboard format, op comes with Copy/Cut
158+ if (gnomeUrls(m_appMime, op).count() == 0)
159+ { // there is no gnome format, tries KDE format
160+ QStringList formats = m_appMime->formats();
161+ int f = formats.count();
162+ while(f--)
163+ {
164+ const QString &mi = formats.at(f);
165+ if(mi.startsWith(QLatin1String("application/x-kde")) )
166+ {
167+ if (mi.contains(QLatin1String("cut")))
168+ {
169+ op = ClipboardCut;
170+ break;
171+ }
172+ }
173+ }
174+ }
175+ }
176+ return op;
177+}
178+
179+
180+//===============================================================================================
181+/*!
182+ * \brief DirModelMimeData::setIntoClipboard
183+ *
184+ * Try to put data in the global cliboard
185+ *
186+ * \note:
187+ * On mobile devices clipboard might not work, in this case a local Clipboard is simulated
188+ *
189+ * \param files
190+ * \param path
191+ * \param isCut
192+ * \return who is owner of clipboard data
193+ */
194+DirModelMimeData::ClipBoardDataOwner
195+DirModelMimeData::setIntoClipboard(const QStringList &files, const QString& path, ClipboardOperation operation)
196+{
197+ static bool firstTime = true;
198+ DirModelMimeData::ClipBoardDataOwner ret = Nobody;
199+ QClipboard *clipboard = QApplication::clipboard();
200+ if (clipboard)
201+ {
202+ ret = Application;
203+ DirModelMimeData *mime = m_globalMimeData ? m_globalMimeData
204+ : new DirModelMimeData();
205+ if (mime->fillClipboard(files, path, operation))
206+ {
207+ clipboard->setMimeData(mime);
208+ //it looks like some mobile devices does not have X or Clipboard does work for other reason
209+ //in this case we simulate our own clipboard, the QClipboard::dataChanged() signal is also
210+ //checked in \ref Clipboard::storeOnClipboard()
211+ if (firstTime)
212+ {
213+ firstTime = false;
214+ if (!m_globalMimeData && !testClipboardContent(files, path))
215+ {
216+ qWarning() << "QClipboard does not work, using own QMimeData storage";
217+ m_globalMimeData = mime;
218+ }
219+ }
220+#if DEBUG_MESSAGES
221+ qDebug() << Q_FUNC_INFO << "mime" << mime
222+ << "own Clipboard Mime Data" << m_globalMimeData;
223+#endif
224+ }
225+ else
226+ if (m_globalMimeData != mime)
227+ {
228+ delete mime;
229+ }
230+ //check if it is necessary to send notification about Clipboard changed
231+ if (m_globalMimeData)
232+ {
233+ ret = MySelf;
234+ }
235+ }
236+ return ret;
237+}
238+
239+
240+
241+bool DirModelMimeData::fillClipboard(const QStringList& files, const QString &path, ClipboardOperation operation)
242+{
243+ bool ret = false;
244+ int index = m_formats.indexOf(KDE_CUT_MIME_TYPE);
245+ if (index != -1 && operation != ClipboardCut)
246+ {
247+ m_formats.removeAt(index);
248+ }
249+ else
250+ if (operation == ClipboardCut)
251+ {
252+ m_formats.append(KDE_CUT_MIME_TYPE);
253+ }
254+ m_urls.clear();
255+ m_gnomeData.clear();
256+ m_gnomeData += operation == ClipboardCut ?
257+ QLatin1String("cut") :
258+ QLatin1String("copy");
259+ QStringList fullPaths = makeFullPath(files, path);
260+ for(int counter = 0; counter < fullPaths.count(); counter++)
261+ {
262+ QUrl item = QUrl::fromLocalFile(fullPaths.at((counter)));
263+ m_urls.append(item);
264+ m_gnomeData += QLatin1Char('\n') + item.toEncoded() ;
265+ }
266+ if (m_urls.count() > 0)
267+ {
268+ setData(GNOME_COPIED_MIME_TYPE, m_gnomeData);
269+ setUrls(m_urls);
270+ ret = true;
271+ }
272+ else
273+ {
274+ // emit error( QObject::tr("Item does not exist"), item);
275+ }
276+ return ret;
277+}
278+
279+//===============================================================================================
280+/*!
281+ * \brief DirModelMimeData::clipboardMimeData
282+ * \return
283+ */
284+const QMimeData *DirModelMimeData::clipboardMimeData()
285+{
286+ const QMimeData *ret = 0;
287+ QClipboard *clipboard = QApplication::clipboard();
288+ if (m_globalMimeData)
289+ {
290+ ret = m_globalMimeData;
291+ }
292+ else
293+ if (clipboard)
294+ {
295+ ret = clipboard->mimeData();
296+ }
297+#if DEBUG_MESSAGES
298+ qDebug() << Q_FUNC_INFO << "clipboard" << clipboard
299+ << "m_ownClipboardMimeData" << m_globalMimeData
300+ << "clipboard->mimeData()" << ret;
301+#endif
302+ return ret;
303+}
304+
305+//===============================================================================================
306+/*!
307+ * \brief DirModelMimeData::localUrls
308+ * \return
309+ */
310+QStringList
311+DirModelMimeData::localUrls(ClipboardOperation& operation)
312+{
313+ m_appMime = clipboardMimeData();
314+ QStringList paths;
315+ //it may have external urls
316+ if (m_appMime)
317+ {
318+ QList<QUrl> urls;
319+ if (m_appMime->hasUrls())
320+ {
321+ urls = m_appMime->urls();
322+ operation = clipBoardOperation();
323+ }
324+ else
325+ {
326+ urls = gnomeUrls(m_appMime, operation);
327+ }
328+ for (int counter=0; counter < urls.count(); counter++)
329+ {
330+ if (urls.at(counter).toString().startsWith(QLatin1String("file://")))
331+ {
332+ paths.append(urls.at(counter).toLocalFile());
333+ }
334+ }
335+ }
336+#if DEBUG_MESSAGES
337+ qDebug() << Q_FUNC_INFO << paths;
338+#endif
339+ return paths;
340+}
341+
342+
343+//===============================================================================================
344+/*!
345+ * \brief DirModelMimeData::testClipboardContent() Gets the clipboard content and compare with data previously stored
346+ * \param files
347+ * \param path
348+ * \return true if clipboard has content and it matches data previously stored
349+ */
350+bool DirModelMimeData::testClipboardContent(const QStringList &files, const QString &path)
351+{
352+ bool ret = false;
353+ ClipboardOperation tmpOperation;
354+ QStringList expectedList = makeFullPath(files,path);
355+ QStringList realList = localUrls(tmpOperation);
356+ if (realList == expectedList)
357+ {
358+ ret = true;
359+ }
360+ else
361+ {
362+ qWarning() << Q_FUNC_INFO << "FAILED, Clipboard does not work";
363+ }
364+ return ret;
365+}
366+
367+//===============================================================================================
368+/*!
369+ * \brief DirModelMimeData::makeFullPath() Just creates a fulpath file list when they do exist
370+ * \param files
371+ * \param path
372+ * \return the list itself
373+ */
374+QStringList DirModelMimeData::makeFullPath(const QStringList& files, const QString &path)
375+{
376+ QStringList fullPathnameList;
377+ QFileInfo fi;
378+ for(int counter = 0; counter < files.count(); counter++)
379+ {
380+ const QString& item = files.at(counter);
381+ fi.setFile(item);
382+ if (!fi.isAbsolute())
383+ {
384+ fi.setFile(path + QDir::separator() + item);
385+ }
386+ if (fi.exists())
387+ {
388+ fullPathnameList.append(fi.absoluteFilePath());
389+ }
390+ }
391+ return fullPathnameList;
392+}
393+
394+
395+//===========================================================================
396+//
397+//===========================================================================
398+Clipboard::Clipboard(QObject *parent):
399+ QObject(parent)
400+ , m_mimeData ( new DirModelMimeData() )
401+ , m_clipboardModifiedByOther(false)
402+{
403+ QClipboard *clipboard = QApplication::clipboard();
404+
405+ connect(clipboard, SIGNAL(dataChanged()), this, SIGNAL(clipboardChanged()));
406+ connect(clipboard, SIGNAL(dataChanged()), this, SLOT(onClipboardChanged()));
407+}
408+
409+
410+Clipboard::~Clipboard()
411+{
412+ delete m_mimeData;
413+}
414+
415+//================================================================================
416+/*!
417+ * \brief Clipboard::clipboardHasChanged() used to identify if the clipboard changed during a Cut operation
418+ *
419+ * \sa \ref endCurrentAction()
420+ */
421+void Clipboard::onClipboardChanged()
422+{
423+ m_clipboardModifiedByOther = true;
424+}
425+
426+
427+//==================================================================
428+/*!
429+ * \brief Clipboard::storeOnClipboard() store data on Clipboard
430+ * \param pathnames files list
431+ * \param op \ref ClipboardOperation as \ref ClipboardCopy or \ref ClipboardCut
432+ *
433+ * Stores data on clipboard by calling \ref DirModelMimeData::setIntoClipboard() which uses Qt class QClipboard
434+ * It is expected that QClipboard class emits the dataChanged() signal when a new content is set into it,
435+ * if it does we caught that signal in \ref clipboardHasChanged() which sets \ref m_clipboardModifiedByOther to true.
436+ */
437+void Clipboard::storeOnClipboard(const QStringList &names, ClipboardOperation op, const QString& curPath)
438+{
439+#if DEBUG_MESSAGES
440+ qDebug() << Q_FUNC_INFO << names << "ClipboardOperation" << op;
441+#endif
442+ DirModelMimeData::ClipBoardDataOwner owner =
443+ m_mimeData->setIntoClipboard(names, curPath, op);
444+ if (owner == DirModelMimeData::MySelf || !m_clipboardModifiedByOther)
445+ {
446+ emit clipboardChanged();
447+ }
448+ m_clipboardModifiedByOther = false;
449+}
450+
451+//===============================================================================================
452+/*!
453+ * \brief Clipboard::copy
454+ * \param pathnames
455+ */
456+void Clipboard::copy(const QStringList &names, const QString& path)
457+{
458+ storeOnClipboard(names, ClipboardCopy, path);
459+}
460+
461+//===============================================================================================
462+/*!
463+ * \brief Clipboard::cut
464+ * \param pathnames
465+ */
466+void Clipboard::cut(const QStringList &names, const QString &path)
467+{
468+ storeOnClipboard(names, ClipboardCut, path);
469+}
470+
471+
472+//=======================================================
473+/*!
474+ * \brief Clipboard::clipboardLocalUrlsCounter
475+ * \return
476+ */
477+int Clipboard::clipboardLocalUrlsCounter()
478+{
479+ ClipboardOperation operation;
480+ return m_mimeData->localUrls(operation).count();
481+}
482+
483+
484+//=======================================================
485+/*!
486+ * \brief Clipboard::paste
487+ * \param operation
488+ * \return
489+ */
490+QStringList Clipboard::paste(ClipboardOperation &operation)
491+{
492+ QStringList items = m_mimeData->localUrls(operation);
493+ if (operation == ClipboardCut)
494+ {
495+ //this must still be false when cut finishes to change the clipboard to the target
496+ m_clipboardModifiedByOther = false;
497+ }
498+ return items;
499+}
500
501=== added file 'folderlistmodel/clipboard.h'
502--- folderlistmodel/clipboard.h 1970-01-01 00:00:00 +0000
503+++ folderlistmodel/clipboard.h 2014-01-29 16:33:58 +0000
504@@ -0,0 +1,132 @@
505+/**************************************************************************
506+ *
507+ * Copyright 2014 Canonical Ltd.
508+ * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
509+ *
510+ * You may use this file under the terms of the BSD license as follows:
511+ *
512+ * "Redistribution and use in source and binary forms, with or without
513+ * modification, are permitted provided that the following conditions are
514+ * met:
515+ * * Redistributions of source code must retain the above copyright
516+ * notice, this list of conditions and the following disclaimer.
517+ * * Redistributions in binary form must reproduce the above copyright
518+ * notice, this list of conditions and the following disclaimer in
519+ * the documentation and/or other materials provided with the
520+ * distribution.
521+ * * Neither the name of Nemo Mobile nor the names of its contributors
522+ * may be used to endorse or promote products derived from this
523+ * software without specific prior written permission.
524+ *
525+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
526+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
527+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
528+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
529+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
530+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
531+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
532+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
533+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
534+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
535+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
536+ *
537+ * File: clipboard.h
538+ * Date: 1/22/2014
539+ */
540+
541+#ifndef CLIPBOARD_H
542+#define CLIPBOARD_H
543+
544+#include <QMimeData>
545+#include <QUrl>
546+#include <QStringList>
547+
548+class DirModelMimeData;
549+
550+enum ClipboardOperation
551+{
552+ NoClipboard, ClipboardCopy, ClipboardCut
553+};
554+
555+
556+
557+/*!
558+ * \brief The Clipboard class handles global clipboard storage
559+ */
560+class Clipboard : public QObject
561+{
562+ Q_OBJECT
563+public:
564+ explicit Clipboard(QObject *parent = 0);
565+ ~Clipboard();
566+ QStringList paste(ClipboardOperation& operation);
567+ int clipboardLocalUrlsCounter();
568+ inline bool hasClipboardModifiedByOtherApplication() const {return m_clipboardModifiedByOther;}
569+
570+public slots:
571+ void cut(const QStringList& names, const QString &path);
572+ void copy(const QStringList& names, const QString &path);
573+
574+
575+signals:
576+ void clipboardChanged();
577+
578+private slots:
579+ void onClipboardChanged ();
580+
581+private:
582+ void storeOnClipboard(const QStringList &names,
583+ ClipboardOperation op,
584+ const QString &curPath);
585+private:
586+ DirModelMimeData * m_mimeData;
587+ bool m_clipboardModifiedByOther;
588+};
589+
590+
591+
592+/*!
593+ * \brief The DirModelMimeData class is the storage on Clipboard
594+ */
595+class DirModelMimeData : public QMimeData
596+{
597+public:
598+ explicit DirModelMimeData();
599+ ~DirModelMimeData();
600+ virtual QStringList formats() const { return m_formats; }
601+ virtual bool hasFormat ( const QString & mimeType ) const;
602+
603+public:
604+ enum ClipBoardDataOwner
605+ {
606+ Nobody, // might have failed
607+ Application,
608+ MySelf
609+ };
610+
611+ ClipBoardDataOwner setIntoClipboard(const QStringList& files,
612+ const QString &path,
613+ ClipboardOperation operation);
614+ const QMimeData * clipboardMimeData();
615+ QStringList localUrls(ClipboardOperation& operation);
616+
617+private:
618+ static QList<QUrl> gnomeUrls(const QMimeData *mime, ClipboardOperation& operation);
619+ ClipboardOperation clipBoardOperation();
620+ bool fillClipboard(const QStringList& files, const QString &path, ClipboardOperation operation);
621+ QStringList makeFullPath(const QStringList& files, const QString &path);
622+ bool testClipboardContent(const QStringList& files, const QString &path);
623+
624+private:
625+ QStringList m_formats;
626+ const QMimeData * m_appMime;
627+ QByteArray m_gnomeData;
628+ QList<QUrl> m_urls;
629+ static DirModelMimeData* m_globalMimeData; //!< some mobile devices do not use X, they may not have clipboard
630+ static int m_instances;
631+};
632+
633+
634+
635+#endif //CLIPBOARD_H
636+
637
638=== modified file 'folderlistmodel/dirmodel.cpp'
639--- folderlistmodel/dirmodel.cpp 2013-12-31 16:57:19 +0000
640+++ folderlistmodel/dirmodel.cpp 2014-01-29 16:33:58 +0000
641@@ -34,6 +34,8 @@
642 #include "ioworkerthread.h"
643 #include "filesystemaction.h"
644 #include "externalfswatcher.h"
645+#include "clipboard.h"
646+#include "fmutil.h"
647
648 #ifndef DO_NOT_USE_TAG_LIB
649 #include <taglib/attachedpictureframe.h>
650@@ -53,7 +55,7 @@
651 #include <QUrl>
652 #include <QDesktopServices>
653
654-#if defined(REGRESSION_TEST_FOLDERLISTMODEL) && QT_VERSION >= 0x050000
655+#if QT_VERSION >= 0x050000
656 # include <QMimeType>
657 # include <QMimeDatabase>
658 #endif
659@@ -98,7 +100,8 @@
660 , mSortOrder(SortAscending)
661 , mCompareFunction(0)
662 , mExtFSWatcher(0)
663- , m_fsAction(new FileSystemAction(this) )
664+ , mClipboard(new Clipboard(this))
665+ , m_fsAction(new FileSystemAction(this) )
666 {
667 mNameFilters = QStringList() << "*";
668
669@@ -130,20 +133,35 @@
670 connect(this, SIGNAL(pathChanged(QString)),
671 m_fsAction, SLOT(pathChanged(QString)));
672
673- connect(m_fsAction, SIGNAL(clipboardChanged()),
674+ connect(mClipboard, SIGNAL(clipboardChanged()),
675 this, SIGNAL(clipboardChanged()));
676
677 connect(m_fsAction, SIGNAL(changed(QFileInfo)),
678 this, SLOT(onItemChanged(QFileInfo)));
679
680+ connect(mClipboard, SIGNAL(clipboardChanged()),
681+ m_fsAction, SLOT(onClipboardChanged()));
682+
683+ connect(m_fsAction, SIGNAL(recopy(QStringList,QString)),
684+ mClipboard, SLOT(copy(QStringList,QString)));
685+
686 setCompareAndReorder();
687+
688+ if (QIcon::themeName().isEmpty() && !FMUtil::hasTriedThemeName())
689+ {
690+ FMUtil::setThemeName();
691+ }
692 }
693
694+
695+
696 DirModel::~DirModel()
697 {
698 stoptExternalFsWatcher();
699 }
700
701+
702+
703 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
704 // roleNames has changed between Qt4 and Qt5. In Qt5 it is a virtual
705 // function and setRoleNames should not be used.
706@@ -158,6 +176,8 @@
707 }
708 #endif
709
710+
711+
712 QHash<int, QByteArray> DirModel::buildRoleNames() const
713 {
714 QHash<int, QByteArray> roles;
715@@ -597,7 +617,7 @@
716
717 void DirModel::copyPaths(const QStringList &items)
718 {
719- m_fsAction->copy(items);
720+ mClipboard->copy(items, mCurrentDir);
721 }
722
723
724@@ -607,7 +627,7 @@
725 {
726 const QFileInfo &fi = mDirectoryContents.at(row);
727 QStringList list(fi.absoluteFilePath());
728- m_fsAction->cut(list);
729+ this->cutPaths(list);
730 }
731 else
732 {
733@@ -618,13 +638,22 @@
734
735 void DirModel::cutPaths(const QStringList &items)
736 {
737- m_fsAction->cut(items);
738+ mClipboard->cut(items, mCurrentDir);
739 }
740
741
742 void DirModel::paste()
743 {
744- m_fsAction->paste();
745+ ClipboardOperation operation;
746+ QStringList items = mClipboard->paste(operation);
747+ if (operation == ClipboardCut)
748+ {
749+ m_fsAction->moveIntoCurrentPath(items);
750+ }
751+ else
752+ {
753+ m_fsAction->copyIntoCurrentPath(items);
754+ }
755 }
756
757
758@@ -923,7 +952,7 @@
759
760 int DirModel::getClipboardUrlsCounter() const
761 {
762- return m_fsAction->clipboardLocalUrlsConunter();
763+ return mClipboard->clipboardLocalUrlsCounter();
764 }
765
766
767
768=== modified file 'folderlistmodel/dirmodel.h'
769--- folderlistmodel/dirmodel.h 2013-12-08 13:15:45 +0000
770+++ folderlistmodel/dirmodel.h 2014-01-29 16:33:58 +0000
771@@ -44,6 +44,7 @@
772
773 class FileSystemAction;
774 class ExternalFSWatcher;
775+class Clipboard;
776
777 /*!
778 * When the External File System Wathcer is enabled,
779@@ -394,6 +395,7 @@
780 SortOrder mSortOrder;
781 CompareFunction mCompareFunction;
782 ExternalFSWatcher* mExtFSWatcher;
783+ Clipboard * mClipboard;
784
785
786 private:
787
788=== modified file 'folderlistmodel/filesystemaction.cpp'
789--- folderlistmodel/filesystemaction.cpp 2013-12-31 16:57:19 +0000
790+++ folderlistmodel/filesystemaction.cpp 2014-01-29 16:33:58 +0000
791@@ -35,6 +35,7 @@
792 */
793
794 #include "filesystemaction.h"
795+#include "clipboard.h"
796
797 #if defined(Q_OS_UNIX)
798 #include <sys/statvfs.h>
799@@ -45,10 +46,6 @@
800 #include <QDirIterator>
801 #include <QDebug>
802 #include <QTimer>
803-#include <QMimeData>
804-#include <QClipboard>
805-#include <QApplication>
806-#include <QUrl>
807 #include <QFileInfo>
808 #include <QDir>
809 #include <QThread>
810@@ -73,48 +70,7 @@
811 #define COMMON_SIZE_ITEM 120
812
813
814-static QLatin1String GNOME_COPIED_MIME_TYPE ("x-special/gnome-copied-files");
815-static QLatin1String KDE_CUT_MIME_TYPE ("application/x-kde-cutselection");
816-
817-
818-class DirModelMimeData : public QMimeData
819-{
820-public:
821- enum ClipBoardDataOwner
822- {
823- Nobody, // might have failed
824- Application,
825- MySelf
826- };
827-
828- explicit DirModelMimeData();
829- ~DirModelMimeData();
830- virtual QStringList formats() const { return m_formats; }
831- virtual bool hasFormat ( const QString & mimeType ) const;
832-public:
833- ClipBoardDataOwner setIntoClipboard(const QStringList& files,
834- const QString &path,
835- ClipboardOperation operation);
836- const QMimeData *clipboardMimeData();
837- QStringList localUrls(ClipboardOperation& operation);
838-private:
839- static QList<QUrl> gnomeUrls(const QMimeData *mime, ClipboardOperation& operation);
840- ClipboardOperation clipBoardOperation();
841- bool fillClipboard(const QStringList& files, const QString &path, ClipboardOperation operation);
842- QStringList makeFullPath(const QStringList& files, const QString &path);
843- bool testClipboardContent(const QStringList& files, const QString &path);
844-private:
845- QStringList m_formats;
846- const QMimeData * m_appMime;
847- QByteArray gnomeData;
848- QList<QUrl> urls;
849- static DirModelMimeData* m_globalMimeData; //!< some mobile devices do not use X, they may not have clipboard
850- static int instances;
851-};
852-
853-
854-int DirModelMimeData::instances = 0;
855-DirModelMimeData* DirModelMimeData::m_globalMimeData = 0;
856+
857
858 void FileSystemAction::CopyFile::clear()
859 {
860@@ -125,341 +81,6 @@
861 target = 0;
862 }
863
864-bool DirModelMimeData::hasFormat ( const QString & mimeType ) const
865-{
866- bool ret = false;
867- if ( mimeType == KDE_CUT_MIME_TYPE )
868- {
869- ret = true;
870- }
871- else
872- {
873- ret = m_formats.contains(mimeType);
874- }
875- return ret;
876-}
877-
878-//===============================================================================================
879-/*!
880- * \brief DirModelMimeData::DirModelMimeData
881- */
882-DirModelMimeData::DirModelMimeData() :
883- QMimeData()
884- , m_appMime(0)
885-{
886- m_formats.append("text/uri-list");
887- m_formats.append(GNOME_COPIED_MIME_TYPE);
888- m_formats.append("text/plain");
889- m_formats.append("COMPOUND_TEXT");
890- m_formats.append("TARGETS");
891- m_formats.append("MULTIPLE");
892- m_formats.append("TIMESTAMP");
893- m_formats.append("SAVE_TARGETS");
894-
895- ++instances;
896-#if DEBUG_MESSAGES
897- qDebug() << Q_FUNC_INFO << this << "instances" << instances;
898-#endif
899-}
900-
901-
902-
903-
904-DirModelMimeData::~DirModelMimeData()
905-{
906- --instances;
907-#if DEBUG_MESSAGES
908- qDebug() << Q_FUNC_INFO << this << "instances" << instances
909- << "m_globalMimeData" << m_globalMimeData;
910-#endif
911- if (instances == 1 && m_globalMimeData)
912- {
913- DirModelMimeData * tmp = m_globalMimeData;
914- m_globalMimeData = 0;
915- delete tmp;
916- }
917-}
918-
919-//===============================================================================================
920-/*!
921- * \brief DirModelMimeData::gnomeUrls
922- * \param mime
923- * \param operation
924- * \return
925- */
926-QList<QUrl>
927-DirModelMimeData::gnomeUrls(const QMimeData * mime,
928- ClipboardOperation& operation)
929-{
930- QList<QUrl> urls;
931- if (mime->hasFormat(GNOME_COPIED_MIME_TYPE))
932- {
933- QByteArray bytes = mime->data(GNOME_COPIED_MIME_TYPE);
934- QList<QString> d = QString(bytes).split(QLatin1String("\n"),
935- QString::SkipEmptyParts);
936- operation = ClipboardCopy;
937- if (d.count() > 0)
938- {
939- if (d.at(0).trimmed().startsWith(QLatin1String("cut")))
940- {
941- operation = ClipboardCut;
942- }
943- for (int counter= 1; counter < d.count(); counter++)
944- {
945- urls.append(d.at(counter).trimmed());
946- }
947- }
948- }
949- return urls;
950-}
951-
952-//===============================================================================================
953-/*!
954- * \brief DirModelMimeData::clipBoardOperation()
955- * \param mime
956- * \return
957- */
958-ClipboardOperation DirModelMimeData::clipBoardOperation()
959-{
960- ClipboardOperation op = ClipboardCopy;
961- m_appMime = clipboardMimeData();
962- if (m_appMime)
963- {
964- //first check for GNOME clipboard format, op comes with Copy/Cut
965- if (gnomeUrls(m_appMime, op).count() == 0)
966- { // there is no gnome format, tries KDE format
967- QStringList formats = m_appMime->formats();
968- int f = formats.count();
969- while(f--)
970- {
971- const QString &mi = formats.at(f);
972- if(mi.startsWith(QLatin1String("application/x-kde")) )
973- {
974- if (mi.contains(QLatin1String("cut")))
975- {
976- op = ClipboardCut;
977- break;
978- }
979- }
980- }
981- }
982- }
983- return op;
984-}
985-
986-
987-//===============================================================================================
988-/*!
989- * \brief DirModelMimeData::setIntoClipboard
990- *
991- * Try to put data in the global cliboard
992- *
993- * \note:
994- * On mobile devices clipboard might not work, in this case a local Clipboard is simulated
995- *
996- * \param files
997- * \param path
998- * \param isCut
999- * \return who is owner of clipboard data
1000- */
1001-DirModelMimeData::ClipBoardDataOwner
1002-DirModelMimeData::setIntoClipboard(const QStringList &files, const QString& path, ClipboardOperation operation)
1003-{
1004- static bool firstTime = true;
1005- DirModelMimeData::ClipBoardDataOwner ret = Nobody;
1006- QClipboard *clipboard = QApplication::clipboard();
1007- if (clipboard)
1008- {
1009- ret = Application;
1010- DirModelMimeData *mime = m_globalMimeData ? m_globalMimeData
1011- : new DirModelMimeData();
1012- if (mime->fillClipboard(files, path, operation))
1013- {
1014- clipboard->setMimeData(mime);
1015- //it looks like some mobile devices does not have X or Clipboard does work for other reason
1016- //in this case we simulate our own clipboard, the QClipboard::dataChanged() signal is also
1017- //checked in \ref FileSystemAction::storeOnClipboard()
1018- if (firstTime)
1019- {
1020- firstTime = false;
1021- if (!m_globalMimeData && !testClipboardContent(files, path))
1022- {
1023- qWarning() << "QClipboard does not work, using own QMimeData storage";
1024- m_globalMimeData = mime;
1025- }
1026- }
1027-#if DEBUG_MESSAGES
1028- qDebug() << Q_FUNC_INFO << "mime" << mime
1029- << "own Clipboard Mime Data" << m_globalMimeData;
1030-#endif
1031- }
1032- else
1033- if (m_globalMimeData != mime)
1034- {
1035- delete mime;
1036- }
1037- //check if it is necessary to send notification about Clipboard changed
1038- if (m_globalMimeData)
1039- {
1040- ret = MySelf;
1041- }
1042- }
1043- return ret;
1044-}
1045-
1046-
1047-bool DirModelMimeData::fillClipboard(const QStringList& files, const QString &path, ClipboardOperation operation)
1048-{
1049- bool ret = false;
1050- int index = m_formats.indexOf(KDE_CUT_MIME_TYPE);
1051- if (index != -1 && operation != ClipboardCut)
1052- {
1053- m_formats.removeAt(index);
1054- }
1055- else
1056- if (operation == ClipboardCut)
1057- {
1058- m_formats.append(KDE_CUT_MIME_TYPE);
1059- }
1060- urls.clear();
1061- gnomeData.clear();
1062- gnomeData += operation == ClipboardCut ?
1063- QLatin1String("cut") :
1064- QLatin1String("copy");
1065- QStringList fullPaths = makeFullPath(files, path);
1066- for(int counter = 0; counter < fullPaths.count(); counter++)
1067- {
1068- QUrl item = QUrl::fromLocalFile(fullPaths.at((counter)));
1069- urls.append(item);
1070- gnomeData += QLatin1Char('\n') + item.toEncoded() ;
1071- }
1072- if (urls.count() > 0)
1073- {
1074- setData(GNOME_COPIED_MIME_TYPE, gnomeData);
1075- setUrls(urls);
1076- ret = true;
1077- }
1078- else
1079- {
1080- // emit error( QObject::tr("Item does not exist"), item);
1081- }
1082- return ret;
1083-}
1084-
1085-//===============================================================================================
1086-/*!
1087- * \brief DirModelMimeData::clipboardMimeData
1088- * \return
1089- */
1090-const QMimeData *DirModelMimeData::clipboardMimeData()
1091-{
1092- const QMimeData *ret = 0;
1093- QClipboard *clipboard = QApplication::clipboard();
1094- if (m_globalMimeData)
1095- {
1096- ret = m_globalMimeData;
1097- }
1098- else
1099- if (clipboard)
1100- {
1101- ret = clipboard->mimeData();
1102- }
1103-#if DEBUG_MESSAGES
1104- qDebug() << Q_FUNC_INFO << "clipboard" << clipboard
1105- << "m_ownClipboardMimeData" << m_globalMimeData
1106- << "clipboard->mimeData()" << ret;
1107-#endif
1108- return ret;
1109-}
1110-
1111-//===============================================================================================
1112-/*!
1113- * \brief DirModelMimeData::localUrls
1114- * \return
1115- */
1116-QStringList
1117-DirModelMimeData::localUrls(ClipboardOperation& operation)
1118-{
1119- m_appMime = clipboardMimeData();
1120- QStringList paths;
1121- //it may have external urls
1122- if (m_appMime)
1123- {
1124- QList<QUrl> urls;
1125- if (m_appMime->hasUrls())
1126- {
1127- urls = m_appMime->urls();
1128- operation = clipBoardOperation();
1129- }
1130- else
1131- {
1132- urls = gnomeUrls(m_appMime, operation);
1133- }
1134- for (int counter=0; counter < urls.count(); counter++)
1135- {
1136- if (urls.at(counter).toString().startsWith(QLatin1String("file://")))
1137- {
1138- paths.append(urls.at(counter).toLocalFile());
1139- }
1140- }
1141- }
1142-#if DEBUG_MESSAGES
1143- qDebug() << Q_FUNC_INFO << paths;
1144-#endif
1145- return paths;
1146-}
1147-
1148-
1149-//===============================================================================================
1150-/*!
1151- * \brief DirModelMimeData::testClipboardContent() Gets the clipboard content and compare with data previously stored
1152- * \param files
1153- * \param path
1154- * \return true if clipboard has content and it matches data previously stored
1155- */
1156-bool DirModelMimeData::testClipboardContent(const QStringList &files, const QString &path)
1157-{
1158- bool ret = false;
1159- ClipboardOperation tmpOperation;
1160- QStringList expectedList = makeFullPath(files,path);
1161- QStringList realList = localUrls(tmpOperation);
1162- if (realList == expectedList)
1163- {
1164- ret = true;
1165- }
1166- else
1167- {
1168- qWarning() << Q_FUNC_INFO << "FAILED, Clipboard does not work";
1169- }
1170- return ret;
1171-}
1172-
1173-//===============================================================================================
1174-/*!
1175- * \brief DirModelMimeData::makeFullPath() Just creates a fulpath file list when they do exist
1176- * \param files
1177- * \param path
1178- * \return the list itself
1179- */
1180-QStringList DirModelMimeData::makeFullPath(const QStringList& files, const QString &path)
1181-{
1182- QStringList fullPathnameList;
1183- QFileInfo fi;
1184- for(int counter = 0; counter < files.count(); counter++)
1185- {
1186- const QString& item = files.at(counter);
1187- fi.setFile(item);
1188- if (!fi.isAbsolute())
1189- {
1190- fi.setFile(path + QDir::separator() + item);
1191- }
1192- if (fi.exists())
1193- {
1194- fullPathnameList.append(fi.absoluteFilePath());
1195- }
1196- }
1197- return fullPathnameList;
1198-}
1199
1200
1201 //===============================================================================================
1202@@ -471,14 +92,10 @@
1203 QObject(parent)
1204 , m_curAction(0)
1205 , m_cancelCurrentAction(false)
1206- , m_busy(false)
1207- , m_mimeData ( new DirModelMimeData() )
1208- , m_clipboardModifiedByOther(false)
1209+ , m_busy(false)
1210+ , m_clipboardChanged(false)
1211 {
1212- QClipboard *clipboard = QApplication::clipboard();
1213
1214- connect(clipboard, SIGNAL(dataChanged()), this, SIGNAL(clipboardChanged()));
1215- connect(clipboard, SIGNAL(dataChanged()), this, SLOT(clipboardHasChanged()));
1216 }
1217
1218 //===============================================================================================
1219@@ -487,7 +104,7 @@
1220 */
1221 FileSystemAction::~FileSystemAction()
1222 {
1223- delete m_mimeData;
1224+
1225 }
1226
1227 //===============================================================================================
1228@@ -497,7 +114,7 @@
1229 */
1230 void FileSystemAction::remove(const QStringList &paths)
1231 {
1232- createAndProcessAction(ActionRemove, paths, NoClipboard);
1233+ createAndProcessAction(ActionRemove, paths);
1234 }
1235
1236 //===============================================================================================
1237@@ -1092,76 +709,72 @@
1238 m_path = path;
1239 }
1240
1241-//===============================================================================================
1242-/*!
1243- * \brief FileSystemAction::copy
1244- * \param pathnames
1245- */
1246-void FileSystemAction::copy(const QStringList &pathnames)
1247-{
1248- storeOnClipboard(pathnames, ClipboardCopy);
1249-}
1250-
1251-//===============================================================================================
1252-/*!
1253- * \brief FileSystemAction::cut
1254- * \param pathnames
1255- */
1256-void FileSystemAction::cut(const QStringList &pathnames)
1257-{
1258- storeOnClipboard(pathnames, ClipboardCut);
1259-}
1260-
1261-//===============================================================================================
1262-/*!
1263- * \brief FileSystemAction::paste
1264- */
1265-void FileSystemAction::paste()
1266-{
1267- ClipboardOperation operation;
1268- QStringList paths = m_mimeData->localUrls(operation);
1269-#if DEBUG_MESSAGES
1270- qDebug() << Q_FUNC_INFO << paths;
1271-#endif
1272- if (paths.count())
1273- {
1274- QFileInfo destination(m_path);
1275- QFileInfo origin(QFileInfo(paths.at(0)).absolutePath());
1276- ActionType actionType = ActionCopy; // start with Copy and check for Cut
1277- if (operation == ClipboardCut)
1278- {
1279- //we allow Copy to backup items, but Cut must Fail
1280- if (destination.absoluteFilePath() == origin.absoluteFilePath())
1281- {
1282- emit error(tr("Cannot paste"),
1283- tr("origin and destination folder are the same"));
1284- return;
1285- }
1286- // cut needs write permission on origin
1287- if (!origin.isWritable())
1288- {
1289- emit error(tr("Cannot paste"),
1290- tr("no write permission on folder ") + origin.absoluteFilePath() );
1291- return;
1292- }
1293- //so far it always returns true since on Linux it is possible to rename
1294- // between different file systems
1295- if ( moveUsingSameFileSystem(paths.at(0)) ) {
1296- actionType = ActionMove;
1297- } else {
1298- actionType = ActionHardMoveCopy; // first step
1299- }
1300+
1301+
1302+void FileSystemAction::copyIntoCurrentPath(const QStringList& items)
1303+{
1304+#if DEBUG_MESSAGES
1305+ qDebug() << Q_FUNC_INFO << items;
1306+#endif
1307+ m_clipboardChanged = false;
1308+ if (items.count())
1309+ {
1310+ QFileInfo destination(m_path);
1311+ if (destination.isWritable())
1312+ {
1313+ createAndProcessAction(ActionCopy, items);
1314+ }
1315+ else
1316+ {
1317+ emit error(tr("Cannot copy items"),
1318+ tr("no write permission on folder ") + destination.absoluteFilePath() );
1319+
1320+ }
1321+ }
1322+}
1323+
1324+
1325+void FileSystemAction::moveIntoCurrentPath(const QStringList& items)
1326+{
1327+#if DEBUG_MESSAGES
1328+ qDebug() << Q_FUNC_INFO << items;
1329+#endif
1330+ m_clipboardChanged = false;
1331+ if (items.count())
1332+ {
1333+ QFileInfo destination(m_path);
1334+ QFileInfo origin(QFileInfo(items.at(0)).absolutePath());
1335+ ActionType actionType = ActionMove;
1336+ static QString titleError = tr("Cannot move items");
1337+ static QString noWriteError = tr("no write permission on folder ");
1338+ //we allow Copy to backup items, but Cut must Fail
1339+ if (destination.absoluteFilePath() == origin.absoluteFilePath())
1340+ {
1341+ emit error(titleError,
1342+ tr("origin and destination folders are the same"));
1343+ return;
1344+ }
1345+ // cut needs write permission on origin
1346+ if (!origin.isWritable())
1347+ {
1348+ emit error(titleError, noWriteError + origin.absoluteFilePath());
1349+ return;
1350+ }
1351+ //check if it is possible to move items
1352+ if ( !moveUsingSameFileSystem(items.at(0)) )
1353+ {
1354+ actionType = ActionHardMoveCopy; // first step
1355 }
1356 if (!destination.isWritable())
1357 {
1358- emit error(tr("Cannot paste"),
1359- tr("no write permission on folder ") + destination.absoluteFilePath() );
1360+ emit error(titleError, noWriteError + destination.absoluteFilePath());
1361 return;
1362 }
1363- createAndProcessAction(actionType, paths, operation);
1364+ createAndProcessAction(actionType, items);
1365 }
1366 }
1367
1368+
1369 //===============================================================================================
1370 /*!
1371 * \brief FileSystemAction::createAndProcessAction
1372@@ -1169,7 +782,7 @@
1373 * \param paths
1374 * \param operation
1375 */
1376-void FileSystemAction::createAndProcessAction(ActionType actionType, const QStringList& paths, ClipboardOperation operation)
1377+void FileSystemAction::createAndProcessAction(ActionType actionType, const QStringList& paths)
1378 {
1379 #if DEBUG_MESSAGES
1380 qDebug() << Q_FUNC_INFO << paths;
1381@@ -1177,7 +790,6 @@
1382 Action *myAction = 0;
1383 int origPathLen = 0;
1384 myAction = createAction(actionType, origPathLen);
1385- myAction->operation = operation;
1386 myAction->origPath = QFileInfo(paths.at(0)).absolutePath();
1387 myAction->baseOrigSize = myAction->origPath.length();
1388 for (int counter=0; counter < paths.count(); counter++)
1389@@ -1197,12 +809,7 @@
1390 //and it is already computed
1391 myAction->steps += myAction->totalBytes / (COPY_BUFFER_SIZE * STEP_FILES);
1392 }
1393- */
1394- if (operation == ClipboardCut)
1395- {
1396- //this must still be false when cut finishes to change the clipboard to the target
1397- m_clipboardModifiedByOther = false;
1398- }
1399+ */
1400 m_queuedActions.append(myAction);
1401 if (!m_busy)
1402 {
1403@@ -1278,16 +885,6 @@
1404 return targetFsId == originFsId;
1405 }
1406
1407-//=======================================================
1408-/*!
1409- * \brief FileSystemAction::clipboardLocalUrlsConunter
1410- * \return
1411- */
1412-int FileSystemAction::clipboardLocalUrlsConunter()
1413-{
1414- ClipboardOperation operation;
1415- return m_mimeData->localUrls(operation).count();
1416-}
1417
1418 //================================================================================
1419 /*!
1420@@ -1296,14 +893,16 @@
1421 * If a Paste was made from a Cut operation, items pasted become avaialable in the clipboard
1422 * as from Copy source operation, so items can be now Pasted again, but with no source removal
1423 *
1424- * It checks for \a m_clipboardModifiedByOther that idenftifies if the clipboard was modified during the
1425+ * It checks for \a m_clipboardChanged that idenftifies if the clipboard was modified during the
1426 * operation maybe by another application.
1427 */
1428 void FileSystemAction::endCurrentAction()
1429 {
1430- if ( m_curAction->origPath != m_curAction->targetPath &&
1431- m_curAction->operation == ClipboardCut &&
1432- !m_clipboardModifiedByOther )
1433+
1434+ if ( !m_clipboardChanged &&
1435+ m_curAction->origPath != m_curAction->targetPath &&
1436+ (m_curAction->type == ActionMove || m_curAction->type == ActionHardMoveRemove)
1437+ )
1438 {
1439 QStringList items;
1440 const ActionEntry *entry;
1441@@ -1319,7 +918,7 @@
1442 {
1443 QString targetPath = m_curAction->targetPath;
1444 //it is not necessary to handle own clipboard here
1445- m_mimeData->setIntoClipboard(items, targetPath, ClipboardCopy);
1446+ emit recopy(items, targetPath);
1447 }
1448 }
1449 }
1450@@ -1544,16 +1143,6 @@
1451 QTimer::singleShot(0, this, slot);
1452 }
1453
1454-//================================================================================
1455-/*!
1456- * \brief FileSystemAction::clipboardHasChanged() used to identify if the clipboard changed during a Cut operation
1457- *
1458- * \sa \ref endCurrentAction()
1459- */
1460-void FileSystemAction::clipboardHasChanged()
1461-{
1462- m_clipboardModifiedByOther = true;
1463-}
1464
1465
1466 //================================================================================
1467@@ -1666,29 +1255,6 @@
1468 return steps;
1469 }
1470
1471-//==================================================================
1472-/*!
1473- * \brief FileSystemAction::storeOnClipboard() store data on Clipboard
1474- * \param pathnames files list
1475- * \param op \ref ClipboardOperation as \ref ClipboardCopy or \ref ClipboardCut
1476- *
1477- * Stores data on clipboard by calling \ref DirModelMimeData::setIntoClipboard() which uses Qt class QClipboard
1478- * It is expected that QClipboard class emits the dataChanged() signal when a new content is set into it,
1479- * if it does we caught that signal in \ref clipboardHasChanged() which sets \ref m_clipboardModifiedByOther to true.
1480- */
1481-void FileSystemAction::storeOnClipboard(const QStringList &pathnames, ClipboardOperation op)
1482-{
1483-#if DEBUG_MESSAGES
1484- qDebug() << Q_FUNC_INFO << pathnames << "ClipboardOperation" << op;
1485-#endif
1486- DirModelMimeData::ClipBoardDataOwner owner =
1487- m_mimeData->setIntoClipboard(pathnames, m_path, op);
1488- if (owner == DirModelMimeData::MySelf || !m_clipboardModifiedByOther)
1489- {
1490- emit clipboardChanged();
1491- }
1492-}
1493-
1494
1495 //==================================================================
1496 bool FileSystemAction::endCopySingleFile()
1497@@ -1722,3 +1288,15 @@
1498 #endif
1499 return ret;
1500 }
1501+
1502+
1503+//==================================================================
1504+/*!
1505+ * \brief FileSystemAction::onClipboardChanged()
1506+ *
1507+ * sets \ref m_clipboardChanged indicating the fhe Clipboard was changed.
1508+ */
1509+void FileSystemAction::onClipboardChanged()
1510+{
1511+ m_clipboardChanged = true;
1512+}
1513
1514=== modified file 'folderlistmodel/filesystemaction.h'
1515--- folderlistmodel/filesystemaction.h 2013-12-31 16:57:19 +0000
1516+++ folderlistmodel/filesystemaction.h 2014-01-29 16:33:58 +0000
1517@@ -52,10 +52,6 @@
1518 class QFile;
1519 class QTemporaryFile;
1520
1521-enum ClipboardOperation
1522-{
1523- NoClipboard, ClipboardCopy, ClipboardCut
1524-};
1525
1526 /*!
1527 * \brief The FileSystemAction class does file system operations copy/cut/paste/remove items
1528@@ -104,16 +100,16 @@
1529
1530 public:
1531 bool isBusy() const;
1532- int getProgressCounter() const;
1533- int clipboardLocalUrlsConunter();
1534+ int getProgressCounter() const;
1535
1536 public slots:
1537 void cancel();
1538 void remove(const QStringList & filePaths);
1539- void pathChanged(const QString& path);
1540- void paste();
1541- void cut(const QStringList&);
1542- void copy(const QStringList&);
1543+ void pathChanged(const QString& path);
1544+ void copyIntoCurrentPath(const QStringList& items);
1545+ void moveIntoCurrentPath(const QStringList& items);
1546+ void onClipboardChanged();
1547+
1548
1549 signals:
1550 void error(const QString& errorTitle, const QString &errorMessage);
1551@@ -123,14 +119,13 @@
1552 void added(const QFileInfo& );
1553 void changed(const QFileInfo&);
1554 void progress(int curItem, int totalItems, int percent);
1555- void clipboardChanged();
1556+ void recopy(const QStringList &names, const QString& path);
1557
1558 private slots:
1559 void processAction();
1560 void processActionEntry();
1561 void processCopyEntry();
1562 bool processCopySingleFile();
1563- void clipboardHasChanged();
1564
1565 private:
1566 enum ActionType
1567@@ -141,8 +136,9 @@
1568 ActionHardMoveCopy,
1569 ActionHardMoveRemove
1570 };
1571- void createAndProcessAction(ActionType actionType, const QStringList& paths,
1572- ClipboardOperation operation=NoClipboard);
1573+
1574+ void createAndProcessAction(ActionType actionType, const QStringList& paths);
1575+
1576 struct CopyFile
1577 {
1578 public:
1579@@ -199,8 +195,7 @@
1580 quint64 totalBytes;
1581 quint64 bytesWritten;
1582 int currEntryIndex;
1583- ActionEntry * currEntry;
1584- ClipboardOperation operation;
1585+ ActionEntry * currEntry;
1586 CopyFile copyFile;
1587 bool done;
1588 Action * auxAction;
1589@@ -213,10 +208,11 @@
1590 bool m_cancelCurrentAction;
1591 bool m_busy;
1592 QString m_path;
1593- DirModelMimeData * m_mimeData;
1594+
1595 QString m_errorTitle;
1596 QString m_errorMsg;
1597- bool m_clipboardModifiedByOther;
1598+ bool m_clipboardChanged; //!< this is set to false in \ref moveIntoCurrentPath() and \ref copyIntoCurrentPath();
1599+
1600
1601 private:
1602 Action * createAction(ActionType, int origBase = 0);
1603@@ -232,8 +228,7 @@
1604 bool copySymLink(const QString& target, const QFileInfo& orig);
1605 void scheduleSlot(const char *slot);
1606 void moveDirToTempAndRemoveItLater(const QString& dir);
1607- bool makeBackupNameForCurrentItem(Action *action);
1608- void storeOnClipboard(const QStringList &pathnames, ClipboardOperation op);
1609+ bool makeBackupNameForCurrentItem(Action *action);
1610 bool endCopySingleFile();
1611 bool isThereDiskSpace(qint64 requiredSize);
1612
1613
1614=== added file 'folderlistmodel/fmutil.cpp'
1615--- folderlistmodel/fmutil.cpp 1970-01-01 00:00:00 +0000
1616+++ folderlistmodel/fmutil.cpp 2014-01-29 16:33:58 +0000
1617@@ -0,0 +1,132 @@
1618+/**************************************************************************
1619+ *
1620+ * Copyright 2014 Canonical Ltd.
1621+ * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
1622+ *
1623+ * This program is free software; you can redistribute it and/or modify
1624+ * it under the terms of the GNU Lesser General Public License as published by
1625+ * the Free Software Foundation; version 3.
1626+ *
1627+ * This program is distributed in the hope that it will be useful,
1628+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1629+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1630+ * GNU Lesser General Public License for more details.
1631+ *
1632+ * You should have received a copy of the GNU Lesser General Public License
1633+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1634+ *
1635+ * File: fmutil.cpp
1636+ * Date: 29/01/2014
1637+ */
1638+
1639+#include "fmutil.h"
1640+
1641+#include <QIcon>
1642+#include <QFileInfo>
1643+#include <QDir>
1644+#include <QDebug>
1645+
1646+bool FMUtil::m_triedThemeName = false;
1647+
1648+FMUtil::FMUtil()
1649+{
1650+}
1651+
1652+
1653+/*!
1654+ * \brief FMUtil::setThemeName() tries to set a theme name in order to get icons
1655+ */
1656+void FMUtil::setThemeName()
1657+{
1658+ QString name;
1659+ //set saying we have tried to set ThemeName
1660+ m_triedThemeName = true;
1661+ QLatin1String ubuntu_mobileTheme("ubuntu-mobile");
1662+ QStringList paths(QIcon::themeSearchPaths());
1663+#if defined(Q_OS_UNIX)
1664+ if (paths.isEmpty())
1665+ {
1666+ paths.append(QLatin1String("/usr/share/icons"));
1667+ }
1668+#endif
1669+ foreach (const QString& dir, paths)
1670+ {
1671+ QDir D(dir);
1672+ if (D.exists())
1673+ {
1674+#if DEBUG_MESSAGES
1675+ qDebug() << Q_FUNC_INFO << "trying theme on Dir" << D.path();
1676+#endif
1677+ QFileInfoList inf = D.entryInfoList(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::System );
1678+ int counter = inf.count();
1679+ //specific names
1680+ while (counter--)
1681+ {
1682+ if (inf.at(counter).fileName() == ubuntu_mobileTheme)
1683+ {
1684+ if (testThemeName(ubuntu_mobileTheme))
1685+ {
1686+ return;
1687+ }
1688+ else
1689+ {
1690+ inf.removeAt(counter);
1691+ }
1692+ }
1693+ }
1694+ //try symlinks
1695+ counter = inf.count();
1696+ while (counter--)
1697+ {
1698+ if (inf.at(counter).isSymLink())
1699+ {
1700+ if (testThemeName(inf.at(counter).fileName()))
1701+ {
1702+ return;
1703+ }
1704+ else
1705+ {
1706+ inf.removeAt(counter);
1707+ }
1708+ }
1709+ }
1710+ //try common directories
1711+ counter = inf.count();
1712+ while (counter--)
1713+ {
1714+ if (testThemeName(inf.at(counter).fileName()))
1715+ {
1716+ return;
1717+ }
1718+ }
1719+ }
1720+ }
1721+ name.clear();
1722+ QIcon::setThemeName(name);
1723+}
1724+
1725+
1726+bool FMUtil::testThemeName(const QString& themeName)
1727+{
1728+ QMimeDatabase mimeBase;
1729+ QStringList mimesToTest = QStringList()
1730+ << "text/plain"
1731+ << "inode/directory"
1732+ << "application/pdf"
1733+ << "application/postscript"
1734+ << "application/x-gzip";
1735+
1736+ QIcon::setThemeName(themeName);
1737+ bool hasTheme = true;
1738+ int counter = mimesToTest.count();
1739+ while(hasTheme && counter--)
1740+ {
1741+ QMimeType mimetype = mimeBase.mimeTypeForName(mimesToTest.at(counter));
1742+ hasTheme = QIcon::hasThemeIcon( mimetype.iconName() ) ||
1743+ QIcon::hasThemeIcon( mimetype.genericIconName() ) ;
1744+ }
1745+#if DEBUG_MESSAGES
1746+ qDebug() << Q_FUNC_INFO << "trying theme name" << themeName << "ret=" << hasTheme;
1747+#endif
1748+ return hasTheme;
1749+}
1750
1751=== added file 'folderlistmodel/fmutil.h'
1752--- folderlistmodel/fmutil.h 1970-01-01 00:00:00 +0000
1753+++ folderlistmodel/fmutil.h 2014-01-29 16:33:58 +0000
1754@@ -0,0 +1,46 @@
1755+/**************************************************************************
1756+ *
1757+ * Copyright 2014 Canonical Ltd.
1758+ * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
1759+ *
1760+ * This program is free software; you can redistribute it and/or modify
1761+ * it under the terms of the GNU Lesser General Public License as published by
1762+ * the Free Software Foundation; version 3.
1763+ *
1764+ * This program is distributed in the hope that it will be useful,
1765+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1766+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1767+ * GNU Lesser General Public License for more details.
1768+ *
1769+ * You should have received a copy of the GNU Lesser General Public License
1770+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1771+ *
1772+ * File: fmutil.h
1773+ * Date: 29/01/2014
1774+ */
1775+
1776+#ifndef FMUTIL_H
1777+#define FMUTIL_H
1778+
1779+#include <QStringList>
1780+#include <QMimeType>
1781+#include <QMimeDatabase>
1782+
1783+/*!
1784+ * \brief The FMUtil class provides some utitlities
1785+ */
1786+class FMUtil
1787+{
1788+public:
1789+ static void setThemeName();
1790+ static inline bool hasTriedThemeName() { return m_triedThemeName; }
1791+
1792+private:
1793+ FMUtil();
1794+ static bool testThemeName(const QString& themeName);
1795+
1796+private:
1797+ static bool m_triedThemeName;
1798+};
1799+
1800+#endif // FMUTIL_H
1801
1802=== modified file 'folderlistmodel/folderlistmodel.pri'
1803--- folderlistmodel/folderlistmodel.pri 2013-11-27 12:04:20 +0000
1804+++ folderlistmodel/folderlistmodel.pri 2014-01-29 16:33:58 +0000
1805@@ -4,7 +4,9 @@
1806 $$PWD/ioworkerthread.cpp \
1807 $$PWD/filesystemaction.cpp \
1808 $$PWD/filecompare.cpp \
1809- $$PWD/externalfswatcher.cpp
1810+ $$PWD/externalfswatcher.cpp \
1811+ $$PWD/clipboard.cpp \
1812+ $$PWD/fmutil.cpp
1813
1814
1815
1816@@ -15,7 +17,9 @@
1817 $$PWD/ioworkerthread.h \
1818 $$PWD/filesystemaction.h \
1819 $$PWD/filecompare.h \
1820- $$PWD/externalfswatcher.h
1821+ $$PWD/externalfswatcher.h \
1822+ $$PWD/clipboard.h \
1823+ $$PWD/fmutil.h
1824
1825
1826
1827
1828=== modified file 'test_folderlistmodel/regression/tst_folderlistmodel.cpp'
1829--- test_folderlistmodel/regression/tst_folderlistmodel.cpp 2013-12-31 16:57:19 +0000
1830+++ test_folderlistmodel/regression/tst_folderlistmodel.cpp 2014-01-29 16:33:58 +0000
1831@@ -29,7 +29,7 @@
1832 #include <QPixmap>
1833 #include <QFileIconProvider>
1834
1835-#if defined(REGRESSION_TEST_FOLDERLISTMODEL) && QT_VERSION >= 0x050000
1836+#if QT_VERSION >= 0x050000
1837 #include <QMimeType>
1838 #include <QMimeDatabase>
1839 #endif
1840@@ -1629,9 +1629,9 @@
1841 }
1842
1843
1844-#if defined(REGRESSION_TEST_FOLDERLISTMODEL) && QT_VERSION >= 0x050000
1845+#if QT_VERSION >= 0x050000
1846 void TestDirModel::getThemeIcons()
1847-{
1848+{
1849 QStringList mimesToTest = QStringList()
1850 << "text/plain"
1851 << "text/x-c++src"
1852@@ -1650,30 +1650,40 @@
1853 QString msg;
1854 QHash<QByteArray, QString> md5IconsTable;
1855
1856+ qDebug() << "QIcon::themeSearchPaths()" << QIcon::themeSearchPaths();
1857+ qDebug() << "QIcon::themeName()" << QIcon::themeName();
1858+
1859+
1860 for (int counter=0; counter < mimesToTest.count(); counter++)
1861 {
1862 QMimeType mimetype = mimeBase.mimeTypeForName(mimesToTest.at(counter));
1863+
1864 msg = QLatin1String("invalid mimetype ") + mimesToTest.at(counter);
1865 if (!mimetype.isValid())
1866 {
1867 QSKIP_ALL_TESTS(qPrintable(msg));
1868 }
1869- QIcon icon = QIcon::fromTheme(mimetype.iconName());
1870- msg = QLatin1String("invalid QIcon::fromTheme ") + mimetype.iconName();
1871+ QString iconName = mimetype.iconName();
1872+ if (!QIcon::hasThemeIcon(iconName) && QIcon::hasThemeIcon(mimetype.genericIconName()))
1873+ {
1874+ iconName = mimetype.genericIconName();
1875+ }
1876+ QIcon icon = QIcon::fromTheme(iconName);
1877+ msg = QLatin1String("invalid QIcon::fromTheme ") + iconName;
1878 if (icon.isNull())
1879 {
1880 QSKIP_ALL_TESTS(qPrintable(msg));
1881 }
1882
1883 QPixmap pix = icon.pixmap(QSize(48,48));
1884- msg = QLatin1String("invalid QPixmap from icon ") + mimetype.iconName();
1885+ msg = QLatin1String("invalid QPixmap from icon ") + iconName;
1886 if (pix.isNull())
1887 {
1888 QSKIP_ALL_TESTS(qPrintable(msg));
1889 }
1890
1891 QImage image = pix.toImage();
1892- msg = QLatin1String("invalid QImage from QPixmap/QIcon ") + mimetype.iconName();
1893+ msg = QLatin1String("invalid QImage from QPixmap/QIcon ") + iconName;
1894 if (image.isNull())
1895 {
1896 QSKIP_ALL_TESTS(qPrintable(msg));
1897@@ -2059,9 +2069,7 @@
1898 break;
1899 }
1900 }
1901- int ret = QTest::qExec(&tc, args);
1902-
1903- return ret;
1904+ return QTest::qExec(&tc, args);
1905 }
1906
1907

Subscribers

People subscribed via source and target branches