1 //=============================================================================
2 //
3 // File : libkvitheme.cpp
4 // Creation date : Sat 30 Dec 2006 14:54:56 by Szymon Stefanek
5 //
6 // This file is part of the KVIrc IRC client distribution
7 // Copyright (C) 2006-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 "ThemeManagementDialog.h"
26 #include "ThemeFunctions.h"
27
28 #include "KviKvsArrayCast.h"
29 #include "KviMessageBox.h"
30 #include "KviModule.h"
31 #include "KviLocale.h"
32 #include "KviCommandFormatter.h"
33 #include "KviError.h"
34 #include "kvi_out.h"
35 #include "KviMainWindow.h"
36 #include "KviIconManager.h"
37 #include "KviConfigurationFile.h"
38 #include "kvi_sourcesdate.h"
39 #include "KviFileUtils.h"
40 #include "KviFileDialog.h"
41 #include "KviTheme.h"
42
43 #include <QFileInfo>
44 #include <QMessageBox>
45
46 QRect g_rectManagementDialogGeometry(0, 0, 0, 0);
47
48 /*
49 @doc: theme.install
50 @type:
51 command
52 @title:
53 theme.install
54 @short:
55 Shows the theme management editor
56 @syntax:
57 theme.install <package_path:string>
58 @description:
59 Attempts to install the themes in the package specified by <package_path>.
60 */
61
theme_kvs_cmd_install(KviKvsModuleCommandCall * c)62 static bool theme_kvs_cmd_install(KviKvsModuleCommandCall * c)
63 {
64 QString szThemePackFile;
65
66 KVSM_PARAMETERS_BEGIN(c)
67 KVSM_PARAMETER("package_path", KVS_PT_STRING, 0, szThemePackFile)
68 KVSM_PARAMETERS_END(c)
69
70 QString szError;
71 if(!ThemeFunctions::installThemePackage(szThemePackFile, szError))
72 {
73 c->error(__tr2qs_ctx("Error installing theme package: %Q", "theme"), &szError);
74 return false;
75 }
76
77 return true;
78 }
79
80 /*
81 @doc: theme.apply
82 @type:
83 command
84 @title:
85 theme.apply
86 @short:
87 Apply a theme.
88 @syntax:
89 theme.apply [-b] [-e] [-u] <theme:string>
90 @switches:
91 !sw: -e | --external
92 <theme> is an absolute directory containing a theme
93 !sw: -b | --builtin
94 <theme> is the name of a builtin theme (a subdirectory of the KVIrc global themes directory)
95 !sw: -u | --user
96 <theme> is the name of a user theme (a subdirectory of the KVIrc local themes directory)
97 @description:
98 Attempts to apply the global theme specified by <theme>.
99 If the -b switch is present then <theme> is assumed to be a name of
100 a builtin installed theme (a subdirectory of the KVIrc global themes directory).
101 If the -l switch is present then <theme> is assumed to be a name of
102 a user installed theme (a subdirectory of the KVIrc local themes directory).
103 If the -e switch is present then <theme> is assumed to be an absolute
104 directory containing the theme data.
105 If no switch is present then KVIrc tries to determine automatically the
106 type of theme (user, builtin or external).
107 */
108
theme_kvs_cmd_apply(KviKvsModuleCommandCall * c)109 static bool theme_kvs_cmd_apply(KviKvsModuleCommandCall * c)
110 {
111 QString szTheme;
112
113 KVSM_PARAMETERS_BEGIN(c)
114 KVSM_PARAMETER("theme", KVS_PT_STRING, 0, szTheme)
115 KVSM_PARAMETERS_END(c)
116
117 KviThemeInfo out;
118 KviThemeInfo::Location eLocation = KviThemeInfo::Auto;
119
120 if(c->switches()->find('b', "builtin"))
121 eLocation = KviThemeInfo::Builtin;
122 else if(c->switches()->find('e', "external"))
123 eLocation = KviThemeInfo::External;
124 else if(c->switches()->find('u', "user"))
125 eLocation = KviThemeInfo::User;
126
127 if(!KviTheme::apply(szTheme, eLocation, out))
128 {
129 QString szErr = out.lastError();
130 c->error(__tr2qs_ctx("Failed to apply theme: %Q", "theme"), &szErr);
131 return false;
132 }
133
134 return true;
135 }
136
137 /*
138 @doc: theme.info
139 @type:
140 function
141 @title:
142 $theme.info
143 @short:
144 Return info about a user defined theme.
145 @description:
146 Returns a hash with information about the global theme specified by <theme>.
147 */
148
theme_kvs_fnc_info(KviKvsModuleFunctionCall * c)149 static bool theme_kvs_fnc_info(KviKvsModuleFunctionCall * c)
150 {
151 QString szTheme;
152
153 KVSM_PARAMETERS_BEGIN(c)
154 KVSM_PARAMETER("theme", KVS_PT_STRING, 0, szTheme)
155 KVSM_PARAMETERS_END(c)
156
157 KviKvsHash * pHash = new KviKvsHash();
158 c->returnValue()->setHash(pHash);
159
160 KviThemeInfo theme;
161 if(!theme.load(szTheme, KviThemeInfo::Auto))
162 {
163 c->warning(__tr2qs_ctx("The theme package '%Q' doesn't exist", "theme"), &szTheme);
164 return true;
165 }
166
167 pHash->set("name", new KviKvsVariant(theme.name()));
168 pHash->set("version", new KviKvsVariant(theme.version()));
169 pHash->set("author", new KviKvsVariant(theme.author()));
170 pHash->set("description", new KviKvsVariant(theme.description()));
171 return true;
172 }
173
174 /*
175 @doc: theme.screenshot
176 @type:
177 command
178 @title:
179 theme.screenshot
180 @short:
181 Makes a screenshot of the KVIrc window
182 @syntax:
183 theme.screenshot [file_name_path:string]
184 @description:
185 Makes a screenshot of the KVIrc main window
186 and saves it in the specified file. If [file_name_path]
187 is not specified then a save file dialog is shown.
188 */
189
theme_kvs_cmd_screenshot(KviKvsModuleCommandCall * c)190 static bool theme_kvs_cmd_screenshot(KviKvsModuleCommandCall * c)
191 {
192 QString szFileName;
193
194 KVSM_PARAMETERS_BEGIN(c)
195 KVSM_PARAMETER("file_name_path", KVS_PT_STRING, KVS_PF_OPTIONAL, szFileName)
196 KVSM_PARAMETERS_END(c)
197
198 KviFileUtils::adjustFilePath(szFileName);
199
200 QString szTmp;
201 c->enterBlockingSection();
202
203 bool bResult = KviFileDialog::askForSaveFileName(
204 szTmp,
205 __tr2qs_ctx("Enter a Filename - KVIrc", "theme"), //dialog header title
206 szFileName,
207 "*.png",
208 false,
209 false,
210 true,
211 g_pMainWindow);
212
213 if(!c->leaveBlockingSection())
214 return false; // need to stop immediately
215
216 if(!bResult)
217 return true;
218
219 szFileName = szTmp;
220
221 if(szFileName.isEmpty())
222 return true; // done
223
224 KviFileUtils::adjustFilePath(szFileName);
225 if(QFileInfo(szFileName).suffix() != "png")
226 szFileName += ".png";
227
228 QString szError;
229 if(!ThemeFunctions::makeKVIrcScreenshot(szFileName))
230 {
231 c->error(__tr2qs_ctx("Error capturing and saving screenshot!", "theme"));
232 return false;
233 }
234
235 return true;
236 }
237
238 /*
239 @doc: theme.dialog
240 @type:
241 command
242 @title:
243 theme.dialog
244 @short:
245 Shows the theme theme management editor
246 @syntax:
247 theme.dialog [-t]
248 @description:
249 Shows the theme theme management editor[br]
250 If the [-t] switch is used, the dialog is opened as toplevel window,
251 otherwise it is opened as part of the current frame window.[br]
252 */
253
theme_kvs_cmd_dialog(KviKvsModuleCommandCall * c)254 static bool theme_kvs_cmd_dialog(KviKvsModuleCommandCall * c)
255 {
256 ThemeManagementDialog::display(c->hasSwitch('t', "toplevel"));
257 return true;
258 }
259
260 /*
261 @doc: theme.pack
262 @type:
263 command
264 @title:
265 theme.pack
266 @short:
267 Creates a kvt package containing a set of themes
268 @syntax:
269 theme.pack <package_path> <package_name> <package_version> <package_description> <package_author> <package_image> <themes>
270 @description:
271 Creates a *.kvt package containing a set of KVIrc themes.[br]
272 <package_path> is the absolute path and file name of the package that should be saved.[br]
273 <package_name> is the visible name of the package (something like "My Theme Set").[br]
274 <package_version> is the version of the package in the form X.Y.Z.[br]
275 <package_description> is a textual description of the package.
276 <package_author> is the name of the person that is creating the package (NOT necessarily the themes contained within).
277 <package_image> is the path of an image to be used as package representative image. If the package is going
278 to contain a single theme you may specify the theme's screenshot here. Pass an empty string if you
279 don't want an image to be stored in the package.
280 <theme> is a either a single path to a directory containing a theme as it's exported by KVIrc,
281 or an array of such paths.
282 */
283
theme_kvs_cmd_pack(KviKvsModuleCommandCall * c)284 static bool theme_kvs_cmd_pack(KviKvsModuleCommandCall * c)
285 {
286 QString szPath, szName, szVersion, szDescription, szAuthor, szImage;
287
288 KviKvsArrayCast aCast;
289
290 KVSM_PARAMETERS_BEGIN(c)
291 KVSM_PARAMETER("package_path", KVS_PT_NONEMPTYSTRING, 0, szPath)
292 KVSM_PARAMETER("package_name", KVS_PT_NONEMPTYSTRING, 0, szName)
293 KVSM_PARAMETER("package_version", KVS_PT_NONEMPTYSTRING, 0, szVersion)
294 KVSM_PARAMETER("package_description", KVS_PT_STRING, 0, szDescription)
295 KVSM_PARAMETER("package_author", KVS_PT_NONEMPTYSTRING, 0, szAuthor)
296 KVSM_PARAMETER("package_image", KVS_PT_STRING, 0, szImage)
297 KVSM_PARAMETER("theme", KVS_PT_ARRAYCAST, 0, aCast)
298 KVSM_PARAMETERS_END(c)
299
300 KviKvsArray * pArray = aCast.array();
301 if((!pArray) || (pArray->size() < 1))
302 {
303 c->error(__tr2qs_ctx("No themes specified", "theme"));
304 return false;
305 }
306
307 kvs_uint_t s = pArray->size();
308 QStringList lThemeList;
309
310 for(kvs_uint_t i = 0; i < s; i++)
311 {
312 KviKvsVariant * v = pArray->at(i);
313 if(!v)
314 continue; // ?
315 QString szVal;
316 v->asString(szVal);
317 if(szVal.isEmpty())
318 continue;
319 lThemeList.append(szVal);
320 }
321
322 KviPointerList<KviThemeInfo> lThemeInfoList;
323 lThemeInfoList.setAutoDelete(true);
324
325 for(const auto & szTheme : lThemeList)
326 {
327 KviThemeInfo * pInfo = new KviThemeInfo();
328 if(!pInfo->load(szTheme, KviThemeInfo::External))
329 {
330 QString szErr = pInfo->lastError();
331 c->error(__tr2qs_ctx("Failed to load theme from directory %Q: %Q", "theme"), &szTheme, &szErr);
332 delete pInfo;
333 return false;
334 }
335
336 lThemeInfoList.append(pInfo);
337 }
338
339 if(lThemeInfoList.isEmpty())
340 {
341 c->error(__tr2qs_ctx("No themes specified: refusing to create an empty theme package", "theme"));
342 return false;
343 }
344
345 QString szError;
346
347 if(
348 ThemeFunctions::packageThemes(
349 szPath,
350 szName,
351 szVersion,
352 szDescription,
353 szAuthor,
354 szImage,
355 lThemeInfoList,
356 szError))
357 return true;
358
359 c->error(szError);
360 return false;
361 }
362
theme_module_init(KviModule * m)363 static bool theme_module_init(KviModule * m)
364 {
365 KVSM_REGISTER_SIMPLE_COMMAND(m, "dialog", theme_kvs_cmd_dialog);
366 KVSM_REGISTER_SIMPLE_COMMAND(m, "install", theme_kvs_cmd_install);
367 KVSM_REGISTER_SIMPLE_COMMAND(m, "apply", theme_kvs_cmd_apply);
368 KVSM_REGISTER_SIMPLE_COMMAND(m, "screenshot", theme_kvs_cmd_screenshot);
369 KVSM_REGISTER_SIMPLE_COMMAND(m, "pack", theme_kvs_cmd_pack);
370
371 KVSM_REGISTER_FUNCTION(m, "info", theme_kvs_fnc_info);
372
373 QString szBuf;
374 m->getDefaultConfigFileName(szBuf);
375 KviConfigurationFile cfg(szBuf, KviConfigurationFile::Read);
376 g_rectManagementDialogGeometry = cfg.readRectEntry("EditorGeometry", QRect(10, 10, 390, 440));
377
378 return true;
379 }
380
theme_module_cleanup(KviModule * m)381 static bool theme_module_cleanup(KviModule * m)
382 {
383 ThemeManagementDialog::cleanup();
384
385 QString szBuf;
386 m->getDefaultConfigFileName(szBuf);
387 KviConfigurationFile cfg(szBuf, KviConfigurationFile::Write);
388 cfg.writeEntry("EditorGeometry", g_rectManagementDialogGeometry);
389
390 return true;
391 }
392
theme_module_can_unload(KviModule *)393 static bool theme_module_can_unload(KviModule *)
394 {
395 return (!ThemeManagementDialog::instance());
396 }
397
398 KVIRC_MODULE(
399 "Theme", // module name
400 "4.0.0", // module version
401 "Copyright (C) 2006 Szymon Stefanek (pragma at kvirc dot net)", // author & (C)
402 "Theme management functions",
403 theme_module_init,
404 theme_module_can_unload,
405 0,
406 theme_module_cleanup,
407 "theme")
408