From 0d191c9da27a7ba7d017b6bb8eee39e83088d2c6 Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Thu, 3 Apr 2014 09:03:47 +0200 Subject: KDirectoryContentsCounter: do not delete currently active worker objects Before this patch, the destructor of KDirectoryContentsCounter might delete the worker object, which lives in another thread, while one of its methods was still being executed. This could cause a crash. Only if the destroyed KDirectoryContentsCounter was the last one, the worker thread was stopped, and the destructor waited until all workers are done. BUG: 332767 FIXED-IN: 4.13.0 REVIEW: 117209 --- src/kitemviews/private/kdirectorycontentscounter.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/kitemviews/private/kdirectorycontentscounter.cpp b/src/kitemviews/private/kdirectorycontentscounter.cpp index 65afb7c3e..7d1e76999 100644 --- a/src/kitemviews/private/kdirectorycontentscounter.cpp +++ b/src/kitemviews/private/kdirectorycontentscounter.cpp @@ -60,14 +60,23 @@ KDirectoryContentsCounter::~KDirectoryContentsCounter() { --m_workersCount; - if (m_workersCount == 0) { + if (m_workersCount > 0) { + // The worker thread will continue running. It could even be running + // a method of m_worker at the moment, so we delete it using + // deleteLater() to prevent a crash. + m_worker->deleteLater(); + } else { + // There are no remaining workers -> stop the worker thread. m_workerThread->quit(); m_workerThread->wait(); delete m_workerThread; m_workerThread = 0; - } - delete m_worker; + // The worker thread has finished running now, so it's safe to delete + // m_worker. deleteLater() would not work at all because the event loop + // which would deliver the event to m_worker is not running any more. + delete m_worker; + } } void KDirectoryContentsCounter::addDirectory(const QString& path) -- cgit v1.3 From a7562862e3f6ccbf5058d0885dff3675eaa2161c Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Mon, 14 Apr 2014 22:46:38 +0200 Subject: Update the "is cut" state of items if necessary The icons of items which are "cut" are shown faded in the view. The "is cut" state of the widget representing an item is updated if the clipboard contents change. Before this commit, if the sort order was changed however, then each widget kept the "is cut" state of the item which had been shown previously at its position. The solution is to update the "is cut" state also if any of the widget's data change. BUG: 332792 REVIEW: 117451 FIXED-IN: 4.12.5 --- src/kitemviews/kstandarditemlistwidget.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp index acdf839ac..54546b440 100644 --- a/src/kitemviews/kstandarditemlistwidget.cpp +++ b/src/kitemviews/kstandarditemlistwidget.cpp @@ -589,6 +589,12 @@ void KStandardItemListWidget::dataChanged(const QHash& cur dirtyRoles = roles; } + // The URL might have changed (i.e., if the sort order of the items has + // been changed). Therefore, the "is cut" state must be updated. + KFileItemClipboard* clipboard = KFileItemClipboard::instance(); + const KUrl itemUrl = data().value("url").value(); + m_isCut = clipboard->isCut(itemUrl); + // The icon-state might depend from other roles and hence is // marked as dirty whenever a role has been changed dirtyRoles.insert("iconPixmap"); -- cgit v1.3 From bf4b163a0eb5938a587cd12cc9a77e6322c1de66 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Thu, 24 Apr 2014 20:16:30 +0200 Subject: Scroll to the right position when going back and show hidden files is enabled. Instead of emitting the directoryLoadingCompleted signal (via slotCompleted) in KFileItemModel::setShowHiddenFiles directly, we now call dispatchPendingItemsToInsert instead. @Frank: Thanks for your help! FIXED-IN: 4.13.1 BUG: 332159 REVIEW: 117021 --- src/kitemviews/kfileitemmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index fd773e1e9..a0f9305cb 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -216,7 +216,7 @@ void KFileItemModel::setShowHiddenFiles(bool show) m_dirLister->setShowingDotFiles(show); m_dirLister->emitChanges(); if (show) { - slotCompleted(); + dispatchPendingItemsToInsert(); } } -- cgit v1.3 From 272cbbd16b03e51b30b6b9d472aa56054a5ea036 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Thu, 24 Apr 2014 20:57:18 +0200 Subject: Fix memory leak with Dropbox version control plugin. In the current version we only call endRetrieval when beginRetrieval was successfully in UpdateItemStatesThread::run(). This causes some problems with version control plugins (like Dropbox plugin), which have to do cleanups in endRetrieval. Now we always call endRetrieval after beginRetrieval when updating the version states. FIXED-IN: 4.13.1 REVIEW: 117753 --- src/views/versioncontrol/updateitemstatesthread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/views/versioncontrol/updateitemstatesthread.cpp b/src/views/versioncontrol/updateitemstatesthread.cpp index 6457f607d..62fcd09aa 100644 --- a/src/views/versioncontrol/updateitemstatesthread.cpp +++ b/src/views/versioncontrol/updateitemstatesthread.cpp @@ -64,9 +64,9 @@ void UpdateItemStatesThread::run() items[i].version = static_cast(state); } } - - m_plugin->endRetrieval(); } + + m_plugin->endRetrieval(); } } -- cgit v1.3 From afa1a8ef1179e8f8d99bf241389fcc2366290326 Mon Sep 17 00:00:00 2001 From: Renato Atilio Date: Sat, 26 Apr 2014 12:28:42 +0200 Subject: Enable the previous and next tab toolbar buttons when multiple tabs are opened. Disable them again when there is only one remaining tab. Additionally set the default state to disabled. BUG: 332628 FIXED-IN: 4.13.1 REVIEW: 117778 --- src/dolphinmainwindow.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 847301434..28169cfb5 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -481,6 +481,8 @@ void DolphinMainWindow::openNewTab(const KUrl& url) m_viewTab.append(viewTab); actionCollection()->action("close_tab")->setEnabled(true); + actionCollection()->action("activate_prev_tab")->setEnabled(true); + actionCollection()->action("activate_next_tab")->setEnabled(true); // Provide a split view, if the startup settings are set this way if (GeneralSettings::splitView()) { @@ -1155,6 +1157,8 @@ void DolphinMainWindow::closeTab(int index) if (m_viewTab.count() == 1) { m_tabBar->removeTab(0); actionCollection()->action("close_tab")->setEnabled(false); + actionCollection()->action("activate_prev_tab")->setEnabled(false); + actionCollection()->action("activate_next_tab")->setEnabled(false); } else { m_tabBar->blockSignals(false); } @@ -1634,11 +1638,13 @@ void DolphinMainWindow::setupActions() KAction* activateNextTab = actionCollection()->addAction("activate_next_tab"); activateNextTab->setText(i18nc("@action:inmenu", "Activate Next Tab")); + activateNextTab->setEnabled(false); connect(activateNextTab, SIGNAL(triggered()), SLOT(activateNextTab())); activateNextTab->setShortcuts(QApplication::isRightToLeft() ? prevTabKeys : nextTabKeys); KAction* activatePrevTab = actionCollection()->addAction("activate_prev_tab"); activatePrevTab->setText(i18nc("@action:inmenu", "Activate Previous Tab")); + activatePrevTab->setEnabled(false); connect(activatePrevTab, SIGNAL(triggered()), SLOT(activatePrevTab())); activatePrevTab->setShortcuts(QApplication::isRightToLeft() ? nextTabKeys : prevTabKeys); -- cgit v1.3 From b5ca0e2de9001d2584073c043c1fbc1921e0174d Mon Sep 17 00:00:00 2001 From: Frank Reininghaus Date: Sat, 26 Apr 2014 12:29:36 +0200 Subject: Do not change the selection when re-sorting the view If a range of items has been selected by Shift-clicking or by pressing Shift+Arrow, then each of them is added individually to the selection before the items are re-sorted. Before this commit, the first and the last item in the range were moved, and all items between them were selected, even though these were not necessarily the items which had been selected before the re-sorting. BUG: 333457 REVIEW: 117603 FIXED-IN: 4.13.1 --- src/kitemviews/kitemlistselectionmanager.cpp | 11 +++++++---- src/tests/kitemlistselectionmanagertest.cpp | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/kitemviews/kitemlistselectionmanager.cpp b/src/kitemviews/kitemlistselectionmanager.cpp index ebff1a30e..1f0a89d06 100644 --- a/src/kitemviews/kitemlistselectionmanager.cpp +++ b/src/kitemviews/kitemlistselectionmanager.cpp @@ -331,6 +331,11 @@ void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QL // Store the current selection (needed in the selectionChanged() signal) const KItemSet previousSelection = selectedItems(); + // endAnchoredSelection() adds all items between m_currentItem and + // m_anchorItem to m_selectedItems. They can then be moved + // individually later in this function. + endAnchoredSelection(); + // Update the current item if (m_currentItem >= itemRange.index && m_currentItem < itemRange.index + itemRange.count) { const int previousCurrentItem = m_currentItem; @@ -342,10 +347,8 @@ void KItemListSelectionManager::itemsMoved(const KItemRange& itemRange, const QL emit currentChanged(newCurrentItem, previousCurrentItem); } - // Update the anchor item - if (m_anchorItem >= itemRange.index && m_anchorItem < itemRange.index + itemRange.count) { - m_anchorItem = movedToIndexes.at(m_anchorItem - itemRange.index); - } + // Start a new anchored selection. + beginAnchoredSelection(m_currentItem); // Update the selections if (!m_selectedItems.isEmpty()) { diff --git a/src/tests/kitemlistselectionmanagertest.cpp b/src/tests/kitemlistselectionmanagertest.cpp index af2610d8c..492d0234f 100644 --- a/src/tests/kitemlistselectionmanagertest.cpp +++ b/src/tests/kitemlistselectionmanagertest.cpp @@ -78,6 +78,7 @@ private slots: void testChangeSelection(); void testDeleteCurrentItem_data(); void testDeleteCurrentItem(); + void testAnchoredSelectionAfterMovingItems(); private: void verifySelectionChange(QSignalSpy& spy, const KItemSet& currentSelection, const KItemSet& previousSelection) const; @@ -413,6 +414,15 @@ void KItemListSelectionManagerTest::testChangeSelection_data() << QVariant::fromValue(QList() << 4 << 5 << 2 << 3)) << (KItemSet() << 0 << 1 << 4 << 5); + QTest::newRow("Move items with active anchored selection") + << KItemSet() + << 0 << 3 + << (KItemSet() << 0 << 1 << 2 << 3) + << MoveItems + << (QList() << QVariant::fromValue(KItemRange(2, 4)) + << QVariant::fromValue(QList() << 4 << 5 << 2 << 3)) + << (KItemSet() << 0 << 1 << 4 << 5); + // Revert sort order QTest::newRow("Revert sort order") << (KItemSet() << 0 << 1) @@ -519,6 +529,22 @@ void KItemListSelectionManagerTest::testDeleteCurrentItem() QCOMPARE(m_selectionManager->currentItem(), newCurrentItemIndex); } +void KItemListSelectionManagerTest::testAnchoredSelectionAfterMovingItems() +{ + m_selectionManager->setCurrentItem(4); + m_selectionManager->beginAnchoredSelection(4); + + // Reverse the items between 0 and 5. + m_selectionManager->itemsMoved(KItemRange(0, 6), QList() << 5 << 4 << 3 << 2 << 1 << 0); + + QCOMPARE(m_selectionManager->currentItem(), 1); + QCOMPARE(m_selectionManager->m_anchorItem, 1); + + // Make 2 the current item -> 1 and 2 should be selected. + m_selectionManager->setCurrentItem(2); + QCOMPARE(m_selectionManager->selectedItems(), KItemSet() << 1 << 2); +} + void KItemListSelectionManagerTest::verifySelectionChange(QSignalSpy& spy, const KItemSet& currentSelection, const KItemSet& previousSelection) const -- cgit v1.3 From 5e82e598ea941c1f174d8e343feb2008552188a2 Mon Sep 17 00:00:00 2001 From: Emmanuel Pescosta Date: Thu, 24 Apr 2014 21:44:28 +0200 Subject: Mount partitions when you open them in a new tab. Instead of just emitting the slotItemMiddleClicked signal in PlacesPanel::slotItemContextMenuRequested we now use triggerItem with Qt::MiddleButton, which does set up the storage first and emit the slotItemMiddleClicked signal afterwards. BUG: 311226 FIXED-IN: 4.13.1 REVIEW: 117755 --- src/panels/places/placespanel.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index d5308eabe..f19fa1e25 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -283,8 +283,9 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos) } else if (action == hideAction) { item->setHidden(hideAction->isChecked()); } else if (action == openInNewTabAction) { - const KUrl url = m_model->item(index)->dataValue("url").value(); - emit placeMiddleClicked(url); + // TriggerItem does set up the storage first and then it will + // emit the slotItemMiddleClicked signal, because of Qt::MiddleButton. + triggerItem(index, Qt::MiddleButton); } else if (action == teardownAction) { m_model->requestTeardown(index); } else if (action == ejectAction) { -- cgit v1.3