Merge lp:~carlos-mazieri/ubuntu-filemanager-app/app-devel-pre4 into lp:ubuntu-filemanager-app

Proposed by Carlos Jose Mazieri
Status: Merged
Approved by: David Planella
Approved revision: 175
Merged at revision: 182
Proposed branch: lp:~carlos-mazieri/ubuntu-filemanager-app/app-devel-pre4
Merge into: lp:ubuntu-filemanager-app
Prerequisite: lp:~carlos-mazieri/ubuntu-filemanager-app/app-devel-pre3
Diff against target: 1605 lines (+1155/-164)
14 files modified
src/plugin/folderlistmodel/CMakeLists.txt (+10/-0)
src/plugin/folderlistmodel/dirmodel.cpp (+106/-139)
src/plugin/folderlistmodel/dirmodel.h (+11/-16)
src/plugin/folderlistmodel/disk/disklocation.cpp (+222/-0)
src/plugin/folderlistmodel/disk/disklocation.h (+81/-0)
src/plugin/folderlistmodel/filecompare.cpp (+2/-3)
src/plugin/folderlistmodel/folderlistmodel.pri (+14/-5)
src/plugin/folderlistmodel/location.cpp (+140/-0)
src/plugin/folderlistmodel/location.h (+132/-0)
src/plugin/folderlistmodel/locationsfactory.cpp (+181/-0)
src/plugin/folderlistmodel/locationsfactory.h (+136/-0)
src/plugin/folderlistmodel/locationurl.cpp (+34/-0)
src/plugin/folderlistmodel/locationurl.h (+40/-0)
src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp (+46/-1)
To merge this branch: bzr merge lp:~carlos-mazieri/ubuntu-filemanager-app/app-devel-pre4
Reviewer Review Type Date Requested Status
Arto Jalkanen Approve
Ubuntu Phone Apps Jenkins Bot continuous-integration Approve
Review via email: mp+218040@code.launchpad.net

Description of the change

Introduces Location, it basicaly handles Urls and their internal paths.

IORequest/DirListWorker and ExternalFSWatcher calls were moved from DirModel class to DiskLocation class

Location provides:
         current path/url -> Location::urlPath()
         its content -> Location::fetchItems()
         navigation -> up=Location::becomeParent() into sub-folders=Location::setFromInfoItem()
         notification about external changes in its current path.

Changed navigation in the file manager:
  DirModel::setPath() now calls LocationsFactory::setNewPath() which can change the location or set a path in the current location.
  DirModel::cdUp()
  DirModel::cdIntoIndex()
  DirModel::openPath()

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
Alan Pope 🍺🐧🐱 πŸ¦„ (popey) wrote :

I've asked Michael Spencer to take a look at this and the other related branches and review. If he has difficulty with that I've asked him to get back to me so we can find another reviewer.

173. By Carlos Jose Mazieri

Fixed using m_info when it can be null.

Revision history for this message
Ubuntu Phone Apps Jenkins Bot (ubuntu-phone-apps-jenkins-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Arto Jalkanen (ajalkane) wrote :

1)

Non-virtual destructors on classes that either inherit or are inherited other classes with virtual functions, these should be virtual destructors:
~Location()
~DiskLocation()
~LocationsFactory()

Especially important are the Location ones and the classes deriving from it. A basic rule-of-thumb is to have a virtual destructor on any class that has virtual functions or that derives from a class that has virtual destructors. Deviating from this rule-of-thumb is sometimes acceptable but there should be heavy reasons for it, and some comment for why it is so would be appreciated. Right now I do not see anything in the code that would warrant them not-being virtual destructors.

It'd be good to check the code on the whole that there's not more than what I noticed in this code-review.

2)

There is const_cast<...> calls. It's a red flag, casting should only be used if definitely needed. Either document why it's needed or try to refactor the code to get rid of it. For example:
const Location * LocationsFactory::setNewPath(const QString& uPath)

Why does it need to return const pointer as it's used in such a way that it's modified? Why not have it return non-const pointer and get rid of the const_casts.

3)

in someplaces when checking pointer there is:
if (m_somePointer == 0)
and other times just:
if (m_somePointer)

Either is fine IMO, but it'd be good to keep the code-base consistent. So use one or the other.

4)

This perplexes me:

void Location::setFromInfoItem(const DirItemInfo *itemInfo)
917 +{
918 + if (m_info)
919 + {
920 + delete m_info;
921 + }
922 + m_info = const_cast<DirItemInfo*> (itemInfo);
923 +}

the name of the function, setFromInfoItem, along with the const parameter to me gives an impression that it will make a copy for the class to use. Instead it does a cast and uses the pointer directly. Perhaps do not use parameter as "const" and rename the function to setInfoItem(DireItemInfo *itemInfo) ? Here I may not understand some details, so feel free to correct me.

5)

Typos:

LocationsFactory::stringAfterSlahes() -> LocationsFactory::stringAfterSlashes()
DiskLocation::stoptExternalFsWatcher() -> DiskLocation::stopExternalFsWatcher()

review: Needs Fixing
174. By Carlos Jose Mazieri

* changed destructor to virtual from classes Location() and DiskLocation
* changed Location::setFromInfoItem(const DirItemInfo *itemInfo) to:
          Location::setInfoItem(DireItemInfo *itemInfo)
* changed const Location * LocationsFactory::setNewPath(const QString& uPath) to
                Location * LocationsFactory::setNewPath(const QString& uPath)
* changed const Location * LocationsFactory::parse(const QString& urlPath) to
                Location * LocationsFactory::parse(const QString& urlPath)
* changed const Location * LocationsFactory::location() const to
                Location * LocationsFactory::location() const

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 :

> 1)
>
> Non-virtual destructors on classes that either inherit or are inherited other
> classes with virtual functions, these should be virtual destructors:
> ~Location()
> ~DiskLocation()
> ~LocationsFactory()
>
> Especially important are the Location ones and the classes deriving from it. A
> basic rule-of-thumb is to have a virtual destructor on any class that has
> virtual functions or that derives from a class that has virtual destructors.
> Deviating from this rule-of-thumb is sometimes acceptable but there should be
> heavy reasons for it, and some comment for why it is so would be appreciated.
> Right now I do not see anything in the code that would warrant them not-being
> virtual destructors.
>

> It'd be good to check the code on the whole that there's not more than what I
> noticed in this code-review

DONE. added virtual for destructors. LocationsFactory does not have any virtual method nor any descendent class.

.
>
> 2)
>
> There is const_cast<...> calls. It's a red flag, casting should only be used
> if definitely needed. Either document why it's needed or try to refactor the
> code to get rid of it. For example:
> const Location * LocationsFactory::setNewPath(const QString& uPath)
>
> Why does it need to return const pointer as it's used in such a way that it's
> modified? Why not have it return non-const pointer and get rid of the
> const_casts.

DONE. removed const

>
> 3)
>
> in someplaces when checking pointer there is:
> if (m_somePointer == 0)
> and other times just:
> if (m_somePointer)
>
> Either is fine IMO, but it'd be good to keep the code-base consistent. So use
> one or the other.

I am used to use "if (pointer)" when asking for avalid address and "if (pointer == 0)" when asking if a pointer is NULL, I could use "if (pointer != 0)" when asking for avalid address, but not "if (!pointer)" which looks like the variable is a bool.

>
> 4)
>
> This perplexes me:
>
> void Location::setFromInfoItem(const DirItemInfo *itemInfo)
> 917 +{
> 918 + if (m_info)
> 919 + {
> 920 + delete m_info;
> 921 + }
> 922 + m_info = const_cast<DirItemInfo*> (itemInfo);
> 923 +}
>

DONE. Changed to Location::setInfoItem(DireItemInfo *itemInfo) (const removed)

>
> the name of the function, setFromInfoItem, along with the const parameter to
> me gives an impression that it will make a copy for the class to use. Instead
> it does a cast and uses the pointer directly. Perhaps do not use parameter as
> "const" and rename the function to setInfoItem(DireItemInfo *itemInfo) ? Here
> I may not understand some details, so feel free to correct me.
>
> 5)
>
> Typos:
>
> LocationsFactory::stringAfterSlahes() ->
> LocationsFactory::stringAfterSlashes()
> DiskLocation::stoptExternalFsWatcher() ->
> DiskLocation::stopExternalFsWatcher()

DONE. Changed.

Revision history for this message
Arto Jalkanen (ajalkane) wrote :

Thanks for the fixes! A couple of things anymore:

> > It'd be good to check the code on the whole that there's not more than what
> I
> > noticed in this code-review
>
>
> DONE. added virtual for destructors. LocationsFactory does not have any
> virtual method nor any descendent class.

But LocationsFactory inherits QObject which does have virtual methods so it's a potential hard to find error even if it's not a problem in code-base currently. Consider for example Qt's resource management where parent QObject is responsible for deleting its children. If LocationsFactory (or any other similar class) is set as a child of some other QObject (practically speaking using the new LocationsFactory(QObject *parent) constructor where parent is not null), then when the parent QObject is deleted then LocationsFactory's destructor is not called - unless you make it virtual.

> I am used to use "if (pointer)" when asking for avalid address and "if
> (pointer == 0)" when asking if a pointer is NULL, I could use "if (pointer !=
> 0)" when asking for avalid address, but not "if (!pointer)" which looks like
> the variable is a bool.

That makes sense, I misread that line. It's good.

> >
> > 4)
> >
> > This perplexes me:
> >
> > void Location::setFromInfoItem(const DirItemInfo *itemInfo)
> > 917 +{
> > 918 + if (m_info)
> > 919 + {
> > 920 + delete m_info;
> > 921 + }
> > 922 + m_info = const_cast<DirItemInfo*> (itemInfo);
> > 923 +}
> >
>
> DONE. Changed to Location::setInfoItem(DireItemInfo *itemInfo) (const removed)

There's still two places with unnecessary const_casts:

143 + mCurLocation = const_cast<Location*> (location);
235 + mCurLocation = const_cast<Location*> (location);

review: Needs Fixing
Revision history for this message
Carlos Jose Mazieri (carlos-mazieri) wrote :

> Thanks for the fixes! A couple of things anymore:
>
> > > It'd be good to check the code on the whole that there's not more than
> what
> > I
> > > noticed in this code-review
> >
> >
> > DONE. added virtual for destructors. LocationsFactory does not have any
> > virtual method nor any descendent class.
>
> But LocationsFactory inherits QObject which does have virtual methods so it's
> a potential hard to find error even if it's not a problem in code-base
> currently. Consider for example Qt's resource management where parent QObject
> is responsible for deleting its children. If LocationsFactory (or any other
> similar class) is set as a child of some other QObject (practically speaking
> using the new LocationsFactory(QObject *parent) constructor where parent is
> not null), then when the parent QObject is deleted then LocationsFactory's
> destructor is not called - unless you make it virtual.
>

  I agree that it is a good programming practice and I can do it, no problem.
  But I am not sure it happens, QObject DOES HAVE virtual destructor which in my opinion makes all descendant destructors to be called.

> > I am used to use "if (pointer)" when asking for avalid address and "if
> > (pointer == 0)" when asking if a pointer is NULL, I could use "if (pointer
> !=
> > 0)" when asking for avalid address, but not "if (!pointer)" which looks like
> > the variable is a bool.
>
> That makes sense, I misread that line. It's good.
>
> > >
> > > 4)
> > >
> > > This perplexes me:
> > >
> > > void Location::setFromInfoItem(const DirItemInfo *itemInfo)
> > > 917 +{
> > > 918 + if (m_info)
> > > 919 + {
> > > 920 + delete m_info;
> > > 921 + }
> > > 922 + m_info = const_cast<DirItemInfo*> (itemInfo);
> > > 923 +}
> > >
> >
> > DONE. Changed to Location::setInfoItem(DireItemInfo *itemInfo) (const
> removed)
>
> There's still two places with unnecessary const_casts:
>
> 143 + mCurLocation = const_cast<Location*> (location);
> 235 + mCurLocation = const_cast<Location*> (location);

Revision history for this message
Arto Jalkanen (ajalkane) wrote :

> > Thanks for the fixes! A couple of things anymore:
> >
> > > > It'd be good to check the code on the whole that there's not more than
> > what
> > > I
> > > > noticed in this code-review
> > >
> > >
> > > DONE. added virtual for destructors. LocationsFactory does not have any
> > > virtual method nor any descendent class.
> >
> > But LocationsFactory inherits QObject which does have virtual methods so
> it's
> > a potential hard to find error even if it's not a problem in code-base
> > currently. Consider for example Qt's resource management where parent
> QObject
> > is responsible for deleting its children. If LocationsFactory (or any other
> > similar class) is set as a child of some other QObject (practically speaking
> > using the new LocationsFactory(QObject *parent) constructor where parent is
> > not null), then when the parent QObject is deleted then LocationsFactory's
> > destructor is not called - unless you make it virtual.
> >
>
> I agree that it is a good programming practice and I can do it, no problem.
> But I am not sure it happens, QObject DOES HAVE virtual destructor which in
> my opinion makes all descendant destructors to be called.

You're right. Shame on me forgetting that when base class has virtual destructor, it makes all descendant classes destructors virtual automatic even without specifically declaring them such.

So yes, it's not a problem.

>
> > > I am used to use "if (pointer)" when asking for avalid address and "if
> > > (pointer == 0)" when asking if a pointer is NULL, I could use "if (pointer
> > !=
> > > 0)" when asking for avalid address, but not "if (!pointer)" which looks
> like
> > > the variable is a bool.
> >
> > That makes sense, I misread that line. It's good.
> >
> > > >
> > > > 4)
> > > >
> > > > This perplexes me:
> > > >
> > > > void Location::setFromInfoItem(const DirItemInfo *itemInfo)
> > > > 917 +{
> > > > 918 + if (m_info)
> > > > 919 + {
> > > > 920 + delete m_info;
> > > > 921 + }
> > > > 922 + m_info = const_cast<DirItemInfo*> (itemInfo);
> > > > 923 +}
> > > >
> > >
> > > DONE. Changed to Location::setInfoItem(DireItemInfo *itemInfo) (const
> > removed)
> >
> > There's still two places with unnecessary const_casts:
> >
> > 143 + mCurLocation = const_cast<Location*> (location);
> > 235 + mCurLocation = const_cast<Location*> (location);

175. By Carlos Jose Mazieri

removed row no necessary const_cast<Location*>

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 :

revision 175 removes:
  143 + mCurLocation = const_cast<Location*> (location);
  235 + mCurLocation = const_cast<Location*> (location);

I think that completes those 5 items, they all have been solved.

Revision history for this message
Arto Jalkanen (ajalkane) wrote :

Thank you for doing these!

review: Approve
Revision history for this message
David Planella (dpm) wrote :

Thanks guys, top-approving as per Arto's last comment.

@Arto, in the future, please feel free to top-approve the merge proposal yourself if you think it's ready to land. Thanks!

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/plugin/folderlistmodel/CMakeLists.txt'
--- src/plugin/folderlistmodel/CMakeLists.txt 2014-04-28 10:21:05 +0000
+++ src/plugin/folderlistmodel/CMakeLists.txt 2014-05-15 23:31:23 +0000
@@ -1,5 +1,7 @@
1include_directories(1include_directories(
2 ${CMAKE_CURRENT_SOURCE_DIR}2 ${CMAKE_CURRENT_SOURCE_DIR}
3 disk
4 trash
3)5)
46
5set(PLUGIN_DIR org/nemomobile/folderlistmodel)7set(PLUGIN_DIR org/nemomobile/folderlistmodel)
@@ -32,6 +34,14 @@
32 ioworkerthread.h34 ioworkerthread.h
33 plugin.cpp35 plugin.cpp
34 plugin.h36 plugin.h
37 location.cpp
38 location.h
39 locationsfactory.cpp
40 locationsfactory.h
41 locationurl.cpp
42 locationurl.h
43 disk/disklocation.cpp
44 disk/disklocation.h
35 trash/qtrashdir.cpp45 trash/qtrashdir.cpp
36 trash/qtrashdir.h46 trash/qtrashdir.h
37)47)
3848
=== modified file 'src/plugin/folderlistmodel/dirmodel.cpp'
--- src/plugin/folderlistmodel/dirmodel.cpp 2014-05-15 23:31:22 +0000
+++ src/plugin/folderlistmodel/dirmodel.cpp 2014-05-15 23:31:23 +0000
@@ -31,12 +31,13 @@
3131
32#include "dirselection.h"32#include "dirselection.h"
33#include "dirmodel.h"33#include "dirmodel.h"
34#include "iorequest.h"
35#include "ioworkerthread.h"
36#include "filesystemaction.h"34#include "filesystemaction.h"
37#include "externalfswatcher.h"
38#include "clipboard.h"35#include "clipboard.h"
39#include "fmutil.h"36#include "fmutil.h"
37#include "locationsfactory.h"
38#include "location.h"
39#include "locationurl.h"
40#include "disklocation.h"
4041
4142
42#ifndef DO_NOT_USE_TAG_LIB43#ifndef DO_NOT_USE_TAG_LIB
@@ -75,7 +76,6 @@
75#define IS_FILE_MANAGER_IDLE() (!mAwaitingResults)76#define IS_FILE_MANAGER_IDLE() (!mAwaitingResults)
7677
7778
78Q_GLOBAL_STATIC(IOWorkerThread, ioWorkerThread)
7979
80namespace {80namespace {
81 QHash<QByteArray, int> roleMapping;81 QHash<QByteArray, int> roleMapping;
@@ -108,9 +108,11 @@
108 , mSortBy(SortByName)108 , mSortBy(SortByName)
109 , mSortOrder(SortAscending)109 , mSortOrder(SortAscending)
110 , mCompareFunction(0) 110 , mCompareFunction(0)
111 , mExtFSWatcher(0)111 , mExtFSWatcher(false)
112 , mClipboard(new Clipboard(this)) 112 , mClipboard(new Clipboard(this))
113 , m_fsAction(new FileSystemAction(this) ) 113 , mLocationFactory(new LocationsFactory(this))
114 , mCurLocation(0)
115 , m_fsAction(new FileSystemAction(this) )
114{116{
115 mNameFilters = QStringList() << "*";117 mNameFilters = QStringList() << "*";
116118
@@ -155,13 +157,40 @@
155 {157 {
156 FMUtil::setThemeName();158 FMUtil::setThemeName();
157 }159 }
160
161 foreach (const Location* l, mLocationFactory->availableLocations())
162 {
163 connect(l, SIGNAL(itemsAdded(DirItemInfoList)),
164 this, SLOT(onItemsAdded(DirItemInfoList)));
165
166 connect(l, SIGNAL(itemsFetched()),
167 this, SLOT(onItemsFetched()));
168
169 connect(l, SIGNAL(extWatcherItemAdded(DirItemInfo)),
170 this, SLOT(onItemAddedOutsideFm(DirItemInfo)));
171
172 connect(l, SIGNAL(extWatcherItemRemoved(DirItemInfo)),
173 this, SLOT(onItemRemovedOutSideFm(DirItemInfo)));
174
175 connect(l, SIGNAL(extWatcherItemChanged(DirItemInfo)),
176 this, SLOT(onItemChangedOutSideFm(DirItemInfo)));
177
178 connect(l, SIGNAL(extWatcherChangesFetched(int)),
179 this, SLOT(onExternalFsWorkerFinished(int)));
180
181 connect(l, SIGNAL(extWatcherPathChanged(QString)),
182 this, SLOT(onThereAreExternalChanges(QString)));
183
184 connect(this, SIGNAL(enabledExternalFSWatcherChanged(bool)),
185 l, SLOT(setUsingExternalWatcher(bool)));
186 }
158}187}
159188
160189
161190
162DirModel::~DirModel()191DirModel::~DirModel()
163{192{
164 stoptExternalFsWatcher();193
165}194}
166195
167196
@@ -371,38 +400,48 @@
371 if (pathName.isEmpty())400 if (pathName.isEmpty())
372 return; 401 return;
373402
374 if (!canReadDir(pathName))403 if (mAwaitingResults) {
375 {
376 emit error(tr("cannot read path"), pathName);
377 return;
378 }
379
380 if (mAwaitingResults) {
381 // TODO: handle the case where pathName != our current path, cancel old404 // TODO: handle the case where pathName != our current path, cancel old
382 // request, start a new one405 // request, start a new one
383 qDebug() << Q_FUNC_INFO << this << "Ignoring path change request, request already running";406 qDebug() << Q_FUNC_INFO << this << "Ignoring path change request, request already running in" << pathName;
384 return;407 return;
385 }408 }
386409
410 Location *location = mLocationFactory->setNewPath(pathName);
411 if (location == 0)
412 {
413 emit error(tr("path or url may not exist or cannot be read"), pathName);
414 qDebug() << Q_FUNC_INFO << this << "path or url may not exist or cannot be read:" << pathName;
415 return;
416 }
417
418 mCurLocation = location;
419 setPathFromCurrentLocation();
420}
421
422/*!
423 * \brief DirModel::setPathFromCurrentLocation() changes current Path using current Location
424 *
425 * Used in \ref cdUp() and \ref cdIntoIndex()
426 */
427void DirModel::setPathFromCurrentLocation()
428{
387 mAwaitingResults = true;429 mAwaitingResults = true;
388 emit awaitingResultsChanged();430 emit awaitingResultsChanged();
389#if DEBUG_MESSAGES431#if DEBUG_MESSAGES
390 qDebug() << Q_FUNC_INFO << this << "Changing to " << pathName << " on " << QThread::currentThreadId();432 qDebug() << Q_FUNC_INFO << this << "Changing to " << mCurLocation->urlPath();
391#endif433#endif
392434
393 clear();435 clear();
394436
395 DirListWorker *dlw = createWorkerRequest(IORequest::DirList, pathName);437 mCurLocation->fetchItems(currentDirFilter(), mIsRecursive);
396 connect(dlw, SIGNAL(itemsAdded(DirItemInfoList)), SLOT(onItemsAdded(DirItemInfoList)));
397 connect(dlw, SIGNAL(workerFinished()), SLOT(onResultsFetched()));
398 ioWorkerThread()->addRequest(dlw);
399438
400 mCurrentDir = pathName;439 mCurrentDir = mCurLocation->urlPath();
401 emit pathChanged(pathName);440 emit pathChanged(mCurLocation->urlPath());
402}441}
403442
404443
405void DirModel::onResultsFetched() {444void DirModel::onItemsFetched() {
406 if (mAwaitingResults) {445 if (mAwaitingResults) {
407#if DEBUG_MESSAGES446#if DEBUG_MESSAGES
408 qDebug() << Q_FUNC_INFO << this << "No longer awaiting results";447 qDebug() << Q_FUNC_INFO << this << "No longer awaiting results";
@@ -611,7 +650,9 @@
611}650}
612ExternalFSWatcher * DirModel::getExternalFSWatcher() const651ExternalFSWatcher * DirModel::getExternalFSWatcher() const
613{652{
614 return mExtFSWatcher;653 const Location *l = mLocationFactory->availableLocations().at(LocationsFactory::LocalDisk);
654 const DiskLocation *disk = static_cast<const DiskLocation*> (l);
655 return disk->getExternalFSWatcher();
615}656}
616#endif657#endif
617658
@@ -624,15 +665,10 @@
624665
625bool DirModel::cdUp()666bool DirModel::cdUp()
626{667{
627 int ret = false;668 int ret = mCurLocation && mCurLocation->becomeParent();
628 if (!mCurrentDir.isEmpty()) // we are in any dir669 if (ret)
629 {670 {
630 QDir current(mCurrentDir);671 setPathFromCurrentLocation();
631 if (current.cdUp())
632 {
633 setPath(current.absolutePath());
634 ret = true;
635 }
636 }672 }
637 return ret;673 return ret;
638}674}
@@ -720,7 +756,9 @@
720 mDirectoryContents.at(row).isDir() &&756 mDirectoryContents.at(row).isDir() &&
721 mDirectoryContents.at(row).isContentReadable())757 mDirectoryContents.at(row).isContentReadable())
722 {758 {
723 ret = cdInto(mDirectoryContents.at(row));759 mCurLocation->setInfoItem(mDirectoryContents.at(row));
760 setPathFromCurrentLocation();
761 ret = true;
724 }762 }
725 else763 else
726 {764 {
@@ -1114,8 +1152,28 @@
11141152
1115bool DirModel::openPath(const QString &filename)1153bool DirModel::openPath(const QString &filename)
1116{1154{
1117 DirItemInfo fi(setParentIfRelative(filename));1155 bool ret = false;
1118 return openItem(fi);1156 //first void any relative path when is root
1157 if ( !(mCurLocation && mCurLocation->isRoot() && filename.startsWith(QLatin1String(".."))) )
1158 {
1159 Location *location = mLocationFactory->setNewPath(filename);
1160 if (location)
1161 {
1162 mCurLocation = location;
1163 setPathFromCurrentLocation();
1164 ret = true;
1165 }
1166 else
1167 {
1168 const DirItemInfo *item = mLocationFactory->lastValidFileInfo();
1169 // DirItemInfo fi(setParentIfRelative(filename));
1170 if (item && item->isFile())
1171 {
1172 ret = openItem(*item);
1173 }
1174 }
1175 }
1176 return ret;
1119}1177}
11201178
1121/*!1179/*!
@@ -1144,76 +1202,8 @@
1144 return ret;1202 return ret;
1145}1203}
11461204
1147/*!1205
1148 * \brief DirModel::createWorkerRequest() create a request for IORequestWorker1206
1149 * \param requestType the common IORequest::DirList to fill a directory content
1150 * or IORequest::DirAutoRefresh that will verify any external File System modification
1151 * \param pathName the path to get content
1152 * \return the thread object
1153 */
1154DirListWorker * DirModel::createWorkerRequest(IORequest::RequestType requestType,
1155 const QString& pathName)
1156{
1157 DirListWorker * reqThread = 0;
1158 QDir::Filter dirFilter = currentDirFilter();
1159 if (requestType == IORequest::DirList)
1160 {
1161 // TODO: we need to set a spinner active before we start getting results from DirListWorker
1162 reqThread = new DirListWorker(pathName, dirFilter, mIsRecursive);
1163 }
1164 else
1165 {
1166 reqThread = new ExternalFileSystemChangesWorker(mDirectoryContents,
1167 pathName,
1168 dirFilter, mIsRecursive);
1169 }
1170 return reqThread;
1171}
1172
1173
1174
1175/*!
1176 * \brief DirModel::startExternalFsWatcher() starts the External File System Watcher
1177 */
1178void DirModel::startExternalFsWatcher()
1179{
1180#if DEBUG_EXT_FS_WATCHER
1181 qDebug() << "[extFsWorker]" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz")
1182 << Q_FUNC_INFO << this;
1183
1184#endif
1185 if (!mExtFSWatcher)
1186 {
1187 mExtFSWatcher = new ExternalFSWatcher(this);
1188 mExtFSWatcher->setIntervalToNotifyChanges(EX_FS_WATCHER_TIMER_INTERVAL);
1189 connect(this, SIGNAL(pathChanged(QString)),
1190 mExtFSWatcher, SLOT(setCurrentPath(QString)));
1191
1192 connect(mExtFSWatcher, SIGNAL(pathModified(QString)),
1193 this, SLOT(onThereAreExternalChanges(QString)));
1194
1195 //setCurrentPath() checks for empty paths
1196 mExtFSWatcher->setCurrentPath(mCurrentDir);
1197 }
1198}
1199
1200
1201
1202/*!
1203 * \brief DirModel::stoptExternalFsWatcher stops the External File System Watcher
1204 */
1205void DirModel::stoptExternalFsWatcher()
1206{
1207#if DEBUG_EXT_FS_WATCHER
1208 qDebug() << "[extFsWatcher]" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz")
1209 << Q_FUNC_INFO << this;
1210#endif
1211 if (mExtFSWatcher)
1212 {
1213 delete mExtFSWatcher;
1214 mExtFSWatcher = 0;
1215 }
1216}
12171207
12181208
1219void DirModel::onThereAreExternalChanges(const QString& pathModifiedOutside)1209void DirModel::onThereAreExternalChanges(const QString& pathModifiedOutside)
@@ -1222,27 +1212,11 @@
1222 {1212 {
1223#if DEBUG_EXT_FS_WATCHER1213#if DEBUG_EXT_FS_WATCHER
1224 qDebug() << "[extFsWatcher]" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz")1214 qDebug() << "[extFsWatcher]" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz")
1225 << Q_FUNC_INFO << this << "File System modified" << pathModifiedOutside;1215 << Q_FUNC_INFO << this << "File System modified in" << pathModifiedOutside;
1226#else
1227 Q_UNUSED(pathModifiedOutside);
1228#endif1216#endif
1229 DirListWorker *w =1217 mCurLocation->fetchExternalChanges(pathModifiedOutside,
1230 createWorkerRequest(IORequest::DirListExternalFSChanges,1218 mDirectoryContents,
1231 mCurrentDir1219 currentDirFilter());
1232 );
1233 ExternalFileSystemChangesWorker *extFsWorker =
1234 static_cast<ExternalFileSystemChangesWorker*> (w);
1235
1236 connect(extFsWorker, SIGNAL(added(DirItemInfo)),
1237 this, SLOT(onItemAddedOutsideFm(DirItemInfo)));
1238 connect(extFsWorker, SIGNAL(removed(DirItemInfo)),
1239 this, SLOT(onItemRemovedOutSideFm(DirItemInfo)));
1240 connect(extFsWorker, SIGNAL(changed(DirItemInfo)),
1241 this, SLOT(onItemChangedOutSideFm(DirItemInfo)));
1242 connect(extFsWorker, SIGNAL(finished(int)),
1243 this, SLOT(onExternalFsWorkerFinished(int)));
1244
1245 ioWorkerThread()->addRequest(extFsWorker);
1246 }1220 }
1247#if DEBUG_EXT_FS_WATCHER1221#if DEBUG_EXT_FS_WATCHER
1248 else1222 else
@@ -1342,7 +1316,7 @@
1342 */1316 */
1343bool DirModel::getEnabledExternalFSWatcher() const1317bool DirModel::getEnabledExternalFSWatcher() const
1344{1318{
1345 return mExtFSWatcher ? true : false;1319 return mExtFSWatcher;
1346}1320}
13471321
13481322
@@ -1351,15 +1325,8 @@
1351 * \param enable1325 * \param enable
1352 */1326 */
1353void DirModel::setEnabledExternalFSWatcher(bool enable)1327void DirModel::setEnabledExternalFSWatcher(bool enable)
1354{1328{
1355 if(enable)1329 emit enabledExternalFSWatcherChanged(enable);
1356 {
1357 startExternalFsWatcher();
1358 }
1359 else
1360 {
1361 stoptExternalFsWatcher();
1362 }
1363}1330}
13641331
13651332
13661333
=== modified file 'src/plugin/folderlistmodel/dirmodel.h'
--- src/plugin/folderlistmodel/dirmodel.h 2014-05-15 23:31:22 +0000
+++ src/plugin/folderlistmodel/dirmodel.h 2014-05-15 23:31:23 +0000
@@ -42,17 +42,11 @@
42#include "diriteminfo.h"42#include "diriteminfo.h"
4343
44class FileSystemAction;44class FileSystemAction;
45class ExternalFSWatcher;
46class Clipboard;45class Clipboard;
47class DirSelection;46class DirSelection;
4847class LocationsFactory;
49/*!48class Location;
50 * When the External File System Wathcer is enabled,49class ExternalFSWatcher;
51 * this is the interval used to check if there has been any change in the current path
52 *
53 * \sa setEnabledExternalFSWatcher()
54 */
55#define EX_FS_WATCHER_TIMER_INTERVAL 900
5650
57class DirModel : public DirItemAbstractListModel51class DirModel : public DirItemAbstractListModel
58{52{
@@ -150,7 +144,7 @@
150144
151public slots:145public slots:
152 void onItemsAdded(const DirItemInfoList &newFiles);146 void onItemsAdded(const DirItemInfoList &newFiles);
153 void onResultsFetched();147 void onItemsFetched();
154148
155signals:149signals:
156 void awaitingResultsChanged();150 void awaitingResultsChanged();
@@ -206,7 +200,7 @@
206 Q_PROPERTY(int clipboardUrlsCounter READ getClipboardUrlsCounter NOTIFY clipboardChanged)200 Q_PROPERTY(int clipboardUrlsCounter READ getClipboardUrlsCounter NOTIFY clipboardChanged)
207 int getClipboardUrlsCounter() const;201 int getClipboardUrlsCounter() const;
208202
209 Q_PROPERTY(bool enableExternalFSWatcher READ getEnabledExternalFSWatcher WRITE setEnabledExternalFSWatcher)203 Q_PROPERTY(bool enableExternalFSWatcher READ getEnabledExternalFSWatcher WRITE setEnabledExternalFSWatcher NOTIFY enabledExternalFSWatcherChanged)
210 bool getEnabledExternalFSWatcher() const;204 bool getEnabledExternalFSWatcher() const;
211205
212 Q_INVOKABLE QString homePath() const;206 Q_INVOKABLE QString homePath() const;
@@ -360,8 +354,8 @@
360 void showHiddenFilesChanged();354 void showHiddenFilesChanged();
361 void sortByChanged();355 void sortByChanged();
362 void sortOrderChanged();356 void sortOrderChanged();
363
364 void clipboardChanged();357 void clipboardChanged();
358 void enabledExternalFSWatcherChanged(bool);
365359
366private slots:360private slots:
367 void onItemRemoved(const QString&);361 void onItemRemoved(const QString&);
@@ -377,12 +371,11 @@
377 QDir::Filter currentDirFilter() const;371 QDir::Filter currentDirFilter() const;
378 QString dirItems(const DirItemInfo& fi) const;372 QString dirItems(const DirItemInfo& fi) const;
379 bool cdInto(const DirItemInfo& fi);373 bool cdInto(const DirItemInfo& fi);
380 bool openItem(const DirItemInfo& fi);374 bool openItem(const DirItemInfo& fi);
381 DirListWorker * createWorkerRequest(IORequest::RequestType requestType,
382 const QString& pathName);
383 bool canReadDir(const QFileInfo& d) const;375 bool canReadDir(const QFileInfo& d) const;
384 bool canReadFile(const QFileInfo& f) const;376 bool canReadFile(const QFileInfo& f) const;
385 QFileInfo setParentIfRelative(const QString &fileOrDir) const;377 QFileInfo setParentIfRelative(const QString &fileOrDir) const;
378 void setPathFromCurrentLocation();
386379
387private:380private:
388 void startExternalFsWatcher();381 void startExternalFsWatcher();
@@ -401,9 +394,11 @@
401 SortBy mSortBy;394 SortBy mSortBy;
402 SortOrder mSortOrder;395 SortOrder mSortOrder;
403 CompareFunction mCompareFunction;396 CompareFunction mCompareFunction;
404 ExternalFSWatcher* mExtFSWatcher;397 bool mExtFSWatcher;
405 Clipboard * mClipboard;398 Clipboard * mClipboard;
406 DirSelection * mSelection;399 DirSelection * mSelection;
400 LocationsFactory * mLocationFactory;
401 Location * mCurLocation;
407402
408403
409private:404private:
410405
=== added directory 'src/plugin/folderlistmodel/disk'
=== added file 'src/plugin/folderlistmodel/disk/disklocation.cpp'
--- src/plugin/folderlistmodel/disk/disklocation.cpp 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/disk/disklocation.cpp 2014-05-15 23:31:23 +0000
@@ -0,0 +1,222 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: disklocation.cpp
19 * Date: 08/03/2014
20 */
21
22#include "disklocation.h"
23#include "iorequest.h"
24#include "ioworkerthread.h"
25#include "externalfswatcher.h"
26
27#include <QDebug>
28
29#if defined(DEBUG_EXT_FS_WATCHER)
30# define DEBUG_WATCHER() qDebug() << "[extFsWatcher]" << QDateTime::currentDateTime().toString("hh:mm:ss.zzz") \
31 << Q_FUNC_INFO << this
32#else
33# define DEBUG_WATCHER() /**/
34#endif
35
36DiskLocation::DiskLocation(int type, QObject *parent)
37 : Location(type, parent)
38 , m_extWatcher(0)
39{
40}
41
42
43DiskLocation::~ DiskLocation()
44{
45 stopExternalFsWatcher();
46}
47
48
49void DiskLocation::fetchItems(QDir::Filter dirFilter, bool recursive)
50{
51 DirListWorker *dlw = new DirListWorker(m_info->absoluteFilePath(), dirFilter, recursive);
52 connect(dlw, SIGNAL(itemsAdded(DirItemInfoList)),
53 this, SIGNAL(itemsAdded(DirItemInfoList)));
54 connect(dlw, SIGNAL(workerFinished()),
55 this, SLOT(onItemsFetched()));
56 workerThread()->addRequest(dlw);
57}
58
59
60bool DiskLocation::becomeParent()
61{
62 bool ret = false;
63 if (m_info && !m_info->isRoot())
64 {
65 DirItemInfo *other = new DirItemInfo(m_info->absolutePath());
66 if (other->isValid())
67 {
68 delete m_info;
69 m_info = other;
70 ret = true;
71 }
72 else
73 {
74 delete other;
75 }
76 }
77 return ret;
78}
79
80
81void DiskLocation::refreshInfo()
82{
83 if (m_info)
84 {
85 DirItemInfo *item = new DirItemInfo(m_info->absoluteFilePath());
86 delete m_info;
87 m_info = item;
88 }
89}
90
91
92/*!
93 * \brief DiskLocation::stopExternalFsWatcher() stops the External File System Watcher
94 */
95void DiskLocation::stopExternalFsWatcher()
96{
97 if (m_extWatcher)
98 {
99 DEBUG_WATCHER();
100 delete m_extWatcher;
101 m_extWatcher = 0;
102 }
103}
104
105
106/*!
107 * \brief DiskLocation::startExternalFsWatcher() starts the External File System Watcher
108 */
109void DiskLocation::startExternalFsWatcher()
110{
111 if (m_extWatcher == 0)
112 {
113 DEBUG_WATCHER();
114 m_extWatcher = new ExternalFSWatcher(this);
115 m_extWatcher->setIntervalToNotifyChanges(EX_FS_WATCHER_TIMER_INTERVAL);
116
117 connect(m_extWatcher, SIGNAL(pathModified(QString)),
118 this, SIGNAL(extWatcherPathChanged(QString)));
119 if (m_info)
120 { //setCurrentPath() checks for empty paths
121 m_extWatcher->setCurrentPath(m_info->absoluteFilePath());
122 }
123 }
124}
125
126
127void DiskLocation::onItemsFetched()
128{
129 if (m_extWatcher)
130 {
131 m_extWatcher->setCurrentPath(m_info->absoluteFilePath());
132 }
133 emit itemsFetched();
134}
135
136
137void DiskLocation::startWorking()
138{
139 if (m_usingExternalWatcher)
140 {
141 startExternalFsWatcher();
142 }
143}
144
145
146void DiskLocation::stopWorking()
147{
148 stopExternalFsWatcher();
149}
150
151
152void DiskLocation::fetchExternalChanges(const QString &path,
153 const DirItemInfoList &list,
154 QDir::Filter dirFilter)
155{
156 ExternalFileSystemChangesWorker *extFsWorker =
157 new ExternalFileSystemChangesWorker(list,
158 path,
159 dirFilter, false);
160 addExternalFsWorkerRequest(extFsWorker);
161
162
163}
164
165void DiskLocation::addExternalFsWorkerRequest(ExternalFileSystemChangesWorker *extFsWorker)
166{
167 connect(extFsWorker, SIGNAL(added(DirItemInfo)),
168 this, SIGNAL(extWatcherItemAdded(DirItemInfo)));
169
170 connect(extFsWorker, SIGNAL(removed(DirItemInfo)),
171 this, SIGNAL(extWatcherItemRemoved(DirItemInfo)));
172
173 connect(extFsWorker, SIGNAL(changed(DirItemInfo)),
174 this, SIGNAL(extWatcherItemChanged(DirItemInfo)));
175
176 connect(extFsWorker, SIGNAL(finished(int)),
177 this, SIGNAL(extWatcherChangesFetched(int)));
178
179 workerThread()->addRequest(extFsWorker);
180}
181
182
183ExternalFSWatcher * DiskLocation::getExternalFSWatcher() const
184{
185 return m_extWatcher;
186}
187
188
189void DiskLocation::setUsingExternalWatcher(bool use)
190{
191 Location::setUsingExternalWatcher(use);
192 if (m_usingExternalWatcher)
193 {
194 startExternalFsWatcher();
195 }
196 else
197 {
198 stopExternalFsWatcher();
199 }
200}
201
202
203DirItemInfo * DiskLocation::validateUrlPath(const QString& uPath)
204{
205 QString myPath(uPath);
206 QFileInfo tmpUrl(uPath);
207 if (tmpUrl.isRelative() && m_info)
208 {
209 tmpUrl.setFile(m_info->absoluteFilePath(), uPath);
210 myPath = tmpUrl.absoluteFilePath();
211 }
212#if DEBUG_MESSAGES
213 qDebug() << Q_FUNC_INFO << "path:" << myPath;
214#endif
215 DirItemInfo * item = new DirItemInfo(myPath);
216 if (!item->isValid() || !item->exists() || !item->isContentReadable())
217 {
218 delete item;
219 item = 0;
220 }
221 return item;
222}
0223
=== added file 'src/plugin/folderlistmodel/disk/disklocation.h'
--- src/plugin/folderlistmodel/disk/disklocation.h 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/disk/disklocation.h 2014-05-15 23:31:23 +0000
@@ -0,0 +1,81 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: disklocation.h
19 * Date: 08/03/2014
20 */
21
22#ifndef DISKLOCATION_H
23#define DISKLOCATION_H
24
25#include "location.h"
26#include <QList>
27
28/*!
29 * When the External File System Wathcer is enabled,
30 * this is the interval used to check if there has been any change in the current path
31 *
32 * \sa setEnabledExternalFSWatcher()
33 */
34#define EX_FS_WATCHER_TIMER_INTERVAL 900
35
36
37class ExternalFSWatcher;
38class ExternalFileSystemChangesWorker;
39
40/*!
41 * \brief The DiskLocation class extends \ref Location for Local Disk and provides a External File System watcher
42 */
43class DiskLocation : public Location
44{
45 Q_OBJECT
46public:
47 explicit DiskLocation(int type, QObject *parent=0);
48 virtual ~DiskLocation();
49
50 ExternalFSWatcher * getExternalFSWatcher() const;
51
52 virtual void fetchItems(QDir::Filter dirFilter, bool recursive = false) ;
53 virtual void fetchExternalChanges(const QString& urlPath,
54 const DirItemInfoList& list,
55 QDir::Filter dirFilter) ;
56 virtual bool becomeParent();
57 virtual void refreshInfo();
58
59 virtual void startExternalFsWatcher();
60 virtual void stopExternalFsWatcher();
61
62 virtual void startWorking();
63 virtual void stopWorking();
64
65 virtual DirItemInfo *validateUrlPath(const QString& urlPath);
66
67protected:
68 void addExternalFsWorkerRequest(ExternalFileSystemChangesWorker *);
69
70public slots:
71 virtual void setUsingExternalWatcher(bool use);
72
73protected slots:
74 void onItemsFetched();
75
76protected:
77 ExternalFSWatcher * m_extWatcher ;
78
79};
80
81#endif // DISKLOCATION_H
082
=== modified file 'src/plugin/folderlistmodel/filecompare.cpp'
--- src/plugin/folderlistmodel/filecompare.cpp 2014-02-05 15:31:44 +0000
+++ src/plugin/folderlistmodel/filecompare.cpp 2014-05-15 23:31:23 +0000
@@ -50,11 +50,10 @@
50 if (b.isDir() && !a.isDir())50 if (b.isDir() && !a.isDir())
51 return false;51 return false;
5252
53 bool ret = QString::localeAwareCompare(a.fileName(), b.fileName()) < 0;53 bool ret = QString::localeAwareCompare(a.absoluteFilePath(), b.absoluteFilePath()) < 0;
54#if DEBUG_MESSAGES54#if DEBUG_MESSAGES
55 qDebug() << Q_FUNC_INFO << ret << a.fileName() << b.fileName();55 qDebug() << Q_FUNC_INFO << ret << a.absoluteFilePath() << b.absoluteFilePath();
56#endif56#endif
57
58 return ret;57 return ret;
59}58}
6059
6160
=== modified file 'src/plugin/folderlistmodel/folderlistmodel.pri'
--- src/plugin/folderlistmodel/folderlistmodel.pri 2014-02-10 23:41:50 +0000
+++ src/plugin/folderlistmodel/folderlistmodel.pri 2014-05-15 23:31:23 +0000
@@ -9,7 +9,12 @@
9 $$PWD/fmutil.cpp \9 $$PWD/fmutil.cpp \
10 $$PWD/dirselection.cpp \10 $$PWD/dirselection.cpp \
11 $$PWD/diriteminfo.cpp \11 $$PWD/diriteminfo.cpp \
12 $$PWD/trash/qtrashdir.cpp12 $$PWD/trash/qtrashdir.cpp \
13 $$PWD/location.cpp \
14 $$PWD/locationsfactory.cpp \
15 $$PWD/disk/disklocation.cpp \
16 $$PWD/locationurl.cpp \
17
1318
1419
15HEADERS += $$PWD/dirmodel.h \20HEADERS += $$PWD/dirmodel.h \
@@ -24,10 +29,14 @@
24 $$PWD/dirselection.h \ 29 $$PWD/dirselection.h \
25 $$PWD/diritemabstractlistmodel.h \30 $$PWD/diritemabstractlistmodel.h \
26 $$PWD/diriteminfo.h \31 $$PWD/diriteminfo.h \
27 $$PWD/trash/qtrashdir.h32 $$PWD/trash/qtrashdir.h \
2833 $$PWD/location.h \
2934 $$PWD/locationsfactory.h \
30INCLUDEPATH += $$PWD $$PWD/trash35 $$PWD/disk/disklocation.h \
36 $$PWD/locationurl.h \
37
38
39INCLUDEPATH += $$PWD $$PWD/trash $$PWD/disk
3140
32greaterThan(QT_MAJOR_VERSION, 4) {41greaterThan(QT_MAJOR_VERSION, 4) {
33 QT += qml42 QT += qml
3443
=== added file 'src/plugin/folderlistmodel/location.cpp'
--- src/plugin/folderlistmodel/location.cpp 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/location.cpp 2014-05-15 23:31:23 +0000
@@ -0,0 +1,140 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: location.cpp
19 * Date: 08/03/2014
20 */
21/**************************************************************************
22 *
23 * Copyright 2014 Canonical Ltd.
24 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
25 *
26 * This program is free software; you can redistribute it and/or modify
27 * it under the terms of the GNU Lesser General Public License as published by
28 * the Free Software Foundation; version 3.
29 *
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 * GNU Lesser General Public License for more details.
34 *
35 * You should have received a copy of the GNU Lesser General Public License
36 * along with this program. If not, see <http://www.gnu.org/licenses/>.
37 *
38 * File: locations.cpp
39 * Date: 04/03/2014
40 */
41
42#include "location.h"
43#include "ioworkerthread.h"
44
45Q_GLOBAL_STATIC(IOWorkerThread, ioWorkerThread)
46
47
48Location::Location(int type, QObject *parent)
49 : QObject(parent)
50 , m_info(0)
51 , m_type(type)
52 , m_usingExternalWatcher(false)
53{
54
55}
56
57Location::~Location()
58{
59 if (m_info)
60 {
61 delete m_info;
62 m_info = 0;
63 }
64}
65
66
67bool Location::isRoot() const
68{
69 return m_info ? m_info->isRoot() : false;
70}
71
72
73bool Location::isWritable() const
74{
75 return m_info->isWritable();
76}
77
78
79bool Location::isReadable() const
80{
81 return m_info ? m_info->isContentReadable() : false;
82}
83
84void Location::setInfoItem(const DirItemInfo &itemInfo)
85{
86 setInfoItem (new DirItemInfo(itemInfo));
87}
88
89void Location::setInfoItem(DirItemInfo *itemInfo)
90{
91 if (m_info)
92 {
93 delete m_info;
94 }
95 m_info = itemInfo;
96}
97
98
99QString Location::urlPath() const
100{
101 return m_info ? m_info->urlPath(): QString();
102}
103
104
105void Location::startWorking()
106{
107
108}
109
110void Location::stopWorking()
111{
112
113}
114
115bool Location::becomeParent()
116{
117 return false;
118}
119
120IOWorkerThread * Location::workerThread() const
121{
122 return ioWorkerThread();
123}
124
125
126//providing an empty method
127void Location::fetchExternalChanges(const QString &path,
128 const DirItemInfoList &list,
129 QDir::Filter dirFilter)
130{
131 Q_UNUSED(path);
132 Q_UNUSED(list);
133 Q_UNUSED(dirFilter);
134}
135
136
137void Location::setUsingExternalWatcher(bool use)
138{
139 m_usingExternalWatcher = use;
140}
0141
=== added file 'src/plugin/folderlistmodel/location.h'
--- src/plugin/folderlistmodel/location.h 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/location.h 2014-05-15 23:31:23 +0000
@@ -0,0 +1,132 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: location.h
19 * Date: 08/03/2014
20 */
21
22#ifndef LOCATION_H
23#define LOCATION_H
24
25#include "diriteminfo.h"
26
27#include <QObject>
28
29class IOWorkerThread;
30
31/*!
32 * \brief The Location class represents any location (full path) where there are items to browse: directories, shares, from Disk and from Network.
33 *
34 * It is an abstract class the must be inherited for specific Location handling as example: \ref DiskLocation and \ref TrashLocation
35 *
36 * The location must be able to:
37 * \li provide the browsing for the location in \ref fetchItems()
38 * \li become itself its parent in \ref becomeParent() it will allow easy \ref DirModel::cdUp()
39 * \li refresh its information in \ref refreshInfo()
40 * \li validate its location (creates a valid DirItemInfo object or any descendent) from a url string
41 *
42 * The \ref startWorking() is called by \ref LocationsFactory just before this location becomes the current in the File Manager
43 * In the same way the \ref stopWorking() is called by \ref LocationsFactory just before this location no longer be the current in the File Manager
44 */
45class Location : public QObject
46{
47 Q_OBJECT
48public:
49 explicit Location( int type, QObject *parent=0);
50 virtual ~Location();
51
52 IOWorkerThread * workerThread() const;
53
54signals:
55 void itemsAdded(const DirItemInfoList &files);
56 void itemsFetched();
57 void extWatcherPathChanged(const QString&);
58 void extWatcherItemRemoved(const DirItemInfo&);
59 void extWatcherItemChanged(const DirItemInfo&);
60 void extWatcherItemAdded(const DirItemInfo&);
61 void extWatcherChangesFetched(int);
62
63public slots:
64 virtual void setUsingExternalWatcher(bool use);
65
66public: //pure functions
67 /*!
68 * \brief fetchItems() gets the content of the Location
69 *
70 * \param dirFilter current Filter
71 * \param recursive should get the content all sub dirs or not, (hardly ever it is true)
72 */
73 virtual void fetchItems(QDir::Filter dirFilter, bool recursive=0) = 0;
74
75 /*!
76 * \brief refreshInfo() It must refresh the DirItemInfo
77 *
78 * It can be used for example after receiving the signal about external disk file system changes
79 * due to the current path permissions might have changed.
80 */
81 virtual void refreshInfo() = 0;
82
83 /*!
84 * \brief becomeParent() The current path location becomes the parent Location
85 *
86 * When \ref isRoot() returns false the current path location becomes the parent path location
87 * in order to make it the current.
88 * It acts like a cdUp, but without fetching items; then calling \ref fetchItems() may get contents.
89 *
90 * \note It must take care of deleting \ref m_info when creating a new DirItemInfo/TrashItemInfo etc.
91 *
92 * \return true if it is possible to do like a cdUp.
93 */
94 virtual bool becomeParent() = 0;
95
96 /*!
97 * \brief validateUrlPath() Validates the urlPath (file or Directory) and creates a new Obeject from this path
98 *
99 * If urlPath is a valid Directory it can be used later to set a new Location.
100 *
101 * \param urlPath
102 * \return a valid pointer to DirItemInfo object or NULL indicating something wrong with the path
103 */
104 virtual DirItemInfo * validateUrlPath(const QString& urlPath) = 0;
105
106public:
107 virtual void fetchExternalChanges(const QString& urlPath,
108 const DirItemInfoList& list,
109 QDir::Filter dirFilter) ;
110 virtual void setInfoItem(const DirItemInfo &itemInfo);
111 virtual void setInfoItem(DirItemInfo *itemInfo);
112 virtual bool isRoot() const;
113 virtual bool isWritable() const;
114 virtual bool isReadable() const;
115 virtual QString urlPath() const;
116 virtual void startWorking();
117 virtual void stopWorking();
118
119 inline const DirItemInfo* info() const { return m_info; }
120 inline int type() const { return m_type; }
121
122protected:
123 DirItemInfo * m_info;
124 int m_type;
125 bool m_usingExternalWatcher;
126
127#if defined(REGRESSION_TEST_FOLDERLISTMODEL)
128 friend class TestDirModel;
129#endif
130
131};
132#endif // LOCATION_H
0133
=== added file 'src/plugin/folderlistmodel/locationsfactory.cpp'
--- src/plugin/folderlistmodel/locationsfactory.cpp 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/locationsfactory.cpp 2014-05-15 23:31:23 +0000
@@ -0,0 +1,181 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: locationsfactory.cpp
19 * Date: 05/03/2014
20 */
21
22#include "diriteminfo.h"
23#include "locationsfactory.h"
24#include "location.h"
25#include "locationurl.h"
26#include "disklocation.h"
27
28
29#include <QDir>
30#include <QDebug>
31
32
33
34LocationsFactory::LocationsFactory(QObject *parent)
35 : QObject(parent)
36 , m_curLoc(0)
37 , m_lastValidFileInfo(0)
38{
39 m_locations.append(new DiskLocation(LocalDisk));
40}
41
42
43LocationsFactory::~LocationsFactory()
44{
45 ::qDeleteAll(m_locations);
46 m_locations.clear();
47}
48
49
50/*!
51 * \brief LocationsFactory::parse() identifies what main location that path/url refers to
52 * \param path it is supposed to be always a full path like: file:///myDir /myDir trash:/// trash:///myDir
53 * \return
54 */
55
56Location * LocationsFactory::parse(const QString& uPath)
57{
58 int index = -1;
59 int type = -1;
60 Location * location = 0;
61 if ( (index = uPath.indexOf(QChar(':'))) != -1 )
62 {
63#if defined(Q_OS_WIN)
64#else
65#if defined(Q_OS_UNIX)
66 if (uPath.startsWith(LocationUrl::TrashRootURL.midRef(0,6)))
67 {
68 type = TrashDisk;
69 m_tmpPath = LocationUrl::TrashRootURL + stringAfterSlashes(uPath, index+1);
70 }
71 else
72#endif //Q_OS_UNIX
73#endif //Q_OS_UNIX
74 if (uPath.startsWith(LocationUrl::DiskRootURL.midRef(0,5)))
75 {
76 type = LocalDisk;
77 m_tmpPath = QDir::rootPath() + stringAfterSlashes(uPath, index+1);
78 }
79 }
80 else
81 {
82 m_tmpPath = stringAfterSlashes(uPath, -1);
83 type = LocalDisk;
84 if (!m_tmpPath.startsWith(QDir::rootPath()) && m_curLoc)
85 {
86 //it can be any, check current location
87 type = m_curLoc->type();
88 }
89 }
90 if (!m_tmpPath.isEmpty() && type != -1)
91 {
92 location = m_locations.at(type);
93 }
94#if DEBUG_MESSAGES
95 qDebug() << Q_FUNC_INFO << "input path:" << uPath << "location result:" << location;
96#endif
97 return location;
98}
99
100
101Location * LocationsFactory::setNewPath(const QString& uPath)
102{
103 storeValidFileInfo(0);
104 Location *location = parse(uPath);
105 if (location)
106 {
107 DirItemInfo *item = location->validateUrlPath(m_tmpPath);
108 if (item)
109 {
110 //isContentReadable() must already carry execution permission
111 if (item->isValid() && item->isDir() && item->isContentReadable())
112 {
113 location->setInfoItem(item);
114 if (location != m_curLoc)
115 {
116 if (m_curLoc)
117 {
118 m_curLoc->stopWorking();
119 }
120 emit locationChanged(m_curLoc, location);
121 location->startWorking();
122 m_curLoc = location;
123 }
124 }
125 else
126 {
127 storeValidFileInfo(item);
128 }
129 }
130 else
131 { // not valid
132 location = 0;
133 }
134 }
135#if DEBUG_MESSAGES
136 qDebug() << Q_FUNC_INFO << "input path:" << uPath << "location result:" << location;
137#endif
138 return location;
139}
140
141
142QString LocationsFactory::stringAfterSlashes(const QString &url, int firstSlashIndex) const
143{
144 QString ret;
145 if (firstSlashIndex >=0)
146 {
147 while ( firstSlashIndex < url.length() && url.at(firstSlashIndex) == QDir::separator())
148 {
149 ++firstSlashIndex;
150 }
151 if (firstSlashIndex < url.length())
152 {
153 ret = url.mid(firstSlashIndex);
154 }
155 }
156 else
157 {
158 ret = url;
159 firstSlashIndex = 0;
160 }
161 //replace any double slashes by just one
162 for(int charCounter = ret.size() -1; charCounter > 0; --charCounter)
163 {
164 if (ret.at(charCounter) == QDir::separator() &&
165 ret.at(charCounter-1) == QDir::separator())
166 {
167 ret.remove(charCounter,1);
168 }
169 }
170 return ret;
171}
172
173
174void LocationsFactory::storeValidFileInfo(const DirItemInfo *item)
175{
176 if (m_lastValidFileInfo)
177 {
178 delete m_lastValidFileInfo;
179 }
180 m_lastValidFileInfo = item;
181}
0182
=== added file 'src/plugin/folderlistmodel/locationsfactory.h'
--- src/plugin/folderlistmodel/locationsfactory.h 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/locationsfactory.h 2014-05-15 23:31:23 +0000
@@ -0,0 +1,136 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: locationsfactory.h
19 * Date: 05/03/2014
20 */
21
22#ifndef LOCATIONSFACTORY_H
23#define LOCATIONSFACTORY_H
24
25#include <QObject>
26#include <QList>
27
28
29class Location;
30class DirItemInfo;
31
32/*!
33 * \brief The LocationsFactory class represents the set of main
34 * URL locations the File Manager supports.
35 *
36 * It is basically devided into main groups:
37 * \li Disk: \ref LocalDisk and \ref TrashDisk
38 * \li Net: \ref NetSambaShare and NetFishShare
39 *
40 * smb:// browses workgroup
41 *
42 * Location parser: \ref parser()
43 * \li \\workkgroup becomes smb://workgroup
44 * \li \\ becomes smb://
45 * \li trash:/ and trash:// becomes trash:///
46 * \li fish:/ and fish:// becomes fish:///
47 * \li file:/ , file:// and file:/// becomes /
48 *
49 * \note Due to current File Manager UI typing method both: "file:" and "trash:" are supported
50 */
51class LocationsFactory : public QObject
52{
53 Q_OBJECT
54public:
55 explicit LocationsFactory(QObject *parent = 0);
56 ~LocationsFactory();
57
58 Q_ENUMS(Locations)
59 enum Locations
60 {
61 LocalDisk, //<! any mounted file system
62 TrashDisk //<! special trash location in the disk
63#if 0
64 NetSambaShare //<! SAMBA or CIFS shares
65 NetFishShare //<! FISH protocol over ssh that provides file sharing
66#endif
67 };
68
69 inline const Location * getLocation(Locations index) const {return m_locations.at(index);}
70
71
72 /*!
73 * \brief parse() Just parses (does not set/change the current location) according to \a urlPath
74 * \param urlPath urlPath the url like: file:///Item trash:///item /item, it MUST point to a valid Directory
75 * \return The location which supports the \a urlPath
76 */
77 Location * parse(const QString& urlPath);
78
79 /*!
80 * \brief setNewPath() Sets a new path, it can be in the current location or on another location
81 *
82 * When the location changes, the signal \ref locationChanged() is fired.
83 *
84 * \param urlPath the url like: file:///Item trash:///item /item, it MUST point to a valid Directory
85 * \return the location that supports the urlPath or NULL when \a urlPath is NOT a valid url or it is not a valid Directory
86 *
87 * \sa \ref parse() \ref location()
88 */
89 Location * setNewPath(const QString& urlPath);
90
91 /*!
92 * \brief location()
93 * \return The current location
94 */
95 Location * location() const { return m_curLoc; }
96
97 /*!
98 * \brief availableLocations()
99 * \return
100 */
101 const QList<Location*>&
102 availableLocations() const { return m_locations; }
103
104 /*!
105 * \brief lastValidFileInfo()
106 *
107 * When calling setNewPath(file_path) using a path to a File instead of a Directory
108 * the setNewPath() is not able to set a new path (current location or other), however it uses
109 * Location::validateUrlPath() which validates the path for files also, then this valid DirItemInfo object
110 * is saved using \ref storeValidFileInfo() for further use.
111 *
112 * \return The last valid DirItemInfo parsed which is not a Directory
113 */
114 const DirItemInfo* lastValidFileInfo() const { return m_lastValidFileInfo; }
115
116 void storeValidFileInfo(const DirItemInfo *item);
117
118signals:
119 void locationChanged(const Location *old, const Location *current);
120
121private:
122 QString stringAfterSlashes(const QString& url, int firstSlashIndex) const;
123
124private:
125 Location * m_curLoc;
126 QList<Location*> m_locations;
127 QString m_tmpPath;
128 const DirItemInfo * m_lastValidFileInfo;
129
130#if defined(REGRESSION_TEST_FOLDERLISTMODEL)
131 friend class TestDirModel;
132#endif
133
134};
135
136#endif // LOCATIONSFACTORY_H
0137
=== added file 'src/plugin/folderlistmodel/locationurl.cpp'
--- src/plugin/folderlistmodel/locationurl.cpp 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/locationurl.cpp 2014-05-15 23:31:23 +0000
@@ -0,0 +1,34 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: locationurl.cpp
19 * Date: 11/03/2014
20 */
21
22#include "locationurl.h"
23
24const QString LocationUrl::TrashRootURL("trash:///");
25const QString LocationUrl::DiskRootURL("file:///");
26#if 0
27QString LocationURL::SmbURL("smb://");
28QString LocationURL::FishURL("fish:///");
29#endif
30
31
32LocationUrl::LocationUrl()
33{
34}
035
=== added file 'src/plugin/folderlistmodel/locationurl.h'
--- src/plugin/folderlistmodel/locationurl.h 1970-01-01 00:00:00 +0000
+++ src/plugin/folderlistmodel/locationurl.h 2014-05-15 23:31:23 +0000
@@ -0,0 +1,40 @@
1/**************************************************************************
2 *
3 * Copyright 2014 Canonical Ltd.
4 * Copyright 2014 Carlos J Mazieri <carlos.mazieri@gmail.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; version 3.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * File: locationurl.h
19 * Date: 11/03/2014
20 */
21
22#ifndef LOCATIONURL_H
23#define LOCATIONURL_H
24
25#include <QString>
26
27class LocationUrl
28{
29public:
30 static const QString DiskRootURL;
31 static const QString TrashRootURL;
32#if 0
33 static const QString SmbURL;
34 static const QString FishURL;
35#endif
36private:
37 LocationUrl();
38};
39
40#endif // LOCATIONURL_H
041
=== modified file 'src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp'
--- src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp 2014-05-15 23:31:22 +0000
+++ src/plugin/test_folderlistmodel/regression/tst_folderlistmodel.cpp 2014-05-15 23:31:23 +0000
@@ -3,7 +3,11 @@
3#include "tempfiles.h"3#include "tempfiles.h"
4#include "externalfswatcher.h"4#include "externalfswatcher.h"
5#include "dirselection.h"5#include "dirselection.h"
6#include "trash/qtrashdir.h"6#include "qtrashdir.h"
7#include "location.h"
8#include "locationurl.h"
9#include "locationsfactory.h"
10#include "disklocation.h"
711
8#if defined(Q_OS_UNIX)12#if defined(Q_OS_UNIX)
9#include <stdio.h>13#include <stdio.h>
@@ -143,6 +147,8 @@
143 void modelSelectionItemsRange();147 void modelSelectionItemsRange();
144148
145 void trashDiretories();149 void trashDiretories();
150 void locationFactory();
151
146152
147private:153private:
148 void initDeepDirs();154 void initDeepDirs();
@@ -2389,6 +2395,45 @@
2389}2395}
23902396
23912397
2398void TestDirModel::locationFactory()
2399{
2400 LocationsFactory factoryLocations(this);
2401 const Location *location = 0;
2402
2403 //Due to current File Manager UI typing method both: "file:" and "trash:" are supported
2404 // location = factoryLocations.setNewPath("trash:");
2405 // QVERIFY(location == 0);
2406
2407 location = factoryLocations.setNewPath("file://////");
2408 QVERIFY(location);
2409 QVERIFY(location->type() == LocationsFactory::LocalDisk);
2410 QCOMPARE(location->info()->absoluteFilePath(), QDir::rootPath());
2411 QCOMPARE(location->urlPath(), QDir::rootPath());
2412 QCOMPARE(location->isRoot(), true);
2413
2414 location = factoryLocations.setNewPath("/");
2415 QVERIFY(location);
2416 QVERIFY(location->type() == LocationsFactory::LocalDisk);
2417 QCOMPARE(location->info()->absoluteFilePath(), QDir::rootPath());
2418 QCOMPARE(location->urlPath(), QDir::rootPath());
2419 QCOMPARE(location->isRoot(), true);
2420
2421 location = factoryLocations.setNewPath("//");
2422 QVERIFY(location);
2423 QVERIFY(location->type() == LocationsFactory::LocalDisk);
2424 QCOMPARE(location->info()->absoluteFilePath(), QDir::rootPath());
2425 QCOMPARE(location->urlPath(), QDir::rootPath());
2426 QCOMPARE(location->isRoot(), true);
2427
2428 location = factoryLocations.setNewPath("//bin");
2429 QVERIFY(location);
2430 QVERIFY(location->type() == LocationsFactory::LocalDisk);
2431 QCOMPARE(location->info()->absoluteFilePath(), QLatin1String("/bin"));
2432 QCOMPARE(location->urlPath(), QLatin1String("/bin"));
2433 QCOMPARE(location->isRoot(), false);
2434}
2435
2436
2392int main(int argc, char *argv[])2437int main(int argc, char *argv[])
2393{2438{
2394 QApplication app(argc, argv);2439 QApplication app(argc, argv);

Subscribers

People subscribed via source and target branches