summaryrefslogtreecommitdiff
path: root/src/modlistdropinfo.cpp
blob: f0bb51bc028a06439e2733f81c5269ba9641da1a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#include "modlistdropinfo.h"

#include "organizercore.h"

ModListDropInfo::ModListDropInfo(const QMimeData* mimeData, OrganizerCore& core)
    : m_rows{}, m_download{-1}, m_localUrls{}, m_url{}
{
  // this only check if the drop is valid, not if the content of the drop
  // matches the target, a drop is valid if either
  // 1. it contains items from another model (drag&drop in modlist or from download
  // list)
  // 2. it contains URLs from MO2 (overwrite or from another mod)
  // 3. it contains a single URL to an external folder
  // 4. it contains a single URL to a valid archive for MO2
  try {
    if (mimeData->hasUrls()) {
      for (auto& url : mimeData->urls()) {
        auto p = relativeUrl(url);
        if (p) {
          m_localUrls.push_back(*p);
        }
      }

      // external drop
      if (m_localUrls.empty() && mimeData->urls().size() == 1) {
        auto url = mimeData->urls()[0];
        if (url.isLocalFile() && !relativeUrl(url)) {
          QFileInfo info(url.toLocalFile());
          if (info.isDir()) {
            m_url = url;
          } else if (core.installationManager()->getSupportedExtensions().contains(
                         info.suffix(), Qt::CaseInsensitive)) {
            m_url = url;
          }
        }
      }

    } else if (mimeData->hasText()) {
      QByteArray encoded = mimeData->data("application/x-qabstractitemmodeldatalist");
      QDataStream stream(&encoded, QIODevice::ReadOnly);

      while (!stream.atEnd()) {
        int sourceRow, col;
        QMap<int, QVariant> roleDataMap;
        stream >> sourceRow >> col >> roleDataMap;
        if (col == 0) {
          m_rows.push_back(sourceRow);
        }
      }

      if (mimeData->text() != ModListDropInfo::ModText) {
        if (mimeData->text() == ModListDropInfo::DownloadText && m_rows.size() == 1) {
          m_download = m_rows[0];
        }
        m_rows = {};
      }
    }
  } catch (std::exception const&) {
    m_rows     = {};
    m_download = -1;
    m_localUrls.clear();
    m_url = {};
  }
}

std::optional<ModListDropInfo::RelativeUrl>
ModListDropInfo::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 {{url, splitPath.join("/"), originName}};
  } else if (sourceFile.startsWith(overwriteDir.canonicalPath())) {
    return {{url, overwriteDir.relativeFilePath(sourceFile),
             ModInfo::getOverwrite()->name()}};
  }

  return {};
}

bool ModListDropInfo::isValid() const
{
  return isLocalFileDrop() || isModDrop() || isDownloadDrop() || m_url.isLocalFile();
}

bool ModListDropInfo::isLocalFileDrop() const
{
  return !m_localUrls.empty();
}

bool ModListDropInfo::isModDrop() const
{
  return !m_rows.empty();
}

bool ModListDropInfo::isDownloadDrop() const
{
  return m_download != -1;
}

bool ModListDropInfo::isExternalArchiveDrop() const
{
  return m_url.isLocalFile() && QFileInfo(m_url.toLocalFile()).isFile();
}

bool ModListDropInfo::isExternalFolderDrop() const
{
  return m_url.isLocalFile() && QFileInfo(m_url.toLocalFile()).isDir();
}