diff options
| -rw-r--r-- | src/mainwindow.cpp | 4 | ||||
| -rw-r--r-- | src/modinfo.cpp | 15 | ||||
| -rw-r--r-- | src/modinfo.h | 8 | ||||
| -rw-r--r-- | src/modlist.cpp | 172 | ||||
| -rw-r--r-- | src/modlist.h | 26 | ||||
| -rw-r--r-- | src/modlistbypriorityproxy.cpp | 72 | ||||
| -rw-r--r-- | src/modlistbypriorityproxy.h | 1 | ||||
| -rw-r--r-- | src/modlistview.cpp | 38 | ||||
| -rw-r--r-- | src/modlistview.h | 6 |
9 files changed, 156 insertions, 186 deletions
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index ea7d5967..df571a2d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -579,10 +579,6 @@ void MainWindow::setupModList() ui->modList->sortByColumn(ModList::COL_PRIORITY, Qt::AscendingOrder); connect( - ui->modList, SIGNAL(dropModeUpdate(bool)), - m_OrganizerCore.modList(), SLOT(dropModeUpdate(bool))); - - connect( ui->modList->header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)), this, SLOT(modListSortIndicatorChanged(int,Qt::SortOrder))); diff --git a/src/modinfo.cpp b/src/modinfo.cpp index a0382fe8..509c3837 100644 --- a/src/modinfo.cpp +++ b/src/modinfo.cpp @@ -47,6 +47,7 @@ using namespace MOShared; std::vector<ModInfo::Ptr> ModInfo::s_Collection; +ModInfo::Ptr ModInfo::s_Overwrite; std::map<QString, unsigned int> ModInfo::s_ModsByName; std::map<std::pair<QString, int>, std::vector<unsigned int>> ModInfo::s_ModsByModID; int ModInfo::s_NextID; @@ -108,13 +109,14 @@ ModInfo::Ptr ModInfo::createFromPlugin(const QString &modName, return result; } -void ModInfo::createFromOverwrite(PluginContainer *pluginContainer, - const MOBase::IPluginGame* game, - MOShared::DirectoryEntry **directoryStructure) +ModInfo::Ptr ModInfo::createFromOverwrite( + PluginContainer *pluginContainer, const MOBase::IPluginGame* game, + MOShared::DirectoryEntry **directoryStructure) { QMutexLocker locker(&s_Mutex); - - s_Collection.push_back(ModInfo::Ptr(new ModInfoOverwrite(pluginContainer, game, directoryStructure))); + ModInfo::Ptr overwrite = ModInfo::Ptr(new ModInfoOverwrite(pluginContainer, game, directoryStructure)); + s_Collection.push_back(overwrite); + return overwrite; } unsigned int ModInfo::getNumMods() @@ -237,6 +239,7 @@ void ModInfo::updateFromDisc(const QString &modDirectory, QMutexLocker lock(&s_Mutex); s_Collection.clear(); s_NextID = 0; + s_Overwrite = nullptr; { // list all directories in the mod directory and make a mod out of each QDir mods(QDir::fromNativeSeparators(modDirectory)); @@ -263,7 +266,7 @@ void ModInfo::updateFromDisc(const QString &modDirectory, } } - createFromOverwrite(pluginContainer, game, directoryStructure); + s_Overwrite = createFromOverwrite(pluginContainer, game, directoryStructure); std::sort(s_Collection.begin(), s_Collection.end(), ModInfo::ByName); diff --git a/src/modinfo.h b/src/modinfo.h index d04f6657..3981be18 100644 --- a/src/modinfo.h +++ b/src/modinfo.h @@ -178,6 +178,11 @@ public: // Static functions: static unsigned int getIndex(const QString &name); /** + * @brief Retrieve the overwrite mod. + */ + static ModInfo::Ptr getOverwrite() { return s_Overwrite; } + + /** * @brief Find the first mod that fulfills the filter function (after no particular order). * * @param filter A function to filter mods by. Should return true for a match. @@ -981,6 +986,7 @@ protected: protected: static std::vector<ModInfo::Ptr> s_Collection; + static ModInfo::Ptr s_Overwrite; static std::map<QString, unsigned int> s_ModsByName; int m_PrimaryCategory; @@ -992,7 +998,7 @@ protected: private: - static void createFromOverwrite(PluginContainer* pluginContainer, + static ModInfo::Ptr createFromOverwrite(PluginContainer* pluginContainer, const MOBase::IPluginGame* game, MOShared::DirectoryEntry** directoryStructure); diff --git a/src/modlist.cpp b/src/modlist.cpp index ca4741e6..b79f0b0e 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -69,7 +69,6 @@ ModList::ModList(PluginContainer *pluginContainer, OrganizerCore *organizer) , m_Modified(false) , m_InNotifyChange(false) , m_FontMetrics(QFont()) - , m_DropOnItems(false) , m_PluginContainer(pluginContainer) { m_LastCheck.start(); @@ -689,14 +688,10 @@ Qt::ItemFlags ModList::flags(const QModelIndex &modelIndex) const result |= Qt::ItemIsEditable; } } - if (m_DropOnItems - && (std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) == flags.end())) { - result |= Qt::ItemIsDropEnabled; - } - } else { - if (!m_DropOnItems) result |= Qt::ItemIsDropEnabled; } - return result; + + // drop check is handled by canDropMimeData + return result | Qt::ItemIsDropEnabled; } @@ -1113,6 +1108,52 @@ int ModList::dropPriority(int row, const QModelIndex& parent) const return newPriority; } +std::vector<int> ModList::sourceRows(const QMimeData* mimeData) const +{ + QByteArray encoded = mimeData->data("application/x-qabstractitemmodeldatalist"); + QDataStream stream(&encoded, QIODevice::ReadOnly); + std::vector<int> sourceRows; + + while (!stream.atEnd()) { + int sourceRow, col; + QMap<int, QVariant> roleDataMap; + stream >> sourceRow >> col >> roleDataMap; + if (col == 0) { + sourceRows.push_back(sourceRow); + } + } + return sourceRows; +} + +std::optional<std::pair<QString, QString>> ModList::relativeUrl(const QUrl& url) const +{ + if (!url.isLocalFile()) { + return {}; + } + + QDir allModsDir(Settings::instance().paths().mods()); + QDir overwriteDir(Settings::instance().paths().overwrite()); + + QFileInfo sourceInfo(url.toLocalFile()); + QString sourceFile = sourceInfo.canonicalFilePath(); + + QString relativePath; + QString originName; + + if (sourceFile.startsWith(allModsDir.canonicalPath())) { + QDir relativeDir(allModsDir.relativeFilePath(sourceFile)); + QStringList splitPath = relativeDir.path().split("/"); + originName = splitPath[0]; + splitPath.pop_front(); + return { { splitPath.join("/"), originName } }; + } + else if (sourceFile.startsWith(overwriteDir.canonicalPath())) { + return { { overwriteDir.relativeFilePath(sourceFile), ModInfo::getOverwrite()->name() } }; + } + + return {}; +} + bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &parent) { if (row == -1) { @@ -1121,45 +1162,23 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa ModInfo::Ptr modInfo = ModInfo::getByIndex(row); QDir modDir = QDir(modInfo->absolutePath()); - QDir allModsDir(Settings::instance().paths().mods()); - QDir overwriteDir(Settings::instance().paths().overwrite()); - QStringList sourceList; QStringList targetList; QList<QPair<QString,QString>> relativePathList; - unsigned int overwriteIndex = ModInfo::findMod([] (ModInfo::Ptr mod) -> bool { - std::vector<ModInfo::EFlag> flags = mod->getFlags(); - return std::find(flags.begin(), flags.end(), ModInfo::FLAG_OVERWRITE) != flags.end(); }); - - QString overwriteName = ModInfo::getByIndex(overwriteIndex)->name(); - for (auto url : mimeData->urls()) { - if (!url.isLocalFile()) { - log::debug("URL drop ignored: \"{}\" is not a local file", url.url()); + auto p = relativeUrl(url); + + if (!p) { + log::debug("URL drop ignored: \"{}\" is not a local file or not a known file to MO", url.url()); continue; } + auto [relativePath, originName] = *p; + QFileInfo sourceInfo(url.toLocalFile()); QString sourceFile = sourceInfo.canonicalFilePath(); - QString relativePath; - QString originName; - - if (sourceFile.startsWith(allModsDir.canonicalPath())) { - QDir relativeDir(allModsDir.relativeFilePath(sourceFile)); - QStringList splitPath = relativeDir.path().split("/"); - originName = splitPath[0]; - splitPath.pop_front(); - relativePath = splitPath.join("/"); - } else if (sourceFile.startsWith(overwriteDir.canonicalPath())) { - originName = overwriteName; - relativePath = overwriteDir.relativeFilePath(sourceFile); - } else { - log::debug("URL drop ignored: \"{}\" is not a known file to MO", sourceFile); - continue; - } - QFileInfo targetInfo(modDir.absoluteFilePath(relativePath)); sourceList << sourceFile; targetList << targetInfo.absoluteFilePath(); @@ -1186,24 +1205,13 @@ bool ModList::dropURLs(const QMimeData *mimeData, int row, const QModelIndex &pa bool ModList::dropMod(const QMimeData *mimeData, int row, const QModelIndex &parent) { - try { - QByteArray encoded = mimeData->data("application/x-qabstractitemmodeldatalist"); - QDataStream stream(&encoded, QIODevice::ReadOnly); - std::vector<int> sourceRows; - - while (!stream.atEnd()) { - int sourceRow, col; - QMap<int, QVariant> roleDataMap; - stream >> sourceRow >> col >> roleDataMap; - if (col == 0) { - sourceRows.push_back(sourceRow); - } - } + int newPriority = dropPriority(row, parent); + if (newPriority == -1) { + return false; + } - int newPriority = dropPriority(row, parent); - if (newPriority == -1) { - return false; - } + try { + std::vector<int> sourceRows = this->sourceRows(mimeData); changeModPriority(sourceRows, newPriority); } catch (const std::exception &e) { @@ -1221,19 +1229,7 @@ bool ModList::dropArchive(const QMimeData* mimeData, int row, const QModelIndex& } try { - QByteArray encoded = mimeData->data("application/x-qabstractitemmodeldatalist"); - QDataStream stream(&encoded, QIODevice::ReadOnly); - std::vector<int> sourceRows; - - while (!stream.atEnd()) { - int sourceRow, col; - QMap<int, QVariant> roleDataMap; - stream >> sourceRow >> col >> roleDataMap; - if (col == 0) { - sourceRows.push_back(sourceRow); - } - } - + std::vector<int> sourceRows = this->sourceRows(mimeData); if (sourceRows.size() == 1) { emit downloadArchiveDropped(sourceRows[0], priority); } @@ -1245,6 +1241,41 @@ bool ModList::dropArchive(const QMimeData* mimeData, int row, const QModelIndex& return false; } +bool ModList::canDropMimeData(const QMimeData* mimeData, Qt::DropAction action, int row, int column, const QModelIndex& parent) const +{ + if (action == Qt::IgnoreAction) { + return false; + } + + if (mimeData->hasUrls()) { + for (auto& url : mimeData->urls()) { + if (!relativeUrl(url)) { + return false; + } + } + if (row == -1 && parent.isValid()) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(parent.row()); + return modInfo->isRegular() && !modInfo->isSeparator(); + } + } + else if (mimeData->hasText()) { + // drop on item + if (row == -1 && parent.isValid()) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(parent.row()); + return modInfo->isSeparator(); + } + else if (hasIndex(row, column, parent)) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(row); + return modInfo->isSeparator() || !parent.isValid(); + } + else { + return true; + } + } + + return false; +} + bool ModList::dropMimeData(const QMimeData *mimeData, Qt::DropAction action, int row, int, const QModelIndex &parent) { if (action == Qt::IgnoreAction) { @@ -1407,15 +1438,6 @@ QMap<int, QVariant> ModList::itemData(const QModelIndex &index) const return result; } - -void ModList::dropModeUpdate(bool dropOnItems) -{ - if (m_DropOnItems != dropOnItems) { - m_DropOnItems = dropOnItems; - } -} - - QString ModList::getColumnName(int column) { switch (column) { diff --git a/src/modlist.h b/src/modlist.h index 2ca2fff1..b2eb6be6 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -199,11 +199,13 @@ public: // implementation of virtual functions of QAbstractItemModel virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual Qt::ItemFlags flags(const QModelIndex &modelIndex) const;
- virtual Qt::DropActions supportedDropActions() const { return Qt::MoveAction | Qt::CopyAction; }
- virtual QStringList mimeTypes() const;
- virtual QMimeData *mimeData(const QModelIndexList &indexes) const;
- virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
- virtual bool removeRows(int row, int count, const QModelIndex &parent);
+ virtual bool removeRows(int row, int count, const QModelIndex& parent);
+
+ Qt::DropActions supportedDropActions() const override { return Qt::MoveAction | Qt::CopyAction; }
+ QStringList mimeTypes() const override;
+ QMimeData *mimeData(const QModelIndexList &indexes) const override;
+ bool canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) const override;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
virtual QModelIndex index(int row, int column,
const QModelIndex &parent = QModelIndex()) const;
@@ -213,10 +215,8 @@ public: // implementation of virtual functions of QAbstractItemModel public slots:
- void dropModeUpdate(bool dropOnItems);
void enableSelected(const QItemSelectionModel *selectionModel);
-
void disableSelected(const QItemSelectionModel *selectionModel);
signals:
@@ -369,6 +369,16 @@ private: private:
+ // retrieve the relative path of file and its origin given a URL from Mime data
+ // returns an empty optional if the URL is not a valid file for dropping
+ //
+ std::optional<std::pair<QString, QString>> relativeUrl(const QUrl&) const;
+
+ // return the source rows from the given mime data for drag&drop of mods or
+ // installation archives
+ //
+ std::vector<int> sourceRows(const QMimeData* mimeData) const;
+
bool dropURLs(const QMimeData* mimeData, int row, const QModelIndex& parent);
bool dropMod(const QMimeData* mimeData, int row, const QModelIndex& parent);
bool dropArchive(const QMimeData* mimeData, int row, const QModelIndex& parent);
@@ -392,8 +402,6 @@ private: QFontMetrics m_FontMetrics;
- bool m_DropOnItems;
-
std::set<unsigned int> m_Overwrite;
std::set<unsigned int> m_Overwritten;
std::set<unsigned int> m_ArchiveOverwrite;
diff --git a/src/modlistbypriorityproxy.cpp b/src/modlistbypriorityproxy.cpp index 1bbf9459..dc51617e 100644 --- a/src/modlistbypriorityproxy.cpp +++ b/src/modlistbypriorityproxy.cpp @@ -210,64 +210,44 @@ bool ModListByPriorityProxy::canDropMimeData(const QMimeData* data, Qt::DropActi bool ModListByPriorityProxy::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) { - // we need to fix the source row + // we need to fix the source model row int sourceRow = -1; - if (row >= 0) { - if (!parent.isValid()) { - if (row < m_Root.children.size()) { - sourceRow = m_Root.children[row]->index; - } - else { - sourceRow = ModInfo::getNumMods(); - } + if (data->hasUrls()) { + if (parent.isValid()) { + sourceRow = static_cast<TreeItem*>(parent.internalPointer())->index; } - else { - auto* item = static_cast<TreeItem*>(parent.internalPointer()); - QStringList what; - for (auto& child : item->children) { - what.append(QString::number(child->index)); + } + else { + if (row >= 0) { + if (!parent.isValid()) { + if (row < m_Root.children.size()) { + sourceRow = m_Root.children[row]->index; + } + else { + sourceRow = ModInfo::getNumMods(); + } } + else { + auto* item = static_cast<TreeItem*>(parent.internalPointer()); - if (row < item->children.size()) { - sourceRow = item->children[row]->index; - } - else if (parent.row() + 1 < m_Root.children.size()) { - sourceRow = m_Root.children[parent.row() + 1]->index; + if (row < item->children.size()) { + sourceRow = item->children[row]->index; + } + else if (parent.row() + 1 < m_Root.children.size()) { + sourceRow = m_Root.children[parent.row() + 1]->index; + } } } - } - else if (parent.isValid()) { - // this is a drop in a separator - sourceRow = m_Root.children[parent.row() + 1]->index; + else if (parent.isValid()) { + // this is a drop in a separator + sourceRow = m_Root.children[parent.row() + 1]->index; + } } return sourceModel()->dropMimeData(data, action, sourceRow, column, QModelIndex()); } -Qt::ItemFlags ModListByPriorityProxy::flags(const QModelIndex& idx) const -{ - if (!idx.isValid()) { - return sourceModel()->flags(QModelIndex()); - } - - // we check the flags of the root node and if drop is not enabled, it - // means we are dragging files. - Qt::ItemFlags rootFlags = sourceModel()->flags(QModelIndex()); - if (!rootFlags.testFlag(Qt::ItemIsDropEnabled)) { - return sourceModel()->flags(mapToSource(idx)); - } - - auto flags = sourceModel()->flags(mapToSource(idx)); - auto* item = static_cast<TreeItem*>(idx.internalPointer()); - - if (item->mod->isSeparator()) { - flags |= Qt::ItemIsDropEnabled; - } - - return flags; -} - QModelIndex ModListByPriorityProxy::index(int row, int column, const QModelIndex& parent) const { if (!hasIndex(row, column, parent)) { diff --git a/src/modlistbypriorityproxy.h b/src/modlistbypriorityproxy.h index fdf59182..725a3242 100644 --- a/src/modlistbypriorityproxy.h +++ b/src/modlistbypriorityproxy.h @@ -31,7 +31,6 @@ public: int rowCount(const QModelIndex& parent = QModelIndex()) const override; QModelIndex parent(const QModelIndex& child) const override; - Qt::ItemFlags flags(const QModelIndex& idx) const override; QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& index) const override; bool hasChildren(const QModelIndex& parent) const override; diff --git a/src/modlistview.cpp b/src/modlistview.cpp index fcf34749..27e23417 100644 --- a/src/modlistview.cpp +++ b/src/modlistview.cpp @@ -2,37 +2,6 @@ #include <widgetutility.h>
#include <QUrl>
#include <QMimeData>
-#include <QProxyStyle>
-
-class ModListViewStyle: public QProxyStyle {
-public:
- ModListViewStyle(QStyle *style, int indentation);
-
- void drawPrimitive (PrimitiveElement element, const QStyleOption *option,
- QPainter *painter, const QWidget *widget = 0) const;
-private:
- int m_Indentation;
-};
-
-ModListViewStyle::ModListViewStyle(QStyle *style, int indentation)
- : QProxyStyle(style), m_Indentation(indentation)
-{
-}
-
-void ModListViewStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option,
- QPainter *painter, const QWidget *widget) const
-{
- if (element == QStyle::PE_IndicatorItemViewItemDrop && !option->rect.isNull()) {
- QStyleOption opt(*option);
- opt.rect.setLeft(m_Indentation);
- if (widget) {
- opt.rect.setRight(widget->width() - 5); // 5 is an arbitrary value that seems to work ok
- }
- QProxyStyle::drawPrimitive(element, &opt, painter, widget);
- } else {
- QProxyStyle::drawPrimitive(element, option, painter, widget);
- }
-}
ModListView::ModListView(QWidget *parent)
: QTreeView(parent)
@@ -43,13 +12,6 @@ ModListView::ModListView(QWidget *parent) setAutoExpandDelay(500);
}
-void ModListView::dragEnterEvent(QDragEnterEvent *event)
-{
- emit dropModeUpdate(event->mimeData()->hasUrls());
-
- QTreeView::dragEnterEvent(event);
-}
-
void ModListView::setModel(QAbstractItemModel *model)
{
QTreeView::setModel(model);
diff --git a/src/modlistview.h b/src/modlistview.h index 982591a3..bc5654ce 100644 --- a/src/modlistview.h +++ b/src/modlistview.h @@ -12,11 +12,6 @@ public: explicit ModListView(QWidget *parent = 0);
void setModel(QAbstractItemModel *model) override;
-signals:
- void dropModeUpdate(bool dropOnRows);
-
-public slots:
-
protected:
// replace the auto-expand timer from QTreeView to avoid
@@ -25,7 +20,6 @@ protected: void timerEvent(QTimerEvent* event) override;
void dragMoveEvent(QDragMoveEvent* event) override;
- void dragEnterEvent(QDragEnterEvent* event) override;
private:
|
