filealias.cpp
1 //------------------------------------------------------------------------------
2 // filealias.cpp
3 //------------------------------------------------------------------------------
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 // 02110-1301 USA
19 //
20 //------------------------------------------------------------------------------
21 // Copyright (C) 2014 "Zalewa" <zalewapl@gmail.com>
22 //------------------------------------------------------------------------------
23 #include "filealias.h"
24 
25 #include <cassert>
26 
27 FileAlias::FileAlias()
28 {
29  d.matchType = FileAlias::LeftToRight;
30 }
31 
32 FileAlias::FileAlias(const QString &name)
33 {
34  d.matchType = FileAlias::LeftToRight;
35  d.name = name;
36 }
37 
38 void FileAlias::addAlias(const QString &val)
39 {
40  if (!d.aliases.contains(val, Qt::CaseInsensitive))
41  {
42  d.aliases << val;
43  }
44 }
45 
46 void FileAlias::addAliases(const QStringList &val)
47 {
48  for (const QString &element : val)
49  {
50  addAlias(element);
51  }
52 }
53 
54 const QStringList &FileAlias::aliases() const
55 {
56  return d.aliases;
57 }
58 
59 void FileAlias::setAliases(const QStringList &val)
60 {
61  d.aliases = val;
62 }
63 
64 FileAlias FileAlias::deserializeQVariant(const QVariant &var)
65 {
66  QVariantMap m = var.toMap();
67  FileAlias result;
68  result.setAliases(m["aliases"].toStringList());
69  result.setMatchType(deserializeMatchType(m["matchType"]));
70  result.setName(m["name"].toString());
71  return result;
72 }
73 
74 QVariant FileAlias::serializeQVariant() const
75 {
76  QVariantMap m;
77  m["aliases"] = aliases();
78  m["matchType"] = serializeMatchType(matchType());
79  m["name"] = name();
80  return m;
81 }
82 
83 FileAlias::MatchType FileAlias::deserializeMatchType(const QVariant &variant)
84 {
85  QString val = variant.toString();
86  if (val == "LeftToRight")
87  return LeftToRight;
88  else if (val == "AllEqual")
89  return AllEqual;
90  // Default return value.
91  return LeftToRight;
92 }
93 
94 QVariant FileAlias::serializeMatchType(MatchType matchType)
95 {
96  switch (matchType)
97  {
98  default:
99  assert(false && "don't know how to serialize this FileAlias::MatchType"); // intentional fall-through
100  case LeftToRight:
101  return "LeftToRight";
102  case AllEqual:
103  return "AllEqual";
104  }
105 }
106 
107 FileAlias FileAlias::freeDoom1Aliases()
108 {
109  FileAlias result;
110  result.setName("doom.wad");
111  QStringList aliases;
112  aliases << "freedomu.wad" << "freedoom1.wad";
113  result.setAliases(aliases);
114  result.setMatchType(LeftToRight);
115  return result;
116 }
117 
118 QList<FileAlias> FileAlias::freeDoom2Aliases()
119 {
120  QStringList bases;
121  // Each of these are equivalent in terms of modern source-ports.
122  // If custom levels require one of those WADs as a base, I'd assume
123  // they will run just fine with any of them, and thus also with freedoom.
124  bases << "doom2.wad" << "tnt.wad" << "plutonia.wad";
125  QList<FileAlias> result;
126  for (const QString &base : bases)
127  {
128  FileAlias alias;
129  alias.setName(base);
130  alias.setMatchType(LeftToRight);
131  QStringList aliases;
132  aliases << "freedoom.wad" << "freedoom2.wad";
133  alias.setAliases(aliases);
134  result << alias;
135  }
136  return result;
137 }
138 
139 bool FileAlias::isSameName(const QString &otherName) const
140 {
141  return d.name.compare(otherName, Qt::CaseInsensitive) == 0;
142 }
143 
144 bool FileAlias::isValid() const
145 {
146  return !name().isEmpty() && !aliases().isEmpty();
147 }
148 
149 FileAlias::MatchType FileAlias::matchType() const
150 {
151  return d.matchType;
152 }
153 
154 void FileAlias::setMatchType(MatchType matchType)
155 {
156  d.matchType = matchType;
157 }
158 
159 const QString &FileAlias::name() const
160 {
161  return d.name;
162 }
163 
164 void FileAlias::setName(const QString &val)
165 {
166  d.name = val;
167 }
168 
170 {
171  QList<FileAlias> result;
172  result << freeDoom1Aliases();
173  for (const FileAlias &alias : freeDoom2Aliases())
174  {
175  result << alias;
176  }
177  return result;
178 }
180 QStringList FileAliasList::aliases(const QList<FileAlias> &candidates, const QString &name)
181 {
182  QStringList allAliases;
183  for (const FileAlias &candidate : candidates)
184  {
185  switch (candidate.matchType())
186  {
187  case FileAlias::LeftToRight:
188  if (candidate.name().compare(name, Qt::CaseInsensitive) == 0)
189  allAliases << candidate.aliases();
190  break;
191  case FileAlias::AllEqual:
192  {
193  QStringList allValidNames;
194  allValidNames << candidate.name();
195  allValidNames << candidate.aliases();
196  if (allValidNames.contains(name, Qt::CaseInsensitive))
197  allAliases << allValidNames;
198  break;
199  }
200  default:
201  assert(false && "unknown FileAlias::MatchType");
202  break;
203  }
204  }
205  // Normalize to remove duplicates and the source name.
206  allAliases.removeDuplicates();
207  allAliases.removeAll(name);
208  return allAliases;
209 }
210 
211 QList<FileAlias> FileAliasList::mergeDuplicates(const QList<FileAlias> &input)
212 {
213  QList<FileAlias> result;
214  for (const FileAlias &alias : input)
215  {
216  bool merged = false;
217  for (auto &aliasOnList : result)
218  {
219  if (aliasOnList.isSameName(alias.name()) && aliasOnList.matchType() == alias.matchType())
220  {
221  aliasOnList.addAliases(alias.aliases());
222  merged = true;
223  break;
224  }
225  }
226  if (!merged)
227  {
228  result << alias;
229  }
230  }
231  return result;
232 }