]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Merge remote-tracking branch 'origin/KDE/4.11'
authorFrank Reininghaus <frank78ac@googlemail.com>
Sat, 26 Oct 2013 07:30:18 +0000 (09:30 +0200)
committerFrank Reininghaus <frank78ac@googlemail.com>
Sat, 26 Oct 2013 07:30:18 +0000 (09:30 +0200)
49 files changed:
src/CMakeLists.txt
src/dolphincontextmenu.cpp
src/dolphindockwidget.cpp
src/dolphinmainwindow.cpp
src/dolphinnewfilemenu.cpp
src/dolphinnewfilemenu.h
src/dolphinpart.cpp
src/dolphinpart.desktop
src/dolphinpart.h
src/dolphinpart_ext.cpp
src/dolphinpart_ext.h
src/dolphinui.rc
src/dolphinviewcontainer.cpp
src/kitemviews/kfileitemlistview.cpp
src/kitemviews/kfileitemlistwidget.cpp
src/kitemviews/kfileitemlistwidget.h
src/kitemviews/kfileitemmodel.cpp
src/kitemviews/kfileitemmodel.h
src/kitemviews/kfileitemmodelrolesupdater.cpp
src/kitemviews/kfileitemmodelrolesupdater.h
src/kitemviews/kitemlistcontroller.cpp
src/kitemviews/kitemlistcontroller.h
src/kitemviews/kitemlistview.cpp
src/kitemviews/kitemlistview.h
src/kitemviews/kitemmodelbase.cpp
src/kitemviews/kitemmodelbase.h
src/kitemviews/kitemrange.h [new file with mode: 0644]
src/kitemviews/kstandarditemlistview.cpp
src/kitemviews/kstandarditemlistview.h
src/kitemviews/kstandarditemlistwidget.cpp
src/kitemviews/kstandarditemlistwidget.h
src/kitemviews/private/kdirectorycontentscounter.cpp [new file with mode: 0644]
src/kitemviews/private/kdirectorycontentscounter.h [new file with mode: 0644]
src/kitemviews/private/kdirectorycontentscounterworker.cpp [new file with mode: 0644]
src/kitemviews/private/kdirectorycontentscounterworker.h [new file with mode: 0644]
src/kitemviews/private/kitemlistsizehintresolver.cpp
src/kitemviews/private/kitemlistviewlayouter.cpp
src/settings/kcm/kcmdolphingeneral.desktop
src/settings/kcm/kcmdolphinnavigation.desktop
src/settings/kcm/kcmdolphinservices.desktop
src/settings/kcm/kcmdolphinviewmodes.desktop
src/tests/kfileitemmodelbenchmark.cpp
src/tests/kfileitemmodeltest.cpp
src/views/dolphinitemlistview.cpp
src/views/dolphinitemlistview.h
src/views/dolphinnewfilemenuobserver.cpp
src/views/dolphinnewfilemenuobserver.h
src/views/dolphinview.cpp
src/views/dolphinview.h

index 6856991d5ef119d994414edbcfc8cba5c3046114..48ea14c18e9696267c60917eb9f3cc0edf9edd98 100644 (file)
@@ -58,6 +58,8 @@ set(dolphinprivate_LIB_SRCS
     kitemviews/kstandarditemlistwidget.cpp
     kitemviews/kstandarditemlistview.cpp
     kitemviews/kstandarditemmodel.cpp
+    kitemviews/private/kdirectorycontentscounter.cpp
+    kitemviews/private/kdirectorycontentscounterworker.cpp
     kitemviews/private/kfileitemclipboard.cpp
     kitemviews/private/kfileitemmodeldirlister.cpp
     kitemviews/private/kfileitemmodelfilter.cpp
@@ -92,6 +94,7 @@ set(dolphinprivate_LIB_SRCS
     views/viewproperties.cpp
     views/zoomlevelinfo.cpp
     dolphinremoveaction.cpp
+    dolphinnewfilemenu.cpp
 )
 
 if(HAVE_NEPOMUK)
index f4b46988619e7bde82c4b6db588b2ce5f60d3386..7d11c3bcdb48d724c68d0c045169119b3fd867aa 100644 (file)
@@ -196,7 +196,7 @@ void DolphinContextMenu::openItemContextMenu()
     if (m_selectedItems.count() == 1) {
         if (m_fileInfo.isDir()) {
             // setup 'Create New' menu
-            DolphinNewFileMenu* newFileMenu = new DolphinNewFileMenu(m_mainWindow);
+            DolphinNewFileMenu* newFileMenu = new DolphinNewFileMenu(m_mainWindow->actionCollection(), this);
             const DolphinView* view = m_mainWindow->activeViewContainer()->view();
             newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown());
             newFileMenu->checkUpToDate();
index 0d8aea7bdf24ad7c398554042898106188a109d7..6495c8da963bef6431061bb34e0ab9e2f4bec3fe 100644 (file)
 
 #include <QStyle>
 
+namespace {
+    // Disable the 'Floatable' feature, i.e., the possibility to drag the
+    // dock widget out of the main window. This works around problems like
+    // https://bugs.kde.org/show_bug.cgi?id=288629
+    // https://bugs.kde.org/show_bug.cgi?id=322299
+    const QDockWidget::DockWidgetFeatures DefaultDockWidgetFeatures = QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetClosable;
+}
+
  // Empty titlebar for the dock widgets when "Lock Layout" has been activated.
 class DolphinDockTitleBar : public QWidget
 {
@@ -45,6 +53,7 @@ DolphinDockWidget::DolphinDockWidget(const QString& title, QWidget* parent, Qt::
     m_locked(false),
     m_dockTitleBar(0)
 {
+    setFeatures(DefaultDockWidgetFeatures);
 }
 
 DolphinDockWidget::DolphinDockWidget(QWidget* parent, Qt::WindowFlags flags) :
@@ -52,6 +61,7 @@ DolphinDockWidget::DolphinDockWidget(QWidget* parent, Qt::WindowFlags flags) :
     m_locked(false),
     m_dockTitleBar(0)
 {
+    setFeatures(DefaultDockWidgetFeatures);
 }
 
 DolphinDockWidget::~DolphinDockWidget()
@@ -71,9 +81,7 @@ void DolphinDockWidget::setLocked(bool lock)
             setFeatures(QDockWidget::NoDockWidgetFeatures);
         } else {
             setTitleBarWidget(0);
-            setFeatures(QDockWidget::DockWidgetMovable |
-                        QDockWidget::DockWidgetFloatable |
-                        QDockWidget::DockWidgetClosable);
+            setFeatures(DefaultDockWidgetFeatures);
         }
     }
 }
index 9da73f96e4f39f0162e23576e0bfd8503c4f0652..0804f4be9330033130a60f900fc2628fbf550070 100644 (file)
@@ -36,6 +36,7 @@
 #include "views/dolphinremoteencoding.h"
 #include "views/draganddrophelper.h"
 #include "views/viewproperties.h"
+#include "views/dolphinnewfilemenuobserver.h"
 
 #ifndef Q_OS_WIN
 #include "panels/terminal/terminalpanel.h"
@@ -127,6 +128,9 @@ DolphinMainWindow::DolphinMainWindow() :
     ViewTab& viewTab = m_viewTab[m_tabIndex];
     viewTab.wasActive = true; // The first opened tab is automatically active
 
+    connect(&DolphinNewFileMenuObserver::instance(), SIGNAL(errorMessage(QString)),
+            this, SLOT(showErrorMessage(QString)));
+
     KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
     undoManager->setUiInterface(new UndoUiInterface());
 
@@ -267,12 +271,12 @@ void DolphinMainWindow::openDirectories(const QList<KUrl>& dirs)
 
     // Open each directory inside a new tab. If the "split view" option has been enabled,
     // always show two directories within one tab.
-    QList<KUrl>::const_iterator it = urlsToOpen.begin();
-    while (it != urlsToOpen.end()) {
+    QList<KUrl>::const_iterator it = urlsToOpen.constBegin();
+    while (it != urlsToOpen.constEnd()) {
         openNewTab(*it);
         ++it;
 
-        if (hasSplitView && (it != urlsToOpen.end())) {
+        if (hasSplitView && (it != urlsToOpen.constEnd())) {
             const int tabIndex = m_viewTab.count() - 1;
             m_viewTab[tabIndex].secondaryView->setUrl(*it);
             ++it;
@@ -1481,7 +1485,7 @@ DolphinViewContainer* DolphinMainWindow::createViewContainer(const KUrl& url, QW
 void DolphinMainWindow::setupActions()
 {
     // setup 'File' menu
-    m_newFileMenu = new DolphinNewFileMenu(this);
+    m_newFileMenu = new DolphinNewFileMenu(actionCollection(), this);
     KMenu* menu = m_newFileMenu->menu();
     menu->setTitle(i18nc("@title:menu Create new folder, file, link, etc.", "Create New"));
     menu->setIcon(KIcon("document-new"));
index 9d9baabe2b6911fee5c0c3debba615e6fb242f1c..da57ca946f34a2c6eb4d235359c87cb3afb5f7a8 100644 (file)
 
 #include "dolphinnewfilemenu.h"
 
-#include "dolphinmainwindow.h"
-#include "dolphinviewcontainer.h"
 #include "views/dolphinnewfilemenuobserver.h"
-#include "views/dolphinview.h"
 
 #include <KActionCollection>
 #include <KIO/Job>
 
-DolphinNewFileMenu::DolphinNewFileMenu(DolphinMainWindow* parent) :
-    KNewFileMenu(parent->actionCollection(), "create_new", parent),
-    m_mainWin(parent)
+DolphinNewFileMenu::DolphinNewFileMenu(KActionCollection* collection, QObject* parent) :
+    KNewFileMenu(collection, "new_menu", parent)
 {
     DolphinNewFileMenuObserver::instance().attach(this);
 }
@@ -43,8 +39,7 @@ DolphinNewFileMenu::~DolphinNewFileMenu()
 void DolphinNewFileMenu::slotResult(KJob* job)
 {
     if (job->error()) {
-        DolphinViewContainer* container = m_mainWin->activeViewContainer();
-        container->showMessage(job->errorString(), DolphinViewContainer::Error);
+        emit errorMessage(job->errorString());
     } else {
         KNewFileMenu::slotResult(job);
     }
index 0d336080baac061724739a625fd346d45b6fd228..e211dfd881319a7495be258485ad1d16f410c94e 100644 (file)
@@ -23,7 +23,8 @@
 
 #include <KNewFileMenu>
 
-class DolphinMainWindow;
+#include "libdolphin_export.h"
+
 class KJob;
 
 /**
@@ -34,20 +35,20 @@ class KJob;
  * All errors are shown in the status bar of Dolphin
  * instead as modal error dialog with an OK button.
  */
-class DolphinNewFileMenu : public KNewFileMenu
+class LIBDOLPHINPRIVATE_EXPORT DolphinNewFileMenu : public KNewFileMenu
 {
     Q_OBJECT
 
 public:
-    DolphinNewFileMenu(DolphinMainWindow* parent);
+    DolphinNewFileMenu(KActionCollection* collection, QObject* parent);
     virtual ~DolphinNewFileMenu();
 
+signals:
+    void errorMessage(const QString& error);
+
 protected slots:
     /** @see KNewFileMenu::slotResult() */
     virtual void slotResult(KJob* job);
-
-private:
-    DolphinMainWindow* m_mainWin;
 };
 
 #endif
index 81fbacb77519e32bd57a66918ef818060d8c997e..90817319333dea9ed3bddf25e2b40ad97e926562 100644 (file)
@@ -37,7 +37,6 @@
 #include <KIO/NetAccess>
 #include <KToolInvocation>
 #include <kauthorized.h>
-#include <KNewFileMenu>
 #include <KMenu>
 #include <KInputDialog>
 #include <KProtocolInfo>
@@ -47,6 +46,7 @@
 #include "dolphinpart_ext.h"
 #endif
 
+#include "dolphinnewfilemenu.h"
 #include "views/dolphinview.h"
 #include "views/dolphinviewactionhandler.h"
 #include "views/dolphinnewfilemenuobserver.h"
@@ -79,6 +79,9 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL
     m_view->setTabsForFilesEnabled(true);
     setWidget(m_view);
 
+    connect(&DolphinNewFileMenuObserver::instance(), SIGNAL(errorMessage(QString)),
+            this, SLOT(slotErrorMessage(QString)));
+
     connect(m_view, SIGNAL(directoryLoadingCompleted()), this, SIGNAL(completed()));
     connect(m_view, SIGNAL(directoryLoadingProgress(int)), this, SLOT(updateProgress(int)));
     connect(m_view, SIGNAL(errorMessage(QString)), this, SLOT(slotErrorMessage(QString)));
@@ -160,16 +163,14 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL
 
 DolphinPart::~DolphinPart()
 {
-    DolphinNewFileMenuObserver::instance().detach(m_newFileMenu);
 }
 
 void DolphinPart::createActions()
 {
     // Edit menu
 
-    m_newFileMenu = new KNewFileMenu(actionCollection(), "new_menu", this);
+    m_newFileMenu = new DolphinNewFileMenu(actionCollection(), this);
     m_newFileMenu->setParentWidget(widget());
-    DolphinNewFileMenuObserver::instance().attach(m_newFileMenu);
     connect(m_newFileMenu->menu(), SIGNAL(aboutToShow()),
             this, SLOT(updateNewMenu()));
 
@@ -572,7 +573,8 @@ void DolphinPart::updateNewMenu()
 
 void DolphinPart::updateStatusBar()
 {
-    emit ReadOnlyPart::setStatusBarText(m_view->statusBarText());
+    const QString escapedText = Qt::convertFromPlainText(m_view->statusBarText());
+    emit ReadOnlyPart::setStatusBarText(QString("<qt>%1</qt>").arg(escapedText));
 }
 
 void DolphinPart::updateProgress(int percent)
@@ -614,89 +616,4 @@ bool DolphinPart::eventFilter(QObject* obj, QEvent* event)
     return KParts::ReadOnlyPart::eventFilter(obj, event);
 }
 
-////
-
-void DolphinPartBrowserExtension::restoreState(QDataStream &stream)
-{
-    KParts::BrowserExtension::restoreState(stream);
-    m_part->view()->restoreState(stream);
-}
-
-void DolphinPartBrowserExtension::saveState(QDataStream &stream)
-{
-    KParts::BrowserExtension::saveState(stream);
-    m_part->view()->saveState(stream);
-}
-
-void DolphinPartBrowserExtension::cut()
-{
-    m_part->view()->cutSelectedItems();
-}
-
-void DolphinPartBrowserExtension::copy()
-{
-    m_part->view()->copySelectedItems();
-}
-
-void DolphinPartBrowserExtension::paste()
-{
-    m_part->view()->paste();
-}
-
-void DolphinPartBrowserExtension::pasteTo(const KUrl&)
-{
-    m_part->view()->pasteIntoFolder();
-}
-
-void DolphinPartBrowserExtension::reparseConfiguration()
-{
-    m_part->view()->readSettings();
-}
-
-////
-
-DolphinPartFileInfoExtension::DolphinPartFileInfoExtension(DolphinPart* part)
-                             : KParts::FileInfoExtension(part)
-{
-}
-
-DolphinPart* DolphinPartFileInfoExtension::part() const
-{
-    return static_cast<DolphinPart*>(parent());
-}
-
-bool DolphinPartFileInfoExtension::hasSelection() const
-{
-    return part()->view()->selectedItemsCount() > 0;
-}
-
-KParts::FileInfoExtension::QueryModes DolphinPartFileInfoExtension::supportedQueryModes() const
-{
-    return (KParts::FileInfoExtension::AllItems | KParts::FileInfoExtension::SelectedItems);
-}
-
-KFileItemList DolphinPartFileInfoExtension::queryFor(KParts::FileInfoExtension::QueryMode mode) const
-{
-    KFileItemList list;
-
-    if (mode == KParts::FileInfoExtension::None)
-      return list;
-
-    if (!(supportedQueryModes() & mode))
-      return list;
-
-    switch (mode) {
-      case KParts::FileInfoExtension::SelectedItems:
-          if (hasSelection())
-              return part()->view()->selectedItems();
-          break;
-      case KParts::FileInfoExtension::AllItems:
-          return part()->view()->items();
-      default:
-          break;
-    }
-
-    return list;
-}
-
 #include "dolphinpart.moc"
index a553034a2cb74c83a91a4c479ac73d7fe2dde623..ac6607cc07fdd9fb318aa6279c61fa0f088b17f2 100644 (file)
@@ -196,6 +196,7 @@ Exec=dolphin
 [Desktop Action compact]
 Name=Compact
 Name[ar]=مضغوط
+Name[bg]=Компактно
 Name[bs]=Sabij
 Name[ca]=Compacte
 Name[ca@valencia]=Compacte
@@ -323,7 +324,7 @@ Name[te]=వివరాలు
 Name[tg]=Тафсилотҳо
 Name[th]=รายละเอียด
 Name[tr]=Ayrıntılar
-Name[ug]=تÛ\95پسÙ\89Ù\84اتÙ\89
+Name[ug]=تÛ\95پسÙ\89Ù\84اتÙ\84ار
 Name[uk]=Подробиці
 Name[uz]=Tafsilotlar
 Name[uz@cyrillic]=Тафсилотлар
index 172bfafc6d14b0dac5c7a5bc3b327902d9b43bbd..7146b46af375aadefbb4300f4cda950159e9e4c5 100644 (file)
 #define DOLPHINPART_H
 
 #include <kparts/part.h>
-#include <kparts/browserextension.h>
-#include <kparts/fileinfoextension.h>
 
 #include <QItemSelectionModel>
 
-class KNewFileMenu;
+class DolphinNewFileMenu;
 class DolphinViewActionHandler;
 class QActionGroup;
 class KAction;
@@ -244,7 +242,7 @@ private:
     DolphinViewActionHandler* m_actionHandler;
     DolphinRemoteEncoding* m_remoteEncoding;
     DolphinPartBrowserExtension* m_extension;
-    KNewFileMenu* m_newFileMenu;
+    DolphinNewFileMenu* m_newFileMenu;
     KAction* m_findFileAction;
     KAction* m_openTerminalAction;
     QString m_nameFilter;
@@ -252,41 +250,4 @@ private:
     Q_DISABLE_COPY(DolphinPart)
 };
 
-class DolphinPartBrowserExtension : public KParts::BrowserExtension
-{
-    Q_OBJECT
-public:
-    DolphinPartBrowserExtension( DolphinPart* part )
-        : KParts::BrowserExtension( part ), m_part(part) {}
-
-    virtual void restoreState(QDataStream &stream);
-    virtual void saveState(QDataStream &stream);
-
-public Q_SLOTS:
-    void cut();
-    void copy();
-    void paste();
-    void pasteTo(const KUrl&);
-    void reparseConfiguration();
-
-private:
-    DolphinPart* m_part;
-};
-
-
-class DolphinPartFileInfoExtension : public KParts::FileInfoExtension
-{
-    Q_OBJECT
-
-public:
-    DolphinPartFileInfoExtension(DolphinPart* part);
-
-    virtual QueryModes supportedQueryModes() const;
-    virtual bool hasSelection() const;
-
-    virtual KFileItemList queryFor(QueryMode mode) const;
-protected:
-    DolphinPart* part() const;
-};
-
 #endif /* DOLPHINPART_H */
index e98c0648ed612d6b0f9107d15a730dc73dffd8e8..fb7a4d2eaf6f0ca50406793449d076ea1833d4dc 100644 (file)
 
 #include <KFileItemList>
 
+
+DolphinPartBrowserExtension::DolphinPartBrowserExtension(DolphinPart* part)
+    :KParts::BrowserExtension( part )
+    ,m_part(part)
+{
+
+}
+
+void DolphinPartBrowserExtension::restoreState(QDataStream &stream)
+{
+    KParts::BrowserExtension::restoreState(stream);
+    m_part->view()->restoreState(stream);
+}
+
+void DolphinPartBrowserExtension::saveState(QDataStream &stream)
+{
+    KParts::BrowserExtension::saveState(stream);
+    m_part->view()->saveState(stream);
+}
+
+void DolphinPartBrowserExtension::cut()
+{
+    m_part->view()->cutSelectedItems();
+}
+
+void DolphinPartBrowserExtension::copy()
+{
+    m_part->view()->copySelectedItems();
+}
+
+void DolphinPartBrowserExtension::paste()
+{
+    m_part->view()->paste();
+}
+
+void DolphinPartBrowserExtension::pasteTo(const KUrl&)
+{
+    m_part->view()->pasteIntoFolder();
+}
+
+void DolphinPartBrowserExtension::reparseConfiguration()
+{
+    m_part->view()->readSettings();
+}
+
+
+DolphinPartFileInfoExtension::DolphinPartFileInfoExtension(DolphinPart* part)
+    :KParts::FileInfoExtension(part)
+    ,m_part(part)
+{
+}
+
+bool DolphinPartFileInfoExtension::hasSelection() const
+{
+    return m_part->view()->selectedItemsCount() > 0;
+}
+
+KParts::FileInfoExtension::QueryModes DolphinPartFileInfoExtension::supportedQueryModes() const
+{
+    return (KParts::FileInfoExtension::AllItems | KParts::FileInfoExtension::SelectedItems);
+}
+
+KFileItemList DolphinPartFileInfoExtension::queryFor(KParts::FileInfoExtension::QueryMode mode) const
+{
+    KFileItemList list;
+
+    if (mode == KParts::FileInfoExtension::None)
+      return list;
+
+    if (!(supportedQueryModes() & mode))
+      return list;
+
+    switch (mode) {
+      case KParts::FileInfoExtension::SelectedItems:
+          if (hasSelection())
+              return m_part->view()->selectedItems();
+          break;
+      case KParts::FileInfoExtension::AllItems:
+          return m_part->view()->items();
+      default:
+          break;
+    }
+
+    return list;
+}
+
 DolphinPartListingFilterExtension::DolphinPartListingFilterExtension(DolphinPart* part)
     : KParts::ListingFilterExtension(part)
     , m_part(part)
index 423e79efedbd11568194887e4017c32e6ff95398..c05962cd97bca5273b529b5501f34bd2eab9b85e 100644 (file)
 #ifndef DOLPHINPART_EXT_H
 #define DOLPHINPART_EXT_H
 
-
+#include <kparts/browserextension.h>
+#include <kparts/fileinfoextension.h>
 #include <kparts/listingextension.h>
 
 class DolphinPart;
 
+class DolphinPartBrowserExtension : public KParts::BrowserExtension
+{
+    Q_OBJECT
+public:
+    DolphinPartBrowserExtension( DolphinPart* part );
+    virtual void restoreState(QDataStream &stream);
+    virtual void saveState(QDataStream &stream);
+
+public Q_SLOTS:
+    void cut();
+    void copy();
+    void paste();
+    void pasteTo(const KUrl&);
+    void reparseConfiguration();
+
+private:
+    DolphinPart* m_part;
+};
+
+class DolphinPartFileInfoExtension : public KParts::FileInfoExtension
+{
+    Q_OBJECT
+
+public:
+    DolphinPartFileInfoExtension(DolphinPart* part);
+
+    virtual QueryModes supportedQueryModes() const;
+    virtual bool hasSelection() const;
+
+    virtual KFileItemList queryFor(QueryMode mode) const;
+
+private:
+    DolphinPart* m_part;
+};
+
 class DolphinPartListingFilterExtension : public KParts::ListingFilterExtension
 {
     Q_OBJECT
index 68e03752f5708e199ac24692d3d4001af015eeaf..52826bb43a1a7556ddca433262caaab8b0235924 100644 (file)
@@ -2,7 +2,7 @@
 <kpartgui name="dolphin" version="14">
     <MenuBar>
         <Menu name="file">
-            <Action name="create_new" />
+            <Action name="new_menu" />
             <Action name="new_window" />
             <Action name="new_tab" />
             <Action name="close_tab" />
index e7c571294be20f9ae13681be58a1de1f36762e62..cc26198a0f4f333bbae4078c641fcbe5fcb6feea 100644 (file)
@@ -508,8 +508,7 @@ void DolphinViewContainer::showItemInfo(const KFileItem& item)
     if (item.isNull()) {
         m_statusBar->resetToDefaultText();
     } else {
-        const QString text = item.isDir() ? item.text() : item.getStatusBarInfo();
-        m_statusBar->setText(text);
+        m_statusBar->setText(item.getStatusBarInfo());
     }
 }
 
index 1ffd5019b48dd9ac4719d3bbc12a2460279164bb..8950c9a1ee4f65ce364f07ff7d5d33bfce938f62 100644 (file)
@@ -221,12 +221,6 @@ void KFileItemListView::onPreviewsShownChanged(bool shown)
 
 void KFileItemListView::onItemLayoutChanged(ItemLayout current, ItemLayout previous)
 {
-    if (previous == DetailsLayout || current == DetailsLayout) {
-        // The details-layout requires some invisible roles that
-        // must be added to the model if the new layout is "details".
-        // If the old layout was "details" the roles will get removed.
-        applyRolesToModel();
-    }
     KStandardItemListView::onItemLayoutChanged(current, previous);
     triggerVisibleIndexRangeUpdate();
 }
index 3a7724134373a9e21c935d996515cd6b3aea8a33..688a4da083d0c5b15022f2c246d4e9cac5a6a542 100644 (file)
@@ -18,6 +18,8 @@
  ***************************************************************************/
 
 #include "kfileitemlistwidget.h"
+#include "kfileitemmodel.h"
+#include "kitemlistview.h"
 
 #include <kmimetype.h>
 #include <KDebug>
@@ -35,6 +37,15 @@ KFileItemListWidgetInformant::~KFileItemListWidgetInformant()
 {
 }
 
+QString KFileItemListWidgetInformant::itemText(int index, const KItemListView* view) const
+{
+    Q_ASSERT(qobject_cast<KFileItemModel*>(view->model()));
+    KFileItemModel* fileItemModel = static_cast<KFileItemModel*>(view->model());
+
+    const KFileItem item = fileItemModel->fileItem(index);
+    return item.text();
+}
+
 QString KFileItemListWidgetInformant::roleText(const QByteArray& role,
                                                const QHash<QByteArray, QVariant>& values) const
 {
index 24c6778281773823122836a16830a1153bc2f7af..1d7bc7f012d7be878a9b2ff8e3e98845c9e9b272 100644 (file)
@@ -31,6 +31,7 @@ public:
     virtual ~KFileItemListWidgetInformant();
 
 protected:
+    virtual QString itemText(int index, const KItemListView* view) const;
     virtual QString roleText(const QByteArray& role, const QHash<QByteArray, QVariant>& values) const;
 };
 
index 7b7c39ad74b643ae6c7ecc9867cdd8ffef46d05d..ea7ac2fc1bdf166a922de70f70c18b718d344c1d 100644 (file)
@@ -152,7 +152,12 @@ int KFileItemModel::count() const
 QHash<QByteArray, QVariant> KFileItemModel::data(int index) const
 {
     if (index >= 0 && index < count()) {
-        return m_itemData.at(index)->values;
+        ItemData* data = m_itemData.at(index);
+        if (data->values.isEmpty()) {
+            data->values = retrieveData(data->item, data->parent);
+        }
+
+        return data->values;
     }
     return QHash<QByteArray, QVariant>();
 }
@@ -163,7 +168,7 @@ bool KFileItemModel::setData(int index, const QHash<QByteArray, QVariant>& value
         return false;
     }
 
-    QHash<QByteArray, QVariant> currentValues = m_itemData.at(index)->values;
+    QHash<QByteArray, QVariant> currentValues = data(index);
 
     // Determine which roles have been changed
     QSet<QByteArray> changedRoles;
@@ -274,12 +279,12 @@ int KFileItemModel::indexForKeyboardSearch(const QString& text, int startFromInd
 {
     startFromIndex = qMax(0, startFromIndex);
     for (int i = startFromIndex; i < count(); ++i) {
-        if (data(i)["text"].toString().startsWith(text, Qt::CaseInsensitive)) {
+        if (fileItem(i).text().startsWith(text, Qt::CaseInsensitive)) {
             return i;
         }
     }
     for (int i = 0; i < startFromIndex; ++i) {
-        if (data(i)["text"].toString().startsWith(text, Qt::CaseInsensitive)) {
+        if (fileItem(i).text().startsWith(text, Qt::CaseInsensitive)) {
             return i;
         }
     }
@@ -439,11 +444,18 @@ bool KFileItemModel::setExpanded(int index, bool expanded)
         m_expandedDirs.remove(targetUrl);
         m_dirLister->stop(url);
 
-        removeFilteredChildren(KFileItemList() << item);
+        const int parentLevel = expandedParentsCount(index);
+        const int itemCount = m_itemData.count();
+        const int firstChildIndex = index + 1;
+
+        int childIndex = firstChildIndex;
+        while (childIndex < itemCount && expandedParentsCount(childIndex) > parentLevel) {
+            ++childIndex;
+        }
+        const int childrenCount = childIndex - firstChildIndex;
 
-        const KFileItemList itemsToRemove = childItems(item);
-        removeFilteredChildren(itemsToRemove);
-        removeItems(itemsToRemove, DeleteItemData);
+        removeFilteredChildren(KItemRangeList() << KItemRange(index, 1 + childrenCount));
+        removeItems(KItemRangeList() << KItemRange(firstChildIndex, childrenCount), DeleteItemData);
     }
 
     return true;
@@ -460,7 +472,9 @@ bool KFileItemModel::isExpanded(int index) const
 bool KFileItemModel::isExpandable(int index) const
 {
     if (index >= 0 && index < count()) {
-        return m_itemData.at(index)->values.value("isExpandable").toBool();
+        // Call data (instead of accessing m_itemData directly)
+        // to ensure that the value is initialized.
+        return data(index).value("isExpandable").toBool();
     }
     return false;
 }
@@ -468,10 +482,7 @@ bool KFileItemModel::isExpandable(int index) const
 int KFileItemModel::expandedParentsCount(int index) const
 {
     if (index >= 0 && index < count()) {
-        const int parentsCount = m_itemData.at(index)->values.value("expandedParentsCount").toInt();
-        if (parentsCount > 0) {
-            return parentsCount;
-        }
+        return expandedParentsCount(m_itemData.at(index));
     }
     return 0;
 }
@@ -547,21 +558,25 @@ void KFileItemModel::applyFilters()
 {
     // Check which shown items from m_itemData must get
     // hidden and hence moved to m_filteredItems.
-    KFileItemList newFilteredItems;
+    QVector<int> newFilteredIndexes;
+
+    const int itemCount = m_itemData.count();
+    for (int index = 0; index < itemCount; ++index) {
+        ItemData* itemData = m_itemData.at(index);
 
-    foreach (ItemData* itemData, m_itemData) {
         // Only filter non-expanded items as child items may never
         // exist without a parent item
         if (!itemData->values.value("isExpanded").toBool()) {
             const KFileItem item = itemData->item;
             if (!m_filter.matches(item)) {
-                newFilteredItems.append(item);
+                newFilteredIndexes.append(index);
                 m_filteredItems.insert(item, itemData);
             }
         }
     }
 
-    removeItems(newFilteredItems, KeepItemData);
+    const KItemRangeList removedRanges = KItemRangeList::fromSortedContainer(newFilteredIndexes);
+    removeItems(removedRanges, KeepItemData);
 
     // Check which hidden items from m_filteredItems should
     // get visible again and hence removed from m_filteredItems.
@@ -580,22 +595,24 @@ void KFileItemModel::applyFilters()
     insertItems(newVisibleItems);
 }
 
-void KFileItemModel::removeFilteredChildren(const KFileItemList& parentsList)
+void KFileItemModel::removeFilteredChildren(const KItemRangeList& itemRanges)
 {
-    if (m_filteredItems.isEmpty()) {
+    if (m_filteredItems.isEmpty() || !m_requestRole[ExpandedParentsCountRole]) {
+        // There are either no filtered items, or it is not possible to expand
+        // folders -> there cannot be any filtered children.
         return;
     }
 
-    // First, we put the parent items into a set to provide fast lookup
-    // while iterating over m_filteredItems and prevent quadratic
-    // complexity if there are N parents and N filtered items.
-    const QSet<KFileItem> parents = parentsList.toSet();
+    QSet<ItemData*> parents;
+    foreach (const KItemRange& range, itemRanges) {
+        for (int index = range.index; index < range.index + range.count; ++index) {
+            parents.insert(m_itemData.at(index));
+        }
+    }
 
     QHash<KFileItem, ItemData*>::iterator it = m_filteredItems.begin();
     while (it != m_filteredItems.end()) {
-        const ItemData* parent = it.value()->parent;
-
-        if (parent && parents.contains(parent->item)) {
+        if (parents.contains(it.value()->parent)) {
             delete it.value();
             it = m_filteredItems.erase(it);
         } else {
@@ -685,7 +702,6 @@ void KFileItemModel::resortAllItems()
         oldUrls.append(itemData->item.url());
     }
 
-    m_groups.clear();
     m_items.clear();
 
     // Resort the items
@@ -694,20 +710,45 @@ void KFileItemModel::resortAllItems()
         m_items.insert(m_itemData.at(i)->item.url(), i);
     }
 
-    // Determine the indexes that have been moved
-    QList<int> movedToIndexes;
-    movedToIndexes.reserve(itemCount);
-    for (int i = 0; i < itemCount; i++) {
-        const int newIndex = m_items.value(oldUrls.at(i));
-        movedToIndexes.append(newIndex);
+    // Determine the first index that has been moved.
+    int firstMovedIndex = 0;
+    while (firstMovedIndex < itemCount
+           && firstMovedIndex == m_items.value(oldUrls.at(firstMovedIndex))) {
+        ++firstMovedIndex;
     }
 
-    // Don't check whether items have really been moved and always emit a
-    // itemsMoved() signal after resorting: In case of grouped items
-    // the groups might change even if the items themselves don't change their
-    // position. Let the receiver of the signal decide whether a check for moved
-    // items makes sense.
-    emit itemsMoved(KItemRange(0, itemCount), movedToIndexes);
+    const bool itemsHaveMoved = firstMovedIndex < itemCount;
+    if (itemsHaveMoved) {
+        m_groups.clear();
+
+        int lastMovedIndex = itemCount - 1;
+        while (lastMovedIndex > firstMovedIndex
+               && lastMovedIndex == m_items.value(oldUrls.at(lastMovedIndex))) {
+            --lastMovedIndex;
+        }
+
+        Q_ASSERT(firstMovedIndex <= lastMovedIndex);
+
+        // Create a list movedToIndexes, which has the property that
+        // movedToIndexes[i] is the new index of the item with the old index
+        // firstMovedIndex + i.
+        const int movedItemsCount = lastMovedIndex - firstMovedIndex + 1;
+        QList<int> movedToIndexes;
+        movedToIndexes.reserve(movedItemsCount);
+        for (int i = firstMovedIndex; i <= lastMovedIndex; ++i) {
+            const int newIndex = m_items.value(oldUrls.at(i));
+            movedToIndexes.append(newIndex);
+        }
+
+        emit itemsMoved(KItemRange(firstMovedIndex, movedItemsCount), movedToIndexes);
+    } else if (groupedSorting()) {
+        // The groups might have changed even if the order of the items has not.
+        const QList<QPair<int, QVariant> > oldGroups = m_groups;
+        m_groups.clear();
+        if (groups() != oldGroups) {
+            emit groupsChanged();
+        }
+    }
 
 #ifdef KFILEITEMMODEL_DEBUG
     kDebug() << "[TIME] Resorting of" << itemCount << "items:" << timer.elapsed();
@@ -821,29 +862,49 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
 {
     dispatchPendingItemsToInsert();
 
-    KFileItemList itemsToRemove = items;
-    if (m_requestRole[ExpandedParentsCountRole]) {
-        // Assure that removing a parent item also results in removing all children
-        foreach (const KFileItem& item, items) {
-            itemsToRemove.append(childItems(item));
-        }
-    }
+    QVector<int> indexesToRemove;
+    indexesToRemove.reserve(items.count());
 
-    if (!m_filteredItems.isEmpty()) {
-        foreach (const KFileItem& item, itemsToRemove) {
+    foreach (const KFileItem& item, items) {
+        const KUrl url = item.url();
+        const int index = m_items.value(url, -1);
+        if (index >= 0) {
+            indexesToRemove.append(index);
+        } else {
+            // Probably the item has been filtered.
             QHash<KFileItem, ItemData*>::iterator it = m_filteredItems.find(item);
             if (it != m_filteredItems.end()) {
                 delete it.value();
                 m_filteredItems.erase(it);
             }
         }
+    }
 
-        if (m_requestRole[ExpandedParentsCountRole]) {
-            removeFilteredChildren(itemsToRemove);
+    std::sort(indexesToRemove.begin(), indexesToRemove.end());
+
+    if (m_requestRole[ExpandedParentsCountRole] && !m_expandedDirs.isEmpty()) {
+        // Assure that removing a parent item also results in removing all children
+        QVector<int> indexesToRemoveWithChildren;
+        indexesToRemoveWithChildren.reserve(m_items.count());
+
+        const int itemCount = m_itemData.count();
+        foreach (int index, indexesToRemove) {
+            indexesToRemoveWithChildren.append(index);
+
+            const int parentLevel = expandedParentsCount(index);
+            int childIndex = index + 1;
+            while (childIndex < itemCount && expandedParentsCount(childIndex) > parentLevel) {
+                indexesToRemoveWithChildren.append(childIndex);
+                ++childIndex;
+            }
         }
+
+        indexesToRemove = indexesToRemoveWithChildren;
     }
 
-    removeItems(itemsToRemove, DeleteItemData);
+    const KItemRangeList itemRanges = KItemRangeList::fromSortedContainer(indexesToRemove);
+    removeFilteredChildren(itemRanges);
+    removeItems(itemRanges, DeleteItemData);
 }
 
 void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >& items)
@@ -895,30 +956,7 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
 
     // Extract the item-ranges out of the changed indexes
     qSort(indexes);
-
-    KItemRangeList itemRangeList;
-    int previousIndex = indexes.at(0);
-    int rangeIndex = previousIndex;
-    int rangeCount = 1;
-
-    const int maxIndex = indexes.count() - 1;
-    for (int i = 1; i <= maxIndex; ++i) {
-        const int currentIndex = indexes.at(i);
-        if (currentIndex == previousIndex + 1) {
-            ++rangeCount;
-        } else {
-            itemRangeList.append(KItemRange(rangeIndex, rangeCount));
-
-            rangeIndex = currentIndex;
-            rangeCount = 1;
-        }
-        previousIndex = currentIndex;
-    }
-
-    if (rangeCount > 0) {
-        itemRangeList.append(KItemRange(rangeIndex, rangeCount));
-    }
-
+    const KItemRangeList itemRangeList = KItemRangeList::fromSortedContainer(indexes);
     emitItemsChangedAndTriggerResorting(itemRangeList, changedRoles);
 }
 
@@ -1056,53 +1094,21 @@ void KFileItemModel::insertItems(QList<ItemData*>& newItems)
 #endif
 }
 
-static KItemRangeList sortedIndexesToKItemRangeList(const QList<int>& sortedNumbers)
+void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBehavior behavior)
 {
-    if (sortedNumbers.empty()) {
-        return KItemRangeList();
-    }
-
-    KItemRangeList result;
-
-    QList<int>::const_iterator it = sortedNumbers.begin();
-    int index = *it;
-    int count = 1;
-
-    ++it;
-
-    QList<int>::const_iterator end = sortedNumbers.end();
-    while (it != end) {
-        if (*it == index + count) {
-            ++count;
-        } else {
-            result << KItemRange(index, count);
-            index = *it;
-            count = 1;
-        }
-        ++it;
+    if (itemRanges.isEmpty()) {
+        return;
     }
 
-    result << KItemRange(index, count);
-    return result;
-}
-
-void KFileItemModel::removeItems(const KFileItemList& items, RemoveItemsBehavior behavior)
-{
-#ifdef KFILEITEMMODEL_DEBUG
-    kDebug() << "Removing " << items.count() << "items";
-#endif
-
     m_groups.clear();
 
-    // Step 1: Determine the indexes of the removed items, remove them from
-    //         the hash m_items, and free the ItemData.
-    QList<int> indexesToRemove;
-    indexesToRemove.reserve(items.count());
-    foreach (const KFileItem& item, items) {
-        const KUrl url = item.url();
-        const int index = m_items.value(url, -1);
-        if (index >= 0) {
-            indexesToRemove.append(index);
+    // Step 1: Remove the items from the hash m_items, and free the ItemData.
+    int removedItemsCount = 0;
+    foreach (const KItemRange& range, itemRanges) {
+        removedItemsCount += range.count;
+
+        for (int index = range.index; index < range.index + range.count; ++index) {
+            const KUrl url = m_itemData.at(index)->item.url();
 
             // Prevent repeated expensive rehashing by using QHash::erase(),
             // rather than QHash::remove().
@@ -1117,14 +1123,7 @@ void KFileItemModel::removeItems(const KFileItemList& items, RemoveItemsBehavior
         }
     }
 
-    if (indexesToRemove.isEmpty()) {
-        return;
-    }
-
-    std::sort(indexesToRemove.begin(), indexesToRemove.end());
-
     // Step 2: Remove the ItemData pointers from the list m_itemData.
-    const KItemRangeList itemRanges = sortedIndexesToKItemRangeList(indexesToRemove);
     int target = itemRanges.at(0).index;
     int source = itemRanges.at(0).index + itemRanges.at(0).count;
     int nextRange = 1;
@@ -1142,7 +1141,7 @@ void KFileItemModel::removeItems(const KFileItemList& items, RemoveItemsBehavior
         }
     }
 
-    m_itemData.erase(m_itemData.end() - indexesToRemove.count(), m_itemData.end());
+    m_itemData.erase(m_itemData.end() - removedItemsCount, m_itemData.end());
 
     // Step 3: Adjust indexes in the hash m_items, starting from the
     //         index of the first removed item.
@@ -1172,30 +1171,75 @@ QList<KFileItemModel::ItemData*> KFileItemModel::createItemDataList(const KUrl&
     foreach (const KFileItem& item, items) {
         ItemData* itemData = new ItemData();
         itemData->item = item;
-        itemData->values = retrieveData(item, parentItem);
         itemData->parent = parentItem;
         itemDataList.append(itemData);
     }
 
+    switch (m_sortRole) {
+    case PermissionsRole:
+    case OwnerRole:
+    case GroupRole:
+    case DestinationRole:
+    case PathRole:
+        // These roles can be determined with retrieveData, and they have to be stored
+        // in the QHash "values" for the sorting.
+        foreach (ItemData* itemData, itemDataList) {
+            itemData->values = retrieveData(itemData->item, parentItem);
+        }
+        break;
+
+    case TypeRole:
+        // At least store the data including the file type for items with known MIME type.
+        foreach (ItemData* itemData, itemDataList) {
+            const KFileItem item = itemData->item;
+            if (item.isDir() || item.isMimeTypeKnown()) {
+                itemData->values = retrieveData(itemData->item, parentItem);
+            }
+        }
+        break;
+
+    default:
+        // The other roles are either resolved by KFileItemModelRolesUpdater
+        // (this includes the SizeRole for directories), or they do not need
+        // to be stored in the QHash "values" for sorting because the data can
+        // be retrieved directly from the KFileItem (NameRole, SiezRole for files,
+        // DateRole).
+        break;
+    }
+
     return itemDataList;
 }
 
+int KFileItemModel::expandedParentsCount(const ItemData* data)
+{
+    // The hash 'values' is only guaranteed to contain the key "expandedParentsCount"
+    // if the corresponding item is expanded, and it is not a top-level item.
+    const ItemData* parent = data->parent;
+    if (parent) {
+        if (parent->parent) {
+            Q_ASSERT(parent->values.contains("expandedParentsCount"));
+            return parent->values.value("expandedParentsCount").toInt() + 1;
+        } else {
+            return 1;
+        }
+    } else {
+        return 0;
+    }
+}
+
 void KFileItemModel::removeExpandedItems()
 {
-    KFileItemList expandedItems;
+    QVector<int> indexesToRemove;
 
     const int maxIndex = m_itemData.count() - 1;
     for (int i = 0; i <= maxIndex; ++i) {
         const ItemData* itemData = m_itemData.at(i);
-        if (itemData->values.value("expandedParentsCount").toInt() > 0) {
-            expandedItems.append(itemData->item);
+        if (itemData->parent) {
+            indexesToRemove.append(i);
         }
     }
 
-    // The m_expandedParentsCountRoot may not get reset before all items with
-    // a bigger count have been removed.
-    removeItems(expandedItems, DeleteItemData);
-
+    removeItems(KItemRangeList::fromSortedContainer(indexesToRemove), DeleteItemData);
     m_expandedDirs.clear();
 
     // Also remove all filtered items which have a parent.
@@ -1405,7 +1449,7 @@ QHash<QByteArray, QVariant> KFileItemModel::retrieveData(const KFileItem& item,
 
     if (m_requestRole[ExpandedParentsCountRole]) {
         if (parent) {
-            const int level = parent->values["expandedParentsCount"].toInt() + 1;
+            const int level = expandedParentsCount(parent) + 1;
             data.insert(sharedValue("expandedParentsCount"), level);
         }
     }
@@ -1429,8 +1473,8 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b) const
     int result = 0;
 
     if (a->parent != b->parent) {
-        const int expansionLevelA = a->values.value("expandedParentsCount").toInt();
-        const int expansionLevelB = b->values.value("expandedParentsCount").toInt();
+        const int expansionLevelA = expandedParentsCount(a);
+        const int expansionLevelB = expandedParentsCount(b);
 
         // If b has a higher expansion level than a, check if a is a parent
         // of b, and make sure that both expansion levels are equal otherwise.
@@ -1450,7 +1494,7 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b) const
             a = a->parent;
         }
 
-        Q_ASSERT(a->values.value("expandedParentsCount").toInt() == b->values.value("expandedParentsCount").toInt());
+        Q_ASSERT(expandedParentsCount(a) == expandedParentsCount(b));
 
         // Compare the last parents of a and b which are different.
         while (a->parent != b->parent) {
@@ -1660,7 +1704,7 @@ QList<QPair<int, QVariant> > KFileItemModel::nameRoleGroups() const
             continue;
         }
 
-        const QString name = m_itemData.at(i)->values.value("text").toString();
+        const QString name = m_itemData.at(i)->item.text();
 
         // Use the first character of the name as group indication
         QChar newFirstChar = name.at(0).toUpper();
@@ -1943,23 +1987,6 @@ QList<QPair<int, QVariant> > KFileItemModel::genericStringRoleGroups(const QByte
     return groups;
 }
 
-KFileItemList KFileItemModel::childItems(const KFileItem& item) const
-{
-    KFileItemList items;
-
-    int index = m_items.value(item.url(), -1);
-    if (index >= 0) {
-        const int parentLevel = m_itemData.at(index)->values.value("expandedParentsCount").toInt();
-        ++index;
-        while (index < m_itemData.count() && m_itemData.at(index)->values.value("expandedParentsCount").toInt() > parentLevel) {
-            items.append(m_itemData.at(index)->item);
-            ++index;
-        }
-    }
-
-    return items;
-}
-
 void KFileItemModel::emitSortProgress(int resolvedCount)
 {
     // Be tolerant against a resolvedCount with a wrong range.
@@ -2086,7 +2113,7 @@ bool KFileItemModel::isConsistent() const
         const ItemData* data = m_itemData.at(i);
         const ItemData* parent = data->parent;
         if (parent) {
-            if (data->values.value("expandedParentsCount").toInt() != parent->values.value("expandedParentsCount").toInt() + 1) {
+            if (expandedParentsCount(data) != expandedParentsCount(parent) + 1) {
                 qWarning() << "expandedParentsCount is inconsistent for parent" << parent->item << "and child" << data->item;
                 return false;
             }
index c87ee9736d3812b5a5296b097efeec3da02df106..d005705492e1a0feb4092808eca2f488ac0143ae 100644 (file)
@@ -309,7 +309,7 @@ private:
     };
 
     void insertItems(QList<ItemData*>& items);
-    void removeItems(const KFileItemList& items, RemoveItemsBehavior behavior);
+    void removeItems(const KItemRangeList& itemRanges, RemoveItemsBehavior behavior);
 
     /**
      * Helper method for insertItems() and removeItems(): Creates
@@ -319,6 +319,8 @@ private:
      */
     QList<ItemData*> createItemDataList(const KUrl& parentUrl, const KFileItemList& items) const;
 
+    static int expandedParentsCount(const ItemData* data);
+
     void removeExpandedItems();
 
     /**
@@ -387,11 +389,6 @@ private:
      */
     bool isChildItem(int index) const;
 
-    /**
-     * @return Recursive list of child items that have \a item as upper most parent.
-     */
-    KFileItemList childItems(const KFileItem& item) const;
-
     /**
      * Is invoked by KFileItemModelRolesUpdater and results in emitting the
      * sortProgress signal with a percent-value of the progress.
@@ -407,7 +404,7 @@ private:
      * Removes filtered items whose expanded parents have been deleted
      * or collapsed via setExpanded(parentIndex, false).
      */
-    void removeFilteredChildren(const KFileItemList& parentsList);
+    void removeFilteredChildren(const KItemRangeList& parents);
 
     /**
      * Maps the QByteArray-roles to RoleTypes and provides translation- and
@@ -490,7 +487,11 @@ private:
 
 inline bool KFileItemModel::isChildItem(int index) const
 {
-    return m_requestRole[ExpandedParentsCountRole] && m_itemData.at(index)->values.value("expandedParentsCount").toInt() > 0;
+    if (m_itemData.at(index)->parent) {
+        return true;
+    } else {
+        return false;
+    }
 }
 
 #endif
index e9b69566d5b542ddb5234961b32bbd1652b85b61..d6445c981f72dcf5a0aa45851d169b056feff14b 100644 (file)
 #include <KConfig>
 #include <KConfigGroup>
 #include <KDebug>
-#include <KDirWatch>
 #include <KFileItem>
 #include <KGlobal>
 #include <KIO/JobUiDelegate>
 #include <KIO/PreviewJob>
 
 #include "private/kpixmapmodifier.h"
+#include "private/kdirectorycontentscounter.h"
 
 #include <QApplication>
 #include <QPainter>
     #include <Nepomuk2/ResourceManager>
 #endif
 
-// Required includes for subItemsCount():
-#ifdef Q_WS_WIN
-    #include <QDir>
-#else
-    #include <dirent.h>
-    #include <QFile>
-#endif
-
 // #define KFILEITEMMODELROLESUPDATER_DEBUG
 
 namespace {
@@ -95,8 +87,7 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
     m_recentlyChangedItemsTimer(0),
     m_recentlyChangedItems(),
     m_changedItems(),
-    m_dirWatcher(0),
-    m_watchedDirs()
+    m_directoryContentsCounter(0)
   #ifdef HAVE_NEPOMUK
   , m_nepomukResourceWatcher(0),
     m_nepomukUriItems()
@@ -135,10 +126,9 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
     m_resolvableRoles += KNepomukRolesProvider::instance().roles();
 #endif
 
-    // When folders are expandable or the item-count is shown for folders, it is necessary
-    // to watch the number of items of the sub-folder to be able to react on changes.
-    m_dirWatcher = new KDirWatch(this);
-    connect(m_dirWatcher, SIGNAL(dirty(QString)), this, SLOT(slotDirWatchDirty(QString)));
+    m_directoryContentsCounter = new KDirectoryContentsCounter(m_model, this);
+    connect(m_directoryContentsCounter, SIGNAL(result(QString,int)),
+            this,                       SLOT(slotDirectoryContentsCountReceived(QString,int)));
 }
 
 KFileItemModelRolesUpdater::~KFileItemModelRolesUpdater()
@@ -367,25 +357,6 @@ void KFileItemModelRolesUpdater::slotItemsRemoved(const KItemRangeList& itemRang
 
     const bool allItemsRemoved = (m_model->count() == 0);
 
-    if (!m_watchedDirs.isEmpty()) {
-        // Don't let KDirWatch watch for removed items
-        if (allItemsRemoved) {
-            foreach (const QString& path, m_watchedDirs) {
-                m_dirWatcher->removeDir(path);
-            }
-            m_watchedDirs.clear();
-        } else {
-            QMutableSetIterator<QString> it(m_watchedDirs);
-            while (it.hasNext()) {
-                const QString& path = it.next();
-                if (m_model->index(KUrl(path)) < 0) {
-                    m_dirWatcher->removeDir(path);
-                    it.remove();
-                }
-            }
-        }
-    }
-
 #ifdef HAVE_NEPOMUK
     if (m_nepomukResourceWatcher) {
         // Don't let the ResourceWatcher watch for removed items
@@ -783,7 +754,7 @@ void KFileItemModelRolesUpdater::applyChangedNepomukRoles(const Nepomuk2::Resour
 #endif
 }
 
-void KFileItemModelRolesUpdater::slotDirWatchDirty(const QString& path)
+void KFileItemModelRolesUpdater::slotDirectoryContentsCountReceived(const QString& path, int count)
 {
     const bool getSizeRole = m_roles.contains("size");
     const bool getIsExpandableRole = m_roles.contains("isExpandable");
@@ -791,16 +762,9 @@ void KFileItemModelRolesUpdater::slotDirWatchDirty(const QString& path)
     if (getSizeRole || getIsExpandableRole) {
         const int index = m_model->index(KUrl(path));
         if (index >= 0) {
-            if (!m_model->fileItem(index).isDir()) {
-                // If INotify is used, KDirWatch issues the dirty() signal
-                // also for changed files inside the directory, even if we
-                // don't enable this behavior explicitly (see bug 309740).
-                return;
-            }
 
             QHash<QByteArray, QVariant> data;
 
-            const int count = subItemsCount(path);
             if (getSizeRole) {
                 data.insert("size", count);
             }
@@ -808,9 +772,11 @@ void KFileItemModelRolesUpdater::slotDirWatchDirty(const QString& path)
                 data.insert("isExpandable", count > 0);
             }
 
-            // Note that we do not block the itemsChanged signal here.
-            // This ensures that a new preview will be generated.
+            disconnect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+                       this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
             m_model->setData(index, data);
+            connect(m_model, SIGNAL(itemsChanged(KItemRangeList,QSet<QByteArray>)),
+                    this,    SLOT(slotItemsChanged(KItemRangeList,QSet<QByteArray>)));
         }
     }
 }
@@ -1037,7 +1003,7 @@ void KFileItemModelRolesUpdater::applySortRole(int index)
         data.insert("type", item.mimeComment());
     } else if (m_model->sortRole() == "size" && item.isLocalFile() && item.isDir()) {
         const QString path = item.localPath();
-        data.insert("size", subItemsCount(path));
+        data.insert("size", m_directoryContentsCounter->countDirectoryContentsSynchronously(path));
     } else {
         // Probably the sort role is a Nepomuk role - just determine all roles.
         data = rolesData(item);
@@ -1105,7 +1071,7 @@ bool KFileItemModelRolesUpdater::applyResolvedRoles(const KFileItem& item, Resol
     return false;
 }
 
-QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileItem& item) const
+QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileItem& item)
 {
     QHash<QByteArray, QVariant> data;
 
@@ -1114,19 +1080,10 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
 
     if ((getSizeRole || getIsExpandableRole) && item.isDir()) {
         if (item.isLocalFile()) {
+            // Tell m_directoryContentsCounter that we want to count the items
+            // inside the directory. The result will be received in slotDirectoryContentsCountReceived.
             const QString path = item.localPath();
-            const int count = subItemsCount(path);
-            if (getSizeRole) {
-                data.insert("size", count);
-            }
-            if (getIsExpandableRole) {
-                data.insert("isExpandable", count > 0);
-            }
-
-            if (!m_dirWatcher->contains(path)) {
-                m_dirWatcher->addDir(path);
-                m_watchedDirs.insert(path);
-            }
+            m_directoryContentsCounter->addDirectory(path);
         } else if (getSizeRole) {
             data.insert("size", -1); // -1 indicates an unknown number of items
         }
@@ -1170,61 +1127,6 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
     return data;
 }
 
-int KFileItemModelRolesUpdater::subItemsCount(const QString& path) const
-{
-    const bool countHiddenFiles = m_model->showHiddenFiles();
-    const bool showFoldersOnly  = m_model->showDirectoriesOnly();
-
-#ifdef Q_WS_WIN
-    QDir dir(path);
-    QDir::Filters filters = QDir::NoDotAndDotDot | QDir::System;
-    if (countHiddenFiles) {
-        filters |= QDir::Hidden;
-    }
-    if (showFoldersOnly) {
-        filters |= QDir::Dirs;
-    } else {
-        filters |= QDir::AllEntries;
-    }
-    return dir.entryList(filters).count();
-#else
-    // Taken from kdelibs/kio/kio/kdirmodel.cpp
-    // Copyright (C) 2006 David Faure <faure@kde.org>
-
-    int count = -1;
-    DIR* dir = ::opendir(QFile::encodeName(path));
-    if (dir) {  // krazy:exclude=syscalls
-        count = 0;
-        struct dirent *dirEntry = 0;
-        while ((dirEntry = ::readdir(dir))) {
-            if (dirEntry->d_name[0] == '.') {
-                if (dirEntry->d_name[1] == '\0' || !countHiddenFiles) {
-                    // Skip "." or hidden files
-                    continue;
-                }
-                if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0') {
-                    // Skip ".."
-                    continue;
-                }
-            }
-
-            // If only directories are counted, consider an unknown file type and links also
-            // as directory instead of trying to do an expensive stat()
-            // (see bugs 292642 and 299997).
-            const bool countEntry = !showFoldersOnly ||
-                                    dirEntry->d_type == DT_DIR ||
-                                    dirEntry->d_type == DT_LNK ||
-                                    dirEntry->d_type == DT_UNKNOWN;
-            if (countEntry) {
-                ++count;
-            }
-        }
-        ::closedir(dir);
-    }
-    return count;
-#endif
-}
-
 void KFileItemModelRolesUpdater::updateAllPreviews()
 {
     if (m_state == Paused) {
index 409f098e8cd60df6e18bf241e230c25c15ba69a0..fced44a85da6be095899c01c7db50253a5b0e082 100644 (file)
@@ -32,7 +32,7 @@
 #include <QSize>
 #include <QStringList>
 
-class KDirWatch;
+class KDirectoryContentsCounter;
 class KFileItemModel;
 class KJob;
 class QPixmap;
@@ -218,12 +218,7 @@ private slots:
 
     void applyChangedNepomukRoles(const Nepomuk2::Resource& resource, const Nepomuk2::Types::Property& property);
 
-    /**
-     * Is invoked if a directory watched by KDirWatch got dirty. Updates
-     * the "isExpandable"- and "size"-roles of the item that matches to
-     * the given path.
-     */
-    void slotDirWatchDirty(const QString& path);
+    void slotDirectoryContentsCountReceived(const QString& path, int count);
 
 private:
     /**
@@ -267,7 +262,7 @@ private:
         ResolveAll
     };
     bool applyResolvedRoles(const KFileItem& item, ResolveHint hint);
-    QHash<QByteArray, QVariant> rolesData(const KFileItem& item) const;
+    QHash<QByteArray, QVariant> rolesData(const KFileItem& item);
 
     /**
      * @return The number of items of the path \a path.
@@ -349,9 +344,8 @@ private:
     // Items which have not been changed repeatedly recently.
     QSet<KFileItem> m_changedItems;
 
-    KDirWatch* m_dirWatcher;
-    mutable QSet<QString> m_watchedDirs; // Required as sadly KDirWatch does not offer a getter method
-                                         // to get all watched directories.
+    KDirectoryContentsCounter* m_directoryContentsCounter;
+
 #ifdef HAVE_NEPOMUK
     Nepomuk2::ResourceWatcher* m_nepomukResourceWatcher;
     mutable QHash<QUrl, KUrl> m_nepomukUriItems;
index 9335ab816c334631ffa53ff6cbf78563e9399097..befb09713ec9fd2c53b0efc03e6c5cb025a10aa6 100644 (file)
@@ -403,6 +403,7 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
             m_selectionManager->clearSelection();
         }
         m_keyboardManager->cancelSearch();
+        emit escapePressed();
         break;
 
     case Qt::Key_Space:
index 4d5fee3450fa8e391dc881f1878e057e863290b0..bb72856e0c1e053c8dc1cdb8d5e432f101a4ed9e 100644 (file)
@@ -230,6 +230,11 @@ signals:
      */
     void aboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* event);
 
+    /**
+     * Is emitted if the Escape key is pressed.
+     */
+    void escapePressed();
+
     void modelChanged(KItemModelBase* current, KItemModelBase* previous);
     void viewChanged(KItemListView* current, KItemListView* previous);
 
index a667150904147ecd72568abdf95e9eb0ce332739..b3d805a917ef2c07be519c49acd33a3ce5f6ff8c 100644 (file)
@@ -1233,6 +1233,13 @@ void KItemListView::slotItemsChanged(const KItemRangeList& itemRanges,
     QAccessible::updateAccessibility(this, 0, QAccessible::TableModelChanged);
 }
 
+void KItemListView::slotGroupsChanged()
+{
+    updateVisibleGroupHeaders();
+    doLayout(NoAnimation);
+    updateSiblingsInformation();
+}
+
 void KItemListView::slotGroupedSortingChanged(bool current)
 {
     m_grouped = current;
@@ -1527,6 +1534,8 @@ void KItemListView::setModel(KItemModelBase* model)
                    this,    SLOT(slotItemsRemoved(KItemRangeList)));
         disconnect(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)),
                    this,    SLOT(slotItemsMoved(KItemRange,QList<int>)));
+        disconnect(m_model, SIGNAL(groupsChanged()),
+                   this,    SLOT(slotGroupsChanged()));
         disconnect(m_model, SIGNAL(groupedSortingChanged(bool)),
                    this,    SLOT(slotGroupedSortingChanged(bool)));
         disconnect(m_model, SIGNAL(sortOrderChanged(Qt::SortOrder,Qt::SortOrder)),
@@ -1550,6 +1559,8 @@ void KItemListView::setModel(KItemModelBase* model)
                 this,    SLOT(slotItemsRemoved(KItemRangeList)));
         connect(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)),
                 this,    SLOT(slotItemsMoved(KItemRange,QList<int>)));
+        connect(m_model, SIGNAL(groupsChanged()),
+                this,    SLOT(slotGroupsChanged()));
         connect(m_model, SIGNAL(groupedSortingChanged(bool)),
                 this,    SLOT(slotGroupedSortingChanged(bool)));
         connect(m_model, SIGNAL(sortOrderChanged(Qt::SortOrder,Qt::SortOrder)),
index 6467b8c915cc252c56bfafbdd46b3534d91d33d7..14360b02bb2d9bae20ed1f0c43a76bf31f356fce 100644 (file)
@@ -394,6 +394,7 @@ protected slots:
     virtual void slotItemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes);
     virtual void slotItemsChanged(const KItemRangeList& itemRanges,
                                   const QSet<QByteArray>& roles);
+    virtual void slotGroupsChanged();
 
     virtual void slotGroupedSortingChanged(bool current);
     virtual void slotSortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous);
index c13c9f88c815430a9802f349f40491b2a261dbfb..edce95ece937a3846d4a6dcb5e105d069989be43 100644 (file)
 
 #include "kitemmodelbase.h"
 
-KItemRange::KItemRange(int index, int count) :
-    index(index),
-    count(count)
-{
-}
-
-bool KItemRange::operator == (const KItemRange& other) const
-{
-    return index == other.index && count == other.count;
-}
-
 KItemModelBase::KItemModelBase(QObject* parent) :
     QObject(parent),
     m_groupedSorting(false),
index 70f688390951986171a6f9fab75f4e28301f0263..c5b9a0ca5f9a2bc146221c83c486753fd0c65e91 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <libdolphin_export.h>
 
+#include <kitemviews/kitemrange.h>
+
 #include <QHash>
 #include <QObject>
 #include <QSet>
 
 class QMimeData;
 
-struct KItemRange
-{
-    KItemRange(int index = 0, int count = 0);
-    int index;
-    int count;
-
-    bool operator == (const KItemRange& other) const;
-};
-typedef QList<KItemRange> KItemRangeList;
-
 /**
  * @brief Base class for model implementations used by KItemListView and KItemListController.
  *
@@ -218,11 +210,20 @@ signals:
      * with the items 5 and 6 then the parameters look like this:
      * - itemRange: has the index 0 and a count of 7.
      * - movedToIndexes: Contains the seven values 5, 6, 2, 3, 4, 0, 1
+     *
+     * This signal implies that the groups might have changed. Therefore,
+     * gropusChanged() is not emitted if this signal is emitted.
      */
     void itemsMoved(const KItemRange& itemRange, const QList<int>& movedToIndexes);
 
     void itemsChanged(const KItemRangeList& itemRanges, const QSet<QByteArray>& roles);
 
+    /**
+     * Is emitted if the groups have changed, even though the order of the
+     * items has not been modified.
+     */
+    void groupsChanged();
+
     void groupedSortingChanged(bool current);
     void sortRoleChanged(const QByteArray& current, const QByteArray& previous);
     void sortOrderChanged(Qt::SortOrder current, Qt::SortOrder previous);
diff --git a/src/kitemviews/kitemrange.h b/src/kitemviews/kitemrange.h
new file mode 100644 (file)
index 0000000..70927b9
--- /dev/null
@@ -0,0 +1,98 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2013 by Frank Reininghaus <frank78ac@googlemail.com>    *
+ *                                                                         *
+ *   Based on the Itemviews NG project from Trolltech Labs:                *
+ *   http://qt.gitorious.org/qt-labs/itemviews-ng                          *
+ *                                                                         *
+ *   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 KITEMRANGE_H
+#define KITEMRANGE_H
+
+#include <QList>
+
+struct KItemRange
+{
+    KItemRange(int index = 0, int count = 0);
+    int index;
+    int count;
+
+    bool operator == (const KItemRange& other) const;
+};
+
+inline KItemRange::KItemRange(int index, int count) :
+    index(index),
+    count(count)
+{
+}
+
+inline bool KItemRange::operator == (const KItemRange& other) const
+{
+    return index == other.index && count == other.count;
+}
+
+
+class KItemRangeList : public QList<KItemRange>
+{
+public:
+    KItemRangeList() : QList<KItemRange>() {}
+    KItemRangeList(const QList<KItemRange>& list) : QList<KItemRange>(list) {}
+
+    template<class Container>
+    static KItemRangeList fromSortedContainer(const Container& container);
+
+    KItemRangeList& operator<<(const KItemRange& range)
+    {
+        append(range);
+        return *this;
+    }
+};
+
+template<class Container>
+KItemRangeList KItemRangeList::fromSortedContainer(const Container& container)
+{
+    typename Container::const_iterator it = container.constBegin();
+    const typename Container::const_iterator end = container.constEnd();
+
+    if (it == end) {
+        return KItemRangeList();
+    }
+
+    KItemRangeList result;
+
+    int index = *it;
+    int count = 1;
+
+    ++it;
+
+    while (it != end) {
+        if (*it == index + count) {
+            ++count;
+        } else {
+            result << KItemRange(index, count);
+            index = *it;
+            count = 1;
+        }
+        ++it;
+    }
+
+    result << KItemRange(index, count);
+    return result;
+}
+
+#endif
index bd4f6081fc1cb9dd8be49a0e31baab3e2177f45c..135cd0b7df0102e698cbde8155fb4a19d4206861 100644 (file)
@@ -48,23 +48,8 @@ void KStandardItemListView::setItemLayout(ItemLayout layout)
     const ItemLayout previous = m_itemLayout;
     m_itemLayout = layout;
 
-    switch (layout) {
-    case IconsLayout:
-        setScrollOrientation(Qt::Vertical);
-        setSupportsItemExpanding(false);
-        break;
-    case DetailsLayout:
-        setScrollOrientation(Qt::Vertical);
-        setSupportsItemExpanding(true);
-        break;
-    case CompactLayout:
-        setScrollOrientation(Qt::Horizontal);
-        setSupportsItemExpanding(false);
-        break;
-    default:
-        Q_ASSERT(false);
-        break;
-    }
+    setSupportsItemExpanding(itemLayoutSupportsItemExpanding(layout));
+    setScrollOrientation(layout == CompactLayout ? Qt::Horizontal : Qt::Vertical);
 
     onItemLayoutChanged(layout, previous);
 
@@ -117,6 +102,11 @@ bool KStandardItemListView::itemSizeHintUpdateRequired(const QSet<QByteArray>& c
     return false;
 }
 
+bool KStandardItemListView::itemLayoutSupportsItemExpanding(ItemLayout layout) const
+{
+    return layout == DetailsLayout;
+}
+
 void KStandardItemListView::onItemLayoutChanged(ItemLayout current, ItemLayout previous)
 {
     Q_UNUSED(current);
index fd4fa861c63d5cb3130f2de01f3bbb5aee98c513..f5b0bfd8cf3f0884b42faa488cf1d926a35f66d3 100644 (file)
@@ -63,6 +63,7 @@ protected:
     virtual KItemListGroupHeaderCreatorBase* defaultGroupHeaderCreator() const;
     virtual void initializeItemListWidget(KItemListWidget* item);
     virtual bool itemSizeHintUpdateRequired(const QSet<QByteArray>& changedRoles) const;
+    virtual bool itemLayoutSupportsItemExpanding(ItemLayout layout) const;
     virtual void onItemLayoutChanged(ItemLayout current, ItemLayout previous);
     virtual void onScrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous);
     virtual void onSupportsItemExpandingChanged(bool supportsExpanding);
index bc0503663bceb1dfdb1065731bbaf6110838c084..302150fec1267d93a094a3c5d2b0e3400acc41ca 100644 (file)
@@ -57,13 +57,12 @@ KStandardItemListWidgetInformant::~KStandardItemListWidgetInformant()
 
 QSizeF KStandardItemListWidgetInformant::itemSizeHint(int index, const KItemListView* view) const
 {
-    const QHash<QByteArray, QVariant> values = view->model()->data(index);
     const KItemListStyleOption& option = view->styleOption();
     const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0);
 
     switch (static_cast<const KStandardItemListView*>(view)->itemLayout()) {
     case KStandardItemListWidget::IconsLayout: {
-        const QString text = KStringHandler::preProcessWrap(values["text"].toString());
+        const QString text = KStringHandler::preProcessWrap(itemText(index, view));
 
         const qreal itemWidth = view->itemSize().width();
         const qreal maxWidth = itemWidth - 2 * option.padding;
@@ -100,6 +99,7 @@ QSizeF KStandardItemListWidgetInformant::itemSizeHint(int index, const KItemList
         // to show all roles without horizontal clipping.
         qreal maximumRequiredWidth = 0.0;
 
+        const QHash<QByteArray, QVariant> values = view->model()->data(index);
         foreach (const QByteArray& role, view->visibleRoles()) {
             const QString text = roleText(role, values);
             const qreal requiredWidth = option.fontMetrics.width(text);
@@ -159,6 +159,11 @@ qreal KStandardItemListWidgetInformant::preferredRoleColumnWidth(const QByteArra
     return width;
 }
 
+QString KStandardItemListWidgetInformant::itemText(int index, const KItemListView* view) const
+{
+    return view->model()->data(index).value("text").toString();
+}
+
 QString KStandardItemListWidgetInformant::roleText(const QByteArray& role,
                                                    const QHash<QByteArray, QVariant>& values) const
 {
@@ -797,11 +802,12 @@ void KStandardItemListWidget::updateExpansionArea()
         const QHash<QByteArray, QVariant> values = data();
         const int expandedParentsCount = values.value("expandedParentsCount", 0).toInt();
         if (expandedParentsCount >= 0) {
+            const KItemListStyleOption& option = styleOption();
             const qreal widgetHeight = size().height();
-            const qreal inc = (widgetHeight - KIconLoader::SizeSmall) / 2;
+            const qreal inc = (widgetHeight - option.iconSize) / 2;
             const qreal x = expandedParentsCount * widgetHeight + inc;
             const qreal y = inc;
-            m_expansionArea = QRectF(x, y, KIconLoader::SizeSmall, KIconLoader::SizeSmall);
+            m_expansionArea = QRectF(x, y, option.iconSize, option.iconSize);
             return;
         }
     }
index 4bf6116fd1121cd263c1cff74aed55ea0a75456b..7dd93b2b819babd5e48271ba47a1d89339b166bb 100644 (file)
@@ -44,6 +44,15 @@ public:
                                            int index,
                                            const KItemListView* view) const;
 protected:
+    /**
+     * @return The value of the "text" role. The default implementation returns
+     *         view->model()->data(index)["text"]. If a derived class can
+     *         prevent the (possibly expensive) construction of the
+     *         QHash<QByteArray, QVariant> returned by KItemModelBase::data(int),
+     *         it can reimplement this function.
+     */
+    virtual QString itemText(int index, const KItemListView* view) const;
+
     /**
      * @return String representation of the role \a role. The representation of
      *         a role might depend on other roles, so the values of all roles
diff --git a/src/kitemviews/private/kdirectorycontentscounter.cpp b/src/kitemviews/private/kdirectorycontentscounter.cpp
new file mode 100644 (file)
index 0000000..fd8479f
--- /dev/null
@@ -0,0 +1,164 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2013 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 "kdirectorycontentscounter.h"
+
+#include "kdirectorycontentscounterworker.h"
+#include <kitemviews/kfileitemmodel.h>
+
+#include <KDirWatch>
+#include <QThread>
+
+KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObject* parent) :
+    QObject(parent),
+    m_model(model),
+    m_queue(),
+    m_workerThread(0),
+    m_worker(0),
+    m_workerIsBusy(false),
+    m_dirWatcher(0),
+    m_watchedDirs()
+{
+    connect(m_model, SIGNAL(itemsRemoved(KItemRangeList)),
+            this,    SLOT(slotItemsRemoved()));
+
+    m_workerThread = new QThread(this);
+    m_worker = new KDirectoryContentsCounterWorker();
+    m_worker->moveToThread(m_workerThread);
+
+    connect(this,     SIGNAL(requestDirectoryContentsCount(QString,KDirectoryContentsCounterWorker::Options)),
+            m_worker, SLOT(countDirectoryContents(QString,KDirectoryContentsCounterWorker::Options)));
+    connect(m_worker, SIGNAL(result(QString,int)),
+            this,     SLOT(slotResult(QString,int)));
+
+    m_workerThread->start();
+
+    m_dirWatcher = new KDirWatch(this);
+    connect(m_dirWatcher, SIGNAL(dirty(QString)), this, SLOT(slotDirWatchDirty(QString)));
+}
+
+KDirectoryContentsCounter::~KDirectoryContentsCounter()
+{
+    m_workerThread->quit();
+    m_workerThread->wait();
+
+    delete m_worker;
+}
+
+void KDirectoryContentsCounter::addDirectory(const QString& path)
+{
+    startWorker(path);
+}
+
+int KDirectoryContentsCounter::countDirectoryContentsSynchronously(const QString& path)
+{
+    if (!m_dirWatcher->contains(path)) {
+        m_dirWatcher->addDir(path);
+        m_watchedDirs.insert(path);
+    }
+
+    KDirectoryContentsCounterWorker::Options options;
+
+    if (m_model->showHiddenFiles()) {
+        options |= KDirectoryContentsCounterWorker::CountHiddenFiles;
+    }
+
+    if (m_model->showDirectoriesOnly()) {
+        options |= KDirectoryContentsCounterWorker::CountDirectoriesOnly;
+    }
+
+    return KDirectoryContentsCounterWorker::subItemsCount(path, options);
+}
+
+void KDirectoryContentsCounter::slotResult(const QString& path, int count)
+{
+    m_workerIsBusy = false;
+
+    if (!m_dirWatcher->contains(path)) {
+        m_dirWatcher->addDir(path);
+        m_watchedDirs.insert(path);
+    }
+
+    if (!m_queue.isEmpty()) {
+        startWorker(m_queue.dequeue());
+    }
+
+    emit result(path, count);
+}
+
+void KDirectoryContentsCounter::slotDirWatchDirty(const QString& path)
+{
+    const int index = m_model->index(KUrl(path));
+    if (index >= 0) {
+        if (!m_model->fileItem(index).isDir()) {
+            // If INotify is used, KDirWatch issues the dirty() signal
+            // also for changed files inside the directory, even if we
+            // don't enable this behavior explicitly (see bug 309740).
+            return;
+        }
+
+        startWorker(path);
+    }
+}
+
+void KDirectoryContentsCounter::slotItemsRemoved()
+{
+    const bool allItemsRemoved = (m_model->count() == 0);
+
+    if (!m_watchedDirs.isEmpty()) {
+        // Don't let KDirWatch watch for removed items
+        if (allItemsRemoved) {
+            foreach (const QString& path, m_watchedDirs) {
+                m_dirWatcher->removeDir(path);
+            }
+            m_watchedDirs.clear();
+            m_queue.clear();
+        } else {
+            QMutableSetIterator<QString> it(m_watchedDirs);
+            while (it.hasNext()) {
+                const QString& path = it.next();
+                if (m_model->index(KUrl(path)) < 0) {
+                    m_dirWatcher->removeDir(path);
+                    it.remove();
+                }
+            }
+        }
+    }
+}
+
+void KDirectoryContentsCounter::startWorker(const QString& path)
+{
+    if (m_workerIsBusy) {
+        m_queue.enqueue(path);
+    } else {
+        KDirectoryContentsCounterWorker::Options options;
+
+        if (m_model->showHiddenFiles()) {
+            options |= KDirectoryContentsCounterWorker::CountHiddenFiles;
+        }
+
+        if (m_model->showDirectoriesOnly()) {
+            options |= KDirectoryContentsCounterWorker::CountDirectoriesOnly;
+        }
+
+        emit requestDirectoryContentsCount(path, options);
+        m_workerIsBusy = true;
+    }
+}
diff --git a/src/kitemviews/private/kdirectorycontentscounter.h b/src/kitemviews/private/kdirectorycontentscounter.h
new file mode 100644 (file)
index 0000000..425c363
--- /dev/null
@@ -0,0 +1,90 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2013 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 KDIRECTORYCONTENTSCOUNTER_H
+#define KDIRECTORYCONTENTSCOUNTER_H
+
+#include "kdirectorycontentscounterworker.h"
+
+#include <QSet>
+#include <QQueue>
+
+class KDirWatch;
+class KFileItemModel;
+class QString;
+
+class KDirectoryContentsCounter : public QObject
+{
+    Q_OBJECT
+
+public:
+    explicit KDirectoryContentsCounter(KFileItemModel* model, QObject* parent = 0);
+    ~KDirectoryContentsCounter();
+
+    /**
+     * Requests the number of items inside the directory \a path. The actual
+     * counting is done asynchronously, and the result is announced via the
+     * signal \a result.
+     *
+     * The directory \a path is watched for changes, and the signal is emitted
+     * again if a change occurs.
+     */
+    void addDirectory(const QString& path);
+
+    /**
+     * In contrast to \a addDirectory, this function counts the items inside
+     * the directory \a path synchronously and returns the result.
+     *
+     * The directory is watched for changes, and the signal \a result is
+     * emitted if a change occurs.
+     */
+    int countDirectoryContentsSynchronously(const QString& path);
+
+signals:
+    /**
+     * Signals that the directory \a path contains \a count items.
+     */
+    void result(const QString& path, int count);
+
+    void requestDirectoryContentsCount(const QString& path, KDirectoryContentsCounterWorker::Options options);
+
+private slots:
+    void slotResult(const QString& path, int count);
+    void slotDirWatchDirty(const QString& path);
+    void slotItemsRemoved();
+
+private:
+    void startWorker(const QString& path);
+
+private:
+    KFileItemModel* m_model;
+
+    QQueue<QString> m_queue;
+
+    QThread* m_workerThread;
+    KDirectoryContentsCounterWorker* m_worker;
+    bool m_workerIsBusy;
+
+    KDirWatch* m_dirWatcher;
+    QSet<QString> m_watchedDirs;    // Required as sadly KDirWatch does not offer a getter method
+                                    // to get all watched directories.
+};
+
+#endif
\ No newline at end of file
diff --git a/src/kitemviews/private/kdirectorycontentscounterworker.cpp b/src/kitemviews/private/kdirectorycontentscounterworker.cpp
new file mode 100644 (file)
index 0000000..e649c20
--- /dev/null
@@ -0,0 +1,95 @@
+/***************************************************************************
+ *   Copyright (C) 2011 by Peter Penz <peter.penz19@gmail.com>             *
+ *   Copyright (C) 2013 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 "kdirectorycontentscounterworker.h"
+
+// Required includes for subItemsCount():
+#ifdef Q_WS_WIN
+    #include <QDir>
+#else
+    #include <dirent.h>
+    #include <QFile>
+#endif
+
+KDirectoryContentsCounterWorker::KDirectoryContentsCounterWorker(QObject* parent) :
+    QObject(parent)
+{
+    qRegisterMetaType<KDirectoryContentsCounterWorker::Options>();
+}
+
+int KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options options)
+{
+    const bool countHiddenFiles = options & CountHiddenFiles;
+    const bool countDirectoriesOnly = options & CountDirectoriesOnly;
+
+#ifdef Q_WS_WIN
+    QDir dir(path);
+    QDir::Filters filters = QDir::NoDotAndDotDot | QDir::System;
+    if (countHiddenFiles) {
+        filters |= QDir::Hidden;
+    }
+    if (countDirectoriesOnly) {
+        filters |= QDir::Dirs;
+    } else {
+        filters |= QDir::AllEntries;
+    }
+    return dir.entryList(filters).count();
+#else
+    // Taken from kdelibs/kio/kio/kdirmodel.cpp
+    // Copyright (C) 2006 David Faure <faure@kde.org>
+
+    int count = -1;
+    DIR* dir = ::opendir(QFile::encodeName(path));
+    if (dir) {  // krazy:exclude=syscalls
+        count = 0;
+        struct dirent *dirEntry = 0;
+        while ((dirEntry = ::readdir(dir))) {
+            if (dirEntry->d_name[0] == '.') {
+                if (dirEntry->d_name[1] == '\0' || !countHiddenFiles) {
+                    // Skip "." or hidden files
+                    continue;
+                }
+                if (dirEntry->d_name[1] == '.' && dirEntry->d_name[2] == '\0') {
+                    // Skip ".."
+                    continue;
+                }
+            }
+
+            // If only directories are counted, consider an unknown file type and links also
+            // as directory instead of trying to do an expensive stat()
+            // (see bugs 292642 and 299997).
+            const bool countEntry = !countDirectoriesOnly ||
+                                    dirEntry->d_type == DT_DIR ||
+                                    dirEntry->d_type == DT_LNK ||
+                                    dirEntry->d_type == DT_UNKNOWN;
+            if (countEntry) {
+                ++count;
+            }
+        }
+        ::closedir(dir);
+    }
+    return count;
+#endif
+}
+
+void KDirectoryContentsCounterWorker::countDirectoryContents(const QString& path, Options options)
+{
+    emit result(path, subItemsCount(path, options));
+}
diff --git a/src/kitemviews/private/kdirectorycontentscounterworker.h b/src/kitemviews/private/kdirectorycontentscounterworker.h
new file mode 100644 (file)
index 0000000..96831ef
--- /dev/null
@@ -0,0 +1,71 @@
+/***************************************************************************
+ *   Copyright (C) 2013 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 KDIRECTORYCONTENTENTSCOUNTERWORKER_H
+#define KDIRECTORYCONTENTENTSCOUNTERWORKER_H
+
+#include <QFlags>
+#include <QMetaType>
+#include <QObject>
+
+class QString;
+
+class KDirectoryContentsCounterWorker : public QObject
+{
+    Q_OBJECT
+
+public:
+    enum Option {
+        NoOptions = 0x0,
+        CountHiddenFiles = 0x1,
+        CountDirectoriesOnly = 0x2
+    };
+    Q_DECLARE_FLAGS(Options, Option)
+
+    explicit KDirectoryContentsCounterWorker(QObject* parent = 0);
+
+    /**
+     * Counts the items inside the directory \a path using the options
+     * \a options.
+     *
+     * @return The number of items.
+     */
+    static int subItemsCount(const QString& path, Options options);
+
+signals:
+    /**
+     * Signals that the directory \a path contains \a count items.
+     */
+    void result(const QString& path, int count);
+
+public slots:
+    /**
+     * Requests the number of items inside the directory \a path using the
+     * options \a options. The result is announced via the signal \a result.
+     */
+    // Note that the full type name KDirectoryContentsCounterWorker::Options
+    // is needed here. Just using 'Options' is OK for the compiler, but
+    // confuses moc.
+    void countDirectoryContents(const QString& path, KDirectoryContentsCounterWorker::Options options);
+};
+
+Q_DECLARE_METATYPE(KDirectoryContentsCounterWorker::Options)
+Q_DECLARE_OPERATORS_FOR_FLAGS(KDirectoryContentsCounterWorker::Options)
+
+#endif
index e44630243b1c148325f26689a2a03d093563c68a..0e2286b453a9c539358528318288c9e695de1b6c 100644 (file)
@@ -120,7 +120,7 @@ void KItemListSizeHintResolver::itemsMoved(const KItemRange& range, const QList<
 
     const int movedRangeEnd = range.index + range.count;
     for (int i = range.index; i < movedRangeEnd; ++i) {
-        const int newIndex = movedToIndexes.at(i);
+        const int newIndex = movedToIndexes.at(i - range.index);
         newSizeHintCache[newIndex] = m_sizeHintCache.at(i);
     }
 
@@ -139,8 +139,5 @@ void KItemListSizeHintResolver::itemsChanged(int index, int count, const QSet<QB
 
 void KItemListSizeHintResolver::clearCache()
 {
-    const int count = m_sizeHintCache.count();
-    for (int i = 0; i < count; ++i) {
-        m_sizeHintCache[i] = QSizeF();
-    }
+    m_sizeHintCache.fill(QSizeF());
 }
index da569b3dc6cf0ee97b8b119efd9aaba31ea4eb03..1e972571806b3748006e6f02195d986deddeb880 100644 (file)
@@ -375,12 +375,9 @@ void KItemListViewLayouter::doLayout()
         if (horizontalScrolling) {
             // Flip everything so that the layout logically can work like having
             // a vertical scrolling
-            itemSize.setWidth(m_itemSize.height());
-            itemSize.setHeight(m_itemSize.width());
-            itemMargin.setWidth(m_itemMargin.height());
-            itemMargin.setHeight(m_itemMargin.width());
-            size.setWidth(m_size.height());
-            size.setHeight(m_size.width());
+            itemSize.transpose();
+            itemMargin.transpose();
+            size.transpose();
 
             if (grouped) {
                 // In the horizontal scrolling case all groups are aligned
@@ -406,12 +403,7 @@ void KItemListViewLayouter::doLayout()
             }
         }
 
-        int rowCount = itemCount / m_columnCount;
-        if (itemCount % m_columnCount != 0) {
-            ++rowCount;
-        }
-
-        m_itemInfos.reserve(itemCount);
+        m_itemInfos.resize(itemCount);
 
         qreal y = m_headerHeight + itemMargin.height();
         int row = 0;
@@ -458,18 +450,10 @@ void KItemListViewLayouter::doLayout()
                     }
                 }
 
-                const QRectF bounds(x, y, itemSize.width(), requiredItemHeight);
-                if (index < m_itemInfos.count()) {
-                    m_itemInfos[index].rect = bounds;
-                    m_itemInfos[index].column = column;
-                    m_itemInfos[index].row = row;
-                } else {
-                    ItemInfo itemInfo;
-                    itemInfo.rect = bounds;
-                    itemInfo.column = column;
-                    itemInfo.row = row;
-                    m_itemInfos.append(itemInfo);
-                }
+                ItemInfo& itemInfo = m_itemInfos[index];
+                itemInfo.rect = QRectF(x, y, itemSize.width(), requiredItemHeight);
+                itemInfo.column = column;
+                itemInfo.row = row;
 
                 if (grouped && horizontalScrolling) {
                     // When grouping is enabled in the horizontal mode, the header alignment
@@ -505,24 +489,9 @@ void KItemListViewLayouter::doLayout()
             y += maxItemHeight + itemMargin.height();
             ++row;
         }
-        if (m_itemInfos.count() > itemCount) {
-            m_itemInfos.erase(m_itemInfos.begin() + itemCount,
-                              m_itemInfos.end());
-        }
 
         if (itemCount > 0) {
-            // Calculate the maximum y-range of the last row for m_maximumScrollOffset
-            m_maximumScrollOffset = m_itemInfos.last().rect.bottom();
-            const qreal rowY = m_itemInfos.last().rect.y();
-
-            int index = m_itemInfos.count() - 2;
-            while (index >= 0 && m_itemInfos[index].rect.bottom() >= rowY) {
-                m_maximumScrollOffset = qMax(m_maximumScrollOffset, m_itemInfos[index].rect.bottom());
-                --index;
-            }
-
-            m_maximumScrollOffset += itemMargin.height();
-
+            m_maximumScrollOffset = y;
             m_maximumItemOffset = m_columnCount * m_columnWidth;
         } else {
             m_maximumScrollOffset = 0;
index 5f3772d28132cf32ff5143a7cabd6982be05fc38..54bece16a3537cb32704414b02b2ae7fa01d888e 100644 (file)
@@ -297,6 +297,7 @@ Comment[zh_CN]=配置常规文件管理器设置
 Comment[zh_TW]=設定一般檔案管理員
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير الملفات
+X-KDE-Keywords[bg]=преглед на файлове
 X-KDE-Keywords[bs]=upravitelj datoteka
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
index ab79449f5a9512a82c2b05c65605f566c184b51b..cecf495bd3f8e9152743afdd69efd06771edea6f 100644 (file)
@@ -297,6 +297,7 @@ Comment[zh_CN]=配置文件管理器导航
 Comment[zh_TW]=設定檔案管理員導覽
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير الملفات
+X-KDE-Keywords[bg]=преглед на файлове
 X-KDE-Keywords[bs]=upravitelj datoteka
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
index 14436dd99fba0452b7b85efb3e3671ce4fec1fa1..de88fb58957cadc20e5103e03dc10576faa5bcfd 100644 (file)
@@ -246,6 +246,7 @@ Comment[zh_CN]=配置文件管理器服务
 Comment[zh_TW]=設定檔案管理員服務
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير الملفات
+X-KDE-Keywords[bg]=преглед на файлове
 X-KDE-Keywords[bs]=upravitelj datoteka
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
index a05d944c2ef726f315e30d95ce186ed34f55ad90..205570cc05780b9cecc47850b753cf6fd471c126 100644 (file)
@@ -295,6 +295,7 @@ Comment[zh_CN]=配置文件管理器视图模式
 Comment[zh_TW]=設定檔案管理員檢視模式
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير الملفات
+X-KDE-Keywords[bg]=преглед на файлове
 X-KDE-Keywords[bs]=upravitelj datoteka
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
index f72e43edeb982a42518604c9b7918758d21d697f..66918b6eec50bd021da324f00a18a6004f0fe1a6 100644 (file)
@@ -185,7 +185,7 @@ void KFileItemModelBenchmark::insertAndRemoveManyItems()
         QCOMPARE(model.count(), initialItems.count() + newItems.count());
 
         if (!removedItems.isEmpty()) {
-            model.removeItems(removedItems, KFileItemModel::DeleteItemData);
+            model.slotItemsDeleted(removedItems);
         }
         QCOMPARE(model.count(), initialItems.count() + newItems.count() - removedItems.count());
     }
index 5dd3417fc5c43225c58328e4b58ebbe987f40382..62ff4fae2d705bb9953a01e0a55c3e4cd1e32075 100644 (file)
@@ -49,6 +49,7 @@ namespace {
     const int DefaultTimeout = 5000;
 };
 
+Q_DECLARE_METATYPE(KItemRange)
 Q_DECLARE_METATYPE(KItemRangeList)
 Q_DECLARE_METATYPE(QList<int>)
 
@@ -88,6 +89,7 @@ private slots:
     void testGeneralParentChildRelationships();
     void testNameRoleGroups();
     void testNameRoleGroupsWithExpandedItems();
+    void testInconsistentModel();
 
 private:
     QStringList itemsInModel() const;
@@ -499,7 +501,8 @@ void KFileItemModelTest::testExpandItems()
     // KFileItemModel::expansionLevelsCompare(const KFileItem& a, const KFileItem& b)
     // yields the correct result for "a/a/1" and "a/a-1/", whis is non-trivial because they share the
     // first three characters.
-    QSet<QByteArray> modelRoles = m_model->roles();
+    QSet<QByteArray> originalModelRoles = m_model->roles();
+    QSet<QByteArray> modelRoles = originalModelRoles;
     modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
     m_model->setRoles(modelRoles);
 
@@ -606,6 +609,18 @@ void KFileItemModelTest::testExpandItems()
     QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(directoryLoadingCompleted()), DefaultTimeout));
     QCOMPARE(m_model->count(), 5);  // 5 items: "a/", "a/a/", "a/a/1", "a/a-1/", "a/a-1/1"
     QCOMPARE(m_model->expandedDirectories(), allFolders);
+
+    // Remove all expanded items by changing the roles
+    spyRemoved.clear();
+    m_model->setRoles(originalModelRoles);
+    QVERIFY(!m_model->isExpanded(0));
+    QCOMPARE(m_model->count(), 1);
+    QVERIFY(!m_model->expandedDirectories().contains(KUrl(m_testDir->name() + 'a')));
+
+    QCOMPARE(spyRemoved.count(), 1);
+    itemRangeList = spyRemoved.takeFirst().at(0).value<KItemRangeList>();
+    QCOMPARE(itemRangeList, KItemRangeList() << KItemRange(1, 4)); // 4 items removed
+    QVERIFY(m_model->isConsistent());
 }
 
 void KFileItemModelTest::testExpandParentItems()
@@ -658,6 +673,28 @@ void KFileItemModelTest::testExpandParentItems()
     QVERIFY(m_model->isExpanded(3));
     QVERIFY(!m_model->isExpanded(4));
     QVERIFY(m_model->isConsistent());
+
+    // Expand "a 1/b1/".
+    m_model->setExpanded(1, true);
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(directoryLoadingCompleted()), DefaultTimeout));
+    QCOMPARE(m_model->count(), 6);
+    QVERIFY(m_model->isExpanded(0));
+    QVERIFY(m_model->isExpanded(1));
+    QVERIFY(!m_model->isExpanded(2));
+    QVERIFY(m_model->isExpanded(3));
+    QVERIFY(m_model->isExpanded(4));
+    QVERIFY(!m_model->isExpanded(5));
+    QVERIFY(m_model->isConsistent());
+
+    // Collapse "a 1/b1/" again, and verify that the previous state is restored.
+    m_model->setExpanded(1, false);
+    QCOMPARE(m_model->count(), 5);
+    QVERIFY(m_model->isExpanded(0));
+    QVERIFY(!m_model->isExpanded(1));
+    QVERIFY(m_model->isExpanded(2));
+    QVERIFY(m_model->isExpanded(3));
+    QVERIFY(!m_model->isExpanded(4));
+    QVERIFY(m_model->isConsistent());
 }
 
 /**
@@ -803,7 +840,8 @@ void KFileItemModelTest::testSorting()
     QCOMPARE(m_model->sortOrder(), Qt::AscendingOrder);
     QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "c" << "c-1" << "c-2" << "c-3" << "d" << "e");
     QCOMPARE(spyItemsMoved.count(), 1);
-    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 2 << 4 << 5 << 3 << 0 << 1 << 6 << 7);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(0, 6));
+    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 2 << 4 << 5 << 3 << 0 << 1);
 
     // Sort by Name, descending
     m_model->setSortDirectoriesFirst(true);
@@ -812,8 +850,10 @@ void KFileItemModelTest::testSorting()
     QCOMPARE(m_model->sortOrder(), Qt::DescendingOrder);
     QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "e" << "d" << "b" << "a");
     QCOMPARE(spyItemsMoved.count(), 2);
-    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 4 << 5 << 0 << 3 << 1 << 2 << 6 << 7);
-    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 0 << 1 << 2 << 3 << 7 << 6 << 5 << 4);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(0, 6));
+    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 4 << 5 << 0 << 3 << 1 << 2);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(4, 4));
+    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 7 << 6 << 5 << 4);
 
     // Sort by Date, descending
     m_model->setSortDirectoriesFirst(true);
@@ -822,7 +862,8 @@ void KFileItemModelTest::testSorting()
     QCOMPARE(m_model->sortOrder(), Qt::DescendingOrder);
     QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "b" << "d" << "a" << "e");
     QCOMPARE(spyItemsMoved.count(), 1);
-    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 0 << 1 << 2 << 3 << 7 << 5 << 4 << 6);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(4, 4));
+    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 7 << 5 << 4 << 6);
 
     // Sort by Date, ascending
     m_model->setSortOrder(Qt::AscendingOrder);
@@ -830,7 +871,8 @@ void KFileItemModelTest::testSorting()
     QCOMPARE(m_model->sortOrder(), Qt::AscendingOrder);
     QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "e" << "a" << "d" << "b");
     QCOMPARE(spyItemsMoved.count(), 1);
-    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 0 << 1 << 2 << 3 << 7 << 6 << 5 << 4);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(4, 4));
+    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 7 << 6 << 5 << 4);
 
     // Sort by Date, ascending, 'Sort Folders First' disabled
     m_model->setSortDirectoriesFirst(false);
@@ -839,7 +881,8 @@ void KFileItemModelTest::testSorting()
     QVERIFY(!m_model->sortDirectoriesFirst());
     QCOMPARE(itemsInModel(), QStringList() << "e" << "a" << "c" << "c-1" << "c-2" << "c-3" << "d" << "b");
     QCOMPARE(spyItemsMoved.count(), 1);
-    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 2 << 4 << 5 << 3 << 0 << 1 << 6 << 7);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(0, 6));
+    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 2 << 4 << 5 << 3 << 0 << 1);
 
     // Sort by Name, ascending, 'Sort Folders First' disabled
     m_model->setSortRole("text");
@@ -847,6 +890,7 @@ void KFileItemModelTest::testSorting()
     QVERIFY(!m_model->sortDirectoriesFirst());
     QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "c" << "c-1" << "c-2" << "c-3" << "d" << "e");
     QCOMPARE(spyItemsMoved.count(), 1);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(0, 8));
     QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 7 << 0 << 2 << 3 << 4 << 5 << 6 << 1);
 
     // Sort by Size, ascending, 'Sort Folders First' disabled
@@ -856,19 +900,15 @@ void KFileItemModelTest::testSorting()
     QVERIFY(!m_model->sortDirectoriesFirst());
     QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "a" << "b" << "e" << "d");
     QCOMPARE(spyItemsMoved.count(), 1);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(0, 8));
     QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 4 << 5 << 0 << 3 << 1 << 2 << 7 << 6);
 
-    QSKIP("2 tests of testSorting() are temporary deactivated as in KFileItemModel resortAllItems() "
-          "always emits a itemsMoved() signal. Before adjusting the tests think about probably introducing "
-          "another signal", SkipSingle);
-    // Internal note: Check comment in KFileItemModel::resortAllItems() for details.
-
     // In 'Sort by Size' mode, folders are always first -> changing 'Sort Folders First' does not resort the model
     m_model->setSortDirectoriesFirst(true);
     QCOMPARE(m_model->sortRole(), QByteArray("size"));
     QCOMPARE(m_model->sortOrder(), Qt::AscendingOrder);
     QVERIFY(m_model->sortDirectoriesFirst());
-    QCOMPARE(itemsInModel(), QStringList() << "c" << "a" << "b" << "e" << "d");
+    QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "a" << "b" << "e" << "d");
     QCOMPARE(spyItemsMoved.count(), 0);
 
     // Sort by Size, descending, 'Sort Folders First' enabled
@@ -876,9 +916,10 @@ void KFileItemModelTest::testSorting()
     QCOMPARE(m_model->sortRole(), QByteArray("size"));
     QCOMPARE(m_model->sortOrder(), Qt::DescendingOrder);
     QVERIFY(m_model->sortDirectoriesFirst());
-    QCOMPARE(itemsInModel(), QStringList() << "c" << "d" << "e" << "b" << "a");
+    QCOMPARE(itemsInModel(), QStringList() << "c" << "c-2" << "c-3" << "c-1" << "d" << "e" << "b" << "a");
     QCOMPARE(spyItemsMoved.count(), 1);
-    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 0 << 4 << 3 << 2 << 1);
+    QCOMPARE(spyItemsMoved.first().at(0).value<KItemRange>(), KItemRange(4, 4));
+    QCOMPARE(spyItemsMoved.takeFirst().at(1).value<QList<int> >(), QList<int>() << 7 << 6 << 5 << 4);
 
     // TODO: Sort by other roles; show/hide hidden files
 }
@@ -1296,7 +1337,7 @@ void KFileItemModelTest::testNameRoleGroups()
     // Rename c.txt to d.txt.
     data.insert("text", "d.txt");
     m_model->setData(2, data);
-    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)), DefaultTimeout));
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(groupsChanged()), DefaultTimeout));
     QCOMPARE(itemsInModel(), QStringList() << "a.txt" << "b.txt" << "d.txt" << "e.txt");
 
     expectedGroups.clear();
@@ -1314,7 +1355,7 @@ void KFileItemModelTest::testNameRoleGroups()
     fileItemC.setUrl(urlC);
 
     m_model->slotRefreshItems(QList<QPair<KFileItem, KFileItem> >() << qMakePair(fileItemD, fileItemC));
-    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsMoved(KItemRange,QList<int>)), DefaultTimeout));
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(groupsChanged()), DefaultTimeout));
     QCOMPARE(itemsInModel(), QStringList() << "a.txt" << "b.txt" << "c.txt" << "e.txt");
 
     expectedGroups.clear();
@@ -1364,6 +1405,63 @@ void KFileItemModelTest::testNameRoleGroupsWithExpandedItems()
     QCOMPARE(m_model->groups(), expectedGroups);
 }
 
+void KFileItemModelTest::testInconsistentModel()
+{
+    QSet<QByteArray> modelRoles = m_model->roles();
+    modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+    m_model->setRoles(modelRoles);
+
+    QStringList files;
+    files << "a/b/c1.txt" << "a/b/c2.txt";
+
+    m_testDir->createFiles(files);
+
+    m_model->loadDirectory(m_testDir->url());
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(itemsInModel(), QStringList() << "a");
+
+    // Expand "a/" and "a/b/".
+    m_model->setExpanded(0, true);
+    QVERIFY(m_model->isExpanded(0));
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(itemsInModel(), QStringList() << "a" << "b");
+
+    m_model->setExpanded(1, true);
+    QVERIFY(m_model->isExpanded(1));
+    QVERIFY(QTest::kWaitForSignal(m_model, SIGNAL(itemsInserted(KItemRangeList)), DefaultTimeout));
+    QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "c1.txt" << "c2.txt");
+
+    // Add the files "c1.txt" and "c2.txt" to the model also as top-level items.
+    // Such a thing can in principle happen when performing a search, and there
+    // are files which
+    // (a) match the search string, and
+    // (b) are children of a folder that matches the search string and is expanded.
+    //
+    // Note that the first item in the list of added items must be new (i.e., not
+    // in the model yet). Otherwise, KFileItemModel::slotItemsAdded() will see that
+    // it receives items that are in the model already and ignore them.
+    KUrl url(m_model->directory().url() + "/a2");
+    KFileItem newItem(KFileItem::Unknown, KFileItem::Unknown, url);
+
+    KFileItemList items;
+    items << newItem << m_model->fileItem(2) << m_model->fileItem(3);
+    m_model->slotItemsAdded(m_model->directory(), items);
+    m_model->slotCompleted();
+    QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "c1.txt" << "c2.txt" << "a2" << "c1.txt" << "c2.txt");
+
+    m_model->setExpanded(0, false);
+
+    // Test that the right items have been removed, see
+    // https://bugs.kde.org/show_bug.cgi?id=324371
+    QCOMPARE(itemsInModel(), QStringList() << "a" << "a2" << "c1.txt" << "c2.txt");
+
+    // Test that resorting does not cause a crash, see
+    // https://bugs.kde.org/show_bug.cgi?id=325359
+    // The crash is not 100% reproducible, but Valgrind will report an invalid memory access.
+    m_model->resortAllItems();
+
+}
+
 QStringList KFileItemModelTest::itemsInModel() const
 {
     QStringList items;
index 039b5f230ba7acc95d31f5d7072cefc6dc7a12ad..4799d76794106e9fb7e6d89aa11e22fae27cdd3d 100644 (file)
@@ -89,10 +89,7 @@ void DolphinItemListView::readSettings()
     beginTransaction();
 
     setEnabledSelectionToggles(GeneralSettings::showSelectionToggle());
-
-    const bool expandableFolders = (itemLayout() == KFileItemListView::DetailsLayout) &&
-                                   DetailsModeSettings::expandableFolders();
-    setSupportsItemExpanding(expandableFolders);
+    setSupportsItemExpanding(itemLayoutSupportsItemExpanding(itemLayout()));
 
     updateFont();
     updateGridSize();
@@ -119,19 +116,19 @@ KItemListWidgetCreatorBase* DolphinItemListView::defaultWidgetCreator() const
     return new KItemListWidgetCreator<DolphinFileItemListWidget>();
 }
 
-void DolphinItemListView::onItemLayoutChanged(ItemLayout current, ItemLayout previous)
+bool DolphinItemListView::itemLayoutSupportsItemExpanding(ItemLayout layout) const
 {
-    Q_UNUSED(previous);
+    return layout == DetailsLayout && DetailsModeSettings::expandableFolders();
+}
 
-    if (current == DetailsLayout) {
-        setSupportsItemExpanding(DetailsModeSettings::expandableFolders());
-        setHeaderVisible(true);
-    } else {
-        setHeaderVisible(false);
-    }
+void DolphinItemListView::onItemLayoutChanged(ItemLayout current, ItemLayout previous)
+{
+    setHeaderVisible(current == DetailsLayout);
 
     updateFont();
     updateGridSize();
+
+    KFileItemListView::onItemLayoutChanged(current, previous);
 }
 
 void DolphinItemListView::onPreviewsShownChanged(bool shown)
index c2d86cc5e21efc0344b6662465e00e8fc65cda42..18bb284ace61ccf2efdecacd590fff0bfce567df 100644 (file)
@@ -50,6 +50,7 @@ public:
 
 protected:
     virtual KItemListWidgetCreatorBase* defaultWidgetCreator() const;
+    virtual bool itemLayoutSupportsItemExpanding(ItemLayout layout) const;
     virtual void onItemLayoutChanged(ItemLayout current, ItemLayout previous);
     virtual void onPreviewsShownChanged(bool shown);
     virtual void onVisibleRolesChanged(const QList<QByteArray>& current,
index 1cb5739d796f55d164185385b1475c824a710d37..7669f15616d0615fa4f7fae58fb9c336a3340cab 100644 (file)
@@ -20,7 +20,7 @@
 #include "dolphinnewfilemenuobserver.h"
 
 #include <KGlobal>
-#include <KNewFileMenu>
+#include "dolphinnewfilemenu.h"
 
 class DolphinNewFileMenuObserverSingleton
 {
@@ -34,20 +34,24 @@ DolphinNewFileMenuObserver& DolphinNewFileMenuObserver::instance()
     return s_DolphinNewFileMenuObserver->instance;
 }
 
-void DolphinNewFileMenuObserver::attach(const KNewFileMenu* menu)
+void DolphinNewFileMenuObserver::attach(const DolphinNewFileMenu* menu)
 {
     connect(menu, SIGNAL(fileCreated(KUrl)),
             this, SIGNAL(itemCreated(KUrl)));
     connect(menu, SIGNAL(directoryCreated(KUrl)),
             this, SIGNAL(itemCreated(KUrl)));
+    connect(menu, SIGNAL(errorMessage(QString)),
+            this, SIGNAL(errorMessage(QString)));
 }
 
-void DolphinNewFileMenuObserver::detach(const KNewFileMenu* menu)
+void DolphinNewFileMenuObserver::detach(const DolphinNewFileMenu* menu)
 {
     disconnect(menu, SIGNAL(fileCreated(KUrl)),
                this, SIGNAL(itemCreated(KUrl)));
     disconnect(menu, SIGNAL(directoryCreated(KUrl)),
                this, SIGNAL(itemCreated(KUrl)));
+    disconnect(menu, SIGNAL(errorMessage(QString)),
+               this, SIGNAL(errorMessage(QString)));
 }
 
 DolphinNewFileMenuObserver::DolphinNewFileMenuObserver() :
index 726122cbc0e51503af09f11a2c797d1aa2d80f5b..239476eb9d2193d6f058fdc8be77011b6e88e096 100644 (file)
@@ -24,7 +24,7 @@
 
 #include "libdolphin_export.h"
 
-class KNewFileMenu;
+class DolphinNewFileMenu;
 class KUrl;
 
 /**
@@ -40,11 +40,12 @@ class LIBDOLPHINPRIVATE_EXPORT DolphinNewFileMenuObserver : public QObject
 
 public:
     static DolphinNewFileMenuObserver& instance();
-    void attach(const KNewFileMenu* menu);
-    void detach(const KNewFileMenu* menu);
+    void attach(const DolphinNewFileMenu* menu);
+    void detach(const DolphinNewFileMenu* menu);
 
 signals:
     void itemCreated(const KUrl& url);
+    void errorMessage(const QString& error);
 
 private:
     DolphinNewFileMenuObserver();
index 20bc9f522534feaa5faab871e63180617a5b8ef2..fd149e0f6aa0a947680c5c3c7481ecda7c24be99 100644 (file)
@@ -154,6 +154,7 @@ DolphinView::DolphinView(const KUrl& url, QWidget* parent) :
     connect(controller, SIGNAL(itemHovered(int)), this, SLOT(slotItemHovered(int)));
     connect(controller, SIGNAL(itemUnhovered(int)), this, SLOT(slotItemUnhovered(int)));
     connect(controller, SIGNAL(itemDropEvent(int,QGraphicsSceneDragDropEvent*)), this, SLOT(slotItemDropEvent(int,QGraphicsSceneDragDropEvent*)));
+    connect(controller, SIGNAL(escapePressed()), this, SLOT(stopLoading()));
     connect(controller, SIGNAL(modelChanged(KItemModelBase*,KItemModelBase*)), this, SLOT(slotModelChanged(KItemModelBase*,KItemModelBase*)));
 
     connect(m_model, SIGNAL(directoryLoadingStarted()),       this, SLOT(slotDirectoryLoadingStarted()));
@@ -485,11 +486,6 @@ void DolphinView::reload()
     restoreState(restoreStream);
 }
 
-void DolphinView::stopLoading()
-{
-    m_model->cancelDirectoryLoading();
-}
-
 void DolphinView::readSettings()
 {
     const int oldZoomLevel = m_view->zoomLevel();
@@ -556,8 +552,8 @@ QString DolphinView::statusBarText() const
         }
 
         if (folderCount + fileCount == 1) {
-            // If only one item is selected, show the filename
-            filesText = i18nc("@info:status", "<filename>%1</filename> selected", list.first().text());
+            // If only one item is selected, show info about it
+            return list.first().getStatusBarInfo();
         } else {
             // At least 2 items are selected
             foldersText = i18ncp("@info:status", "1 Folder selected", "%1 Folders selected", folderCount);
@@ -724,6 +720,11 @@ void DolphinView::pasteIntoFolder()
     }
 }
 
+void DolphinView::stopLoading()
+{
+    m_model->cancelDirectoryLoading();
+}
+
 bool DolphinView::eventFilter(QObject* watched, QEvent* event)
 {
     switch (event->type()) {
@@ -1666,7 +1667,7 @@ QMimeData* DolphinView::selectionMimeData() const
 void DolphinView::updateWritableState()
 {
     const bool wasFolderWritable = m_isFolderWritable;
-    m_isFolderWritable = true;
+    m_isFolderWritable = false;
 
     const KFileItem item = m_model->rootItem();
     if (!item.isNull()) {
index 86bc5c159d43702e0330a99ee031785599f7e6ab..a6f969bc1b7d8e27c233588199a9f6ac5e404397 100644 (file)
@@ -217,7 +217,6 @@ public:
     QList<QByteArray> visibleRoles() const;
 
     void reload();
-    void stopLoading();
 
     /**
      * Refreshes the view to get synchronized with the settings (e.g. icons size,
@@ -369,6 +368,8 @@ public slots:
      */
     void pasteIntoFolder();
 
+    void stopLoading();
+
     /** Activates the view if the item list container gets focus. */
     virtual bool eventFilter(QObject* watched, QEvent* event);