Changeset View
Changeset View
Standalone View
Standalone View
src/kitemviews/kfileitemmodel.cpp
Show First 20 Lines • Show All 49 Lines • ▼ Show 20 Line(s) | 39 | KFileItemModel::KFileItemModel(QObject* parent) : | |||
---|---|---|---|---|---|
50 | m_requestRole(), | 50 | m_requestRole(), | ||
51 | m_maximumUpdateIntervalTimer(nullptr), | 51 | m_maximumUpdateIntervalTimer(nullptr), | ||
52 | m_resortAllItemsTimer(nullptr), | 52 | m_resortAllItemsTimer(nullptr), | ||
53 | m_pendingItemsToInsert(), | 53 | m_pendingItemsToInsert(), | ||
54 | m_groups(), | 54 | m_groups(), | ||
55 | m_expandedDirs(), | 55 | m_expandedDirs(), | ||
56 | m_urlsToExpand() | 56 | m_urlsToExpand() | ||
57 | { | 57 | { | ||
58 | m_collator.setNumericMode(true); | 58 | m_collator.setNumericMode(true); | ||
bruns: this causes the dirty state - maybe also do the forced (re)initialization here? | |||||
59 | 59 | | |||
60 | loadSortingSettings(); | 60 | loadSortingSettings(); | ||
loadSortingSettings(), which sets dirty, is also called from slotSortingChoiceChanged(), so the forced initialization has to be done there too. bruns: `loadSortingSettings()`, which sets `dirty`, is also called from `slotSortingChoiceChanged()`… | |||||
61 | 61 | | |||
62 | // Workaround for bug https://bugreports.qt.io/browse/QTBUG-69361 | ||||
63 | // Force the clean state of QCollator in single thread to avoid thread safety problems in sort | ||||
64 | m_collator.compare(QString(), QString()); | ||||
65 | | ||||
62 | m_dirLister = new KFileItemModelDirLister(this); | 66 | m_dirLister = new KFileItemModelDirLister(this); | ||
63 | m_dirLister->setDelayedMimeTypes(true); | 67 | m_dirLister->setDelayedMimeTypes(true); | ||
64 | 68 | | |||
65 | const QWidget* parentWidget = qobject_cast<QWidget*>(parent); | 69 | const QWidget* parentWidget = qobject_cast<QWidget*>(parent); | ||
66 | if (parentWidget) { | 70 | if (parentWidget) { | ||
67 | m_dirLister->setMainWindow(parentWidget->window()); | 71 | m_dirLister->setMainWindow(parentWidget->window()); | ||
68 | } | 72 | } | ||
69 | 73 | | |||
Show All 33 Lines | |||||
103 | // resorting is postponed until the timer has been exceeded. | 107 | // resorting is postponed until the timer has been exceeded. | ||
104 | m_resortAllItemsTimer = new QTimer(this); | 108 | m_resortAllItemsTimer = new QTimer(this); | ||
105 | m_resortAllItemsTimer->setInterval(500); | 109 | m_resortAllItemsTimer->setInterval(500); | ||
106 | m_resortAllItemsTimer->setSingleShot(true); | 110 | m_resortAllItemsTimer->setSingleShot(true); | ||
107 | connect(m_resortAllItemsTimer, &QTimer::timeout, this, &KFileItemModel::resortAllItems); | 111 | connect(m_resortAllItemsTimer, &QTimer::timeout, this, &KFileItemModel::resortAllItems); | ||
108 | 112 | | |||
109 | connect(GeneralSettings::self(), &GeneralSettings::sortingChoiceChanged, this, &KFileItemModel::slotSortingChoiceChanged); | 113 | connect(GeneralSettings::self(), &GeneralSettings::sortingChoiceChanged, this, &KFileItemModel::slotSortingChoiceChanged); | ||
110 | } | 114 | } | ||
111 | 115 | | |||
Please explain why we need this workaround here (see my previous comment) elvisangelaccio: Please explain why we need this workaround here (see my previous comment) | |||||
112 | KFileItemModel::~KFileItemModel() | 116 | KFileItemModel::~KFileItemModel() | ||
I don't know what @elvisangelaccio thinks about this, but i'm against it. This feels like a hacky workaround to me that should not be needed. markg: I don't know what @elvisangelaccio thinks about this, but i'm against it. This feels like a… | |||||
Maybe better: // Force initialization from the main thread. The collator is captured by reference and passed to the threads, // and if it is not in a clean state all threads will try to initialize it in parallel. bruns: Maybe better:
```
// Force initialization from the main thread. The collator is captured by… | |||||
113 | { | 117 | { | ||
bruns: `m_collator.compare(QString(), QString());` is sufficient | |||||
114 | qDeleteAll(m_itemData); | 118 | qDeleteAll(m_itemData); | ||
115 | qDeleteAll(m_filteredItems); | 119 | qDeleteAll(m_filteredItems); | ||
116 | qDeleteAll(m_pendingItemsToInsert); | 120 | qDeleteAll(m_pendingItemsToInsert); | ||
117 | } | 121 | } | ||
118 | 122 | | |||
119 | void KFileItemModel::loadDirectory(const QUrl &url) | 123 | void KFileItemModel::loadDirectory(const QUrl &url) | ||
120 | { | 124 | { | ||
121 | m_dirLister->openUrl(url); | 125 | m_dirLister->openUrl(url); | ||
▲ Show 20 Lines • Show All 1581 Lines • ▼ Show 20 Line(s) | 1706 | } else if (!isDirA && isDirB) { | |||
1703 | return false; | 1707 | return false; | ||
1704 | } | 1708 | } | ||
1705 | } | 1709 | } | ||
1706 | 1710 | | |||
1707 | result = sortRoleCompare(a, b, collator); | 1711 | result = sortRoleCompare(a, b, collator); | ||
1708 | 1712 | | |||
1709 | return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0; | 1713 | return (sortOrder() == Qt::AscendingOrder) ? result < 0 : result > 0; | ||
1710 | } | 1714 | } | ||
1711 | 1715 | | |||
apol: it's "lambda". | |||||
1712 | /** | | |||
1713 | * Helper class for KFileItemModel::sort(). | | |||
1714 | */ | | |||
1715 | class KFileItemModelLessThan | | |||
1716 | { | | |||
1717 | public: | | |||
1718 | KFileItemModelLessThan(const KFileItemModel* model, const QCollator& collator) : | | |||
1719 | m_model(model), | | |||
1720 | m_collator(collator) | | |||
1721 | { | | |||
1722 | } | | |||
1723 | | ||||
1724 | KFileItemModelLessThan(const KFileItemModelLessThan& other) : | | |||
1725 | m_model(other.m_model), | | |||
1726 | m_collator() | | |||
1727 | { | | |||
1728 | m_collator.setCaseSensitivity(other.m_collator.caseSensitivity()); | | |||
1729 | m_collator.setIgnorePunctuation(other.m_collator.ignorePunctuation()); | | |||
1730 | m_collator.setLocale(other.m_collator.locale()); | | |||
1731 | m_collator.setNumericMode(other.m_collator.numericMode()); | | |||
1732 | } | | |||
1733 | | ||||
1734 | ~KFileItemModelLessThan() = default; | | |||
1735 | //We do not delete m_model as the pointer was passed from outside ant it will be deleted elsewhere. | | |||
1736 | | ||||
1737 | KFileItemModelLessThan& operator=(const KFileItemModelLessThan& other) | | |||
1738 | { | | |||
1739 | m_model = other.m_model; | | |||
1740 | m_collator = other.m_collator; | | |||
1741 | return *this; | | |||
1742 | } | | |||
1743 | | ||||
1744 | bool operator()(const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b) const | | |||
1745 | { | | |||
1746 | return m_model->lessThan(a, b, m_collator); | | |||
1747 | } | | |||
1748 | | ||||
1749 | private: | | |||
1750 | const KFileItemModel* m_model; | | |||
1751 | QCollator m_collator; | | |||
1752 | }; | | |||
1753 | | ||||
1754 | void KFileItemModel::sort(QList<KFileItemModel::ItemData*>::iterator begin, | 1716 | void KFileItemModel::sort(QList<KFileItemModel::ItemData*>::iterator begin, | ||
1755 | QList<KFileItemModel::ItemData*>::iterator end) const | 1717 | QList<KFileItemModel::ItemData*>::iterator end) const | ||
1756 | { | 1718 | { | ||
1757 | KFileItemModelLessThan lessThan(this, m_collator); | 1719 | auto lambdaLessThan = [&] (const KFileItemModel::ItemData* a, const KFileItemModel::ItemData* b) | ||
1720 | { | ||||
1721 | return lessThan(a, b, m_collator); | ||||
1722 | }; | ||||
1758 | 1723 | | |||
1759 | if (m_sortRole == NameRole) { | 1724 | if (m_sortRole == NameRole) { | ||
1760 | // Sorting by name can be expensive, in particular if natural sorting is | 1725 | // Sorting by name can be expensive, in particular if natural sorting is | ||
1761 | // enabled. Use all CPU cores to speed up the sorting process. | 1726 | // enabled. Use all CPU cores to speed up the sorting process. | ||
1762 | static const int numberOfThreads = QThread::idealThreadCount(); | 1727 | static const int numberOfThreads = QThread::idealThreadCount(); | ||
1763 | parallelMergeSort(begin, end, lessThan, numberOfThreads); | 1728 | parallelMergeSort(begin, end, lambdaLessThan, numberOfThreads); | ||
1764 | } else { | 1729 | } else { | ||
1765 | // Sorting by other roles is quite fast. Use only one thread to prevent | 1730 | // Sorting by other roles is quite fast. Use only one thread to prevent | ||
1766 | // problems caused by non-reentrant comparison functions, see | 1731 | // problems caused by non-reentrant comparison functions, see | ||
1767 | // https://bugs.kde.org/show_bug.cgi?id=312679 | 1732 | // https://bugs.kde.org/show_bug.cgi?id=312679 | ||
1768 | mergeSort(begin, end, lessThan); | 1733 | mergeSort(begin, end, lambdaLessThan); | ||
1769 | } | 1734 | } | ||
1770 | } | 1735 | } | ||
1771 | 1736 | | |||
1772 | int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const QCollator& collator) const | 1737 | int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const QCollator& collator) const | ||
1773 | { | 1738 | { | ||
1774 | const KFileItem& itemA = a->item; | 1739 | const KFileItem& itemA = a->item; | ||
1775 | const KFileItem& itemB = b->item; | 1740 | const KFileItem& itemB = b->item; | ||
1776 | 1741 | | |||
▲ Show 20 Lines • Show All 635 Lines • Show Last 20 Lines |
this causes the dirty state - maybe also do the forced (re)initialization here?