1 //=============================================================================
2 //
3 // File : KviTheme.cpp
4 // Creation date : Mon Jan 08 2007 03:23:00 CEST by Szymon Stefanek
5 //
6 // This file is part of the KVIrc IRC client distribution
7 // Copyright (C) 2007-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 // This program is FREE software. You can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the HOPE that it will be USEFUL,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 // See the GNU General Public License for more details.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with this program. If not, write to the Free Software Foundation,
21 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24
25 #include "KviTheme.h"
26 #include "KviFileUtils.h"
27 #include "KviConfigurationFile.h"
28 #include "KviLocale.h"
29 #include "KviMiscUtils.h"
30 #include "kvi_sourcesdate.h"
31
32 #include <QImage>
33 #include <QDir>
34 #include <QStringList>
35
36 #define KVI_THEME_SMALL_SCREENSHOT_NAME "screenshot_small.png"
37 #define KVI_THEME_MEDIUM_SCREENSHOT_NAME "screenshot_medium.png"
38 #define KVI_THEME_LARGE_SCREENSHOT_NAME "screenshot.png"
39
40 #define QIMAGE_SCALE_MIN Qt::KeepAspectRatio
41
KviThemeInfo()42 KviThemeInfo::KviThemeInfo()
43 : KviHeapObject()
44 {
45 }
46
47 KviThemeInfo::~KviThemeInfo()
48 = default;
49
setDirectoryAndLocation(const QString & szDirectory,Location eLocation)50 void KviThemeInfo::setDirectoryAndLocation(const QString & szDirectory, Location eLocation)
51 {
52 switch(eLocation)
53 {
54 case Auto:
55 g_pApp->getLocalKvircDirectory(m_szDirectory, KviApplication::Themes, szDirectory);
56 if(KviFileUtils::directoryExists(m_szDirectory))
57 {
58 m_eLocation = User;
59 }
60 else
61 {
62 g_pApp->getGlobalKvircDirectory(m_szDirectory, KviApplication::Themes, szDirectory);
63 if(KviFileUtils::directoryExists(m_szDirectory))
64 {
65 m_eLocation = Builtin;
66 }
67 else
68 {
69 m_eLocation = External;
70 m_szDirectory = szDirectory;
71 m_szSubdirectory = KviFileUtils::extractFileName(szDirectory, false);
72 }
73 }
74 break;
75 case Builtin:
76 m_eLocation = eLocation;
77 m_szSubdirectory = szDirectory;
78 g_pApp->getGlobalKvircDirectory(m_szDirectory, KviApplication::Themes, m_szSubdirectory);
79 break;
80 case User:
81 m_eLocation = eLocation;
82 m_szSubdirectory = szDirectory;
83 g_pApp->getLocalKvircDirectory(m_szDirectory, KviApplication::Themes, m_szSubdirectory);
84 break;
85 default: // assume external
86 {
87 m_eLocation = External;
88 m_szDirectory = szDirectory;
89 m_szSubdirectory = KviFileUtils::extractFileName(szDirectory, false);
90 }
91 break;
92 }
93
94 KviQString::ensureLastCharIs(m_szDirectory, QChar(KVI_PATH_SEPARATOR_CHAR));
95
96 //qDebug(
97 // "[KviTheme::setDirectoryAndLocation] Directory(%s), Subdirectory(%s), Location(%d)",
98 // m_szDirectory.toUtf8().data(),
99 // m_szSubdirectory.toUtf8().data(),
100 // m_eLocation
101 // );
102 }
103
load(const QString & szDirectory,Location eLocation)104 bool KviThemeInfo::load(const QString & szDirectory, Location eLocation)
105 {
106 setDirectoryAndLocation(szDirectory, eLocation);
107
108 QString szThemeInfoFileName = m_szDirectory + KVI_THEMEINFO_FILE_NAME;
109 QString szThemeDataFileName = m_szDirectory + KVI_THEMEDATA_FILE_NAME;
110
111 if(!KviFileUtils::fileExists(szThemeInfoFileName))
112 {
113 m_szLastError = __tr2qs("The theme information file does not exist");
114 return false;
115 }
116
117 if(!KviFileUtils::fileExists(szThemeDataFileName))
118 {
119 m_szLastError = __tr2qs("The theme data file does not exist");
120 return false;
121 }
122
123 KviConfigurationFile cfg(szThemeInfoFileName, KviConfigurationFile::Read);
124
125 cfg.setGroup(KVI_THEMEINFO_CONFIG_GROUP);
126
127 m_szThemeEngineVersion = cfg.readEntry("ThemeEngineVersion", "1.0.0");
128 if(KviMiscUtils::compareVersions(m_szThemeEngineVersion, KVI_CURRENT_THEME_ENGINE_VERSION) < 0)
129 {
130 m_szLastError = QString(__tr2qs("This KVIrc executable is too old for this theme (minimum theme engine version required is %1 while this theme engine has version %2)")).arg(m_szThemeEngineVersion, KVI_CURRENT_THEME_ENGINE_VERSION);
131 return false; // incompatible theme engine (will not work)
132 }
133
134 // mandatory fields
135 m_szName = cfg.readEntry("Name", "");
136
137 if(m_szName.isEmpty())
138 {
139 m_szLastError = __tr2qs("Theme information file is not valid");
140 return false;
141 }
142
143 // optional fields
144 m_szVersion = cfg.readEntry("Version", "");
145 if(m_szVersion.isEmpty())
146 m_szVersion = "?.?.?";
147 m_szAuthor = cfg.readEntry("Author", "");
148 QString szUnknown = __tr2qs("Unknown");
149 if(m_szAuthor.isEmpty())
150 m_szAuthor = szUnknown;
151 m_szDescription = cfg.readEntry("Description", "");
152 m_szDate = cfg.readEntry("Date", "");
153 if(m_szDate.isEmpty())
154 m_szDate = szUnknown;
155 m_szApplication = cfg.readEntry("Application", "");
156 if(m_szApplication.isEmpty())
157 m_szApplication = szUnknown;
158
159 //qDebug(
160 // "[KviTheme::load] Directory(%s), Subdirectory(%s), Location(%d)",
161 // m_szDirectory.toUtf8().data(),
162 // m_szSubdirectory.toUtf8().data(),
163 // m_eLocation
164 // );
165
166 return true;
167 }
168
save(const QString & szThemeFileName)169 bool KviThemeInfo::save(const QString & szThemeFileName)
170 {
171 KviConfigurationFile inf(szThemeFileName, KviConfigurationFile::Write);
172
173 inf.clear();
174
175 inf.setGroup(KVI_THEMEINFO_CONFIG_GROUP);
176
177 inf.writeEntry("Name", m_szName);
178 inf.writeEntry("Version", m_szVersion);
179 inf.writeEntry("Author", m_szAuthor);
180 inf.writeEntry("Description", m_szDescription);
181 inf.writeEntry("Date", m_szDate);
182 inf.writeEntry("ThemeEngineVersion", KVI_CURRENT_THEME_ENGINE_VERSION);
183 inf.writeEntry("Application", "KVIrc " KVI_VERSION "." KVI_SOURCES_DATE);
184
185 return true;
186 }
187
smallScreenshotPath()188 QString KviThemeInfo::smallScreenshotPath()
189 {
190 QString szRet = m_szDirectory;
191 szRet.append(KVI_THEME_SMALL_SCREENSHOT_NAME);
192 return szRet;
193 }
194
smallScreenshot()195 const QPixmap & KviThemeInfo::smallScreenshot()
196 {
197 if(!m_pixScreenshotSmall.isNull())
198 return m_pixScreenshotSmall;
199
200 QString szFileName = m_szDirectory;
201 szFileName.append(KVI_THEME_SMALL_SCREENSHOT_NAME);
202 QPixmap pix(szFileName);
203 if(!pix.isNull())
204 {
205 m_pixScreenshotSmall = pix;
206 return m_pixScreenshotSmall;
207 }
208 // try to scale it from the large one (and save it by the way)
209 pix = mediumScreenshot();
210 if(pix.isNull())
211 return m_pixScreenshotSmall;
212
213 if(pix.width() > 300 || pix.height() > 225)
214 {
215 QImage sbri = pix.toImage();
216 pix = QPixmap::fromImage(sbri.scaled(300, 225, QIMAGE_SCALE_MIN, Qt::SmoothTransformation));
217 }
218 pix.save(szFileName, "PNG");
219
220 m_pixScreenshotSmall = pix;
221 return m_pixScreenshotSmall;
222 }
223
mediumScreenshot()224 const QPixmap & KviThemeInfo::mediumScreenshot()
225 {
226 if(!m_pixScreenshotMedium.isNull())
227 return m_pixScreenshotMedium;
228
229 QString szFileName = m_szDirectory;
230 szFileName.append(KVI_THEME_MEDIUM_SCREENSHOT_NAME);
231 QPixmap pix(szFileName);
232 if(!pix.isNull())
233 {
234 m_pixScreenshotMedium = pix;
235 return m_pixScreenshotMedium;
236 }
237 // try to scale it from the large one (and save it by the way)
238 pix = largeScreenshot();
239 if(pix.isNull())
240 return m_pixScreenshotMedium;
241 if(pix.width() > 600 || pix.height() > 450)
242 {
243 QImage sbri = pix.toImage();
244 pix.fromImage(sbri.scaled(640, 450, QIMAGE_SCALE_MIN, Qt::SmoothTransformation));
245 }
246 pix.save(szFileName, "PNG");
247
248 m_pixScreenshotMedium = pix;
249 return m_pixScreenshotMedium;
250 }
251
largeScreenshot()252 const QPixmap & KviThemeInfo::largeScreenshot()
253 {
254 if(!m_pixScreenshotLarge.isNull())
255 return m_pixScreenshotLarge;
256
257 QString szFileName = m_szDirectory;
258 szFileName.append(KVI_THEME_LARGE_SCREENSHOT_NAME);
259 QPixmap pix(szFileName);
260 if(pix.isNull())
261 return m_pixScreenshotLarge;
262 m_pixScreenshotLarge = pix;
263 return m_pixScreenshotLarge;
264 }
265
266 namespace KviTheme
267 {
saveScreenshots(KviThemeInfo & options,const QString & szOriginalScreenshotPath)268 bool saveScreenshots(KviThemeInfo & options, const QString & szOriginalScreenshotPath)
269 {
270 QImage pix(szOriginalScreenshotPath);
271 if(pix.isNull())
272 {
273 options.setLastError(__tr2qs("Failed to load the specified screenshot image"));
274 return false;
275 }
276
277 QImage out;
278
279 QString szScreenshotPath = options.directory();
280
281 if(szScreenshotPath.isEmpty())
282 {
283 options.setLastError(__tr2qs("Invalid option"));
284 return false;
285 }
286
287 if(!pix.save(szScreenshotPath + KVI_THEME_LARGE_SCREENSHOT_NAME, "PNG"))
288 {
289 options.setLastError(__tr2qs("Failed to save the screenshot image"));
290 return false;
291 }
292
293 if(pix.width() > 600 || pix.height() > 450)
294 out = pix.scaled(640, 450, QIMAGE_SCALE_MIN, Qt::SmoothTransformation);
295 else
296 out = pix;
297
298 if(!out.save(szScreenshotPath + KVI_THEME_MEDIUM_SCREENSHOT_NAME, "PNG"))
299 {
300 options.setLastError(__tr2qs("Failed to save the screenshot image"));
301 return false;
302 }
303
304 if(pix.width() > 300 || pix.height() > 225)
305 out = pix.scaled(300, 225, QIMAGE_SCALE_MIN, Qt::SmoothTransformation);
306 else
307 out = pix;
308
309 if(!out.save(szScreenshotPath + KVI_THEME_SMALL_SCREENSHOT_NAME, "PNG"))
310 {
311 options.setLastError(__tr2qs("Failed to save the screenshot image"));
312 return false;
313 }
314
315 return true;
316 }
317
installedThemeDirectories(QStringList & slThemes,KviThemeInfo::Location eLocation)318 void installedThemeDirectories(QStringList & slThemes, KviThemeInfo::Location eLocation)
319 {
320 QString szThemePath;
321 switch(eLocation)
322 {
323 case KviThemeInfo::Builtin:
324 g_pApp->getGlobalKvircDirectory(szThemePath, KviApplication::Themes);
325 break;
326 case KviThemeInfo::User:
327 g_pApp->getLocalKvircDirectory(szThemePath, KviApplication::Themes);
328 break;
329 default:
330 return;
331 break;
332 }
333
334 QDir d(szThemePath);
335 QStringList sl = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
336
337 for(auto & it : sl)
338 slThemes.append(it);
339 }
340 };
341