diff --git a/krusader/Panel/listpanel.h b/krusader/Panel/listpanel.h --- a/krusader/Panel/listpanel.h +++ b/krusader/Panel/listpanel.h @@ -192,6 +192,8 @@ _manager->newTab(url, nextToThis ? this : 0); } void resetNavigatorMode(); // set navigator mode after focus was lost + // update filesystem meta info, disk-free and mount status + void updateFilesystemStats(const QString &metaInfo, KIO::filesize_t total, KIO::filesize_t free); signals: void signalStatus(QString msg); // emmited when we need to update the status bar @@ -237,7 +239,6 @@ KrErrorDisplay *vfsError; private: - void updateFilesystemStats(const QUrl &url); // update disk-free and mount status bool handleDropInternal(QDropEvent *event, const QString &dir); int popupPosition() const; // 0: West, 1: North, 2: East, 3: South void setPopupPosition(int); diff --git a/krusader/Panel/listpanel.cpp b/krusader/Panel/listpanel.cpp --- a/krusader/Panel/listpanel.cpp +++ b/krusader/Panel/listpanel.cpp @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -752,8 +751,6 @@ searchBar->hideBar(); } - updateFilesystemStats(currentUrl); - if (compareMode) otherPanel()->view->refresh(); @@ -763,73 +760,34 @@ slotUpdateTotals(); } -void ListPanel::updateFilesystemStats(const QUrl &url) +void ListPanel::updateFilesystemStats(const QString &metaInfo, + KIO::filesize_t total, KIO::filesize_t free) { - mediaButton->mountPointChanged(QString()); - freeSpace->setText(QString()); - - if (!KConfigGroup(krConfig, "Look&Feel").readEntry("ShowSpaceInformation", true)) { - status->setText(func->files()->metaInformation().isEmpty() - ? i18n("Space information disabled") - : func->files()->metaInformation()); - return; - } - - if (!url.isLocalFile()) { - status->setText(func->files()->metaInformation().isEmpty() - ? i18n("No space information on non-local filesystems") - : func->files()->metaInformation()); - return; - } - - // check for special filesystems; - QString path = url.path(); // must be local url - if (path.left(4) == "/dev") { - status->setText(i18n("No space information on [dev]")); - return; - } -#ifdef BSD - if (path.left(5) == "/procfs") { // /procfs is a special case - no volume information - status->setText(i18n("No space information on [procfs]")); - return; - } -#else - if (path.left(5) == "/proc") { // /proc is a special case - no volume information - status->setText(i18n("No space information on [proc]")); - return; - } -#endif + QString statusText, mountPointText, freeSpaceText; - KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(path); - if(!info.isValid()) { - status->setText(i18n("Space information unavailable")); - return; - } - int perc = 0; - if (info.size() != 0) { // make sure that if totalsize==0, then perc=0 - perc = (int)(((float)info.available() / (float)info.size()) * 100.0); - } - // mount point information - find it in the list first - KMountPoint::List lst = KMountPoint::currentMountPoints(); - QString fstype = i18nc("Unknown file system type", "unknown"); - for (KMountPoint::List::iterator it = lst.begin(); it != lst.end(); ++it) { - if ((*it)->mountPoint() == info.mountPoint()) { - fstype = (*it)->mountType(); - break; - } + if (!metaInfo.isEmpty()) { + statusText = metaInfo; + mountPointText = freeSpaceText = ""; + } else { + const int perc = total == 0 ? 0 : (int)(((float)free / (float)total) * 100.0); + // get mount point + const QString path = func->files()->currentDirectory().path(); + const KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByPath(path); + mountPointText = mountPoint ? mountPoint->mountPoint() : ""; + const QString fstype = + mountPoint ? mountPoint->mountType() : i18nc("Unknown file system type", "unknown"); + + statusText = i18nc("%1=free space,%2=total space,%3=percentage of usage, " + "%4=mountpoint,%5=filesystem type", + "%1 free out of %2 (%3%) on %4 [(%5)]", KIO::convertSize(free), + KIO::convertSize(total), perc, mountPointText, fstype); + + freeSpaceText = " " + i18n("%1 free", KIO::convertSize(free)); } - QString stats = i18nc("%1=free space,%2=total space,%3=percentage of usage, " - "%4=mountpoint,%5=filesystem type", - "%1 free out of %2 (%3%) on %4 [(%5)]", - KIO::convertSize(info.available()), - KIO::convertSize(info.size()), perc, - info.mountPoint(), fstype); - - status->setText(stats); - - freeSpace->setText(" " + i18n("%1 free", KIO::convertSize(info.available()))); - mediaButton->mountPointChanged(info.mountPoint()); + status->setText(statusText); + freeSpace->setText(freeSpaceText); + mediaButton->mountPointChanged(mountPointText); } void ListPanel::handleDrop(QDropEvent *event, bool onView) diff --git a/krusader/Panel/panelfunc.cpp b/krusader/Panel/panelfunc.cpp --- a/krusader/Panel/panelfunc.cpp +++ b/krusader/Panel/panelfunc.cpp @@ -313,6 +313,7 @@ // (re)connect vfs signals disconnect(files(), 0, panel, 0); connect(files(), SIGNAL(refreshDone(bool)), panel, SLOT(slotStartUpdate(bool))); + connect(files(), &vfs::filesystemInfoChanged, panel, &ListPanel::updateFilesystemStats); connect(files(), SIGNAL(refreshJobStarted(KIO::Job*)), panel, SLOT(slotJobStarted(KIO::Job*))); connect(files(), SIGNAL(error(QString)), diff --git a/krusader/VFS/default_vfs.h b/krusader/VFS/default_vfs.h --- a/krusader/VFS/default_vfs.h +++ b/krusader/VFS/default_vfs.h @@ -55,25 +55,27 @@ Q_OBJECT public: default_vfs(); - ~default_vfs() {} - virtual void copyFiles(const QList &urls, const QUrl &destination, + void copyFiles(const QList &urls, const QUrl &destination, KIO::CopyJob::CopyMode mode = KIO::CopyJob::Copy, bool showProgressInfo = true, bool reverseQueueMode = false, bool startPaused = false) Q_DECL_OVERRIDE; - virtual void dropFiles(const QUrl &destination, QDropEvent *event) Q_DECL_OVERRIDE; + void dropFiles(const QUrl &destination, QDropEvent *event) Q_DECL_OVERRIDE; - virtual void addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, + void addFiles(const QList &fileUrls, KIO::CopyJob::CopyMode mode, QString dir = "") Q_DECL_OVERRIDE; - virtual void deleteFiles(const QStringList &fileNames, + void deleteFiles(const QStringList &fileNames, bool forceDeletion = false) Q_DECL_OVERRIDE; - virtual void mkDir(const QString &name) Q_DECL_OVERRIDE; - virtual void rename(const QString &fileName, const QString &newName) Q_DECL_OVERRIDE; + void mkDir(const QString &name) Q_DECL_OVERRIDE; + void rename(const QString &fileName, const QString &newName) Q_DECL_OVERRIDE; /// Return URL for file name - even if file does not exist. - virtual QUrl getUrl(const QString &name) Q_DECL_OVERRIDE; + QUrl getUrl(const QString &name) Q_DECL_OVERRIDE; + + QString mountPoint() { return _mountPoint; } + bool hasAutoUpdate() Q_DECL_OVERRIDE { return !_watcher.isNull(); } + void updateFilesystemInfo() Q_DECL_OVERRIDE; protected: - virtual bool refreshInternal(const QUrl &origin, bool showHidden) Q_DECL_OVERRIDE; - virtual bool ignoreRefresh() Q_DECL_OVERRIDE; + bool refreshInternal(const QUrl &origin, bool showHidden) Q_DECL_OVERRIDE; protected slots: /// Handle result after dir listing job is finished @@ -99,6 +101,7 @@ QPointer _watcher; // dir watcher used to detect changes in the current dir bool _listError; // for async operation, return list job result + QString _mountPoint; // the mount point of the current dir }; #endif diff --git a/krusader/VFS/default_vfs.cpp b/krusader/VFS/default_vfs.cpp --- a/krusader/VFS/default_vfs.cpp +++ b/krusader/VFS/default_vfs.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -150,7 +151,8 @@ void default_vfs::connectJob(KJob *job, const QUrl &destination) { // (additional) direct refresh if on local fs because watcher is too slow - connect(job, &KIO::Job::result, this, [=](KJob* job) { slotJobResult(job, isLocal()); }); + const bool refresh = cleanUrl(destination) == _currentDirectory && isLocal(); + connect(job, &KIO::Job::result, this, [=](KJob* job) { slotJobResult(job, refresh); }); connect(job, &KIO::Job::result, [=]() { emit filesystemChanged(destination); }); } @@ -166,6 +168,31 @@ return absoluteUrl; } +void default_vfs::updateFilesystemInfo() +{ + if (!KConfigGroup(krConfig, "Look&Feel").readEntry("ShowSpaceInformation", true)) { + _mountPoint = ""; + emit filesystemInfoChanged(i18n("Space information disabled"), 0, 0); + return; + } + + if (!_currentDirectory.isLocalFile()) { + _mountPoint = ""; + emit filesystemInfoChanged(i18n("No space information on non-local filesystems"), 0, 0); + return; + } + + const KDiskFreeSpaceInfo info = KDiskFreeSpaceInfo::freeSpaceInfo(_currentDirectory.path()); + if (!info.isValid()) { + _mountPoint = ""; + emit filesystemInfoChanged(i18n("Space information unavailable"), 0, 0); + return; + } + + _mountPoint = info.mountPoint(); + emit filesystemInfoChanged("", info.size(), info.available()); +} + // ==== protected ==== bool default_vfs::refreshInternal(const QUrl &directory, bool showHidden) @@ -208,11 +235,6 @@ return !_listError; } -bool default_vfs::ignoreRefresh() -{ - return !_watcher.isNull(); -} - // ==== protected slots ==== void default_vfs::slotListResult(KJob *job) diff --git a/krusader/VFS/krvfshandler.cpp b/krusader/VFS/krvfshandler.cpp --- a/krusader/VFS/krvfshandler.cpp +++ b/krusader/VFS/krvfshandler.cpp @@ -29,6 +29,8 @@ // QtCore #include +#include + #include "default_vfs.h" #include "virt_vfs.h" #include "../krservices.h" @@ -71,14 +73,25 @@ } } - // refresh all vfs currently showing this directory + QString mountPoint = ""; + if (directory.isLocalFile()) { + KMountPoint::Ptr kMountPoint = KMountPoint::currentMountPoints().findByPath(directory.path()); + if (kMountPoint) + mountPoint = kMountPoint->mountPoint(); + } + for(QPointer vfsPointer: _vfs_list) { // always refresh virtual vfs showing a virtual directory; it can contain files from various // places, we don't know if they were (re)moved, refreshing is also fast enough vfs *vfs = vfsPointer.data(); const QUrl vfsDir = vfs->currentDirectory(); - if (vfsDir == vfs::cleanUrl(directory) || (vfsDir.scheme() == "virt" && !vfs->isRoot())) { - vfs->mayRefresh(); + if ((vfsDir == vfs::cleanUrl(directory) || (vfsDir.scheme() == "virt" && !vfs->isRoot())) + && !vfs->hasAutoUpdate()) { + // refresh all vfs currently showing this directory... + vfs->refresh(); + } else if (!mountPoint.isEmpty() && mountPoint == vfs->mountPoint()) { + // ..or refresh filesystem info if mount point is the same (for free space update) + vfs->updateFilesystemInfo(); } } } diff --git a/krusader/VFS/vfs.h b/krusader/VFS/vfs.h --- a/krusader/VFS/vfs.h +++ b/krusader/VFS/vfs.h @@ -76,9 +76,9 @@ virtual ~vfs(); // VfileContainer implementation - virtual inline QList vfiles() { return _vfiles.values(); } - virtual inline unsigned long numVfiles() { return _vfiles.count(); } - virtual inline bool isRoot() { + inline QList vfiles() { return _vfiles.values(); } + inline unsigned long numVfiles() { return _vfiles.count(); } + inline bool isRoot() { const QString path = _currentDirectory.path(); return path.isEmpty() || path == "/"; } @@ -106,7 +106,15 @@ /// trailing slash. virtual QUrl getUrl(const QString &name) = 0; /// Return a list of URLs for multiple files/directories in the current directory. - virtual QList getUrls(const QStringList &names); + QList getUrls(const QStringList &names); + + /// Return the filesystem mount point of the current directory. Empty string by default. + virtual QString mountPoint() { return QString(); } + /// Returns true if this VFS implementation does not need to be notified about changes in the + /// current directory. Else false. + virtual bool hasAutoUpdate() { return false; } + /// Notify this VFS that the filesystem info of the current directory may have changed. + virtual void updateFilesystemInfo() {} /// Returns the current directory path of this VFS. inline QUrl currentDirectory() { return _currentDirectory; } @@ -129,9 +137,6 @@ } /// Returns true if this VFS is currently refreshing the current directory. inline bool isRefreshing() { return _isRefreshing; } - /// Return a displayable string containing special filesystem meta information. Or an empty - /// string by default. - virtual QString metaInformation() { return QString(); } /// Calculate the amount of space occupied by a file or directory in the current directory /// (recursive). @@ -155,25 +160,25 @@ /// Returns true if directory was read. Returns false if failed or refresh job was killed. // optional TODO: add an async version of this bool refresh(const QUrl &directory = QUrl()); - /// Notify this VFS that the current directory content may have changed. - void mayRefresh(); signals: /// Emitted when this VFS is currently refreshing the VFS directory. void refreshJobStarted(KIO::Job *job); /// Emitted when an error occured in this VFS during refresh. void error(const QString &msg); /// Emitted when the content of a directory was changed by this VFS. void filesystemChanged(const QUrl &directory); + /// Emitted when the information for the filesystem of the current directory changed. + /// Information is either + /// * 'metaInfo': a displayable string about the fs, empty by default, OR + /// * 'total' and 'free': filesystem size and free space, both 0 by default + void filesystemInfoChanged(const QString &metaInfo, KIO::filesize_t total, KIO::filesize_t free); /// Emitted before a directory path is opened for reading. Used for automounting. void aboutToOpenDir(const QString &path); protected: /// Fill the vfs dictionary with vfiles, must be implemented for each VFS. virtual bool refreshInternal(const QUrl &origin, bool showHidden) = 0; - /// Returns true if this VFS implementation does not need to be notified about changes in the - /// current directory. - virtual bool ignoreRefresh() { return false; } /// Returns true if showing hidden files is set in config. bool showHiddenFiles(); diff --git a/krusader/VFS/vfs.cpp b/krusader/VFS/vfs.cpp --- a/krusader/VFS/vfs.cpp +++ b/krusader/VFS/vfs.cpp @@ -172,15 +172,9 @@ clear(tempVfiles); - return true; -} + updateFilesystemInfo(); -void vfs::mayRefresh() -{ - if (ignoreRefresh()) { - return; - } - refresh(); + return true; } // ==== protected ==== diff --git a/krusader/VFS/virt_vfs.h b/krusader/VFS/virt_vfs.h --- a/krusader/VFS/virt_vfs.h +++ b/krusader/VFS/virt_vfs.h @@ -43,7 +43,6 @@ Q_OBJECT public: virt_vfs(); - ~virt_vfs(); /// Create virtual files in this VFS. Copy mode and showProgressInfo are ignored. void copyFiles(const QList &urls, const QUrl &destination, @@ -68,9 +67,6 @@ /// Returns the URL of the real file or an empty URL if file with name does not exist. QUrl getUrl(const QString& name) Q_DECL_OVERRIDE; - virtual QString metaInformation() Q_DECL_OVERRIDE { - return _metaInfo; - } void setMetaInformation(QString info); protected: diff --git a/krusader/VFS/virt_vfs.cpp b/krusader/VFS/virt_vfs.cpp --- a/krusader/VFS/virt_vfs.cpp +++ b/krusader/VFS/virt_vfs.cpp @@ -55,8 +55,6 @@ _type = VFS_VIRT; } -virt_vfs::~virt_vfs() {} - void virt_vfs::copyFiles(const QList &urls, const QUrl &destination, KIO::CopyJob::CopyMode /*mode*/, bool /*showProgressInfo*/, bool /*reverseQueueMode*/, bool /*startPaused*/) @@ -218,9 +216,7 @@ void virt_vfs::setMetaInformation(QString info) { - _metaInfo = info; - _metaInfoDict[currentDir()] = _metaInfo; - refresh(); + _metaInfoDict[currentDir()] = info; } // ==== protected ==== @@ -243,7 +239,9 @@ } QList *urlList = _virtVfsDict[currentDir()]; - _metaInfo = _metaInfoDict[currentDir()]; + + const QString metaInfo = _metaInfoDict[currentDir()]; + emit filesystemInfoChanged(metaInfo.isEmpty() ? i18n("Virtual filesystem") : metaInfo, 0, 0); QMutableListIterator it(*urlList); while (it.hasNext()) {