summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mainwindow.cpp4
-rw-r--r--src/modinfo.cpp15
-rw-r--r--src/modinfo.h8
-rw-r--r--src/modlist.cpp172
-rw-r--r--src/modlist.h26
-rw-r--r--src/modlistbypriorityproxy.cpp72
-rw-r--r--src/modlistbypriorityproxy.h1
-rw-r--r--src/modlistview.cpp38
-rw-r--r--src/modlistview.h6
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: