Changeset View
Changeset View
Standalone View
Standalone View
containments/desktop/plugins/folder/foldermodel.cpp
Show First 20 Lines • Show All 88 Lines • ▼ Show 20 Line(s) | 85 | { | |||
---|---|---|---|---|---|
89 | } | 89 | } | ||
90 | 90 | | |||
91 | KDirLister::handleError(job); | 91 | KDirLister::handleError(job); | ||
92 | } | 92 | } | ||
93 | 93 | | |||
94 | FolderModel::FolderModel(QObject *parent) : QSortFilterProxyModel(parent), | 94 | FolderModel::FolderModel(QObject *parent) : QSortFilterProxyModel(parent), | ||
95 | m_dirWatch(nullptr), | 95 | m_dirWatch(nullptr), | ||
96 | m_dragInProgress(false), | 96 | m_dragInProgress(false), | ||
97 | m_urlChangedWhileDragging(false), | ||||
97 | m_previewGenerator(0), | 98 | m_previewGenerator(0), | ||
98 | m_viewAdapter(0), | 99 | m_viewAdapter(0), | ||
99 | m_actionCollection(this), | 100 | m_actionCollection(this), | ||
100 | m_newMenu(0), | 101 | m_newMenu(0), | ||
101 | m_fileItemActions(0), | 102 | m_fileItemActions(0), | ||
102 | m_usedByContainment(false), | 103 | m_usedByContainment(false), | ||
103 | m_locked(true), | 104 | m_locked(true), | ||
104 | m_sortMode(0), | 105 | m_sortMode(0), | ||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Line(s) | 176 | if (url == m_url) { | |||
177 | return; | 178 | return; | ||
178 | } | 179 | } | ||
179 | 180 | | |||
180 | beginResetModel(); | 181 | beginResetModel(); | ||
181 | m_url = url; | 182 | m_url = url; | ||
182 | m_isDirCache.clear(); | 183 | m_isDirCache.clear(); | ||
183 | m_dirModel->dirLister()->openUrl(resolvedUrl); | 184 | m_dirModel->dirLister()->openUrl(resolvedUrl); | ||
184 | clearDragImages(); | 185 | clearDragImages(); | ||
186 | m_dragIndexes.clear(); | ||||
185 | endResetModel(); | 187 | endResetModel(); | ||
186 | 188 | | |||
187 | emit urlChanged(); | 189 | emit urlChanged(); | ||
188 | emit resolvedUrlChanged(); | 190 | emit resolvedUrlChanged(); | ||
189 | 191 | | |||
190 | m_errorString.clear(); | 192 | m_errorString.clear(); | ||
191 | emit errorStringChanged(); | 193 | emit errorStringChanged(); | ||
192 | 194 | | |||
193 | if (m_dirWatch) { | 195 | if (m_dirWatch) { | ||
194 | delete m_dirWatch; | 196 | delete m_dirWatch; | ||
195 | } | 197 | } | ||
196 | 198 | | |||
197 | if (resolvedUrl.isValid()) { | 199 | if (resolvedUrl.isValid()) { | ||
198 | m_dirWatch = new KDirWatch(this); | 200 | m_dirWatch = new KDirWatch(this); | ||
199 | connect(m_dirWatch, &KDirWatch::created, this, &FolderModel::iconNameChanged); | 201 | connect(m_dirWatch, &KDirWatch::created, this, &FolderModel::iconNameChanged); | ||
200 | connect(m_dirWatch, &KDirWatch::dirty, this, &FolderModel::iconNameChanged); | 202 | connect(m_dirWatch, &KDirWatch::dirty, this, &FolderModel::iconNameChanged); | ||
201 | m_dirWatch->addFile(resolvedUrl.toLocalFile() + QLatin1String("/.directory")); | 203 | m_dirWatch->addFile(resolvedUrl.toLocalFile() + QLatin1String("/.directory")); | ||
202 | } | 204 | } | ||
203 | 205 | | |||
206 | if (m_dragInProgress) { | ||||
207 | m_urlChangedWhileDragging = true; | ||||
208 | } | ||||
209 | | ||||
204 | emit iconNameChanged(); | 210 | emit iconNameChanged(); | ||
205 | } | 211 | } | ||
206 | 212 | | |||
207 | QUrl FolderModel::resolvedUrl() const | 213 | QUrl FolderModel::resolvedUrl() const | ||
208 | { | 214 | { | ||
209 | return m_dirModel->dirLister()->url(); | 215 | return m_dirModel->dirLister()->url(); | ||
210 | } | 216 | } | ||
211 | 217 | | |||
Show All 21 Lines | 232 | { | |||
233 | return rootItem.iconName(); | 239 | return rootItem.iconName(); | ||
234 | } | 240 | } | ||
235 | 241 | | |||
236 | QString FolderModel::errorString() const | 242 | QString FolderModel::errorString() const | ||
237 | { | 243 | { | ||
238 | return m_errorString; | 244 | return m_errorString; | ||
239 | } | 245 | } | ||
240 | 246 | | |||
247 | bool FolderModel::dragging() const | ||||
248 | { | ||||
249 | return m_dragInProgress; | ||||
250 | } | ||||
251 | | ||||
241 | bool FolderModel::usedByContainment() const | 252 | bool FolderModel::usedByContainment() const | ||
242 | { | 253 | { | ||
243 | return m_usedByContainment; | 254 | return m_usedByContainment; | ||
244 | } | 255 | } | ||
245 | 256 | | |||
246 | void FolderModel::setUsedByContainment(bool used) | 257 | void FolderModel::setUsedByContainment(bool used) | ||
247 | { | 258 | { | ||
248 | if (m_usedByContainment != used) { | 259 | if (m_usedByContainment != used) { | ||
▲ Show 20 Lines • Show All 504 Lines • ▼ Show 20 Line(s) | |||||
753 | 764 | | |||
754 | void FolderModel::dragSelected(int x, int y) | 765 | void FolderModel::dragSelected(int x, int y) | ||
755 | { | 766 | { | ||
756 | if (m_dragInProgress) { | 767 | if (m_dragInProgress) { | ||
757 | return; | 768 | return; | ||
758 | } | 769 | } | ||
759 | 770 | | |||
760 | m_dragInProgress = true; | 771 | m_dragInProgress = true; | ||
772 | emit draggingChanged(); | ||||
773 | m_urlChangedWhileDragging = false; | ||||
761 | 774 | | |||
762 | // Avoid starting a drag synchronously in a mouse handler or interferes with | 775 | // Avoid starting a drag synchronously in a mouse handler or interferes with | ||
763 | // child event filtering in parent items (and thus e.g. press-and-hold hand- | 776 | // child event filtering in parent items (and thus e.g. press-and-hold hand- | ||
764 | // ling in a containment). | 777 | // ling in a containment). | ||
765 | QMetaObject::invokeMethod(this, "dragSelectedInternal", Qt::QueuedConnection, | 778 | QMetaObject::invokeMethod(this, "dragSelectedInternal", Qt::QueuedConnection, | ||
766 | Q_ARG(int, x), | 779 | Q_ARG(int, x), | ||
767 | Q_ARG(int, y)); | 780 | Q_ARG(int, y)); | ||
768 | } | 781 | } | ||
769 | 782 | | |||
770 | void FolderModel::dragSelectedInternal(int x, int y) | 783 | void FolderModel::dragSelectedInternal(int x, int y) | ||
771 | { | 784 | { | ||
772 | if (!m_viewAdapter || !m_selectionModel->hasSelection()) { | 785 | if (!m_viewAdapter || !m_selectionModel->hasSelection()) { | ||
773 | m_dragInProgress = false; | 786 | m_dragInProgress = false; | ||
787 | emit draggingChanged(); | ||||
774 | return; | 788 | return; | ||
775 | } | 789 | } | ||
776 | 790 | | |||
777 | ItemViewAdapter *adapter = qobject_cast<ItemViewAdapter *>(m_viewAdapter); | 791 | ItemViewAdapter *adapter = qobject_cast<ItemViewAdapter *>(m_viewAdapter); | ||
778 | QQuickItem *item = qobject_cast<QQuickItem *>(adapter->adapterView()); | 792 | QQuickItem *item = qobject_cast<QQuickItem *>(adapter->adapterView()); | ||
779 | 793 | | |||
780 | QDrag *drag = new QDrag(item); | 794 | QDrag *drag = new QDrag(item); | ||
781 | 795 | | |||
Show All 9 Lines | |||||
791 | QModelIndexList sourceDragIndexes; | 805 | QModelIndexList sourceDragIndexes; | ||
792 | 806 | | |||
793 | foreach (const QModelIndex &index, m_dragIndexes) { | 807 | foreach (const QModelIndex &index, m_dragIndexes) { | ||
794 | sourceDragIndexes.append(mapToSource(index)); | 808 | sourceDragIndexes.append(mapToSource(index)); | ||
795 | } | 809 | } | ||
796 | 810 | | |||
797 | drag->setMimeData(m_dirModel->mimeData(sourceDragIndexes)); | 811 | drag->setMimeData(m_dirModel->mimeData(sourceDragIndexes)); | ||
798 | 812 | | |||
813 | // Due to spring-loading (aka auto-expand), the URL might change | ||||
814 | // while the drag is in-flight - in that case we don't want to | ||||
815 | // unnecessarily emit dataChanged() for (possibly invalid) indices | ||||
816 | // after it ends. | ||||
817 | const QUrl currentUrl(m_dirModel->dirLister()->url()); | ||||
818 | | ||||
799 | item->grabMouse(); | 819 | item->grabMouse(); | ||
800 | drag->exec(supportedDragActions()); | 820 | drag->exec(supportedDragActions()); | ||
801 | m_dragInProgress = false; | 821 | | ||
802 | item->ungrabMouse(); | 822 | item->ungrabMouse(); | ||
803 | 823 | | |||
824 | m_dragInProgress = false; | ||||
825 | emit draggingChanged(); | ||||
826 | m_urlChangedWhileDragging = false; | ||||
827 | | ||||
828 | if (m_dirModel->dirLister()->url() == currentUrl) { | ||||
804 | const QModelIndex first(m_dragIndexes.first()); | 829 | const QModelIndex first(m_dragIndexes.first()); | ||
805 | const QModelIndex last(m_dragIndexes.last()); | 830 | const QModelIndex last(m_dragIndexes.last()); | ||
806 | m_dragIndexes.clear(); | 831 | m_dragIndexes.clear(); | ||
807 | // TODO: Optimize to emit contiguous groups. | 832 | // TODO: Optimize to emit contiguous groups. | ||
808 | emit dataChanged(first, last, QVector<int>() << BlankRole); | 833 | emit dataChanged(first, last, QVector<int>() << BlankRole); | ||
809 | } | 834 | } | ||
835 | } | ||||
810 | 836 | | |||
811 | void FolderModel::drop(QQuickItem *target, QObject* dropEvent, int row) | 837 | void FolderModel::drop(QQuickItem *target, QObject* dropEvent, int row) | ||
812 | { | 838 | { | ||
813 | QMimeData *mimeData = qobject_cast<QMimeData *>(dropEvent->property("mimeData").value<QObject *>()); | 839 | QMimeData *mimeData = qobject_cast<QMimeData *>(dropEvent->property("mimeData").value<QObject *>()); | ||
814 | 840 | | |||
815 | if (!mimeData) { | 841 | if (!mimeData) { | ||
816 | return; | 842 | return; | ||
817 | } | 843 | } | ||
818 | 844 | | |||
819 | if (m_dragInProgress && row == -1) { | 845 | if (m_dragInProgress && row == -1 && !m_urlChangedWhileDragging) { | ||
820 | if (m_locked || mimeData->urls().isEmpty()) { | 846 | if (m_locked || mimeData->urls().isEmpty()) { | ||
821 | return; | 847 | return; | ||
822 | } | 848 | } | ||
823 | 849 | | |||
824 | setSortMode(-1); | 850 | setSortMode(-1); | ||
825 | 851 | | |||
826 | emit move(dropEvent->property("x").toInt(), dropEvent->property("y").toInt(), | 852 | emit move(dropEvent->property("x").toInt(), dropEvent->property("y").toInt(), | ||
827 | mimeData->urls()); | 853 | mimeData->urls()); | ||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Line(s) | |||||
870 | Qt::MouseButtons buttons(dropEvent->property("buttons").toInt()); | 896 | Qt::MouseButtons buttons(dropEvent->property("buttons").toInt()); | ||
871 | Qt::KeyboardModifiers modifiers(dropEvent->property("modifiers").toInt()); | 897 | Qt::KeyboardModifiers modifiers(dropEvent->property("modifiers").toInt()); | ||
872 | 898 | | |||
873 | QDropEvent ev(pos, possibleActions, mimeData, buttons, modifiers); | 899 | QDropEvent ev(pos, possibleActions, mimeData, buttons, modifiers); | ||
874 | ev.setDropAction(proposedAction); | 900 | ev.setDropAction(proposedAction); | ||
875 | 901 | | |||
876 | QUrl dropTargetUrl; | 902 | QUrl dropTargetUrl; | ||
877 | 903 | | |||
904 | // So we get to run mostLocalUrl() over the current URL. | ||||
905 | if (item.isNull()) { | ||||
906 | item = m_dirModel->dirLister()->rootItem(); | ||||
907 | } | ||||
908 | | ||||
878 | if (item.isNull()) { | 909 | if (item.isNull()) { | ||
879 | dropTargetUrl = m_dirModel->dirLister()->url(); | 910 | dropTargetUrl = m_dirModel->dirLister()->url(); | ||
880 | } else if (m_parseDesktopFiles && item.isDesktopFile()) { | 911 | } else if (m_parseDesktopFiles && item.isDesktopFile()) { | ||
881 | const KDesktopFile file(item.targetUrl().path()); | 912 | const KDesktopFile file(item.targetUrl().path()); | ||
882 | 913 | | |||
883 | if (file.readType() == QLatin1String("Link")) { | 914 | if (file.readType() == QLatin1String("Link")) { | ||
884 | dropTargetUrl = QUrl(file.readUrl()); | 915 | dropTargetUrl = QUrl(file.readUrl()); | ||
885 | } else { | 916 | } else { | ||
▲ Show 20 Lines • Show All 697 Lines • Show Last 20 Lines |