Finished chess animator.
[tagua/yd.git] / src / pref_theme.cpp
blobf0de5e2a9d880cd974005cdbf42b089cb0f25ca7
1 /*
2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@sns.it>
3 (c) 2006 Maurizio Monge <maurizio.monge@kdemail.net>
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; either version 2 of the License, or
8 (at your option) any later version.
9 */
11 #include <QDateTime>
12 #include <QDir>
13 #include <QFileInfo>
14 #include <QStringList>
15 #include <QListWidgetItem>
16 #include <kstandarddirs.h>
17 #include "global.h"
18 #include "luaapi/loader.h"
19 #include "variants/variants.h"
20 #include "kboard.h"
21 #include "pref_theme.h"
23 class PrefTheme::ThemeInfo {
24 public:
25 QString file_name;
26 QString name;
27 QString description;
28 QStringList variants;
29 QDateTime last_modified;
31 ThemeInfo(const QString& f, const QString& n,
32 const QString& d, const QStringList& v, const QDateTime& t)
33 : file_name(f)
34 , name(n)
35 , description(d)
36 , variants(v)
37 , last_modified(t) {}
40 PrefTheme::ThemeInfoList PrefTheme::to_theme_info_list(const QStringList& files, const Settings& s) {
41 std::map<QString, ThemeInfo> cache;
43 SettingArray themes = s.group("themes").array("theme");
44 foreach (Settings s_theme, themes) {
45 QStringList variants;
46 SettingArray s_variants = s_theme.group("variants").array("variant");
47 foreach (Settings s_var, s_variants) {
48 variants.append(s_var["name"].value<QString>());
50 QString f = s_theme["file-name"].value<QString>();
51 cache.insert(std::make_pair(f, ThemeInfo(f,
52 s_theme["name"].value<QString>(),
53 s_theme["description"].value<QString>(),
54 variants,
55 QDateTime::fromString(s_theme["last-modified"].value<QString>()))));
58 ThemeInfoList allluafiles;
59 ThemeInfoList retv;
60 bool updated = false;
61 for(int i=0;i<files.size();i++) {
62 QDateTime lm = QFileInfo(files[i]).lastModified();
63 std::map<QString, ThemeInfo>::iterator it = cache.find(files[i]);
65 if(it != cache.end() && it->second.last_modified == lm) {
66 if(!it->second.name.isEmpty())
67 retv << it->second;
69 else {
70 updated = true;
71 LuaApi::Loader l(NULL);
72 l.runFile(files[i]);
74 if(l.error()) {
75 allluafiles << ThemeInfo(files[i], QString(), QString(), QStringList(), lm );
76 std::cout << " --> Error loading " << files[i] << std::endl
77 << l.errorString() << std::endl;
78 continue;
81 QString name = l.getString("name");
82 if(name.isEmpty()) {
83 allluafiles << ThemeInfo(files[i], QString(), QString(), QStringList(), lm );
84 continue;
87 ThemeInfo t(files[i], name, l.getString("description"), l.getStringList("variants"), lm);
88 retv << t;
89 allluafiles << t;
93 if(updated) {
94 SettingArray themes = s.group("themes").newArray("theme");
96 for (int i = 0; i < allluafiles.size(); i++) {
97 Settings s_theme = themes.append();
98 s_theme["file-name"] = allluafiles[i].file_name;
99 s_theme["name"] = allluafiles[i].name;
100 s_theme["description"] = allluafiles[i].description;
102 SettingArray variants = s_theme.group("variants").newArray("variant");
103 foreach (QString v, allluafiles[i].variants) {
104 Settings s_var = variants.append();
105 s_var["name"] = v;
108 s_theme["last-modified"] = allluafiles[i].last_modified.toString();
112 return retv;
115 OptList PrefTheme::get_file_options(const QString& f) {
116 if(boost::shared_ptr<OptList> o = m_new_theme_options[f])
117 return *o;
119 LuaApi::Loader l(NULL);
120 l.runFile(f);
122 boost::shared_ptr<OptList> o = boost::shared_ptr<OptList>(new OptList(l.getOptList("options")));
123 SettingMap<QString> s_lua = settings.group("lua-settings").map<QString>("entry", "file-name");
124 Settings entry = s_lua.insert(f);
125 options_list_load_from_settings(*o, entry.group("options"));
127 m_new_theme_options[f] = o;
128 return *o;
131 PrefTheme::PrefTheme(QWidget *parent)
132 : QWidget(parent)
133 , m_pieces_opt_widget(NULL)
134 , m_squares_opt_widget(NULL) {
135 setupUi(this);
136 listPieces->setSelectionMode(QAbstractItemView::SingleSelection);
137 listSquares->setSelectionMode(QAbstractItemView::SingleSelection);
138 connect(listPieces, SIGNAL(itemSelectionChanged()), this, SLOT(piecesThemeChanged()));
139 connect(listSquares, SIGNAL(itemSelectionChanged()), this, SLOT(squaresThemeChanged()));
140 connect(checkPieces, SIGNAL(toggled(bool)), this, SLOT(piecesThemeChecked(bool)));
141 connect(checkSquares, SIGNAL(toggled(bool)), this, SLOT(squaresThemeChecked(bool)));
142 connect(comboVariant, SIGNAL(currentIndexChanged(int)), this, SLOT(variantChanged()));
143 m_pieces_opt_layout = new QHBoxLayout(widgetPieces);
144 m_pieces_opt_layout->setMargin(0);
145 m_squares_opt_layout = new QHBoxLayout(widgetSquares);
146 m_squares_opt_layout->setMargin(0);
148 MasterSettings s(".kboard_config_cache");
150 KStandardDirs* dirs = KGlobal::dirs();
151 m_pieces_themes = to_theme_info_list(
152 dirs->findAllResources("appdata", "themes/Pieces/*.lua", KStandardDirs::Recursive),
153 s.group("pieces"));
154 m_squares_themes = to_theme_info_list(
155 dirs->findAllResources("appdata", "themes/Squares/*.lua", KStandardDirs::Recursive),
156 s.group("squares"));
158 const Variant::Variants& all = Variant::allVariants();
159 for(Variant::Variants::const_iterator it = all.begin(); it != all.end(); ++it)
160 comboVariant->addItem(it->first, QVariant(it->first));
162 variantChanged();
165 PrefTheme::~PrefTheme() {
169 void PrefTheme::apply() {
170 SettingMap<QString> variants = settings.group("variants").map<QString>("variant", "name");
172 for(std::map<QString, QString>::iterator it = m_new_piece_themes.begin();
173 it != m_new_piece_themes.end(); ++it) {
174 Settings var = variants.insert(it->first);
175 var["pieces-theme"] = it->second;
177 for(std::map<QString, bool>::iterator it = m_new_use_def_pieces.begin();
178 it != m_new_use_def_pieces.end(); ++it) {
179 Settings var = variants.insert(it->first);
180 var["use-def-pieces"] = it->second;
182 for(std::map<QString, QString>::iterator it = m_new_square_themes.begin();
183 it != m_new_square_themes.end(); ++it) {
184 Settings var = variants.insert(it->first);
185 var["squares-theme"] = it->second;
187 for(std::map<QString, bool>::iterator it = m_new_use_def_squares.begin();
188 it != m_new_use_def_squares.end(); ++it) {
189 Settings var = variants.insert(it->first);
190 var["use-def-squares"] = it->second;
193 for(std::map<QString, boost::shared_ptr<OptList> >::iterator it = m_new_theme_options.begin();
194 it != m_new_theme_options.end(); ++it) {
195 SettingMap<QString> s_lua = settings.group("lua-settings").map<QString>("entry", "file-name");
196 Settings entry = s_lua.insert(it->first);
197 options_list_save_to_settings(*it->second, entry.group("options"));
201 void PrefTheme::update_list_view(QListWidget* list, const ThemeInfoList& themes,
202 QString variant, QString settings) {
203 list->clear();
205 int selected = 0;
206 QListWidgetItem *prev_sel = 0;
208 for(int i=0;i<themes.size();i++) {
209 bool ok1 = themes[i].variants.contains(variant, Qt::CaseInsensitive);
210 bool ok2 = themes[i].variants.contains(variant+"[default]", Qt::CaseInsensitive);
211 if(!ok1 && !ok2)
212 continue;
214 int ok = themes[i].file_name == settings ? 3 : ok2 ? 2 : 1;
215 QListWidgetItem *w = new QListWidgetItem(themes[i].name, list);
217 w->setData(Qt::UserRole, i);
218 if(ok > selected) {
219 if(prev_sel)
220 list->setItemSelected(prev_sel, false);
221 list->setItemSelected(w, true);
222 prev_sel = w;
223 selected = ok;
228 void PrefTheme::variantChanged() {
229 QString c = comboVariant->itemData(comboVariant->currentIndex()).toString();
230 VariantInfo *vi = Variant::variant(c);
231 if(!vi) {
232 checkPieces->hide();
233 listPieces->clear();
234 listPieces->setEnabled(false);
235 labelPieces->setText(QString());
236 labelPieces->setEnabled(false);
237 checkSquares->hide();
238 listSquares->clear();
239 listSquares->setEnabled(false);
240 labelSquares->setText(QString());
241 labelSquares->setEnabled(false);
242 return;
245 QString vname = vi->name();
246 QString vproxy = vi->themeProxy();
247 SettingMap<QString> variants = settings.group("variants").map<QString>("variant", "name");
248 Settings var = variants.insert(vname);
250 bool ck = vname != vproxy;
251 checkSquares->setVisible(ck);
252 checkPieces->setVisible(ck);
253 if(ck) {
254 bool dp = m_new_use_def_pieces.count(vname) ? m_new_use_def_pieces[vname]
255 : (var["use-def-pieces"] | true).value();
256 bool ds = m_new_use_def_squares.count(vname) ? m_new_use_def_squares[vname]
257 : (var["use-def-squares"] | true).value();
258 checkPieces->setText("Same as "+vproxy);
259 checkPieces->setChecked(dp);
260 listPieces->setEnabled(!dp);
261 labelPieces->setEnabled(!dp);
262 checkSquares->setText("Same as "+vproxy);
263 checkSquares->setChecked(ds);
264 listSquares->setEnabled(!ds);
265 labelSquares->setEnabled(!ds);
267 else {
268 listPieces->setEnabled(true);
269 labelPieces->setEnabled(true);
270 listSquares->setEnabled(true);
271 labelSquares->setEnabled(true);
274 QString pth = m_new_piece_themes.count(vname) ? m_new_piece_themes[vname]
275 : (var["pieces-theme"] | QString()).value();
276 QString sth = m_new_square_themes.count(vname) ? m_new_square_themes[vname]
277 : (var["squares-theme"] | QString()).value();
278 update_list_view(listPieces, m_pieces_themes, vproxy, pth);
279 update_list_view(listSquares, m_squares_themes, vproxy, sth);
282 void PrefTheme::piecesThemeChanged() {
283 QList<QListWidgetItem *> l = listPieces->selectedItems();
284 if(!l.isEmpty()) {
285 int i = l[0]->data(Qt::UserRole).toInt();
286 if(i>=0 && i<m_pieces_themes.size()) {
287 labelPieces->setText(m_pieces_themes[i].description);
289 QString c = comboVariant->itemData(comboVariant->currentIndex()).toString();
290 VariantInfo *vi = Variant::variant(c);
291 if(vi)
292 m_new_piece_themes[vi->name()] = m_pieces_themes[i].file_name;
294 if(m_pieces_opt_widget) {
295 delete m_pieces_opt_widget;
296 m_pieces_opt_widget = NULL;
298 OptList ol = get_file_options(m_pieces_themes[i].file_name);
299 if(ol.size() != 0) {
300 m_pieces_opt_widget = new OptionWidget(ol, widgetPieces);
301 m_pieces_opt_layout->addWidget(m_pieces_opt_widget);
303 return;
306 labelPieces->setText(QString());
309 void PrefTheme::piecesThemeChecked(bool ck) {
310 listPieces->setEnabled(!ck);
311 labelPieces->setEnabled(!ck);
313 QString c = comboVariant->itemData(comboVariant->currentIndex()).toString();
314 VariantInfo *vi = Variant::variant(c);
315 if(vi)
316 m_new_use_def_pieces[vi->name()] = ck;
319 void PrefTheme::squaresThemeChanged() {
320 QList<QListWidgetItem *> l = listSquares->selectedItems();
321 if(!l.isEmpty()) {
322 int i = l[0]->data(Qt::UserRole).toInt();
323 if(i>=0 && i<m_squares_themes.size()) {
324 labelSquares->setText(m_squares_themes[i].description);
326 QString c = comboVariant->itemData(comboVariant->currentIndex()).toString();
327 VariantInfo *vi = Variant::variant(c);
328 if(vi)
329 m_new_square_themes[vi->name()] = m_squares_themes[i].file_name;
331 if(m_squares_opt_widget) {
332 delete m_squares_opt_widget;
333 m_squares_opt_widget = NULL;
335 OptList ol = get_file_options(m_squares_themes[i].file_name);
336 if(ol.size() != 0) {
337 m_squares_opt_widget = new OptionWidget(ol, widgetSquares);
338 m_squares_opt_layout->addWidget(m_squares_opt_widget);
340 return;
343 labelSquares->setText(QString());
346 void PrefTheme::squaresThemeChecked(bool ck) {
347 listSquares->setEnabled(!ck);
348 labelSquares->setEnabled(!ck);
350 QString c = comboVariant->itemData(comboVariant->currentIndex()).toString();
351 VariantInfo *vi = Variant::variant(c);
352 if(vi)
353 m_new_use_def_squares[vi->name()] = ck;
356 QString PrefTheme::getBestTheme(VariantInfo* vi, ThemeType type) {
357 QString group = type == Pieces ? "pieces" :
358 type == Squares ? "squares" : "figurines";
359 QString pattern = type == Pieces ? "themes/Pieces/*.lua" :
360 type == Squares ? "themes/Squares/*.lua" : "themes/Figurines/*.lua";
361 QString tag = group + "-theme";
362 QString deftag = "use-def-" + group;
363 QString v = vi->name();
364 SettingMap<QString> variants = settings.group("variants").map<QString>("variant", "name");
365 Settings var = variants.insert(v);
366 if (v != vi->themeProxy() &&
367 (var[deftag] | true) )
368 v = vi->themeProxy();
370 if (var[tag])
371 return var[tag].value<QString>();
373 MasterSettings s(".kboard_config_cache.xml");
374 KStandardDirs* dirs = KGlobal::dirs();
375 ThemeInfoList themes = to_theme_info_list(dirs->findAllResources("appdata", pattern, KStandardDirs::Recursive), s.group(group));
377 int best = 0;
378 QString retv;
379 for(int i=0;i<themes.size();i++) {
380 bool ok1 = themes[i].variants.contains(v, Qt::CaseInsensitive);
381 bool ok2 = themes[i].variants.contains(v+"[default]", Qt::CaseInsensitive);
382 if(!ok1 && !ok2)
383 continue;
385 int ok = ok2 ? 2 : 1;
386 if(ok > best) {
387 retv = themes[i].file_name;
388 best = ok;
392 if (!retv.isEmpty())
393 var[tag] = retv;
394 return retv;
397 #include "pref_theme.moc"