From addb38645b41507ae8e0536bb83d3b99d365f664 Mon Sep 17 00:00:00 2001 From: Mikaƫl Capelle Date: Mon, 28 Dec 2020 13:44:26 +0100 Subject: Clean drag&drop of URLs and mods/archives. --- src/modlist.cpp | 172 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 97 insertions(+), 75 deletions(-) (limited to 'src/modlist.cpp') 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 ModList::sourceRows(const QMimeData* mimeData) const +{ + QByteArray encoded = mimeData->data("application/x-qabstractitemmodeldatalist"); + QDataStream stream(&encoded, QIODevice::ReadOnly); + std::vector sourceRows; + + while (!stream.atEnd()) { + int sourceRow, col; + QMap roleDataMap; + stream >> sourceRow >> col >> roleDataMap; + if (col == 0) { + sourceRows.push_back(sourceRow); + } + } + return sourceRows; +} + +std::optional> 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> relativePathList; - unsigned int overwriteIndex = ModInfo::findMod([] (ModInfo::Ptr mod) -> bool { - std::vector 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 sourceRows; - - while (!stream.atEnd()) { - int sourceRow, col; - QMap 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 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 sourceRows; - - while (!stream.atEnd()) { - int sourceRow, col; - QMap roleDataMap; - stream >> sourceRow >> col >> roleDataMap; - if (col == 0) { - sourceRows.push_back(sourceRow); - } - } - + std::vector 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 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) { -- cgit v1.3.1