diff options
| -rw-r--r-- | src/CMakeLists.txt | 24 | ||||
| -rw-r--r-- | src/dolphinmainwindow.cpp | 3 | ||||
| -rw-r--r-- | src/dolphinviewcontainer.cpp | 14 | ||||
| -rw-r--r-- | src/dolphinviewcontainer.h | 2 | ||||
| -rw-r--r-- | src/kitemviews/kfileitemmodel.cpp | 45 | ||||
| -rw-r--r-- | src/kitemviews/kfileitemmodel.h | 8 | ||||
| -rw-r--r-- | src/kitemviews/private/kfileitemmodelsortalgorithm.cpp | 190 | ||||
| -rw-r--r-- | src/kitemviews/private/kfileitemmodelsortalgorithm.h | 180 | ||||
| -rw-r--r-- | src/main.cpp | 3 | ||||
| -rw-r--r-- | src/panels/folders/folderspanel.cpp | 3 | ||||
| -rw-r--r-- | src/panels/places/placespanel.cpp | 15 | ||||
| -rw-r--r-- | src/views/dolphinremoteencoding.cpp | 5 | ||||
| -rw-r--r-- | src/views/dolphinview.cpp | 32 | ||||
| -rw-r--r-- | src/views/dolphinview.h | 13 | ||||
| -rw-r--r-- | src/views/draganddrophelper.cpp | 16 | ||||
| -rw-r--r-- | src/views/draganddrophelper.h | 11 | ||||
| -rw-r--r-- | src/views/versioncontrol/updateitemstatesthread.cpp | 26 | ||||
| -rw-r--r-- | src/views/versioncontrol/updateitemstatesthread.h | 9 | ||||
| -rw-r--r-- | src/views/versioncontrol/versioncontrolobserver.cpp | 34 |
19 files changed, 278 insertions, 355 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 41efa3589..ffb232ce2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,8 +1,17 @@ -macro_optional_find_package(Soprano) macro_optional_find_package(NepomukCore) +set_package_properties(NepomukCore PROPERTIES DESCRIPTION "Nepomuk Core libraries" + URL "http://www.kde.org" + TYPE OPTIONAL + PURPOSE "For adding desktop-wide tagging support to dolphin" + ) + macro_optional_find_package(NepomukWidgets) -macro_log_feature(NepomukCore_FOUND "Nepomuk Core" "Nepomuk Core functionality" "http://www.kde.org" FALSE "" "For fetching additional file metadata in dolphin") -macro_log_feature(NepomukWidgets_FOUND "Nepomuk Widgets" "Nepomuk Widgets" "http://www.kde.org" FALSE "" "For adding desktop-wide tagging support to dolphin") +set_package_properties(NepomukWidgets PROPERTIES DESCRIPTION "Nepomuk Widgets" + URL "http://www.kde.org" + TYPE OPTIONAL + PURPOSE "For adding desktop-wide tagging support to dolphin" + ) + if(NepomukCore_FOUND AND NepomukWidgets_FOUND) set(HAVE_NEPOMUK TRUE) endif() @@ -15,7 +24,13 @@ configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h ) include_directories( ${KACTIVITIES_INCLUDE_DIRS} ) if(HAVE_NEPOMUK) - # Yes, Soprano includes is what we need here + find_package(Soprano 2.7.56) + set_package_properties(Soprano PROPERTIES DESCRIPTION "Qt-based RDF storage and parsing solution" + URL "http://soprano.sourceforge.net" + TYPE REQUIRED + PURPOSE "Required for everything (storage and general data management)" + ) + include_directories( ${SOPRANO_INCLUDE_DIR} ${NEPOMUK_CORE_INCLUDE_DIR} ${NEPOMUK_WIDGETS_INCLUDE_DIR} ) endif() @@ -45,7 +60,6 @@ set(dolphinprivate_LIB_SRCS kitemviews/kstandarditemmodel.cpp kitemviews/private/kfileitemclipboard.cpp kitemviews/private/kfileitemmodeldirlister.cpp - kitemviews/private/kfileitemmodelsortalgorithm.cpp kitemviews/private/kfileitemmodelfilter.cpp kitemviews/private/kitemlistheaderwidget.cpp kitemviews/private/kitemlistkeyboardsearchmanager.cpp diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp index 9454c8c42..8ed31dea4 100644 --- a/src/dolphinmainwindow.cpp +++ b/src/dolphinmainwindow.cpp @@ -1276,7 +1276,8 @@ void DolphinMainWindow::tabDropEvent(int tab, QDropEvent* event) const ViewTab& viewTab = m_viewTab[tab]; const DolphinView* view = viewTab.isPrimaryViewActive ? viewTab.primaryView->view() : viewTab.secondaryView->view(); - const QString error = DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event); + QString error; + DragAndDropHelper::dropUrls(view->rootItem(), view->url(), event, error); if (!error.isEmpty()) { activeViewContainer()->showMessage(error, DolphinViewContainer::Error); } diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp index 8800a1732..b2c8605d8 100644 --- a/src/dolphinviewcontainer.cpp +++ b/src/dolphinviewcontainer.cpp @@ -128,6 +128,8 @@ DolphinViewContainer::DolphinViewContainer(const KUrl& url, QWidget* parent) : this, SLOT(slotUrlNavigatorLocationChanged(KUrl))); connect(m_urlNavigator, SIGNAL(historyChanged()), this, SLOT(slotHistoryChanged())); + connect(m_urlNavigator, SIGNAL(returnPressed()), + this, SLOT(slotReturnPressed())); // Initialize status bar m_statusBar = new DolphinStatusBar(this); @@ -574,6 +576,8 @@ void DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged(const KUrl& void DolphinViewContainer::slotUrlNavigatorLocationChanged(const KUrl& url) { + slotReturnPressed(); + if (KProtocolManager::supportsListing(url)) { setSearchModeEnabled(isSearchUrl(url)); m_view->setUrl(url); @@ -616,7 +620,8 @@ void DolphinViewContainer::slotUrlNavigatorLocationChanged(const KUrl& url) void DolphinViewContainer::dropUrls(const KUrl& destination, QDropEvent* event) { - const QString error = DragAndDropHelper::dropUrls(KFileItem(), destination, event); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), destination, event, error); if (!error.isEmpty()) { showMessage(error, Error); } @@ -657,6 +662,13 @@ void DolphinViewContainer::slotHistoryChanged() } } +void DolphinViewContainer::slotReturnPressed() +{ + if (!GeneralSettings::editableUrl()) { + m_urlNavigator->setUrlEditable(false); + } +} + void DolphinViewContainer::startSearching() { const KUrl url = m_searchBox->urlForSearching(); diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h index e2d1b1875..bc58531a2 100644 --- a/src/dolphinviewcontainer.h +++ b/src/dolphinviewcontainer.h @@ -282,6 +282,8 @@ private slots: void slotHistoryChanged(); + void slotReturnPressed(); + /** * Gets the search URL from the searchbox and starts searching. */ diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp index 6c015db37..69db217d8 100644 --- a/src/kitemviews/kfileitemmodel.cpp +++ b/src/kitemviews/kfileitemmodel.cpp @@ -58,7 +58,6 @@ KFileItemModel::KFileItemModel(QObject* parent) : m_urlsToExpand() { m_dirLister = new KFileItemModelDirLister(this); - m_dirLister->setAutoUpdate(true); m_dirLister->setDelayedMimeTypes(true); const QWidget* parentWidget = qobject_cast<QWidget*>(parent); @@ -658,7 +657,7 @@ void KFileItemModel::resortAllItems() m_items.clear(); // Resort the items - KFileItemModelSortAlgorithm::sort(this, m_itemData.begin(), m_itemData.end()); + sort(m_itemData.begin(), m_itemData.end()); for (int i = 0; i < itemCount; ++i) { m_items.insert(m_itemData.at(i)->item.url(), i); } @@ -941,7 +940,7 @@ void KFileItemModel::insertItems(const KFileItemList& items) m_groups.clear(); QList<ItemData*> sortedItems = createItemDataList(items); - KFileItemModelSortAlgorithm::sort(this, sortedItems.begin(), sortedItems.end()); + sort(sortedItems.begin(), sortedItems.end()); #ifdef KFILEITEMMODEL_DEBUG kDebug() << "[TIME] Sorting:" << timer.elapsed(); @@ -1020,7 +1019,7 @@ void KFileItemModel::removeItems(const KFileItemList& items) sortedItems.append(m_itemData.at(index)); } } - KFileItemModelSortAlgorithm::sort(this, sortedItems.begin(), sortedItems.end()); + sort(sortedItems.begin(), sortedItems.end()); QList<int> indexesToRemove; indexesToRemove.reserve(items.count()); @@ -1346,6 +1345,44 @@ bool KFileItemModel::lessThan(const ItemData* a, const ItemData* b) const return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0; } +/** + * Helper class for KFileItemModel::sort(). + */ +class KFileItemModelLessThan +{ +public: + KFileItemModelLessThan(const KFileItemModel* model) : + m_model(model) + { + } + + bool operator()(const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b) const + { + return m_model->lessThan(a, b); + } + +private: + const KFileItemModel* m_model; +}; + +void KFileItemModel::sort(QList<KFileItemModel::ItemData*>::iterator begin, + QList<KFileItemModel::ItemData*>::iterator end) const +{ + KFileItemModelLessThan lessThan(this); + + if (m_sortRole == NameRole) { + // Sorting by name can be expensive, in particular if natural sorting is + // enabled. Use all CPU cores to speed up the sorting process. + static const int numberOfThreads = QThread::idealThreadCount(); + parallelMergeSort(begin, end, lessThan, numberOfThreads); + } else { + // Sorting by other roles is quite fast. Use only one thread to prevent + // problems caused by non-reentrant comparison functions, see + // https://bugs.kde.org/show_bug.cgi?id=312679 + mergeSort(begin, end, lessThan); + } +} + int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b) const { const KFileItem& itemA = a->item; diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h index ef9dc98b9..304161a02 100644 --- a/src/kitemviews/kfileitemmodel.h +++ b/src/kitemviews/kfileitemmodel.h @@ -342,6 +342,12 @@ private: bool lessThan(const ItemData* a, const ItemData* b) const; /** + * Sorts the items between \a begin and \a end using the comparison + * function lessThan(). + */ + void sort(QList<ItemData*>::iterator begin, QList<ItemData*>::iterator end) const; + + /** * Helper method for lessThan() and expandedParentsCountCompare(): Compares * the passed item-data using m_sortRole as criteria. Both items must * have the same parent item, otherwise the comparison will be wrong. @@ -476,7 +482,7 @@ private: // and done step after step in slotCompleted(). QSet<KUrl> m_urlsToExpand; - friend class KFileItemModelSortAlgorithm; // Accesses lessThan() method + friend class KFileItemModelLessThan; // Accesses lessThan() method friend class KFileItemModelRolesUpdater; // Accesses emitSortProgress() method friend class KFileItemModelTest; // For unit testing friend class KFileItemListViewTest; // For unit testing diff --git a/src/kitemviews/private/kfileitemmodelsortalgorithm.cpp b/src/kitemviews/private/kfileitemmodelsortalgorithm.cpp deleted file mode 100644 index ab650efea..000000000 --- a/src/kitemviews/private/kfileitemmodelsortalgorithm.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2012 by Peter Penz <[email protected]> * - * * - * 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 "kfileitemmodelsortalgorithm.h" - -#include <QThread> -#include <QtCore> - -void KFileItemModelSortAlgorithm::sort(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end) -{ - if (model->sortRole() == model->roleForType(KFileItemModel::NameRole)) { - // Sorting by name can be expensive, in particular if natural sorting is - // enabled. Use all CPU cores to speed up the sorting process. - static const int numberOfThreads = QThread::idealThreadCount(); - parallelSort(model, begin, end, numberOfThreads); - } else { - // Sorting by other roles is quite fast. Use only one thread to prevent - // problems caused by non-reentrant comparison functions, see - // https://bugs.kde.org/show_bug.cgi?id=312679 - sequentialSort(model, begin, end); - } -} - -void KFileItemModelSortAlgorithm::sequentialSort(KFileItemModel* model, - QList< KFileItemModel::ItemData* >::iterator begin, - QList< KFileItemModel::ItemData* >::iterator end) -{ - // The implementation is based on qStableSortHelper() from qalgorithms.h - // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - - const int span = end - begin; - if (span < 2) { - return; - } - - const QList<KFileItemModel::ItemData*>::iterator middle = begin + span / 2; - sequentialSort(model, begin, middle); - sequentialSort(model, middle, end); - merge(model, begin, middle, end); -} - -void KFileItemModelSortAlgorithm::parallelSort(KFileItemModel* model, - QList< KFileItemModel::ItemData* >::iterator begin, - QList< KFileItemModel::ItemData* >::iterator end, - const int numberOfThreads) -{ - const int span = end - begin; - - if (numberOfThreads > 1 && span > 100) { - const int newNumberOfThreads = numberOfThreads / 2; - const QList<KFileItemModel::ItemData*>::iterator middle = begin + span / 2; - - QFuture<void> future = QtConcurrent::run(parallelSort, model, begin, middle, newNumberOfThreads); - parallelSort(model, middle, end, newNumberOfThreads); - - future.waitForFinished(); - - merge(model, begin, middle, end); - } else { - sequentialSort(model, begin, end); - } -} - -void KFileItemModelSortAlgorithm::merge(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator pivot, - QList<KFileItemModel::ItemData*>::iterator end) -{ - // The implementation is based on qMerge() from qalgorithms.h - // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - - const int len1 = pivot - begin; - const int len2 = end - pivot; - - if (len1 == 0 || len2 == 0) { - return; - } - - if (len1 + len2 == 2) { - if (model->lessThan(*(begin + 1), *(begin))) { - qSwap(*begin, *(begin + 1)); - } - return; - } - - QList<KFileItemModel::ItemData*>::iterator firstCut; - QList<KFileItemModel::ItemData*>::iterator secondCut; - int len2Half; - if (len1 > len2) { - const int len1Half = len1 / 2; - firstCut = begin + len1Half; - secondCut = lowerBound(model, pivot, end, *firstCut); - len2Half = secondCut - pivot; - } else { - len2Half = len2 / 2; - secondCut = pivot + len2Half; - firstCut = upperBound(model, begin, pivot, *secondCut); - } - - reverse(firstCut, pivot); - reverse(pivot, secondCut); - reverse(firstCut, secondCut); - - const QList<KFileItemModel::ItemData*>::iterator newPivot = firstCut + len2Half; - merge(model, begin, firstCut, newPivot); - merge(model, newPivot, secondCut, end); -} - - -QList<KFileItemModel::ItemData*>::iterator -KFileItemModelSortAlgorithm::lowerBound(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end, - const KFileItemModel::ItemData* value) -{ - // The implementation is based on qLowerBound() from qalgorithms.h - // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - - QList<KFileItemModel::ItemData*>::iterator middle; - int n = int(end - begin); - int half; - - while (n > 0) { - half = n >> 1; - middle = begin + half; - if (model->lessThan(*middle, value)) { - begin = middle + 1; - n -= half + 1; - } else { - n = half; - } - } - return begin; -} - -QList<KFileItemModel::ItemData*>::iterator -KFileItemModelSortAlgorithm::upperBound(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end, - const KFileItemModel::ItemData* value) -{ - // The implementation is based on qUpperBound() from qalgorithms.h - // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - - QList<KFileItemModel::ItemData*>::iterator middle; - int n = end - begin; - int half; - - while (n > 0) { - half = n >> 1; - middle = begin + half; - if (model->lessThan(value, *middle)) { - n = half; - } else { - begin = middle + 1; - n -= half + 1; - } - } - return begin; -} - -void KFileItemModelSortAlgorithm::reverse(QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end) -{ - // The implementation is based on qReverse() from qalgorithms.h - // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - - --end; - while (begin < end) { - qSwap(*begin++, *end--); - } -} diff --git a/src/kitemviews/private/kfileitemmodelsortalgorithm.h b/src/kitemviews/private/kfileitemmodelsortalgorithm.h index 07e5d4a81..1d5689432 100644 --- a/src/kitemviews/private/kfileitemmodelsortalgorithm.h +++ b/src/kitemviews/private/kfileitemmodelsortalgorithm.h @@ -1,79 +1,143 @@ -/*************************************************************************** - * Copyright (C) 2012 by Peter Penz <[email protected]> * - * * - * 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 * - ***************************************************************************/ +/***************************************************************************** + * Copyright (C) 2012 by Peter Penz <[email protected]> * + * Copyright (C) 2012 by Emmanuel Pescosta <[email protected]> * + * Copyright (C) 2013 by Frank Reininghaus <[email protected]> * + * * + * 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 KFILEITEMMODELSORTALGORITHM_H #define KFILEITEMMODELSORTALGORITHM_H -#include <libdolphin_export.h> +#include <QtCore> -#include <kitemviews/kfileitemmodel.h> +#include <algorithm> /** - * @brief Sort algorithm for sorting items of KFileItemModel. - * - * Sorts the items by using KFileItemModel::lessThan() as comparison criteria. - * The merge sort algorithm is used to assure a worst-case - * of O(n * log(n)) and to keep the number of comparisons low. + * Sorts the items using the merge sort algorithm is used to assure a + * worst-case of O(n * log(n)) and to keep the number of comparisons low. * * The implementation is based on qStableSortHelper() from qalgorithms.h * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - * The sorting implementations of qAlgorithms could not be used as they - * don't support having a member-function as comparison criteria. */ -class LIBDOLPHINPRIVATE_EXPORT KFileItemModelSortAlgorithm + +template <typename RandomAccessIterator, typename LessThan> +static void mergeSort(RandomAccessIterator begin, + RandomAccessIterator end, + LessThan lessThan) { -public: - static void sort(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end); + // The implementation is based on qStableSortHelper() from qalgorithms.h + // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). -private: - static void sequentialSort(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end); + const int span = end - begin; + if (span < 2) { + return; + } - static void parallelSort(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end, - const int numberOfThreads); + const RandomAccessIterator middle = begin + span / 2; + mergeSort(begin, middle, lessThan); + mergeSort(middle, end, lessThan); + merge(begin, middle, end, lessThan); +} - static void merge(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator pivot, - QList<KFileItemModel::ItemData*>::iterator end); +/** + * Uses up to \a numberOfThreads threads to sort the items between + * \a begin and \a end. Only item ranges longer than + * \a parallelMergeSortingThreshold are split to be sorted by two different + * threads. + * + * The comparison function \a lessThan must be reentrant. + */ - static QList<KFileItemModel::ItemData*>::iterator - lowerBound(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end, - const KFileItemModel::ItemData* value); +template <typename RandomAccessIterator, typename LessThan> +static void parallelMergeSort(RandomAccessIterator begin, + RandomAccessIterator end, + LessThan lessThan, + int numberOfThreads, + int parallelMergeSortingThreshold = 100) +{ + const int span = end - begin; - static QList<KFileItemModel::ItemData*>::iterator - upperBound(KFileItemModel* model, - QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end, - const KFileItemModel::ItemData* value); + if (numberOfThreads > 1 && span > parallelMergeSortingThreshold) { + const int newNumberOfThreads = numberOfThreads / 2; + const RandomAccessIterator middle = begin + span / 2; - static void reverse(QList<KFileItemModel::ItemData*>::iterator begin, - QList<KFileItemModel::ItemData*>::iterator end); -}; + QFuture<void> future = QtConcurrent::run(parallelMergeSort<RandomAccessIterator, LessThan>, begin, middle, lessThan, newNumberOfThreads, parallelMergeSortingThreshold); + parallelMergeSort(middle, end, lessThan, newNumberOfThreads, parallelMergeSortingThreshold); -#endif + future.waitForFinished(); + + merge(begin, middle, end, lessThan); + } else { + mergeSort(begin, end, lessThan); + } +} + +/** + * Merges the sorted item ranges between \a begin and \a pivot and + * between \a pivot and \a end into a single sorted range between + * \a begin and \a end. + * + * The implementation is based on qMerge() from qalgorithms.h + * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + */ + +template <typename RandomAccessIterator, typename LessThan> +static void merge(RandomAccessIterator begin, + RandomAccessIterator pivot, + RandomAccessIterator end, + LessThan lessThan) +{ + // The implementation is based on qMerge() from qalgorithms.h + // Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + + const int len1 = pivot - begin; + const int len2 = end - pivot; + + if (len1 == 0 || len2 == 0) { + return; + } + if (len1 + len2 == 2) { + if (lessThan(*(begin + 1), *(begin))) { + qSwap(*begin, *(begin + 1)); + } + return; + } + + RandomAccessIterator firstCut; + RandomAccessIterator secondCut; + int len2Half; + if (len1 > len2) { + const int len1Half = len1 / 2; + firstCut = begin + len1Half; + secondCut = std::lower_bound(pivot, end, *firstCut, lessThan); + len2Half = secondCut - pivot; + } else { + len2Half = len2 / 2; + secondCut = pivot + len2Half; + firstCut = std::upper_bound(begin, pivot, *secondCut, lessThan); + } + + std::rotate(firstCut, pivot, secondCut); + + RandomAccessIterator newPivot = firstCut + len2Half; + merge(begin, firstCut, newPivot, lessThan); + merge(newPivot, secondCut, end, lessThan); +} + +#endif diff --git a/src/main.cpp b/src/main.cpp index 9577259b5..06328bd2e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -50,6 +50,9 @@ KDE_EXPORT int kdemain(int argc, char **argv) about.addAuthor(ki18nc("@info:credit", "David Faure"), ki18nc("@info:credit", "Developer"), + about.addAuthor(ki18nc("@info:credit", "Emmanuel Pescosta"), + ki18nc("@info:credit", "Developer"), + "[email protected]"); about.addAuthor(ki18nc("@info:credit", "Aaron J. Seigo"), ki18nc("@info:credit", "Developer"), diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp index 6e3a7678f..8ce853a2a 100644 --- a/src/panels/folders/folderspanel.cpp +++ b/src/panels/folders/folderspanel.cpp @@ -236,7 +236,8 @@ void FoldersPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* eve event->buttons(), event->modifiers()); - const QString error = DragAndDropHelper::dropUrls(destItem, destItem.url(), &dropEvent); + QString error; + DragAndDropHelper::dropUrls(destItem, destItem.url(), &dropEvent, error); if (!error.isEmpty()) { emit errorMessage(error); } diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp index 61c15a7a1..9f9306946 100644 --- a/src/panels/places/placespanel.cpp +++ b/src/panels/places/placespanel.cpp @@ -352,7 +352,11 @@ void PlacesPanel::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even event->buttons(), event->modifiers()); - DragAndDropHelper::dropUrls(KFileItem(), destUrl, &dropEvent); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), destUrl, &dropEvent, error); + if (!error.isEmpty()) { + emit errorMessage(error); + } } void PlacesPanel::slotItemDropEventStorageSetupDone(int index, bool success) @@ -364,7 +368,11 @@ void PlacesPanel::slotItemDropEventStorageSetupDone(int index, bool success) if (success) { KUrl destUrl = m_model->placesItem(index)->url(); - DragAndDropHelper::dropUrls(KFileItem(), destUrl, m_itemDropEvent); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), destUrl, m_itemDropEvent, error); + if (!error.isEmpty()) { + emit errorMessage(error); + } } delete m_itemDropEventMimeData; @@ -384,7 +392,8 @@ void PlacesPanel::slotAboveItemDropEvent(int index, QGraphicsSceneDragDropEvent* void PlacesPanel::slotUrlsDropped(const KUrl& dest, QDropEvent* event, QWidget* parent) { Q_UNUSED(parent); - const QString error = DragAndDropHelper::dropUrls(KFileItem(), dest, event); + QString error; + DragAndDropHelper::dropUrls(KFileItem(), dest, event, error); if (!error.isEmpty()) { emit errorMessage(error); } diff --git a/src/views/dolphinremoteencoding.cpp b/src/views/dolphinremoteencoding.cpp index 375b3fd46..04b350eda 100644 --- a/src/views/dolphinremoteencoding.cpp +++ b/src/views/dolphinremoteencoding.cpp @@ -38,7 +38,6 @@ #include <KMenu> #include <KProtocolInfo> #include <KProtocolManager> -#include <KIO/SlaveConfig> #include <KIO/Scheduler> #include <KConfigGroup> @@ -132,9 +131,7 @@ void DolphinRemoteEncoding::updateMenu() m_menu->menu()->actions().at(i)->setChecked(false); } - QString charset = KGlobal::charsets()->descriptionForEncoding(KIO::SlaveConfig::self()->configData(m_currentURL.protocol(), - m_currentURL.host(), DATA_KEY)); - + const QString charset = KGlobal::charsets()->descriptionForEncoding(KProtocolManager::charsetFor(m_currentURL)); if (!charset.isEmpty()) { int id = 0; bool isFound = false; diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp index 502ffd428..d1e154f68 100644 --- a/src/views/dolphinview.cpp +++ b/src/views/dolphinview.cpp @@ -1023,14 +1023,16 @@ void DolphinView::slotItemDropEvent(int index, QGraphicsSceneDragDropEvent* even event->buttons(), event->modifiers()); - const QString error = DragAndDropHelper::dropUrls(destItem, destUrl, &dropEvent); + QString error; + KonqOperations* op = DragAndDropHelper::dropUrls(destItem, destUrl, &dropEvent, error); if (!error.isEmpty()) { emit infoMessage(error); } - if (destUrl == url()) { + if (op && destUrl == url()) { // Mark the dropped urls as selected. - markPastedUrlsAsSelected(event->mimeData()); + m_clearSelectionBeforeSelectingNewItems = true; + connect(op, SIGNAL(urlPasted(KUrl)), this, SLOT(slotUrlPasted(KUrl))); } } @@ -1066,6 +1068,11 @@ void DolphinView::slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons } } +void DolphinView::slotAboutToCreate(const KUrl::List& urls) +{ + m_selectedUrls << urls; +} + void DolphinView::slotSelectionChanged(const QSet<int>& current, const QSet<int>& previous) { const int currentCount = current.count(); @@ -1523,8 +1530,11 @@ void DolphinView::applyModeToView() void DolphinView::pasteToUrl(const KUrl& url) { - markPastedUrlsAsSelected(QApplication::clipboard()->mimeData()); - KonqOperations::doPaste(this, url); + KonqOperations* op = KonqOperations::doPasteV2(this, url); + if (op) { + m_clearSelectionBeforeSelectingNewItems = true; + connect(op, SIGNAL(aboutToCreate(KUrl::List)), this, SLOT(slotAboutToCreate(KUrl::List))); + } } KUrl::List DolphinView::simplifiedSelectedUrls() const @@ -1552,18 +1562,6 @@ QMimeData* DolphinView::selectionMimeData() const return m_model->createMimeData(selectedIndexes); } -void DolphinView::markPastedUrlsAsSelected(const QMimeData* mimeData) -{ - const KUrl::List sourceUrls = KUrl::List::fromMimeData(mimeData); - KUrl::List destUrls; - foreach (const KUrl& source, sourceUrls) { - KUrl destination(url().url() + '/' + source.fileName()); - destUrls << destination; - } - markUrlsAsSelected(destUrls); - m_clearSelectionBeforeSelectingNewItems = true; -} - void DolphinView::updateWritableState() { const bool wasFolderWritable = m_isFolderWritable; diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h index a2fe9f62a..13cc66545 100644 --- a/src/views/dolphinview.h +++ b/src/views/dolphinview.h @@ -566,6 +566,11 @@ private slots: void slotModelChanged(KItemModelBase* current, KItemModelBase* previous); void slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons); + /* + * Is called when new items get pasted or dropped. + */ + void slotAboutToCreate(const KUrl::List& urls); + /** * Emits the signal \a selectionChanged() with a small delay. This is * because getting all file items for the selection can be an expensive @@ -722,14 +727,6 @@ private: QMimeData* selectionMimeData() const; /** - * Is invoked after a paste operation or a drag & drop - * operation and URLs from \a mimeData as selected. - * This allows to select all newly pasted - * items in restoreViewState(). - */ - void markPastedUrlsAsSelected(const QMimeData* mimeData); - - /** * Updates m_isFolderWritable dependent on whether the folder represented by * the current URL is writable. If the state has changed, the signal * writeableStateChanged() will be emitted. diff --git a/src/views/draganddrophelper.cpp b/src/views/draganddrophelper.cpp index f81d4d0bf..f8ae0ad03 100644 --- a/src/views/draganddrophelper.cpp +++ b/src/views/draganddrophelper.cpp @@ -28,10 +28,13 @@ #include <QtDBus> #include <QDropEvent> -QString DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destUrl, QDropEvent* event) +KonqOperations* DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destUrl, QDropEvent* event, QString& error) { + error.clear(); + if (!destItem.isNull() && !destItem.isWritable()) { - return i18nc("@info:status", "Access denied. Could not write to <filename>%1</filename>", destUrl.pathOrUrl()); + error = i18nc("@info:status", "Access denied. Could not write to <filename>%1</filename>", destUrl.pathOrUrl()); + return 0; } const QMimeData* mimeData = event->mimeData(); @@ -49,15 +52,16 @@ QString DragAndDropHelper::dropUrls(const KFileItem& destItem, const KUrl& destU const KUrl::List urls = KUrl::List::fromMimeData(event->mimeData()); foreach (const KUrl& url, urls) { if (url == destUrl) { - return i18nc("@info:status", "A folder cannot be dropped into itself"); + error = i18nc("@info:status", "A folder cannot be dropped into itself"); + return 0; } } - KonqOperations::doDrop(destItem, destUrl, event, QApplication::activeWindow()); + return KonqOperations::doDrop(destItem, destUrl, event, QApplication::activeWindow(), QList<QAction*>()); } else { - KonqOperations::doDrop(KFileItem(), destUrl, event, QApplication::activeWindow()); + return KonqOperations::doDrop(KFileItem(), destUrl, event, QApplication::activeWindow(), QList<QAction*>()); } - return QString(); + return 0; } diff --git a/src/views/draganddrophelper.h b/src/views/draganddrophelper.h index ac16f7cf2..eda5fc5c2 100644 --- a/src/views/draganddrophelper.h +++ b/src/views/draganddrophelper.h @@ -29,6 +29,7 @@ class KFileItem; class KUrl; class QDropEvent; class QWidget; +class KonqOperations; class LIBDOLPHINPRIVATE_EXPORT DragAndDropHelper { @@ -46,13 +47,15 @@ public: * @param destUrl URL of the item destination. Is used only if destItem::isNull() * is true. * @param event Drop event. - * @return Error message intended to be shown for users if dropping is not + * @param error Error message intended to be shown for users if dropping is not * possible. If an empty string is returned, the dropping has been * successful. + * @return KonqOperations pointer */ - static QString dropUrls(const KFileItem& destItem, - const KUrl& destUrl, - QDropEvent* event); + static KonqOperations* dropUrls(const KFileItem& destItem, + const KUrl& destUrl, + QDropEvent* event, + QString& error); }; #endif diff --git a/src/views/versioncontrol/updateitemstatesthread.cpp b/src/views/versioncontrol/updateitemstatesthread.cpp index e07d72c76..fa005f8f1 100644 --- a/src/views/versioncontrol/updateitemstatesthread.cpp +++ b/src/views/versioncontrol/updateitemstatesthread.cpp @@ -23,13 +23,13 @@ #include <QMutexLocker> -UpdateItemStatesThread::UpdateItemStatesThread() : +UpdateItemStatesThread::UpdateItemStatesThread(KVersionControlPlugin* plugin, + const QList<VersionControlObserver::ItemState>& itemStates) : QThread(), m_globalPluginMutex(0), - m_plugin(0), - m_itemMutex(), + m_plugin(plugin), m_retrievedItems(false), - m_itemStates() + m_itemStates(itemStates) { // Several threads may share one instance of a plugin. A global // mutex is required to serialize the retrieval of version control @@ -42,32 +42,16 @@ UpdateItemStatesThread::~UpdateItemStatesThread() { } -void UpdateItemStatesThread::setData(KVersionControlPlugin* plugin, - const QList<VersionControlObserver::ItemState>& itemStates) -{ - // The locks are taken in the same order as in run() - // to avoid potential deadlock. - QMutexLocker pluginLocker(m_globalPluginMutex); - QMutexLocker itemLocker(&m_itemMutex); - - m_itemStates = itemStates; - m_plugin = plugin; -} - void UpdateItemStatesThread::run() { Q_ASSERT(!m_itemStates.isEmpty()); Q_ASSERT(m_plugin); - QMutexLocker itemLocker(&m_itemMutex); - const QString directory = m_itemStates.first().item.url().directory(KUrl::AppendTrailingSlash); m_retrievedItems = false; - itemLocker.unlock(); QMutexLocker pluginLocker(m_globalPluginMutex); if (m_plugin->beginRetrieval(directory)) { - itemLocker.relock(); const int count = m_itemStates.count(); KVersionControlPlugin2* pluginV2 = qobject_cast<KVersionControlPlugin2*>(m_plugin); @@ -99,13 +83,11 @@ void UpdateItemStatesThread::unlockPlugin() QList<VersionControlObserver::ItemState> UpdateItemStatesThread::itemStates() const { - QMutexLocker locker(&m_itemMutex); return m_itemStates; } bool UpdateItemStatesThread::retrievedItems() const { - QMutexLocker locker(&m_itemMutex); return m_retrievedItems; } diff --git a/src/views/versioncontrol/updateitemstatesthread.h b/src/views/versioncontrol/updateitemstatesthread.h index f0f91d7d2..a28169755 100644 --- a/src/views/versioncontrol/updateitemstatesthread.h +++ b/src/views/versioncontrol/updateitemstatesthread.h @@ -38,9 +38,6 @@ class LIBDOLPHINPRIVATE_EXPORT UpdateItemStatesThread : public QThread Q_OBJECT public: - UpdateItemStatesThread(); - virtual ~UpdateItemStatesThread(); - /** * @param plugin Version control plugin that is used to update the * state of the items. Whenever the plugin is accessed @@ -49,8 +46,9 @@ public: * UpdateItemStatesThread::unlockPlugin() must be used. * @param itemStates List of items, where the states get updated. */ - void setData(KVersionControlPlugin* plugin, - const QList<VersionControlObserver::ItemState>& itemStates); + UpdateItemStatesThread(KVersionControlPlugin* plugin, + const QList<VersionControlObserver::ItemState>& itemStates); + virtual ~UpdateItemStatesThread(); /** * Whenever the plugin is accessed by the thread creator, lockPlugin() must @@ -76,7 +74,6 @@ private: QMutex* m_globalPluginMutex; // Protects the m_plugin globally KVersionControlPlugin* m_plugin; - mutable QMutex m_itemMutex; // Protects m_retrievedItems and m_itemStates bool m_retrievedItems; QList<VersionControlObserver::ItemState> m_itemStates; }; diff --git a/src/views/versioncontrol/versioncontrolobserver.cpp b/src/views/versioncontrol/versioncontrolobserver.cpp index 64bc26867..402a2de54 100644 --- a/src/views/versioncontrol/versioncontrolobserver.cpp +++ b/src/views/versioncontrol/versioncontrolobserver.cpp @@ -108,12 +108,7 @@ QList<QAction*> VersionControlObserver::actions(const KFileItemList& items) cons if (pluginV2) { // Use version 2 of the KVersionControlPlugin which allows providing actions // also for non-versioned directories. - if (m_updateItemStatesThread && m_updateItemStatesThread->lockPlugin()) { - actions = pluginV2->actions(items); - m_updateItemStatesThread->unlockPlugin(); - } else { - actions = pluginV2->actions(items); - } + actions = pluginV2->actions(items); } else if (isVersioned()) { // Support deprecated interfaces from KVersionControlPlugin version 1. // Context menu actions where only available for versioned directories. @@ -125,14 +120,8 @@ QList<QAction*> VersionControlObserver::actions(const KFileItemList& items) cons } } - if (m_updateItemStatesThread && m_updateItemStatesThread->lockPlugin()) { - actions = directory.isEmpty() ? m_plugin->contextMenuActions(items) - : m_plugin->contextMenuActions(directory); - m_updateItemStatesThread->unlockPlugin(); - } else { - actions = directory.isEmpty() ? m_plugin->contextMenuActions(items) - : m_plugin->contextMenuActions(directory); - } + actions = directory.isEmpty() ? m_plugin->contextMenuActions(items) + : m_plugin->contextMenuActions(directory); } return actions; @@ -238,20 +227,12 @@ void VersionControlObserver::slotThreadFinished() void VersionControlObserver::updateItemStates() { Q_ASSERT(m_plugin); - if (!m_updateItemStatesThread) { - m_updateItemStatesThread = new UpdateItemStatesThread(); - connect(m_updateItemStatesThread, SIGNAL(finished()), - this, SLOT(slotThreadFinished())); - connect(m_updateItemStatesThread, SIGNAL(finished()), - m_updateItemStatesThread, SLOT(deleteLater())); - } - else { + if (m_updateItemStatesThread) { // An update is currently ongoing. Wait until the thread has finished // the update (see slotThreadFinished()). m_pendingItemStatesUpdate = true; return; } - QList<ItemState> itemStates; const int itemCount = m_model->count(); itemStates.reserve(itemCount); @@ -269,7 +250,12 @@ void VersionControlObserver::updateItemStates() if (!m_silentUpdate) { emit infoMessage(i18nc("@info:status", "Updating version information...")); } - m_updateItemStatesThread->setData(m_plugin, itemStates); + m_updateItemStatesThread = new UpdateItemStatesThread(m_plugin, itemStates); + connect(m_updateItemStatesThread, SIGNAL(finished()), + this, SLOT(slotThreadFinished())); + connect(m_updateItemStatesThread, SIGNAL(finished()), + m_updateItemStatesThread, SLOT(deleteLater())); + m_updateItemStatesThread->start(); // slotThreadFinished() is called when finished } } |
