diff options
Diffstat (limited to 'launcher/minecraft/mod/ModFolderModel.cpp')
| -rw-r--r-- | launcher/minecraft/mod/ModFolderModel.cpp | 898 |
1 files changed, 446 insertions, 452 deletions
diff --git a/launcher/minecraft/mod/ModFolderModel.cpp b/launcher/minecraft/mod/ModFolderModel.cpp index 1571a01d39..faaa814590 100644 --- a/launcher/minecraft/mod/ModFolderModel.cpp +++ b/launcher/minecraft/mod/ModFolderModel.cpp @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see <https://www.gnu.org/licenses/>. - * + * * This file incorporates work covered by the following copyright and * permission notice: * @@ -49,531 +49,525 @@ #include <algorithm> #include "LocalModParseTask.h" -ModFolderModel::ModFolderModel(const QString &dir) : QAbstractListModel(), m_dir(dir) +ModFolderModel::ModFolderModel(const QString& dir) + : QAbstractListModel(), m_dir(dir) { - FS::ensureFolderPathExists(m_dir.absolutePath()); - m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | QDir::Dirs); - m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware); - m_watcher = new QFileSystemWatcher(this); - connect(m_watcher, SIGNAL(directoryChanged(QString)), this, SLOT(directoryChanged(QString))); + FS::ensureFolderPathExists(m_dir.absolutePath()); + m_dir.setFilter(QDir::Readable | QDir::NoDotAndDotDot | QDir::Files | + QDir::Dirs); + m_dir.setSorting(QDir::Name | QDir::IgnoreCase | QDir::LocaleAware); + m_watcher = new QFileSystemWatcher(this); + connect(m_watcher, SIGNAL(directoryChanged(QString)), this, + SLOT(directoryChanged(QString))); } void ModFolderModel::startWatching() { - if(is_watching) - return; - - update(); - - is_watching = m_watcher->addPath(m_dir.absolutePath()); - if (is_watching) - { - qDebug() << "Started watching " << m_dir.absolutePath(); - } - else - { - qDebug() << "Failed to start watching " << m_dir.absolutePath(); - } + if (is_watching) + return; + + update(); + + is_watching = m_watcher->addPath(m_dir.absolutePath()); + if (is_watching) { + qDebug() << "Started watching " << m_dir.absolutePath(); + } else { + qDebug() << "Failed to start watching " << m_dir.absolutePath(); + } } void ModFolderModel::stopWatching() { - if(!is_watching) - return; - - is_watching = !m_watcher->removePath(m_dir.absolutePath()); - if (!is_watching) - { - qDebug() << "Stopped watching " << m_dir.absolutePath(); - } - else - { - qDebug() << "Failed to stop watching " << m_dir.absolutePath(); - } + if (!is_watching) + return; + + is_watching = !m_watcher->removePath(m_dir.absolutePath()); + if (!is_watching) { + qDebug() << "Stopped watching " << m_dir.absolutePath(); + } else { + qDebug() << "Failed to stop watching " << m_dir.absolutePath(); + } } bool ModFolderModel::update() { - if (!isValid()) { - return false; - } - if(m_update) { - scheduled_update = true; - return true; - } - - auto task = new ModFolderLoadTask(m_dir); - m_update = task->result(); - QThreadPool *threadPool = QThreadPool::globalInstance(); - connect(task, &ModFolderLoadTask::succeeded, this, &ModFolderModel::finishUpdate); - threadPool->start(task); - return true; + if (!isValid()) { + return false; + } + if (m_update) { + scheduled_update = true; + return true; + } + + auto task = new ModFolderLoadTask(m_dir); + m_update = task->result(); + QThreadPool* threadPool = QThreadPool::globalInstance(); + connect(task, &ModFolderLoadTask::succeeded, this, + &ModFolderModel::finishUpdate); + threadPool->start(task); + return true; } void ModFolderModel::finishUpdate() { - auto keys1 = modsIndex.keys(); - QSet<QString> currentSet(keys1.begin(), keys1.end()); - auto & newMods = m_update->mods; - auto keys2 = newMods.keys(); - QSet<QString> newSet(keys2.begin(), keys2.end()); - - // see if the kept mods changed in some way - { - QSet<QString> kept = currentSet; - kept.intersect(newSet); - for(auto & keptMod: kept) { - auto & newMod = newMods[keptMod]; - auto row = modsIndex[keptMod]; - auto & currentMod = mods[row]; - if(newMod.dateTimeChanged() == currentMod.dateTimeChanged()) { - // no significant change, ignore... - continue; - } - auto & oldMod = mods[row]; - if(oldMod.isResolving()) { - activeTickets.remove(oldMod.resolutionTicket()); - } - oldMod = newMod; - resolveMod(mods[row]); - emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1)); - } - } - - // remove mods no longer present - { - QSet<QString> removed = currentSet; - QList<int> removedRows; - removed.subtract(newSet); - for(auto & removedMod: removed) { - removedRows.append(modsIndex[removedMod]); - } - std::sort(removedRows.begin(), removedRows.end(), std::greater<int>()); - for(auto iter = removedRows.begin(); iter != removedRows.end(); iter++) { - int removedIndex = *iter; - beginRemoveRows(QModelIndex(), removedIndex, removedIndex); - auto removedIter = mods.begin() + removedIndex; - if(removedIter->isResolving()) { - activeTickets.remove(removedIter->resolutionTicket()); - } - mods.erase(removedIter); - endRemoveRows(); - } - } - - // add new mods to the end - { - QSet<QString> added = newSet; - added.subtract(currentSet); - beginInsertRows(QModelIndex(), mods.size(), mods.size() + added.size() - 1); - for(auto & addedMod: added) { - mods.append(newMods[addedMod]); - resolveMod(mods.last()); - } - endInsertRows(); - } - - // update index - { - modsIndex.clear(); - int idx = 0; - for(auto & mod: mods) { - modsIndex[mod.mmc_id()] = idx; - idx++; - } - } - - m_update.reset(); - - emit updateFinished(); - - if(scheduled_update) { - scheduled_update = false; - update(); - } + auto keys1 = modsIndex.keys(); + QSet<QString> currentSet(keys1.begin(), keys1.end()); + auto& newMods = m_update->mods; + auto keys2 = newMods.keys(); + QSet<QString> newSet(keys2.begin(), keys2.end()); + + // see if the kept mods changed in some way + { + QSet<QString> kept = currentSet; + kept.intersect(newSet); + for (auto& keptMod : kept) { + auto& newMod = newMods[keptMod]; + auto row = modsIndex[keptMod]; + auto& currentMod = mods[row]; + if (newMod.dateTimeChanged() == currentMod.dateTimeChanged()) { + // no significant change, ignore... + continue; + } + auto& oldMod = mods[row]; + if (oldMod.isResolving()) { + activeTickets.remove(oldMod.resolutionTicket()); + } + oldMod = newMod; + resolveMod(mods[row]); + emit dataChanged(index(row, 0), + index(row, columnCount(QModelIndex()) - 1)); + } + } + + // remove mods no longer present + { + QSet<QString> removed = currentSet; + QList<int> removedRows; + removed.subtract(newSet); + for (auto& removedMod : removed) { + removedRows.append(modsIndex[removedMod]); + } + std::sort(removedRows.begin(), removedRows.end(), std::greater<int>()); + for (auto iter = removedRows.begin(); iter != removedRows.end(); + iter++) { + int removedIndex = *iter; + beginRemoveRows(QModelIndex(), removedIndex, removedIndex); + auto removedIter = mods.begin() + removedIndex; + if (removedIter->isResolving()) { + activeTickets.remove(removedIter->resolutionTicket()); + } + mods.erase(removedIter); + endRemoveRows(); + } + } + + // add new mods to the end + { + QSet<QString> added = newSet; + added.subtract(currentSet); + beginInsertRows(QModelIndex(), mods.size(), + mods.size() + added.size() - 1); + for (auto& addedMod : added) { + mods.append(newMods[addedMod]); + resolveMod(mods.last()); + } + endInsertRows(); + } + + // update index + { + modsIndex.clear(); + int idx = 0; + for (auto& mod : mods) { + modsIndex[mod.mmc_id()] = idx; + idx++; + } + } + + m_update.reset(); + + emit updateFinished(); + + if (scheduled_update) { + scheduled_update = false; + update(); + } } void ModFolderModel::resolveMod(Mod& m) { - if(!m.shouldResolve()) { - return; - } - - auto task = new LocalModParseTask(nextResolutionTicket, m.type(), m.filename()); - auto result = task->result(); - result->id = m.mmc_id(); - activeTickets.insert(nextResolutionTicket, result); - m.setResolving(true, nextResolutionTicket); - nextResolutionTicket++; - QThreadPool *threadPool = QThreadPool::globalInstance(); - connect(task, &LocalModParseTask::finished, this, &ModFolderModel::finishModParse); - threadPool->start(task); + if (!m.shouldResolve()) { + return; + } + + auto task = + new LocalModParseTask(nextResolutionTicket, m.type(), m.filename()); + auto result = task->result(); + result->id = m.mmc_id(); + activeTickets.insert(nextResolutionTicket, result); + m.setResolving(true, nextResolutionTicket); + nextResolutionTicket++; + QThreadPool* threadPool = QThreadPool::globalInstance(); + connect(task, &LocalModParseTask::finished, this, + &ModFolderModel::finishModParse); + threadPool->start(task); } void ModFolderModel::finishModParse(int token) { - auto iter = activeTickets.find(token); - if(iter == activeTickets.end()) { - return; - } - auto result = *iter; - activeTickets.remove(token); - int row = modsIndex[result->id]; - auto & mod = mods[row]; - mod.finishResolvingWithDetails(result->details); - emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); + auto iter = activeTickets.find(token); + if (iter == activeTickets.end()) { + return; + } + auto result = *iter; + activeTickets.remove(token); + int row = modsIndex[result->id]; + auto& mod = mods[row]; + mod.finishResolvingWithDetails(result->details); + emit dataChanged(index(row), index(row, columnCount(QModelIndex()) - 1)); } void ModFolderModel::disableInteraction(bool disabled) { - if (interaction_disabled == disabled) { - return; - } - interaction_disabled = disabled; - if(size()) { - emit dataChanged(index(0), index(size() - 1)); - } + if (interaction_disabled == disabled) { + return; + } + interaction_disabled = disabled; + if (size()) { + emit dataChanged(index(0), index(size() - 1)); + } } void ModFolderModel::directoryChanged(QString path) { - update(); + update(); } bool ModFolderModel::isValid() { - return m_dir.exists() && m_dir.isReadable(); + return m_dir.exists() && m_dir.isReadable(); } -// FIXME: this does not take disabled mod (with extra .disable extension) into account... -bool ModFolderModel::installMod(const QString &filename) +// FIXME: this does not take disabled mod (with extra .disable extension) into +// account... +bool ModFolderModel::installMod(const QString& filename) { - if(interaction_disabled) { - return false; - } - - // NOTE: fix for GH-1178: remove trailing slash to avoid issues with using the empty result of QFileInfo::fileName - auto originalPath = FS::NormalizePath(filename); - QFileInfo fileinfo(originalPath); - - if (!fileinfo.exists() || !fileinfo.isReadable()) - { - qWarning() << "Caught attempt to install non-existing file or file-like object:" << originalPath; - return false; - } - qDebug() << "installing: " << fileinfo.absoluteFilePath(); - - Mod installedMod(fileinfo); - if (!installedMod.valid()) - { - qDebug() << originalPath << "is not a valid mod. Ignoring it."; - return false; - } - - auto type = installedMod.type(); - if (type == Mod::MOD_UNKNOWN) - { - qDebug() << "Cannot recognize mod type of" << originalPath << ", ignoring it."; - return false; - } - - auto newpath = FS::NormalizePath(FS::PathCombine(m_dir.path(), fileinfo.fileName())); - if(originalPath == newpath) - { - qDebug() << "Overwriting the mod (" << originalPath << ") with itself makes no sense..."; - return false; - } - - if (type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE || type == Mod::MOD_LITEMOD) - { - if(QFile::exists(newpath) || QFile::exists(newpath + QString(".disabled"))) - { - if(!QFile::remove(newpath)) - { - // FIXME: report error in a user-visible way - qWarning() << "Copy from" << originalPath << "to" << newpath << "has failed."; - return false; - } - qDebug() << newpath << "has been deleted."; - } - if (!QFile::copy(fileinfo.filePath(), newpath)) - { - qWarning() << "Copy from" << originalPath << "to" << newpath << "has failed."; - // FIXME: report error in a user-visible way - return false; - } - FS::updateTimestamp(newpath); - installedMod.repath(QFileInfo(newpath)); - update(); - return true; - } - else if (type == Mod::MOD_FOLDER) - { - QString from = fileinfo.filePath(); - if(QFile::exists(newpath)) - { - qDebug() << "Ignoring folder " << from << ", it would merge with " << newpath; - return false; - } - - if (!FS::copy(from, newpath)()) - { - qWarning() << "Copy of folder from" << originalPath << "to" << newpath << "has (potentially partially) failed."; - return false; - } - installedMod.repath(QFileInfo(newpath)); - update(); - return true; - } - return false; + if (interaction_disabled) { + return false; + } + + // NOTE: fix for GH-1178: remove trailing slash to avoid issues with using + // the empty result of QFileInfo::fileName + auto originalPath = FS::NormalizePath(filename); + QFileInfo fileinfo(originalPath); + + if (!fileinfo.exists() || !fileinfo.isReadable()) { + qWarning() << "Caught attempt to install non-existing file or " + "file-like object:" + << originalPath; + return false; + } + qDebug() << "installing: " << fileinfo.absoluteFilePath(); + + Mod installedMod(fileinfo); + if (!installedMod.valid()) { + qDebug() << originalPath << "is not a valid mod. Ignoring it."; + return false; + } + + auto type = installedMod.type(); + if (type == Mod::MOD_UNKNOWN) { + qDebug() << "Cannot recognize mod type of" << originalPath + << ", ignoring it."; + return false; + } + + auto newpath = + FS::NormalizePath(FS::PathCombine(m_dir.path(), fileinfo.fileName())); + if (originalPath == newpath) { + qDebug() << "Overwriting the mod (" << originalPath + << ") with itself makes no sense..."; + return false; + } + + if (type == Mod::MOD_SINGLEFILE || type == Mod::MOD_ZIPFILE || + type == Mod::MOD_LITEMOD) { + if (QFile::exists(newpath) || + QFile::exists(newpath + QString(".disabled"))) { + if (!QFile::remove(newpath)) { + // FIXME: report error in a user-visible way + qWarning() << "Copy from" << originalPath << "to" << newpath + << "has failed."; + return false; + } + qDebug() << newpath << "has been deleted."; + } + if (!QFile::copy(fileinfo.filePath(), newpath)) { + qWarning() << "Copy from" << originalPath << "to" << newpath + << "has failed."; + // FIXME: report error in a user-visible way + return false; + } + FS::updateTimestamp(newpath); + installedMod.repath(QFileInfo(newpath)); + update(); + return true; + } else if (type == Mod::MOD_FOLDER) { + QString from = fileinfo.filePath(); + if (QFile::exists(newpath)) { + qDebug() << "Ignoring folder " << from << ", it would merge with " + << newpath; + return false; + } + + if (!FS::copy(from, newpath)()) { + qWarning() << "Copy of folder from" << originalPath << "to" + << newpath << "has (potentially partially) failed."; + return false; + } + installedMod.repath(QFileInfo(newpath)); + update(); + return true; + } + return false; } -bool ModFolderModel::setModStatus(const QModelIndexList& indexes, ModStatusAction enable) +bool ModFolderModel::setModStatus(const QModelIndexList& indexes, + ModStatusAction enable) { - if(interaction_disabled) { - return false; - } - - if(indexes.isEmpty()) - return true; - - for (auto index: indexes) - { - if(index.column() != 0) { - continue; - } - setModStatus(index.row(), enable); - } - return true; + if (interaction_disabled) { + return false; + } + + if (indexes.isEmpty()) + return true; + + for (auto index : indexes) { + if (index.column() != 0) { + continue; + } + setModStatus(index.row(), enable); + } + return true; } bool ModFolderModel::deleteMods(const QModelIndexList& indexes) { - if(interaction_disabled) { - return false; - } - - if(indexes.isEmpty()) - return true; - - for (auto i: indexes) - { - Mod &m = mods[i.row()]; - m.destroy(); - } - return true; + if (interaction_disabled) { + return false; + } + + if (indexes.isEmpty()) + return true; + + for (auto i : indexes) { + Mod& m = mods[i.row()]; + m.destroy(); + } + return true; } -int ModFolderModel::columnCount(const QModelIndex &parent) const +int ModFolderModel::columnCount(const QModelIndex& parent) const { - return NUM_COLUMNS; + return NUM_COLUMNS; } -QVariant ModFolderModel::data(const QModelIndex &index, int role) const +QVariant ModFolderModel::data(const QModelIndex& index, int role) const { - if (!index.isValid()) - return QVariant(); - - int row = index.row(); - int column = index.column(); - - if (row < 0 || row >= mods.size()) - return QVariant(); - - switch (role) - { - case Qt::DisplayRole: - switch (column) - { - case NameColumn: - return mods[row].name(); - case VersionColumn: { - switch(mods[row].type()) { - case Mod::MOD_FOLDER: - return tr("Folder"); - case Mod::MOD_SINGLEFILE: - return tr("File"); - default: - break; - } - return mods[row].version(); - } - case DateColumn: - return mods[row].dateTimeChanged(); - - default: - return QVariant(); - } - - case Qt::ToolTipRole: - return mods[row].mmc_id(); - - case Qt::CheckStateRole: - switch (column) - { - case ActiveColumn: - return mods[row].enabled() ? Qt::Checked : Qt::Unchecked; - default: - return QVariant(); - } - default: - return QVariant(); - } + if (!index.isValid()) + return QVariant(); + + int row = index.row(); + int column = index.column(); + + if (row < 0 || row >= mods.size()) + return QVariant(); + + switch (role) { + case Qt::DisplayRole: + switch (column) { + case NameColumn: + return mods[row].name(); + case VersionColumn: { + switch (mods[row].type()) { + case Mod::MOD_FOLDER: + return tr("Folder"); + case Mod::MOD_SINGLEFILE: + return tr("File"); + default: + break; + } + return mods[row].version(); + } + case DateColumn: + return mods[row].dateTimeChanged(); + + default: + return QVariant(); + } + + case Qt::ToolTipRole: + return mods[row].mmc_id(); + + case Qt::CheckStateRole: + switch (column) { + case ActiveColumn: + return mods[row].enabled() ? Qt::Checked : Qt::Unchecked; + default: + return QVariant(); + } + default: + return QVariant(); + } } -bool ModFolderModel::setData(const QModelIndex &index, const QVariant &value, int role) +bool ModFolderModel::setData(const QModelIndex& index, const QVariant& value, + int role) { - if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid()) - { - return false; - } - - if (role == Qt::CheckStateRole) - { - return setModStatus(index.row(), Toggle); - } - return false; + if (index.row() < 0 || index.row() >= rowCount(index) || !index.isValid()) { + return false; + } + + if (role == Qt::CheckStateRole) { + return setModStatus(index.row(), Toggle); + } + return false; } -bool ModFolderModel::setModStatus(int row, ModFolderModel::ModStatusAction action) +bool ModFolderModel::setModStatus(int row, + ModFolderModel::ModStatusAction action) { - if(row < 0 || row >= mods.size()) { - return false; - } - - auto &mod = mods[row]; - bool desiredStatus; - switch(action) { - case Enable: - desiredStatus = true; - break; - case Disable: - desiredStatus = false; - break; - case Toggle: - default: - desiredStatus = !mod.enabled(); - break; - } - - if(desiredStatus == mod.enabled()) { - return true; - } - - // preserve the row, but change its ID - auto oldId = mod.mmc_id(); - if(!mod.enable(!mod.enabled())) { - return false; - } - auto newId = mod.mmc_id(); - if(modsIndex.contains(newId)) { - // NOTE: this could handle a corner case, where we are overwriting a file, because the same 'mod' exists both enabled and disabled - // But is it necessary? - } - modsIndex.remove(oldId); - modsIndex[newId] = row; - emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1)); - return true; + if (row < 0 || row >= mods.size()) { + return false; + } + + auto& mod = mods[row]; + bool desiredStatus; + switch (action) { + case Enable: + desiredStatus = true; + break; + case Disable: + desiredStatus = false; + break; + case Toggle: + default: + desiredStatus = !mod.enabled(); + break; + } + + if (desiredStatus == mod.enabled()) { + return true; + } + + // preserve the row, but change its ID + auto oldId = mod.mmc_id(); + if (!mod.enable(!mod.enabled())) { + return false; + } + auto newId = mod.mmc_id(); + if (modsIndex.contains(newId)) { + // NOTE: this could handle a corner case, where we are overwriting a + // file, because the same 'mod' exists both enabled and disabled But is + // it necessary? + } + modsIndex.remove(oldId); + modsIndex[newId] = row; + emit dataChanged(index(row, 0), index(row, columnCount(QModelIndex()) - 1)); + return true; } -QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, int role) const +QVariant ModFolderModel::headerData(int section, Qt::Orientation orientation, + int role) const { - switch (role) - { - case Qt::DisplayRole: - switch (section) - { - case ActiveColumn: - return QString(); - case NameColumn: - return tr("Name"); - case VersionColumn: - return tr("Version"); - case DateColumn: - return tr("Last changed"); - default: - return QVariant(); - } - - case Qt::ToolTipRole: - switch (section) - { - case ActiveColumn: - return tr("Is the mod enabled?"); - case NameColumn: - return tr("The name of the mod."); - case VersionColumn: - return tr("The version of the mod."); - case DateColumn: - return tr("The date and time this mod was last changed (or added)."); - default: - return QVariant(); - } - default: - return QVariant(); - } - return QVariant(); + switch (role) { + case Qt::DisplayRole: + switch (section) { + case ActiveColumn: + return QString(); + case NameColumn: + return tr("Name"); + case VersionColumn: + return tr("Version"); + case DateColumn: + return tr("Last changed"); + default: + return QVariant(); + } + + case Qt::ToolTipRole: + switch (section) { + case ActiveColumn: + return tr("Is the mod enabled?"); + case NameColumn: + return tr("The name of the mod."); + case VersionColumn: + return tr("The version of the mod."); + case DateColumn: + return tr("The date and time this mod was last changed (or " + "added)."); + default: + return QVariant(); + } + default: + return QVariant(); + } + return QVariant(); } -Qt::ItemFlags ModFolderModel::flags(const QModelIndex &index) const +Qt::ItemFlags ModFolderModel::flags(const QModelIndex& index) const { - Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); - auto flags = defaultFlags; - if(interaction_disabled) { - flags &= ~Qt::ItemIsDropEnabled; - } - else - { - flags |= Qt::ItemIsDropEnabled; - if(index.isValid()) { - flags |= Qt::ItemIsUserCheckable; - } - } - return flags; + Qt::ItemFlags defaultFlags = QAbstractListModel::flags(index); + auto flags = defaultFlags; + if (interaction_disabled) { + flags &= ~Qt::ItemIsDropEnabled; + } else { + flags |= Qt::ItemIsDropEnabled; + if (index.isValid()) { + flags |= Qt::ItemIsUserCheckable; + } + } + return flags; } Qt::DropActions ModFolderModel::supportedDropActions() const { - // copy from outside, move from within and other mod lists - return Qt::CopyAction | Qt::MoveAction; + // copy from outside, move from within and other mod lists + return Qt::CopyAction | Qt::MoveAction; } QStringList ModFolderModel::mimeTypes() const { - QStringList types; - types << "text/uri-list"; - return types; + QStringList types; + types << "text/uri-list"; + return types; } -bool ModFolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int, int, const QModelIndex&) +bool ModFolderModel::dropMimeData(const QMimeData* data, Qt::DropAction action, + int, int, const QModelIndex&) { - if (action == Qt::IgnoreAction) - { - return true; - } - - // check if the action is supported - if (!data || !(action & supportedDropActions())) - { - return false; - } - - // files dropped from outside? - if (data->hasUrls()) - { - auto urls = data->urls(); - for (auto url : urls) - { - // only local files may be dropped... - if (!url.isLocalFile()) - { - continue; - } - // TODO: implement not only copy, but also move - // FIXME: handle errors here - installMod(url.toLocalFile()); - } - return true; - } - return false; + if (action == Qt::IgnoreAction) { + return true; + } + + // check if the action is supported + if (!data || !(action & supportedDropActions())) { + return false; + } + + // files dropped from outside? + if (data->hasUrls()) { + auto urls = data->urls(); + for (auto url : urls) { + // only local files may be dropped... + if (!url.isLocalFile()) { + continue; + } + // TODO: implement not only copy, but also move + // FIXME: handle errors here + installMod(url.toLocalFile()); + } + return true; + } + return false; } |
