1 /*
2 * Hedgewars, a free turn based strategy game
3 * Copyright (c) 2004-2015 Andrey Korotaev <unC0Rr@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; version 2 of the License
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 /**
20 * @file
21 * @brief DataManager class implementation
22 */
23
24 #include <QMap>
25 #include <QStringList>
26 #include <QStandardItemModel>
27 #include <QFileInfo>
28 #include <QSettings>
29 #include <QColor>
30
31 #include <SDL.h>
32
33 #include "hwconsts.h"
34 #include "HWApplication.h"
35 #include "sdlkeys.h"
36 #include "KeyMap.h"
37 #include "physfs.h"
38
39 #include "DataManager.h"
40
41 #include "GameStyleModel.h"
42 #include "HatModel.h"
43 #include "MapModel.h"
44 #include "ThemeModel.h"
45
DataManager()46 DataManager::DataManager()
47 {
48 m_hatModel = NULL;
49 m_staticMapModel = NULL;
50 m_missionMapModel = NULL;
51 m_themeModel = NULL;
52 m_colorsModel = NULL;
53 m_bindsModel = NULL;
54 m_gameStyleModel = NULL;
55 }
56
57
instance()58 DataManager & DataManager::instance()
59 {
60 static DataManager instance;
61 return instance;
62 }
63
64
entryList(const QString & subDirectory,QDir::Filters filters,const QStringList & nameFilters,bool withDLC) const65 QStringList DataManager::entryList(
66 const QString & subDirectory,
67 QDir::Filters filters,
68 const QStringList & nameFilters,
69 bool withDLC
70 ) const
71 {
72 QDir tmpDir(QString("physfs://%1").arg(subDirectory));
73 QStringList result = tmpDir.entryList(nameFilters, filters);
74
75 // sort case-insensitive
76 QMap<QString, QString> sortedFileNames;
77 QString absolutePath = datadir->absolutePath().toLocal8Bit().data();
78 foreach ( QString fn, result)
79 {
80 // Filter out DLC entries if desired
81 QString realDir = PHYSFS_getRealDir(QString(subDirectory + "/" + fn).toLocal8Bit().data());
82 if(withDLC || realDir == absolutePath)
83 sortedFileNames.insert(fn.toLower(), fn);
84 }
85 result = sortedFileNames.values();
86
87 return result;
88 }
89
gameStyleModel()90 GameStyleModel * DataManager::gameStyleModel()
91 {
92 if (m_gameStyleModel == NULL) {
93 m_gameStyleModel = new GameStyleModel();
94 m_gameStyleModel->loadGameStyles();
95 }
96 return m_gameStyleModel;
97 }
98
hatModel()99 HatModel * DataManager::hatModel()
100 {
101 if (m_hatModel == NULL) {
102 m_hatModel = new HatModel();
103 m_hatModel->loadHats();
104 }
105 return m_hatModel;
106 }
107
staticMapModel()108 MapModel * DataManager::staticMapModel()
109 {
110 if (m_staticMapModel == NULL) {
111 m_staticMapModel = new MapModel(MapModel::StaticMap, this);
112 }
113 return m_staticMapModel;
114 }
115
missionMapModel()116 MapModel * DataManager::missionMapModel()
117 {
118 if (m_missionMapModel == NULL) {
119 m_missionMapModel = new MapModel(MapModel::MissionMap, this);
120 }
121 return m_missionMapModel;
122 }
123
themeModel()124 ThemeModel * DataManager::themeModel()
125 {
126 if (m_themeModel == NULL) {
127 m_themeModel = new ThemeModel();
128 }
129 return m_themeModel;
130 }
131
colorsModel()132 QStandardItemModel * DataManager::colorsModel()
133 {
134 if(m_colorsModel == NULL)
135 {
136 m_colorsModel = new QStandardItemModel();
137
138 int i = 0;
139 while(colors[i])
140 {
141 QStandardItem * item = new QStandardItem();
142 item->setData(QColor(colors[i]));
143 m_colorsModel->appendRow(item);
144 ++i;
145 }
146 }
147
148 return m_colorsModel;
149 }
150
bindsModel()151 QStandardItemModel * DataManager::bindsModel()
152 {
153 KeyMap km = KeyMap::instance();
154 if(m_bindsModel == NULL)
155 {
156 m_bindsModel = new QStandardItemModel();
157
158 QStandardItem * firstItem = new QStandardItem();
159 firstItem->setData(tr("Use Default"), Qt::DisplayRole);
160 firstItem->setData("default", Qt::UserRole + 1);
161 m_bindsModel->appendRow(firstItem);
162
163 for(int j = 0; sdlkeys[j][1][0] != '\0'; j++)
164 {
165 QStandardItem * item = new QStandardItem();
166 QString keyId = QString(sdlkeys[j][0]);
167 QString keyDisplay;
168 bool isKeyboard = sdlkeys_iskeyboard[j] == true;
169 if (keyId == "none" || (!isKeyboard))
170 keyDisplay = HWApplication::translate("binds (keys)", sdlkeys[j][1]);
171 else
172 // Get key name with respect to keyboard layout
173 keyDisplay = QString(SDL_GetKeyName(SDL_GetKeyFromScancode(km.getScancodeFromKeyname(sdlkeys[j][0]))));
174
175 bool kbFallback = keyDisplay.trimmed().isEmpty();
176 if (kbFallback)
177 {
178 keyDisplay = QString(sdlkeys[j][1]);
179 if ((QString(sdlkeys[j][0]) != "f13") && (QString(sdlkeys[j][0]) != "f14") && (QString(sdlkeys[j][0]) != "f15"))
180 {
181 // If SDL doesn't know a name, show fallback name and a warning
182 //: Name of QWERTY US keyboard layout
183 keyDisplay = keyDisplay + QString(" ") + HWApplication::translate("binds (keys)", "(QWERTY)");
184 }
185 }
186 if (isKeyboard)
187 {
188 if (!kbFallback)
189 keyDisplay = HWApplication::translate("binds (keys)", keyDisplay.toUtf8().constData());
190 keyDisplay = HWApplication::translate("binds (keys)", "Keyboard") + QString(": ") + keyDisplay;
191 }
192 item->setData(keyDisplay, Qt::DisplayRole);
193 item->setData(sdlkeys[j][0], Qt::UserRole + 1);
194 m_bindsModel->appendRow(item);
195 }
196 }
197
198 return m_bindsModel;
199 }
200
settingsFileName()201 QString DataManager::settingsFileName()
202 {
203 if(m_settingsFileName.isEmpty())
204 {
205 QFile settingsFile(cfgdir->absoluteFilePath("settings.ini"));
206
207 if(!settingsFile.exists())
208 {
209 QFile oldSettingsFile(cfgdir->absoluteFilePath("hedgewars.ini"));
210
211 settingsFile.open(QFile::WriteOnly);
212 settingsFile.close();
213
214 if(oldSettingsFile.exists())
215 {
216 QSettings sOld(oldSettingsFile.fileName(), QSettings::IniFormat);
217 QSettings sNew(settingsFile.fileName(), QSettings::IniFormat);
218 sNew.setIniCodec("UTF-8");
219
220 foreach(const QString & key, sOld.allKeys())
221 {
222 if(key.startsWith("colors/color"))
223 sNew.setValue(key, sOld.value(key).value<QColor>().name());
224 else
225 sNew.setValue(key, sOld.value(key));
226 }
227 }
228 }
229
230 m_settingsFileName = settingsFile.fileName();
231 }
232
233 return m_settingsFileName;
234 }
235
safeFileName(QString fileName)236 QString DataManager::safeFileName(QString fileName)
237 {
238 fileName.replace('\\', '_');
239 fileName.replace('/', '_');
240 fileName.replace(':', '_');
241
242 return fileName;
243 }
244
reload()245 void DataManager::reload()
246 {
247 // removed for now (also code was a bit unclean, could lead to segfault if
248 // reload() is called before all members are initialized - because currently
249 // they are initialized in the getter methods rather than the constructor)
250 }
251
resetColors()252 void DataManager::resetColors()
253 {
254 for(int i = colorsModel()->rowCount() - 1; i >= 0; --i)
255 {
256 m_colorsModel->item(i)->setData(QColor(colors[i]));
257 }
258 }
259
ensureFileExists(const QString & fileName)260 bool DataManager::ensureFileExists(const QString &fileName)
261 {
262 QFile tmpfile(fileName);
263 if (!tmpfile.exists())
264 return tmpfile.open(QFile::WriteOnly);
265 else
266 return true;
267 }
268