]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Fixed performance issues related to selections and deleting of files:
authorPeter Penz <peter.penz19@gmail.com>
Sat, 11 Jul 2009 17:48:05 +0000 (17:48 +0000)
committerPeter Penz <peter.penz19@gmail.com>
Sat, 11 Jul 2009 17:48:05 +0000 (17:48 +0000)
- Don't connect to KDirLister::itemDeleted(const KFileItem&), but KDirLister::itemsDeleted(const KFileItemList&). Otherwise Dolphin is informed about each single file deletion instead of getting the deleted items as a list. Thanks to David Faure for the hint!

- DolphinViewContainer::updateStatusBar() can be expensive when a lot of files are selected, as the file size must get retrieved. Assure that fast calls for updateStatusBar() don't trigger a synchronous update, do the update after 300 ms where no further update has been triggered.

- Dolphin provides a list of file items when emitting the selectionChanged() signal. Collecting the file items is a quite expensive operation, so use the same approach as when updating the statusbar: only emit the selection changed signal when no change has been done within 300 ms. This improves the performance when doing huge selections a lot.

- Make updateStatusBar() a private method, the main window should not need to take care about updating the statusbar (this is done internally now by DolphinViewContainer).

BUG: 199090
BUG: 195787
CCBUG: 199352
CCBUG: 188218

svn path=/trunk/KDE/kdebase/apps/; revision=995015

src/dolphinmainwindow.cpp
src/dolphinview.cpp
src/dolphinview.h
src/dolphinviewcontainer.cpp
src/dolphinviewcontainer.h

index 8796e6b0f07cc1e8d40c082b7978a5f0e8b995a1..a95b5a0d29157b4e923d35c80f496f9de0a9b508 100644 (file)
@@ -274,8 +274,6 @@ void DolphinMainWindow::slotSelectionChanged(const KFileItemList& selection)
         compareFilesAction->setEnabled(false);
     }
 
-    m_activeViewContainer->updateStatusBar();
-
     emit selectionChanged(selection);
 }
 
index d4dbbd2c28b6eb4fb64132e00ef220d158b2681a..4a81b12ea949802b804cddf18db3ead37f8ae8d0 100644 (file)
@@ -98,6 +98,7 @@ DolphinView::DolphinView(QWidget* parent,
     m_columnView(0),
     m_fileItemDelegate(0),
     m_selectionModel(0),
+    m_selectionChangedTimer(0),
     m_dolphinModel(dolphinModel),
     m_dirLister(dirLister),
     m_proxyModel(proxyModel),
@@ -188,7 +189,7 @@ void DolphinView::setActive(bool active)
 
     QColor color = KColorScheme(QPalette::Active, KColorScheme::View).background().color();
     if (active) {
-        emit selectionChanged(selectedItems());
+        emitSelectionChangedSignal();
     } else {
         color.setAlpha(150);
     }
@@ -958,6 +959,14 @@ void DolphinView::triggerItem(const KFileItem& item)
     emit itemTriggered(item); // caught by DolphinViewContainer or DolphinPart
 }
 
+void DolphinView::emitDelayedSelectionChangedSignal()
+{
+    // Invoke emitSelectionChangedSignal() with a delay of 300 ms. This assures
+    // that fast selection changes don't result in expensive operations to
+    // collect all file items for the signal (see DolphinView::selectedItems()).
+    m_selectionChangedTimer->start();
+}
+
 void DolphinView::emitSelectionChangedSignal()
 {
     emit selectionChanged(DolphinView::selectedItems());
@@ -1436,6 +1445,12 @@ void DolphinView::createView()
         m_selectionModel = view->selectionModel();
     }
 
+    m_selectionChangedTimer = new QTimer(this);
+    m_selectionChangedTimer->setSingleShot(true);
+    m_selectionChangedTimer->setInterval(300);
+    connect(m_selectionChangedTimer, SIGNAL(timeout()),
+            this, SLOT(emitSelectionChangedSignal()));
+
     // reparent the selection model, as it should not be deleted
     // when deleting the model
     m_selectionModel->setParent(this);
@@ -1454,7 +1469,7 @@ void DolphinView::createView()
     m_topLayout->insertWidget(1, view);
 
     connect(view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
-            this, SLOT(emitSelectionChangedSignal()));
+            this, SLOT(emitDelayedSelectionChangedSignal()));
     connect(view->verticalScrollBar(), SIGNAL(valueChanged(int)),
             this, SLOT(emitContentsMoved()));
     connect(view->horizontalScrollBar(), SIGNAL(valueChanged(int)),
index 24f56f40325e57807e42321b530249c5c48b0d7a..44915f6c01e094b8d74971125584687a1722316c 100644 (file)
@@ -580,6 +580,19 @@ private slots:
      */
     void triggerItem(const KFileItem& index);
 
+    /**
+     * Emits the signal \a selectionChanged() with a small delay. This is
+     * because getting all file items for the signal can be an expensive
+     * operation. Fast selection changes are collected in this case and
+     * the signal is emitted only after no selection change has been done
+     * within a small delay.
+     */
+    void emitDelayedSelectionChangedSignal();
+
+    /**
+     * Is called by emitDelayedSelectionChangedSignal() and emits the
+     * signal \a selectionChanged() with all selected file items as parameter.
+     */
     void emitSelectionChangedSignal();
 
     /**
@@ -785,7 +798,9 @@ private:
     DolphinDetailsView* m_detailsView;
     DolphinColumnView* m_columnView;
     DolphinFileItemDelegate* m_fileItemDelegate;
+
     QItemSelectionModel* m_selectionModel;
+    QTimer* m_selectionChangedTimer;
 
     DolphinModel* m_dolphinModel;
     KDirLister* m_dirLister;
index d8f90f3576f8a28cf729c4bf4c33ccf12c58c6bd..356ff274ee7cfd612ba98e8827d88a8d11b46206 100644 (file)
@@ -75,6 +75,7 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow,
     m_view(0),
     m_filterBar(0),
     m_statusBar(0),
+    m_statusBarTimer(0),
     m_dirLister(0),
     m_proxyModel(0)
 {
@@ -113,11 +114,11 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow,
     m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
 
     connect(m_dirLister, SIGNAL(clear()),
-            this, SLOT(updateStatusBar()));
+            this, SLOT(delayedStatusBarUpdate()));
     connect(m_dirLister, SIGNAL(percent(int)),
             this, SLOT(updateProgress(int)));
-    connect(m_dirLister, SIGNAL(deleteItem(const KFileItem&)),
-            this, SLOT(updateStatusBar()));
+    connect(m_dirLister, SIGNAL(itemsDeleted(const KFileItemList&)),
+            this, SLOT(delayedStatusBarUpdate()));
     connect(m_dirLister, SIGNAL(completed()),
             this, SLOT(slotDirListerCompleted()));
     connect(m_dirLister, SIGNAL(infoMessage(const QString&)),
@@ -152,6 +153,8 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow,
             this, SLOT(saveRootUrl(const KUrl&)));
     connect(m_view, SIGNAL(redirection(KUrl, KUrl)),
             this, SLOT(redirect(KUrl, KUrl)));
+    connect(m_view, SIGNAL(selectionChanged(const KFileItemList&)),
+            this, SLOT(delayedStatusBarUpdate()));
 
     connect(m_urlNavigator, SIGNAL(urlChanged(const KUrl&)),
             this, SLOT(restoreView(const KUrl&)));
@@ -159,6 +162,11 @@ DolphinViewContainer::DolphinViewContainer(DolphinMainWindow* mainWindow,
             this, SLOT(slotHistoryChanged()));
 
     m_statusBar = new DolphinStatusBar(this, m_view);
+    m_statusBarTimer = new QTimer(this);
+    m_statusBarTimer->setSingleShot(true);
+    m_statusBarTimer->setInterval(300);
+    connect(m_statusBarTimer, SIGNAL(timeout()),
+            this, SLOT(updateStatusBar()));
 
     m_filterBar = new FilterBar(this);
     m_filterBar->setVisible(settings->filterBar());
@@ -246,6 +254,37 @@ bool DolphinViewContainer::isUrlEditable() const
     return m_urlNavigator->isUrlEditable();
 }
 
+void DolphinViewContainer::delayedStatusBarUpdate()
+{
+    // Invoke updateStatusBar() with a small delay. This assures that
+    // when a lot of delayedStatusBarUpdates() are done in a short time,
+    // no bottleneck is given.
+    m_statusBarTimer->start();
+}
+
+void DolphinViewContainer::updateStatusBar()
+{
+    // As the item count information is less important
+    // in comparison with other messages, it should only
+    // be shown if:
+    // - the status bar is empty or
+    // - shows already the item count information or
+    // - shows only a not very important information
+    // - if any progress is given don't show the item count info at all
+    const QString msg(m_statusBar->message());
+    const bool updateStatusBarMsg = (msg.isEmpty()
+                                     || (msg == m_statusBar->defaultText())
+                                     || (m_statusBar->type() == DolphinStatusBar::Information))
+                                    && (m_statusBar->progress() == 100);
+
+    const QString text(m_view->statusBarText());
+    m_statusBar->setDefaultText(text);
+
+    if (updateStatusBarMsg) {
+        m_statusBar->setMessage(text, DolphinStatusBar::Default);
+    }
+}
+
 void DolphinViewContainer::updateProgress(int percent)
 {
     if (!m_showProgress) {
@@ -274,7 +313,7 @@ void DolphinViewContainer::slotDirListerCompleted()
         m_showProgress = false;
     }
 
-    updateStatusBar();
+    delayedStatusBarUpdate();
     QMetaObject::invokeMethod(this, "restoreContentsPos", Qt::QueuedConnection);
 
     // Enable the 'File'->'Create New...' menu only if the directory
@@ -325,33 +364,10 @@ void DolphinViewContainer::closeFilterBar()
     emit showFilterBarChanged(false);
 }
 
-void DolphinViewContainer::updateStatusBar()
-{
-    // As the item count information is less important
-    // in comparison with other messages, it should only
-    // be shown if:
-    // - the status bar is empty or
-    // - shows already the item count information or
-    // - shows only a not very important information
-    // - if any progress is given don't show the item count info at all
-    const QString msg(m_statusBar->message());
-    const bool updateStatusBarMsg = (msg.isEmpty() ||
-                                     (msg == m_statusBar->defaultText()) ||
-                                     (m_statusBar->type() == DolphinStatusBar::Information)) &&
-                                    (m_statusBar->progress() == 100);
-
-    const QString text(m_view->statusBarText());
-    m_statusBar->setDefaultText(text);
-
-    if (updateStatusBarMsg) {
-        m_statusBar->setMessage(text, DolphinStatusBar::Default);
-    }
-}
-
 void DolphinViewContainer::setNameFilter(const QString& nameFilter)
 {
     m_view->setNameFilter(nameFilter);
-    updateStatusBar();
+    delayedStatusBarUpdate();
 }
 
 void DolphinViewContainer::openContextMenu(const KFileItem& item,
index db6ee69d54a99147effc3c24a0c47bace052a46b..1f8f1caf6259dc56082ece151bbc02f683f40aa9 100644 (file)
@@ -120,20 +120,28 @@ public slots:
      */
     void showFilterBar(bool show);
 
+signals:
+    /**
+     * Is emitted whenever the filter bar has changed its visibility state.
+     */
+    void showFilterBarChanged(bool shown);
+
+private slots: 
     /**
      * Updates the number of items (= number of files + number of
      * directories) in the statusbar. If files are selected, the number
-     * of selected files and the sum of the filesize is shown.
+     * of selected files and the sum of the filesize is shown. The update
+     * is done asynchronously, as getting the sum of the
+     * filesizes can be an expensive operation.
      */
-    void updateStatusBar();
+    void delayedStatusBarUpdate();
 
-signals:
     /**
-     * Is emitted whenever the filter bar has changed its visibility state.
+     * Is invoked by DolphinViewContainer::delayedStatusBarUpdate() and
+     * updates the status bar synchronously.
      */
-    void showFilterBarChanged(bool shown);
+    void updateStatusBar();
 
-private slots:
     void updateProgress(int percent);
 
     /**
@@ -256,7 +264,9 @@ private:
     DolphinView* m_view;
 
     FilterBar* m_filterBar;
+
     DolphinStatusBar* m_statusBar;
+    QTimer* m_statusBarTimer;
 
     DolphinModel* m_dolphinModel;
     DolphinDirLister* m_dirLister;