From 8dffe65032c498a218079f941d88af6053b28d7f Mon Sep 17 00:00:00 2001 From: Mikaƫl Capelle Date: Thu, 31 Dec 2020 20:05:23 +0100 Subject: Documentation for ModListView. --- src/modlistview.cpp | 74 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 50 insertions(+), 24 deletions(-) (limited to 'src/modlistview.cpp') diff --git a/src/modlistview.cpp b/src/modlistview.cpp index 37dcb2ca..99cc4c4c 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -27,6 +27,14 @@ using namespace MOBase; +// delegate to remove indentation for mods when using collapsible +// separator +// +// the delegate works by removing the indentation of the child items +// before drawing, but unfortunately this normally breaks event +// handling (e.g. checkbox, edit, etc.), so we also need to override +// the visualRect() function from the mod list view. +// class ModListStyledItemDelegated : public QStyledItemDelegate { ModListView* m_view; @@ -301,32 +309,34 @@ std::pair ModListView::selected() const void ModListView::setSelected(const QModelIndex& current, const QModelIndexList& selected) { - // reset the selection and the index setCurrentIndex(indexModelToView(current)); for (auto idx : selected) { selectionModel()->select(indexModelToView(idx), QItemSelectionModel::Select | QItemSelectionModel::Rows); } } -void ModListView::expandItem(const QModelIndex& index) { +void ModListView::expandItem(const QModelIndex& index) +{ + // the group proxy (QtGroupingProxy and ModListByPriorityProxy) emit + // those with their own index, so we need to do this manually if (index.model() == m_sortProxy->sourceModel()) { - expand(m_sortProxy->mapFromSource(index)); + setExpanded(m_sortProxy->mapFromSource(index), true); } else if (index.model() == model()) { - expand(index); + setExpanded(index, true); } } void ModListView::onModPrioritiesChanged(std::vector const& indices) { - // expand separator whose priority has changed + // expand separator whose priority has changed and parents for (auto index : indices) { auto idx = indexModelToView(m_core->modList()->index(index, 0)); if (hasCollapsibleSeparators() && model()->hasChildren(idx)) { - expand(idx); + setExpanded(idx, true); } if (idx.parent().isValid()) { - expand(idx.parent()); + setExpanded(idx.parent(), true); } } @@ -386,7 +396,7 @@ void ModListView::onModInstalled(const QString& modName) QModelIndex qIndex = indexModelToView(m_core->modList()->index(index, 0)); if (hasCollapsibleSeparators()) { - expand(qIndex); + setExpanded(qIndex, true); } // focus, scroll to and select @@ -500,10 +510,7 @@ void ModListView::refreshFilters() { auto [current, sourceRows] = selected(); - int idxRow = currentIndex().row(); - QVariant currentIndexName = model()->index(idxRow, 0).data(); setCurrentIndex(QModelIndex()); - m_filters->refresh(); setSelected(current, sourceRows); @@ -538,6 +545,8 @@ void ModListView::onExternalFolderDropped(const QUrl& url, int priority) return; } + // TODO: this is currently a silent copy, which can take some time, but there is + // no clean method to do this in uibase if (!copyDir(fileInfo.absoluteFilePath(), newMod->absolutePath(), true)) { return; } @@ -757,6 +766,8 @@ void ModListView::setModel(QAbstractItemModel* model) QRect ModListView::visualRect(const QModelIndex& index) const { + // this shift the visualRect() from QTreeView to match the new actual + // zone after removing indentation (see the ModListStyledItemDelegated) QRect rect = QTreeView::visualRect(index); if (hasCollapsibleSeparators()) { if (index.isValid() && !index.model()->hasChildren(index) && index.parent().isValid()) { @@ -771,6 +782,15 @@ QRect ModListView::visualRect(const QModelIndex& index) const QModelIndexList ModListView::selectedIndexes() const { + // during drag&drop events, we fake the return value of selectedIndexes() + // to allow drag&drop of a parent into its children + // + // this is only "active" during the actual dragXXXEvent and dropEvent method, + // not during the whole drag&drop event + // + // selectedIndexes() is a protected method from QTreeView which is little + // used so this should not break anything + // return m_inDragMoveEvent ? QModelIndexList() : QTreeView::selectedIndexes(); } @@ -815,14 +835,10 @@ void ModListView::onDoubleClicked(const QModelIndex& index) ModInfo::Ptr modInfo = ModInfo::getByIndex(modIndex); - Qt::KeyboardModifiers modifiers = QApplication::queryKeyboardModifiers(); + const auto modifiers = QApplication::queryKeyboardModifiers(); if (modifiers.testFlag(Qt::ControlModifier)) { try { shell::Explore(modInfo->absolutePath()); - - // workaround to cancel the editor that might have opened because of - // selection-click - closePersistentEditor(index); } catch (const std::exception& e) { reportError(e.what()); @@ -830,9 +846,7 @@ void ModListView::onDoubleClicked(const QModelIndex& index) } else if (modifiers.testFlag(Qt::ShiftModifier)) { try { - QModelIndex idx = m_core->modList()->index(modIndex, 0); - actions().visitNexusOrWebPage({ idx }); - closePersistentEditor(index); + actions().visitNexusOrWebPage({ indexViewToModel(index) }); } catch (const std::exception& e) { reportError(e.what()); @@ -855,14 +869,15 @@ void ModListView::onDoubleClicked(const QModelIndex& index) } actions().displayModInformation(modIndex, tab); - // workaround to cancel the editor that might have opened because of - // selection-click - closePersistentEditor(index); } catch (const std::exception& e) { reportError(e.what()); } } + + // workaround to cancel the editor that might have opened because of + // selection-click + closePersistentEditor(index); } void ModListView::onSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) @@ -924,10 +939,14 @@ void ModListView::onFiltersCriteria(const std::vectormimeData()); QTreeView::dragEnterEvent(event); - + // there is no drop event for invalid data since canDropMimeData + // returns false, so we notify user on drag enter ModListDropInfo dropInfo(event->mimeData(), *m_core); if (dropInfo.isValid() && !dropInfo.isLocalFileDrop() @@ -938,11 +957,13 @@ void ModListView::dragEnterEvent(QDragEnterEvent* event) void ModListView::dragMoveEvent(QDragMoveEvent* event) { + // this replace the openTimer from QTreeView to prevent + // auto-collapse of items if (autoExpandDelay() >= 0) { m_openTimer.start(autoExpandDelay(), this); } - // bypass QTreeView + // see selectedIndexes() m_inDragMoveEvent = true; QAbstractItemView::dragMoveEvent(event); m_inDragMoveEvent = false; @@ -950,8 +971,12 @@ void ModListView::dragMoveEvent(QDragMoveEvent* event) void ModListView::dropEvent(QDropEvent* event) { + // this event is used by the byPriorityProxy to know if allow + // dropping mod between a separator and its first mod (there + // is no way to deduce this except using dropIndicatorPosition()) emit dropEntered(event->mimeData(), static_cast(dropIndicatorPosition())); + // see selectedIndexes() m_inDragMoveEvent = true; QTreeView::dropEvent(event); m_inDragMoveEvent = false; @@ -959,6 +984,7 @@ void ModListView::dropEvent(QDropEvent* event) void ModListView::timerEvent(QTimerEvent* event) { + // prevent auto-collapse, see dragMoveEvent() if (event->timerId() == m_openTimer.timerId()) { QPoint pos = viewport()->mapFromGlobal(QCursor::pos()); if (state() == QAbstractItemView::DraggingState -- cgit v1.3.1