From 7ee008e150bc5bcf76082d726f719ee0fdfda982 Mon Sep 17 00:00:00 2001 From: SulfurNitride Date: Wed, 11 Feb 2026 02:37:39 -0600 Subject: Fluorine Manager: full Linux port of Mod Organizer 2 Complete native Linux port with FUSE-based virtual filesystem, Proton/umu-run integration, and Flatpak packaging. Key features: - FUSE VFS replacing Windows USVFS (in-process + standalone helper for Flatpak) - Proton/GE-Proton/umu-run launcher with env var forwarding - Flatpak support (sandbox-aware VFS, NXM handler, umu-run) - Wine prefix management UI - Case-insensitive path resolution for Linux filesystems - QSettings-safe INI handling (avoids Bethesda INI corruption) - Portable instance support with auto-generated launcher scripts Co-Authored-By: Claude Opus 4.6 --- libs/uibase/src/sortabletreewidget.cpp | 116 +++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 libs/uibase/src/sortabletreewidget.cpp (limited to 'libs/uibase/src/sortabletreewidget.cpp') diff --git a/libs/uibase/src/sortabletreewidget.cpp b/libs/uibase/src/sortabletreewidget.cpp new file mode 100644 index 0000000..5cfbdd4 --- /dev/null +++ b/libs/uibase/src/sortabletreewidget.cpp @@ -0,0 +1,116 @@ +/* +Mod Organizer shared UI functionality + +Copyright (C) 2013 Sebastian Herbord. All rights reserved. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include + +namespace MOBase +{ + +SortableTreeWidget::SortableTreeWidget(QWidget* parent) + : QTreeWidget(parent), m_LocalMoveOnly(false) +{} + +void SortableTreeWidget::setLocalMoveOnly(bool localOnly) +{ + m_LocalMoveOnly = localOnly; +} + +void SortableTreeWidget::dropEvent(QDropEvent* event) +{ + // only react on internal drag&drop + if (event->source() == this) { + QTreeWidget::dropEvent(event); + } +} + +Qt::DropActions SortableTreeWidget::supportedDropActions() const +{ + // we do our own drop handling, this ensures dropMimeData is called. + return Qt::CopyAction; +} + +bool SortableTreeWidget::dropMimeData(QTreeWidgetItem* parent, int index, + const QMimeData*, Qt::DropAction) +{ + // TODO: ignores type of action set up in designer, always moves + return this->moveSelection(parent, index); +} + +bool SortableTreeWidget::moveSelection(QTreeWidgetItem* parent, int idx) +{ + QModelIndex parentIndex = indexFromItem(parent); + std::vector persistentIndices; + Q_FOREACH (const QModelIndex& index, selectedIndexes()) { + if (index == parentIndex) + return false; + if (m_LocalMoveOnly && (parentIndex != index.parent())) + return false; + if (index.column() != 0) + continue; + persistentIndices.push_back(index); + } + + int targetRow = -1; + if (itemsExpandable() || !parentIndex.isValid()) { + targetRow = model()->index(idx, 0, parentIndex).row(); + + if (targetRow < 0) { + targetRow = idx; + } + } else { + // if items aren't expandable, we can't be placing items on sublevels + targetRow = parentIndex.row(); + parentIndex = QModelIndex(); + } + + // remove items from the list, store in temporary location + QList temp; + for (auto iter = persistentIndices.rbegin(); iter != persistentIndices.rend(); + ++iter) { + QTreeWidgetItem* item = itemFromIndex(*iter); + if (item == nullptr) + continue; + if ((item == nullptr) || (item->parent() == nullptr)) { + temp.append(takeTopLevelItem(iter->row())); + } else { + temp.append(item->parent()->takeChild(iter->row())); + } + } + + if (idx == -1) { + // append + if (parentIndex.isValid()) { + parent->addChildren(temp); + } else { + addTopLevelItems(temp); + } + } else { + if (parentIndex.isValid()) { + parent->insertChildren(std::min(targetRow, parent->childCount()), temp); + } else { + insertTopLevelItems(std::min(targetRow, topLevelItemCount()), temp); + } + } + emit itemsMoved(); + return true; +} + +} // namespace MOBase -- cgit v1.3.1