[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdebase/apps/dolphin/src
From:       Peter Penz <peter.penz () gmx ! at>
Date:       2009-07-11 17:48:07
Message-ID: 1247334487.428732.2244.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 995015 by ppenz:

Fixed performance issues related to selections and deleting of files:

- 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

 M  +0 -2      dolphinmainwindow.cpp  
 M  +17 -2     dolphinview.cpp  
 M  +15 -0     dolphinview.h  
 M  +44 -28    dolphinviewcontainer.cpp  
 M  +16 -6     dolphinviewcontainer.h  


--- trunk/KDE/kdebase/apps/dolphin/src/dolphinmainwindow.cpp #995014:995015
@@ -274,8 +274,6 @@
         compareFilesAction->setEnabled(false);
     }
 
-    m_activeViewContainer->updateStatusBar();
-
     emit selectionChanged(selection);
 }
 
--- trunk/KDE/kdebase/apps/dolphin/src/dolphinview.cpp #995014:995015
@@ -98,6 +98,7 @@
     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 @@
 
     QColor color = KColorScheme(QPalette::Active, \
KColorScheme::View).background().color();  if (active) {
-        emit selectionChanged(selectedItems());
+        emitSelectionChangedSignal();
     } else {
         color.setAlpha(150);
     }
@@ -958,6 +959,14 @@
     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 @@
         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 @@
     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)),
--- trunk/KDE/kdebase/apps/dolphin/src/dolphinview.h #995014:995015
@@ -580,6 +580,19 @@
      */
     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 @@
     DolphinDetailsView* m_detailsView;
     DolphinColumnView* m_columnView;
     DolphinFileItemDelegate* m_fileItemDelegate;
+
     QItemSelectionModel* m_selectionModel;
+    QTimer* m_selectionChangedTimer;
 
     DolphinModel* m_dolphinModel;
     KDirLister* m_dirLister;
--- trunk/KDE/kdebase/apps/dolphin/src/dolphinviewcontainer.cpp #995014:995015
@@ -75,6 +75,7 @@
     m_view(0),
     m_filterBar(0),
     m_statusBar(0),
+    m_statusBarTimer(0),
     m_dirLister(0),
     m_proxyModel(0)
 {
@@ -113,11 +114,11 @@
     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 @@
             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 @@
             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 @@
     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 @@
         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 @@
     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,
--- trunk/KDE/kdebase/apps/dolphin/src/dolphinviewcontainer.h #995014:995015
@@ -120,20 +120,28 @@
      */
     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 @@
     DolphinView* m_view;
 
     FilterBar* m_filterBar;
+
     DolphinStatusBar* m_statusBar;
+    QTimer* m_statusBarTimer;
 
     DolphinModel* m_dolphinModel;
     DolphinDirLister* m_dirLister;


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic