settings/viewmodes/viewmodesettings.cpp
settings/viewmodes/viewsettingstab.cpp
statusbar/dolphinstatusbar.cpp
+ statusbar/mountpointobserver.cpp
+ statusbar/mountpointobservercache.cpp
+ statusbar/spaceinfoobserver.cpp
statusbar/statusbarspaceinfo.cpp
views/zoomlevelinfo.cpp
)
QAction* action = 0;
const bool isDir = !m_fileInfo.isNull() && m_fileInfo.isDir();
if (isDir && (m_selectedItems.count() == 1)) {
+ const QPair<bool, QString> pasteInfo = KonqOperations::pasteInfo(m_fileInfo.url());
action = new QAction(KIcon("edit-paste"), i18nc("@action:inmenu", "Paste Into Folder"), this);
- const QMimeData* mimeData = QApplication::clipboard()->mimeData();
- const KUrl::List pasteData = KUrl::List::fromMimeData(mimeData);
- action->setEnabled(!pasteData.isEmpty() && selectedItemsProperties().supportsWriting());
+ action->setEnabled(pasteInfo.first);
connect(action, SIGNAL(triggered()), m_mainWindow, SLOT(pasteIntoFolder()));
} else {
action = m_mainWindow->actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
prevTabKeys.append(QKeySequence(Qt::CTRL | Qt::SHIFT | Qt::Key_Tab));
KAction* activateNextTab = actionCollection()->addAction("activate_next_tab");
+ activateNextTab->setIconText(i18nc("@action:inmenu", "Next Tab"));
activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab"));
activateNextTab->setEnabled(false);
connect(activateNextTab, SIGNAL(triggered()), SLOT(activateNextTab()));
activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys);
KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab");
+ activatePrevTab->setIconText(i18nc("@action:inmenu", "Previous Tab"));
activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab"));
activatePrevTab->setEnabled(false);
connect(activatePrevTab, SIGNAL(triggered()), SLOT(activatePrevTab()));
Name[he]=מרוכז
Name[hu]=Kompakt
Name[ia]=Compacte
+Name[id]=Kompak
Name[is]=Þjappað
Name[it]=Compatta
Name[kk]=Ықшамды
return m_layouter->lastVisibleIndex();
}
-void KItemListView::calculateItemSizeHints(QVector<QSizeF>& sizeHints) const
+void KItemListView::calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint) const
{
- widgetCreator()->calculateItemSizeHints(sizeHints, this);
+ widgetCreator()->calculateItemSizeHints(logicalHeightHints, logicalWidthHint, this);
}
void KItemListView::setSupportsItemExpanding(bool supportsExpanding)
int lastVisibleIndex() const;
/**
- * @return Required size for all items in the model.
- * The returned value might be larger than KItemListView::itemSize().
+ * @return Calculates the required size for all items in the model.
+ * It might be larger than KItemListView::itemSize().
* In this case the layout grid will be stretched to assure an
* unclipped item.
+ * NOTE: the logical height (width) is actually the
+ * width (height) if the scroll orientation is Qt::Vertical!
*/
- void calculateItemSizeHints(QVector<QSizeF>& sizeHints) const;
+ void calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint) const;
/**
* If set to true, items having child-items can be expanded to show the child-items as
virtual void recycle(KItemListWidget* widget);
- virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const = 0;
+ virtual void calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const = 0;
virtual qreal preferredRoleColumnWidth(const QByteArray& role,
int index,
virtual KItemListWidget* create(KItemListView* view);
- virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
+ virtual void calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const;
virtual qreal preferredRoleColumnWidth(const QByteArray& role,
int index,
}
template<class T>
-void KItemListWidgetCreator<T>::calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+void KItemListWidgetCreator<T>::calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const
{
- return m_informant->calculateItemSizeHints(sizeHints, view);
+ return m_informant->calculateItemSizeHints(logicalHeightHints, logicalWidthHint, view);
}
template<class T>
KItemListWidgetInformant();
virtual ~KItemListWidgetInformant();
- virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const = 0;
+ virtual void calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const = 0;
virtual qreal preferredRoleColumnWidth(const QByteArray& role,
int index,
{
}
-void KStandardItemListWidgetInformant::calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+void KStandardItemListWidgetInformant::calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const
{
switch (static_cast<const KStandardItemListView*>(view)->itemLayout()) {
case KStandardItemListWidget::IconsLayout:
- calculateIconsLayoutItemSizeHints(sizeHints, view);
+ calculateIconsLayoutItemSizeHints(logicalHeightHints, logicalWidthHint, view);
break;
case KStandardItemListWidget::CompactLayout:
- calculateCompactLayoutItemSizeHints(sizeHints, view);
+ calculateCompactLayoutItemSizeHints(logicalHeightHints, logicalWidthHint, view);
break;
case KStandardItemListWidget::DetailsLayout:
- calculateDetailsLayoutItemSizeHints(sizeHints, view);
+ calculateDetailsLayoutItemSizeHints(logicalHeightHints, logicalWidthHint, view);
break;
default:
return baseFont;
}
-void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+void KStandardItemListWidgetInformant::calculateIconsLayoutItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const
{
const KItemListStyleOption& option = view->styleOption();
const QFont& normalFont = option.font;
QTextOption textOption(Qt::AlignHCenter);
textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
- for (int index = 0; index < sizeHints.count(); ++index) {
- if (!sizeHints.at(index).isEmpty()) {
+ for (int index = 0; index < logicalHeightHints.count(); ++index) {
+ if (logicalHeightHints.at(index) > 0.0) {
continue;
}
// Add one line for each additional information
textHeight += additionalRolesSpacing;
- sizeHints[index] = QSizeF(itemWidth, textHeight + spacingAndIconHeight);
+ logicalHeightHints[index] = textHeight + spacingAndIconHeight;
}
+
+ logicalWidthHint = itemWidth;
}
-void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const
{
const KItemListStyleOption& option = view->styleOption();
const QFontMetrics& normalFontMetrics = option.fontMetrics;
const QFontMetrics linkFontMetrics(customizedFontForLinks(option.font));
- for (int index = 0; index < sizeHints.count(); ++index) {
- if (!sizeHints.at(index).isEmpty()) {
+ for (int index = 0; index < logicalHeightHints.count(); ++index) {
+ if (logicalHeightHints.at(index) > 0.0) {
continue;
}
width = maxWidth;
}
- sizeHints[index] = QSizeF(width, height);
+ logicalHeightHints[index] = width;
}
+
+ logicalWidthHint = height;
}
-void KStandardItemListWidgetInformant::calculateDetailsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const
+void KStandardItemListWidgetInformant::calculateDetailsLayoutItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const
{
const KItemListStyleOption& option = view->styleOption();
const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height());
-
- for (int index = 0; index < sizeHints.count(); ++index) {
- if (!sizeHints.at(index).isEmpty()) {
- continue;
- }
-
- sizeHints[index] = QSizeF(-1, height);
- }
+ logicalHeightHints.fill(height);
+ logicalWidthHint = -1.0;
}
KStandardItemListWidget::KStandardItemListWidget(KItemListWidgetInformant* informant, QGraphicsItem* parent) :
KStandardItemListWidgetInformant();
virtual ~KStandardItemListWidgetInformant();
- virtual void calculateItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
+ virtual void calculateItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const;
virtual qreal preferredRoleColumnWidth(const QByteArray& role,
int index,
*/
virtual QFont customizedFontForLinks(const QFont& baseFont) const;
- void calculateIconsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
- void calculateCompactLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
- void calculateDetailsLayoutItemSizeHints(QVector<QSizeF>& sizeHints, const KItemListView* view) const;
+ void calculateIconsLayoutItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const;
+ void calculateCompactLayoutItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const;
+ void calculateDetailsLayoutItemSizeHints(QVector<qreal>& logicalHeightHints, qreal& logicalWidthHint, const KItemListView* view) const;
friend class KStandardItemListWidget; // Accesses roleText()
};
void KFileItemClipboard::updateCutItems()
{
const QMimeData* mimeData = QApplication::clipboard()->mimeData();
+
+ // mimeData can be 0 according to https://bugs.kde.org/show_bug.cgi?id=335053
+ if (!mimeData) {
+ m_cutItems.clear();
+ emit cutItemsChanged();
+ return;
+ }
+
const QByteArray data = mimeData->data("application/x-kde-cutselection");
const bool isCutSelection = (!data.isEmpty() && data.at(0) == QLatin1Char('1'));
if (isCutSelection) {
KItemListSizeHintResolver::KItemListSizeHintResolver(const KItemListView* itemListView) :
m_itemListView(itemListView),
- m_sizeHintCache(),
+ m_logicalHeightHintCache(),
+ m_logicalWidthHint(0.0),
m_needsResolving(false)
{
}
QSizeF KItemListSizeHintResolver::sizeHint(int index)
{
updateCache();
- return m_sizeHintCache.at(index);
+ return QSizeF(m_logicalWidthHint, m_logicalHeightHintCache.at(index));
}
void KItemListSizeHintResolver::itemsInserted(const KItemRangeList& itemRanges)
insertedCount += range.count;
}
- const int currentCount = m_sizeHintCache.count();
- m_sizeHintCache.reserve(currentCount + insertedCount);
+ const int currentCount = m_logicalHeightHintCache.count();
+ m_logicalHeightHintCache.reserve(currentCount + insertedCount);
// We build the new list from the end to the beginning to mimize the
// number of moves.
- m_sizeHintCache.insert(m_sizeHintCache.end(), insertedCount, QSizeF());
+ m_logicalHeightHintCache.insert(m_logicalHeightHintCache.end(), insertedCount, 0.0);
int sourceIndex = currentCount - 1;
- int targetIndex = m_sizeHintCache.count() - 1;
+ int targetIndex = m_logicalHeightHintCache.count() - 1;
int itemsToInsertBeforeCurrentRange = insertedCount;
for (int rangeIndex = itemRanges.count() - 1; rangeIndex >= 0; --rangeIndex) {
// First: move all existing items that must be put behind 'range'.
while (targetIndex >= itemsToInsertBeforeCurrentRange + range.index + range.count) {
- m_sizeHintCache[targetIndex] = m_sizeHintCache[sourceIndex];
+ m_logicalHeightHintCache[targetIndex] = m_logicalHeightHintCache[sourceIndex];
--sourceIndex;
--targetIndex;
}
// Then: insert QSizeF() for the items which are inserted into 'range'.
while (targetIndex >= itemsToInsertBeforeCurrentRange + range.index) {
- m_sizeHintCache[targetIndex] = QSizeF();
+ m_logicalHeightHintCache[targetIndex] = 0.0;
--targetIndex;
}
}
m_needsResolving = true;
- Q_ASSERT(m_sizeHintCache.count() == m_itemListView->model()->count());
+ Q_ASSERT(m_logicalHeightHintCache.count() == m_itemListView->model()->count());
}
void KItemListSizeHintResolver::itemsRemoved(const KItemRangeList& itemRanges)
{
- const QVector<QSizeF>::iterator begin = m_sizeHintCache.begin();
- const QVector<QSizeF>::iterator end = m_sizeHintCache.end();
+ const QVector<qreal>::iterator begin = m_logicalHeightHintCache.begin();
+ const QVector<qreal>::iterator end = m_logicalHeightHintCache.end();
KItemRangeList::const_iterator rangeIt = itemRanges.constBegin();
const KItemRangeList::const_iterator rangeEnd = itemRanges.constEnd();
- QVector<QSizeF>::iterator destIt = begin + rangeIt->index;
- QVector<QSizeF>::iterator srcIt = destIt + rangeIt->count;
+ QVector<qreal>::iterator destIt = begin + rangeIt->index;
+ QVector<qreal>::iterator srcIt = destIt + rangeIt->count;
++rangeIt;
}
}
- m_sizeHintCache.erase(destIt, end);
+ m_logicalHeightHintCache.erase(destIt, end);
// Note that the cache size might temporarily not match the model size if
// this function is called from KItemListView::setModel() to empty the cache.
- if (!m_sizeHintCache.isEmpty() && m_itemListView->model()) {
- Q_ASSERT(m_sizeHintCache.count() == m_itemListView->model()->count());
+ if (!m_logicalHeightHintCache.isEmpty() && m_itemListView->model()) {
+ Q_ASSERT(m_logicalHeightHintCache.count() == m_itemListView->model()->count());
}
}
void KItemListSizeHintResolver::itemsMoved(const KItemRange& range, const QList<int>& movedToIndexes)
{
- QVector<QSizeF> newSizeHintCache(m_sizeHintCache);
+ QVector<qreal> newLogicalHeightHintCache(m_logicalHeightHintCache);
const int movedRangeEnd = range.index + range.count;
for (int i = range.index; i < movedRangeEnd; ++i) {
const int newIndex = movedToIndexes.at(i - range.index);
- newSizeHintCache[newIndex] = m_sizeHintCache.at(i);
+ newLogicalHeightHintCache[newIndex] = m_logicalHeightHintCache.at(i);
}
- m_sizeHintCache = newSizeHintCache;
+ m_logicalHeightHintCache = newLogicalHeightHintCache;
}
void KItemListSizeHintResolver::itemsChanged(int index, int count, const QSet<QByteArray>& roles)
{
Q_UNUSED(roles);
while (count) {
- m_sizeHintCache[index] = QSizeF();
+ m_logicalHeightHintCache[index] = 0.0;
++index;
--count;
}
void KItemListSizeHintResolver::clearCache()
{
- m_sizeHintCache.fill(QSizeF());
+ m_logicalHeightHintCache.fill(0.0);
m_needsResolving = true;
}
void KItemListSizeHintResolver::updateCache()
{
if (m_needsResolving) {
- m_itemListView->calculateItemSizeHints(m_sizeHintCache);
+ m_itemListView->calculateItemSizeHints(m_logicalHeightHintCache, m_logicalWidthHint);
m_needsResolving = false;
}
}
private:
const KItemListView* m_itemListView;
- mutable QVector<QSizeF> m_sizeHintCache;
+ mutable QVector<qreal> m_logicalHeightHintCache;
+ mutable qreal m_logicalWidthHint;
bool m_needsResolving;
};
// to get the physical horizontal direction
QPointF pos(y, x);
pos.rx() -= m_scrollOffset;
+ sizeHint.transpose();
return QRectF(pos, sizeHint);
}
break;
}
- const qreal itemWidth = m_sizeHintResolver->sizeHint(index).width();
+ const qreal itemWidth = (m_scrollOrientation == Qt::Vertical)
+ ? m_sizeHintResolver->sizeHint(index).width()
+ : m_sizeHintResolver->sizeHint(index).height();
if (itemWidth > headerWidth) {
headerWidth = itemWidth;
while (index < itemCount && column < m_columnCount) {
qreal requiredItemHeight = itemSize.height();
const QSizeF sizeHint = m_sizeHintResolver->sizeHint(index);
- const qreal sizeHintHeight = horizontalScrolling ? sizeHint.width() : sizeHint.height();
+ const qreal sizeHintHeight = sizeHint.height();
if (sizeHintHeight > requiredItemHeight) {
requiredItemHeight = sizeHintHeight;
}
QAction* copyAction = new QAction(KIcon("edit-copy"), i18nc("@action:inmenu", "Copy"), this);
connect(copyAction, SIGNAL(triggered()), this, SLOT(copy()));
- QAction* pasteAction = new QAction(KIcon("edit-paste"), i18nc("@action:inmenu", "Paste"), this);
- const QMimeData* mimeData = QApplication::clipboard()->mimeData();
- const KUrl::List pasteData = KUrl::List::fromMimeData(mimeData);
+ const QPair<bool, QString> pasteInfo = KonqOperations::pasteInfo(m_fileItem.url());
+ QAction* pasteAction = new QAction(KIcon("edit-paste"), pasteInfo.second, this);
connect(pasteAction, SIGNAL(triggered()), this, SLOT(paste()));
- pasteAction->setEnabled(!pasteData.isEmpty() && capabilities.supportsWriting());
+ pasteAction->setEnabled(pasteInfo.first);
popup->addAction(cutAction);
popup->addAction(copyAction);
void TreeViewContextMenu::paste()
{
- QClipboard* clipboard = QApplication::clipboard();
- const QMimeData* mimeData = clipboard->mimeData();
-
- const KUrl::List source = KUrl::List::fromMimeData(mimeData);
- const KUrl& dest = m_fileItem.url();
- if (KonqMimeData::decodeIsCutSelection(mimeData)) {
- KonqOperations::copy(m_parent, KonqOperations::MOVE, source, dest);
- clipboard->clear();
- } else {
- KonqOperations::copy(m_parent, KonqOperations::COPY, source, dest);
- }
+ KonqOperations::doPaste(m_parent, m_fileItem.url());
}
void TreeViewContextMenu::rename()
found = true;
if (newBookmark.metaDataItem("UDI").isEmpty()) {
item->setBookmark(newBookmark);
+ item->setText(i18nc("KFile System Bookmarks", newBookmark.text().toUtf8().data()));
}
break;
}
X-KDE-Keywords[he]=מנהל קבצים
X-KDE-Keywords[hu]=fájlkezelő
X-KDE-Keywords[ia]=gerente de file
+X-KDE-Keywords[id]=manajer berkas
X-KDE-Keywords[is]=skráastjóri
X-KDE-Keywords[it]=gestore dei file
X-KDE-Keywords[kk]=file manager
X-KDE-Keywords[he]=מנהל קבצים
X-KDE-Keywords[hu]=fájlkezelő
X-KDE-Keywords[ia]=gerente de file
+X-KDE-Keywords[id]=manajer berkas
X-KDE-Keywords[is]=skráastjóri
X-KDE-Keywords[it]=gestore dei file
X-KDE-Keywords[kk]=file manager
X-KDE-Keywords[he]=מנהל קבצים
X-KDE-Keywords[hu]=fájlkezelő
X-KDE-Keywords[ia]=gerente de file
+X-KDE-Keywords[id]=manajer berkas
X-KDE-Keywords[is]=skráastjóri
X-KDE-Keywords[it]=gestore dei file
X-KDE-Keywords[kk]=file manager
X-KDE-Keywords[he]=מנהל קבצים
X-KDE-Keywords[hu]=fájlkezelő
X-KDE-Keywords[ia]=gerente de file
+X-KDE-Keywords[id]=manajer berkas
X-KDE-Keywords[is]=skráastjóri
X-KDE-Keywords[it]=gestore dei file
X-KDE-Keywords[kk]=file manager
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Frank Reininghaus <frank78ac@googlemail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "mountpointobserver.h"
+#include "mountpointobservercache.h"
+
+MountPointObserver::MountPointObserver(const QString& mountPoint, QObject* parent) :
+ QObject(parent),
+ m_mountPoint(mountPoint),
+ m_referenceCount(0),
+ m_spaceInfo(KDiskFreeSpaceInfo::freeSpaceInfo(mountPoint))
+{
+}
+
+MountPointObserver* MountPointObserver::observerForPath(const QString& path)
+{
+ MountPointObserver* observer = MountPointObserverCache::instance()->observerForPath(path);
+ return observer;
+}
+
+void MountPointObserver::update()
+{
+ if (m_referenceCount == 0) {
+ delete this;
+ } else {
+ const KDiskFreeSpaceInfo spaceInfo = KDiskFreeSpaceInfo::freeSpaceInfo(m_mountPoint);
+ if (spaceInfo.size() != m_spaceInfo.size() || spaceInfo.available() != m_spaceInfo.available()) {
+ m_spaceInfo = spaceInfo;
+ emit spaceInfoChanged();
+ }
+ }
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Frank Reininghaus <frank78ac@googlemail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef MOUNTPOINTOBSERVER_H
+#define MOUNTPOINTOBSERVER_H
+
+#include <KDiskFreeSpaceInfo>
+
+#include <QObject>
+
+/**
+ * A MountPointObserver can be used to determine the free space on a mount
+ * point. It will then check the free space periodically, and emit the signal
+ * spaceInfoChanged() if the return value of spaceInfo() has changed.
+ *
+ * Since multiple users which watch paths on the same mount point can share
+ * a MountPointObserver, it is not possible to create a MountPointObserver
+ * manually. Instead, the function observerForPath(QString&) should be called,
+ * which returns either an existing or a newly created MountPointObserver for
+ * the mount point where the path is mounted. observerForPath(QString&) looks
+ * for a suitable MountPointObserver in an internal cache and creates new
+ * MountPointObservers and adds them to the cache if necessary.
+ *
+ * Reference counting is used to keep track of the number of users, and to
+ * decide when the object can be deleted. A user of this class should call
+ * the method ref() when it starts using it, and deref() when it does not need
+ * the MountPointObserver any more.
+ *
+ * The object will not be deleted immediately if the reference count reaches
+ * zero. The object will only be destroyed when the next periodic update of
+ * the free space information happens, and the reference count is still zero.
+ * This approach makes it possible to re-use the object if a new user requests
+ * the free space for the same mount point before the next update.
+ */
+class MountPointObserver : public QObject
+{
+ Q_OBJECT
+
+ explicit MountPointObserver(const QString& mountPoint, QObject* parent = 0);
+ virtual ~MountPointObserver() {}
+
+public:
+ /**
+ * Obtains information about the available space on the observed mount point.
+ */
+ KDiskFreeSpaceInfo spaceInfo() const { return m_spaceInfo; }
+
+ /**
+ * Call this function to indicate that the caller intends to continue using this object. An
+ * internal reference count is increased then. When the observer is not needed any more,
+ * deref() should be called, which decreases the reference count again.
+ */
+ void ref() { ++m_referenceCount; }
+
+ /**
+ * This function can be used to indicate that the caller does not need this MountPointObserver
+ * any more. Internally, a reference count is decreased. If the reference count is zero while
+ * update() is called, the object deletes itself.
+ */
+ void deref()
+ {
+ --m_referenceCount;
+ Q_ASSERT(m_referenceCount >= 0);
+ }
+
+ /**
+ * Returns a MountPointObserver for the given \a path. If the caller intends to continue using
+ * the returned object, it must call its ref() method.
+ */
+ static MountPointObserver* observerForPath(const QString& path);
+
+signals:
+ /**
+ * This signal is emitted if the information that spaceInfo() will return has changed.
+ */
+ void spaceInfoChanged();
+
+public slots:
+ /**
+ * If this slot is invoked, MountPointObserver checks if the available space on the observed
+ * mount point has changed, and emits spaceInfoChanged() if that is the case.
+ */
+ void update();
+
+private:
+ const QString m_mountPoint;
+ int m_referenceCount;
+ KDiskFreeSpaceInfo m_spaceInfo;
+
+ friend class MountPointObserverCache;
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Frank Reininghaus <frank78ac@googlemail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "mountpointobservercache.h"
+
+#include "mountpointobserver.h"
+
+#include <KGlobal>
+#include <KMountPoint>
+
+#include <QTimer>
+
+class MountPointObserverCacheSingleton
+{
+public:
+ MountPointObserverCache instance;
+};
+K_GLOBAL_STATIC(MountPointObserverCacheSingleton, s_MountPointObserverCache)
+
+
+MountPointObserverCache::MountPointObserverCache() :
+ m_observerForMountPoint(),
+ m_mountPointForObserver(),
+ m_updateTimer(0)
+{
+ m_updateTimer = new QTimer(this);
+}
+
+MountPointObserverCache::~MountPointObserverCache()
+{
+}
+
+MountPointObserverCache* MountPointObserverCache::instance()
+{
+ return &s_MountPointObserverCache->instance;
+}
+
+MountPointObserver* MountPointObserverCache::observerForPath(const QString& path)
+{
+ // Try to share the observer with other paths that have the same mount point.
+ QString mountPointPath;
+ KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByPath(path);
+ if (mountPoint) {
+ mountPointPath = mountPoint->mountPoint();
+ } else {
+ // Even if determining the mount point failed, KDiskFreeSpaceInfo might still
+ // be able to retrieve information about the path.
+ mountPointPath = path;
+ }
+
+ MountPointObserver* observer = m_observerForMountPoint.value(mountPointPath);
+ if (!observer) {
+ observer = new MountPointObserver(mountPointPath, this);
+ m_observerForMountPoint.insert(mountPointPath, observer);
+ m_mountPointForObserver.insert(observer, mountPointPath);
+ Q_ASSERT(m_observerForMountPoint.count() == m_mountPointForObserver.count());
+
+ connect(observer, SIGNAL(destroyed(QObject*)), this, SLOT(slotObserverDestroyed(QObject*)));
+
+ if (!m_updateTimer->isActive()) {
+ m_updateTimer->start(10000);
+ }
+
+ connect(m_updateTimer, SIGNAL(timeout()), observer, SLOT(update()));
+ }
+
+ return observer;
+}
+
+void MountPointObserverCache::slotObserverDestroyed(QObject* observer)
+{
+ Q_ASSERT(m_mountPointForObserver.contains(observer));
+ const QString& path = m_mountPointForObserver.value(observer);
+ Q_ASSERT(m_observerForMountPoint.contains(path));
+ m_observerForMountPoint.remove(path);
+ m_mountPointForObserver.remove(observer);
+
+ Q_ASSERT(m_observerForMountPoint.count() == m_mountPointForObserver.count());
+
+ if (m_mountPointForObserver.isEmpty()) {
+ m_updateTimer->stop();
+ }
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Frank Reininghaus <frank78ac@googlemail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef MOUNTPOINTOBSERVERCACHE_H
+#define MOUNTPOINTOBSERVERCACHE_H
+
+#include <QHash>
+#include <QObject>
+
+class MountPointObserver;
+class QTimer;
+
+class MountPointObserverCache : public QObject
+{
+ Q_OBJECT
+
+ MountPointObserverCache();
+ virtual ~MountPointObserverCache();
+
+public:
+ static MountPointObserverCache* instance();
+
+ /**
+ * Returns a MountPointObserver for the given \a path. A new observer is created if necessary.
+ */
+ MountPointObserver* observerForPath(const QString& path);
+
+private slots:
+ /**
+ * Removes the given \a observer from the cache.
+ */
+ void slotObserverDestroyed(QObject* observer);
+
+private:
+ QHash<QString, MountPointObserver*> m_observerForMountPoint;
+ QHash<QObject*, QString> m_mountPointForObserver;
+ QTimer* m_updateTimer;
+
+ friend class MountPointObserverCacheSingleton;
+};
+
+#endif
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Frank Reininghaus <frank78ac@googlemail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "spaceinfoobserver.h"
+
+#include "mountpointobserver.h"
+
+#include <KUrl>
+
+SpaceInfoObserver::SpaceInfoObserver(const KUrl& url, QObject* parent) :
+ QObject(parent),
+ m_mountPointObserver(0)
+{
+ if (url.isLocalFile()) {
+ m_mountPointObserver = MountPointObserver::observerForPath(url.toLocalFile());
+ m_mountPointObserver->ref();
+ connect(m_mountPointObserver, SIGNAL(spaceInfoChanged()), this, SIGNAL(valuesChanged()));
+ }
+}
+
+SpaceInfoObserver::~SpaceInfoObserver()
+{
+ if (m_mountPointObserver) {
+ m_mountPointObserver->deref();
+ m_mountPointObserver = 0;
+ }
+}
+
+quint64 SpaceInfoObserver::size() const
+{
+ if (m_mountPointObserver && m_mountPointObserver->spaceInfo().isValid()) {
+ return m_mountPointObserver->spaceInfo().size();
+ } else {
+ return 0;
+ }
+}
+
+quint64 SpaceInfoObserver::available() const
+{
+ if (m_mountPointObserver && m_mountPointObserver->spaceInfo().isValid()) {
+ return m_mountPointObserver->spaceInfo().available();
+ } else {
+ return 0;
+ }
+}
+
+void SpaceInfoObserver::setUrl(const KUrl& url)
+{
+ if (url.isLocalFile()) {
+ MountPointObserver* newObserver = MountPointObserver::observerForPath(url.toLocalFile());
+ if (newObserver != m_mountPointObserver) {
+ if (m_mountPointObserver) {
+ disconnect(m_mountPointObserver, SIGNAL(spaceInfoChanged()), this, SIGNAL(valuesChanged()));
+ m_mountPointObserver->deref();
+ m_mountPointObserver = 0;
+ }
+
+ m_mountPointObserver = newObserver;
+ m_mountPointObserver->ref();
+ connect(m_mountPointObserver, SIGNAL(spaceInfoChanged()), this, SIGNAL(valuesChanged()));
+
+ emit valuesChanged();
+ }
+ } else {
+ if (m_mountPointObserver) {
+ disconnect(m_mountPointObserver, SIGNAL(spaceInfoChanged()), this, SIGNAL(valuesChanged()));
+ m_mountPointObserver->deref();
+ m_mountPointObserver = 0;
+
+ emit valuesChanged();
+ }
+ }
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2014 by Frank Reininghaus <frank78ac@googlemail.com> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef SPACEINFOOBSERVER_H
+#define SPACEINFOOBSERVER_H
+
+#include <QObject>
+
+class KUrl;
+class MountPointObserver;
+
+class SpaceInfoObserver : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit SpaceInfoObserver(const KUrl& url, QObject* parent = 0);
+ virtual ~SpaceInfoObserver();
+
+ quint64 size() const;
+ quint64 available() const;
+
+ void setUrl(const KUrl& url);
+
+signals:
+ /**
+ * This signal is emitted if the information that size() and/or available() will return has changed.
+ */
+ void valuesChanged();
+
+private:
+ MountPointObserver* m_mountPointObserver;
+};
+
+#endif
#include "statusbarspaceinfo.h"
-#include <KDiskFreeSpaceInfo>
+#include "spaceinfoobserver.h"
+
#include <KLocale>
#include <KIO/Job>
-#include <QTimer>
#include <QKeyEvent>
StatusBarSpaceInfo::StatusBarSpaceInfo(QWidget* parent) :
KCapacityBar(KCapacityBar::DrawTextInline, parent),
- m_kBSize(0),
- m_timer(0)
+ m_observer(0)
{
- // Use a timer to update the space information. Polling is useful
- // here, as files can be deleted/added outside the scope of Dolphin.
- m_timer = new QTimer(this);
- connect(m_timer, SIGNAL(timeout()), this, SLOT(calculateSpaceInfo()));
}
StatusBarSpaceInfo::~StatusBarSpaceInfo()
{
if (m_url != url) {
m_url = url;
- if (isVisible()) {
- calculateSpaceInfo();
+ if (m_observer) {
+ m_observer->setUrl(url);
}
}
}
void StatusBarSpaceInfo::showEvent(QShowEvent* event)
{
KCapacityBar::showEvent(event);
- if (!event->spontaneous()) {
- calculateSpaceInfo();
- m_timer->start(10000);
- }
+ m_observer.reset(new SpaceInfoObserver(m_url, this));
+ slotValuesChanged();
+ connect(m_observer.data(), SIGNAL(valuesChanged()), this, SLOT(slotValuesChanged()));
}
void StatusBarSpaceInfo::hideEvent(QHideEvent* event)
{
- m_timer->stop();
+ m_observer.reset();
KCapacityBar::hideEvent(event);
}
-void StatusBarSpaceInfo::calculateSpaceInfo()
+void StatusBarSpaceInfo::slotValuesChanged()
{
- // KDiskFreeSpace is for local paths only
- if (!m_url.isLocalFile()) {
- setText(i18nc("@info:status", "Unknown size"));
- setValue(0);
- update();
- return;
- }
-
- KDiskFreeSpaceInfo job = KDiskFreeSpaceInfo::freeSpaceInfo(m_url.toLocalFile());
- if (!job.isValid()) {
+ Q_ASSERT(m_observer);
+ const quint64 size = m_observer->size();
+ if (size == 0) {
setText(i18nc("@info:status", "Unknown size"));
setValue(0);
update();
- return;
- }
-
- KIO::filesize_t kBSize = job.size() / 1024;
- KIO::filesize_t kBUsed = job.used() / 1024;
-
- const bool valuesChanged = (kBUsed != static_cast<quint64>(value())) || (kBSize != m_kBSize);
- if (valuesChanged) {
- setText(i18nc("@info:status Free disk space", "%1 free",
- KIO::convertSize(job.available())));
+ } else {
+ const quint64 available = m_observer->available();
+ const quint64 used = size - available;
+ const int percentUsed = qRound(100.0 * qreal(used) / qreal(size));
+ setText(i18nc("@info:status Free disk space", "%1 free", KIO::convertSize(available)));
setUpdatesEnabled(false);
- m_kBSize = kBSize;
- setValue(kBSize > 0 ? (kBUsed * 100) / kBSize : 0);
+ setValue(percentUsed);
setUpdatesEnabled(true);
update();
}
class QHideEvent;
class QShowEvent;
+class SpaceInfoObserver;
+
/**
* @short Shows the available space for the volume represented
* by the given URL as part of the status bar.
void hideEvent(QHideEvent* event);
private slots:
- /**
- * Calculates the space information for the current set URL.
- */
- void calculateSpaceInfo();
+ void slotValuesChanged();
private:
- quint64 m_kBSize;
+ QScopedPointer<SpaceInfoObserver> m_observer;
KUrl m_url;
- QTimer* m_timer;
};
#endif
}
}
-void DolphinView::showHoverInformation(const KFileItem& item)
-{
- emit requestItemInfo(item);
-}
-
-void DolphinView::clearHoverInformation()
-{
- emit requestItemInfo(KFileItem());
-}
-
void DolphinView::slotDeleteFileFinished(KJob* job)
{
if (job->error() == 0) {
*/
void updateSortFoldersFirst(bool foldersFirst);
- /**
- * Updates the status bar to show hover information for the
- * item \a item. If currently other items are selected,
- * no hover information is shown.
- * @see DolphinView::clearHoverInformation()
- */
- void showHoverInformation(const KFileItem& item);
-
- /**
- * Clears the hover information shown in the status bar.
- * @see DolphinView::showHoverInformation().
- */
- void clearHoverInformation();
-
/**
* Indicates in the status bar that the delete operation
* of the job \a job has been finished.
#include <QLabel>
#include <QVBoxLayout>
-/**
- * Helper function for sorting items with qSort() in
- * DolphinView::renameSelectedItems().
- */
-bool lessThan(const KFileItem& item1, const KFileItem& item2)
-{
- return KStringHandler::naturalCompare(item1.name(), item2.name()) < 0;
-}
-
RenameDialog::RenameDialog(QWidget *parent, const KFileItemList& items) :
KDialog(parent),
m_renameOneItem(false),