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.
13 #include <QStringList>
14 #include <QListWidgetItem>
16 #include <KDesktopFile>
17 #include <KStandardDirs>
19 #include "mastersettings.h"
20 #include "luaapi/loader.h"
21 #include "variants/variants.h"
23 #include "pref_theme.h"
25 void PrefTheme::read_theme_info(ThemeInfo
& info
, const QString
& desktopFile
) {
26 info
.desktopFile
= desktopFile
;
27 if (!KDesktopFile::isDesktopFile(desktopFile
)) {
31 KDesktopFile
theme(desktopFile
);
32 KConfigGroup themeData
= theme
.desktopGroup();
34 info
.name
= theme
.readName();
35 info
.description
= theme
.readComment();
36 info
.description
.replace("|", "\n");
37 info
.variants
= themeData
.readEntry("X-Tagua-Variants").split(QRegExp("\\s*,\\s*"));
38 info
.file_name
= themeData
.readEntry("X-Tagua-Script");
39 if (info
.file_name
.isEmpty()) {
40 // use a file with the same name as the .desktop, but with as .lua extension
41 info
.file_name
= desktopFile
;
42 info
.file_name
.replace(QRegExp("\\.desktop$"), ".lua");
45 QFileInfo
filePath(info
.file_name
);
46 QFileInfo
desktopPath(desktopFile
);
47 if (!filePath
.isAbsolute()) {
48 // the file is relative to the .desktop directory
49 info
.file_name
= QDir(desktopPath
.path()).filePath(info
.file_name
);
54 PrefTheme::ThemeInfoList
PrefTheme::to_theme_info_list(const QStringList
& files
, const Settings
& s
) {
55 std::cout
<< "about to examine " << files
.size() << " desktop files" << std::endl
;
56 std::map
<QString
, ThemeInfo
> cache
;
58 SettingArray themes
= s
.group("themes").array("theme");
59 foreach (Settings s_theme
, themes
) {
60 ThemeInfo info
= ThemeInfo::fromSettings(s_theme
);
61 cache
[info
.desktopFile
] = info
;
64 ThemeInfoList allluafiles
;
68 for(int i
= 0; i
< files
.size(); i
++) {
69 QDateTime lm
= QFileInfo(files
[i
]).lastModified();
70 std::map
<QString
, ThemeInfo
>::iterator it
= cache
.find(files
[i
]);
72 if (it
!= cache
.end() && it
->second
.last_modified
== lm
) {
73 if (!it
->second
.name
.isEmpty())
80 info
.last_modified
= lm
;
81 read_theme_info(info
, files
[i
]);
85 if (info
.name
.isEmpty()) {
86 ERROR("No name property in " << files
[i
]);
92 SettingArray themes
= s
.group("themes").newArray("theme");
94 for (int i
= 0; i
< allluafiles
.size(); i
++) {
95 Settings s_theme
= themes
.append();
96 allluafiles
[i
].save(s_theme
);
103 OptList
PrefTheme::get_file_options(const QString
& f
, bool reload_defaults
) {
105 if(boost::shared_ptr
<OptList
> o
= m_new_theme_options
[f
])
111 boost::shared_ptr
<OptList
> o(new OptList(l
.getValue
<OptList
>("options", 0, NULL
, true)));
113 ERROR(l
.errorString());
117 if(!reload_defaults
) {
118 SettingMap
<QString
> s_lua
= settings().group("lua-settings").map
<QString
>("entry", "file-name");
119 Settings entry
= s_lua
.insert(f
);
120 options_list_load_from_settings(*o
, entry
.group("options"));
122 m_new_theme_options
[f
] = o
;
127 PrefTheme::PrefTheme(QWidget
*parent
)
133 c
= new Category(NULL
, this);
134 m_categories
["pieces"] = c
;
135 tabWidget
->addTab(c
, "&Pieces");
137 c
= new Category(NULL
, this);
138 m_categories
["squares"] = c
;
139 tabWidget
->addTab(c
, "&Squares");
141 c
= new Category(NULL
, this);
142 m_categories
["controls"] = c
;
143 tabWidget
->addTab(c
, "&Controls");
145 MasterSettings
s(".tagua_config_cache.xml");
146 connect(comboVariant
, SIGNAL(currentIndexChanged(int)), this, SLOT(variantChanged()));
148 for(CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
149 Category
* c
= cit
->second
;
151 c
->m_list
->setSelectionMode(QAbstractItemView::SingleSelection
);
152 connect(c
->m_list
, SIGNAL(itemSelectionChanged()), c
, SLOT(themeChanged()));
153 connect(c
->m_check
, SIGNAL(toggled(bool)), c
, SLOT(themeChecked(bool)));
154 c
->m_opt_layout
= new QHBoxLayout(c
->m_widget
);
155 c
->m_opt_layout
->setMargin(0);
157 c
->m_themes
= to_theme_info_list(
158 KGlobal::dirs()->findAllResources("appdata", "themes/"+cit
->first
+"/*.desktop", KStandardDirs::Recursive
),
162 std::cout
<< "loaded " << c
->m_themes
.size() << " themes" << std::endl
;
165 const Variant::Variants
& all
= Variant::allVariants();
166 for(Variant::Variants::const_iterator it
= all
.begin(); it
!= all
.end(); ++it
)
167 comboVariant
->addItem(it
->first
, QVariant(it
->first
));
172 PrefTheme::~PrefTheme() {
176 void PrefTheme::apply() {
177 SettingMap
<QString
> variants
= settings().group("variants").map
<QString
>("variant", "name");
179 for(CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
180 Category
* c
= cit
->second
;
182 for(std::map
<QString
, QString
>::iterator it
= c
->m_new_themes
.begin();
183 it
!= c
->m_new_themes
.end(); ++it
) {
184 Settings var
= variants
.insert(it
->first
);
185 var
[cit
->first
+"-theme"] = it
->second
;
187 for(std::map
<QString
, bool>::iterator it
= c
->m_new_use_def
.begin();
188 it
!= c
->m_new_use_def
.end(); ++it
) {
189 Settings var
= variants
.insert(it
->first
);
190 var
[cit
->first
+"-use-def"] = it
->second
;
194 for(std::map
<QString
, boost::shared_ptr
<OptList
> >::iterator it
= m_new_theme_options
.begin();
195 it
!= m_new_theme_options
.end(); ++it
) {
196 SettingMap
<QString
> s_lua
= settings().group("lua-settings").map
<QString
>("entry", "file-name");
197 Settings entry
= s_lua
.insert(it
->first
);
198 options_list_save_to_settings(*it
->second
, entry
.group("options"));
202 void PrefTheme::update_list_view(QListWidget
* list
, const ThemeInfoList
& themes
,
203 QString variant
, QString settings_theme
) {
207 QListWidgetItem
*prev_sel
= 0;
209 for (int i
= 0; i
< themes
.size(); i
++) {
211 ok
= themes
[i
].variants
.contains("any", Qt::CaseInsensitive
) ? 1 : ok
;
212 ok
= themes
[i
].variants
.contains("any[default]", Qt::CaseInsensitive
) ? 2 : ok
;
213 ok
= themes
[i
].variants
.contains(variant
, Qt::CaseInsensitive
) ? 3 : ok
;
214 ok
= themes
[i
].variants
.contains(variant
+"[default]", Qt::CaseInsensitive
) ? 4 : ok
;
217 ok
= (themes
[i
].desktopFile
== settings_theme
) ? 5 : ok
;
218 QListWidgetItem
*w
= new QListWidgetItem(themes
[i
].name
, list
);
220 w
->setData(Qt::UserRole
, i
);
223 list
->setItemSelected(prev_sel
, false);
224 list
->setItemSelected(w
, true);
231 void PrefTheme::variantChanged() {
232 QString c
= comboVariant
->itemData(comboVariant
->currentIndex()).toString();
233 VariantInfo
*vi
= Variant::variant(c
);
235 for(CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
236 Category
* c
= cit
->second
;
240 c
->m_list
->setEnabled(false);
241 c
->m_label
->setText(QString());
242 c
->m_label
->setEnabled(false);
248 QString vname
= vi
->name();
249 QString vproxy
= vi
->themeProxy();
250 SettingMap
<QString
> variants
= settings().group("variants").map
<QString
>("variant", "name");
251 Settings var
= variants
.insert(vname
);
252 bool ck
= vname
!= vproxy
;
254 for(CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
255 Category
* c
= cit
->second
;
257 c
->m_check
->setVisible(ck
);
259 bool d
= c
->m_new_use_def
.count(vname
) ? c
->m_new_use_def
[vname
]
260 : (var
[cit
->first
+"-use-def"] | true).value();
261 c
->m_check
->setText("Same as "+vproxy
);
262 c
->m_check
->setChecked(d
);
263 c
->m_list
->setEnabled(!d
);
264 c
->m_label
->setEnabled(!d
);
267 c
->m_list
->setEnabled(true);
268 c
->m_label
->setEnabled(true);
271 QString th
= c
->m_new_themes
.count(vname
) ? c
->m_new_themes
[vname
]
272 : (var
[cit
->first
+"-theme"] | QString()).value();
273 update_list_view(c
->m_list
, c
->m_themes
, vproxy
, th
);
277 ThemeInfo
PrefTheme::getBestTheme(VariantInfo
* vi
, const QString
& category
) {
278 QString tag
= category
+ "-theme";
279 QString deftag
= category
+ "-use-def";
280 QString v
= vi
->name();
281 SettingMap
<QString
> variants
= settings().group("variants").map
<QString
>("variant", "name");
282 if (v
!= vi
->themeProxy() &&
283 (variants
.insert(v
)[deftag
] | true) )
284 v
= vi
->themeProxy();
286 Settings var
= variants
.insert(v
);
288 // there is a theme in the settings, so pick this
290 read_theme_info(res
, var
[tag
].value
<QString
>());
294 MasterSettings
s(".tagua_config_cache.xml");
295 KStandardDirs
* dirs
= KGlobal::dirs();
296 ThemeInfoList themes
= to_theme_info_list(dirs
->findAllResources("appdata", "themes/"+category
+"/*.desktop",
297 KStandardDirs::Recursive
), s
.group(category
));
298 std::cout
<< "found " << themes
.size() << " themes" << std::endl
;
302 for(int i
=0;i
<themes
.size();i
++) {
304 ok
= themes
[i
].variants
.contains("any", Qt::CaseInsensitive
) ? 1 : ok
;
305 ok
= themes
[i
].variants
.contains("any[default]", Qt::CaseInsensitive
) ? 2 : ok
;
306 ok
= themes
[i
].variants
.contains(v
, Qt::CaseInsensitive
) ? 3 : ok
;
307 ok
= themes
[i
].variants
.contains(v
+"[default]", Qt::CaseInsensitive
) ? 4 : ok
;
318 var
[tag
] = retv
->desktopFile
;
323 PrefThemeCategory::PrefThemeCategory(QWidget
* parent
, PrefTheme
* owner
)
327 , m_opt_widget(NULL
) {
329 m_reset
= new QAction(KIcon("eraser"), "&Reset to default", this);
330 m_reset
->setShortcut(Qt::CTRL
+Qt::Key_Z
);
331 connect(m_reset
, SIGNAL(triggered()), this, SLOT(reset()));
332 m_resetButton
->setDefaultAction(m_reset
);
333 m_resetButton
->setToolButtonStyle(Qt::ToolButtonIconOnly
);
336 void PrefThemeCategory::reset() {
340 QList
<QListWidgetItem
*> l
= m_list
->selectedItems();
344 int i
= l
[0]->data(Qt::UserRole
).toInt();
345 if (i
>= 0 && i
< m_themes
.size()) {
346 OptList ol
= m_parent
->get_file_options(m_themes
[i
].file_name
, true);
347 qobject_cast
<OptionWidget
*>(m_opt_widget
)->setValues(ol
);
351 void PrefThemeCategory::themeChanged() {
352 QList
<QListWidgetItem
*> l
= m_list
->selectedItems();
354 int i
= l
[0]->data(Qt::UserRole
).toInt();
355 if(i
>=0 && i
<m_themes
.size()) {
356 m_label
->setText(m_themes
[i
].description
);
358 QString c
= m_parent
->comboVariant
->itemData(m_parent
->comboVariant
->currentIndex()).toString();
359 VariantInfo
*vi
= Variant::variant(c
);
361 m_new_themes
[vi
->name()] = m_themes
[i
].desktopFile
;
367 OptList ol
= m_parent
->get_file_options(m_themes
[i
].file_name
);
369 m_opt_widget
= new OptionWidget(ol
, m_widget
);
370 m_opt_layout
->addWidget(m_opt_widget
);
371 m_reset
->setEnabled(true);
374 m_reset
->setEnabled(false);
378 m_label
->setText(QString());
381 void PrefThemeCategory::themeChecked(bool ck
) {
382 m_list
->setEnabled(!ck
);
383 m_label
->setEnabled(!ck
);
385 QString c
= m_parent
->comboVariant
->itemData(m_parent
->comboVariant
->currentIndex()).toString();
386 VariantInfo
*vi
= Variant::variant(c
);
388 m_new_use_def
[vi
->name()] = ck
;