2 Copyright (c) 2006 Paolo Capriotti <p.capriotti@gmail.com>
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 <QListWidgetItem>
14 #include <QStringList>
17 #include <KStandardDirs>
20 #include "luaapi/loader.h"
21 #include "mastersettings.h"
22 #include "pref_theme.h"
26 typedef boost::shared_ptr
<Variant
> VariantPtr
;
28 PrefTheme::ThemeInfoList
PrefTheme::to_theme_info_list(const QStringList
& files
, const Settings
& s
) {
29 //std::cout << "about to examine " << files.size() << " desktop files" << std::endl;
30 std::map
<QString
, ThemeInfo
> cached_info
;
32 SettingArray themes
= s
.group("themes").array("theme");
33 foreach (Settings s_theme
, themes
) {
34 ThemeInfo info
= ThemeInfo::fromSettings(s_theme
);
35 cached_info
[info
.desktopFile
] = info
;
38 ThemeInfoList all_themes
;
41 for(int i
= 0; i
< files
.size(); i
++) {
42 QFileInfo
file_info(files
[i
]);
43 std::map
<QString
, ThemeInfo
>::iterator it
= cached_info
.find(files
[i
]);
45 if (it
!= cached_info
.end()
47 && it
->second
.last_modified
== file_info
.lastModified() ) {
48 all_themes
<< it
->second
;
49 cached_info
.erase(it
);
54 ThemeInfo theme_info
= ThemeInfo::fromDesktopFile(files
[i
]);
55 all_themes
<< theme_info
;
57 if (theme_info
.name
.isEmpty())
58 kError() << "No name property in" << files
[i
];
62 if(!cached_info
.empty())
65 /* rewrite the cached configuration */
67 SettingArray themes
= s
.group("themes").newArray("theme");
69 for (int i
= 0; i
< all_themes
.size(); i
++) {
70 Settings s_theme
= themes
.append();
71 all_themes
[i
].save(s_theme
);
79 OptList
PrefTheme::get_file_options(const QString
& f
, bool reload_defaults
) {
80 //std::cout << "get file options for " << f << std::endl;
82 if(!reload_defaults
) {
83 std::map
<QString
, OptList
>::iterator it
= m_new_theme_options
.find(f
);
85 if(it
!= m_new_theme_options
.end())
89 LuaApi::Loader lua_context
;
90 lua_context
.runFile(f
);
92 if(lua_context
.error()) {
93 kError() << lua_context
.errorString();
94 lua_context
.clearError();
96 m_new_theme_options
[f
] = OptList();
100 OptList o
= lua_context
.getValue
<OptList
>("options", 0, NULL
, true);
101 if(lua_context
.error()) {
102 kError() << lua_context
.errorString();
103 lua_context
.clearError();
106 if(!reload_defaults
) {
107 SettingMap
<QString
> s_lua
= settings().group("lua-settings").map
<QString
>("entry", "file-name");
108 Settings entry
= s_lua
.insert(f
);
109 options_list_load_from_settings(o
, entry
.group("options"));
111 m_new_theme_options
[f
] = o
;
117 int PrefTheme::theme_ok_for_variant(const ThemeInfo
& theme_info
, const QString
& variant_name
) {
118 if(theme_info
.variants
.contains(variant_name
+"[default]", Qt::CaseInsensitive
))
120 if(theme_info
.variants
.contains(variant_name
, Qt::CaseInsensitive
))
122 if(theme_info
.variants
.contains("any[default]", Qt::CaseInsensitive
))
124 if(theme_info
.variants
.contains("any", Qt::CaseInsensitive
))
130 PrefTheme::PrefTheme(const QString
& currentVariant
, QWidget
*parent
)
136 c
= new Category(NULL
, this);
137 m_categories
["pieces"] = c
;
138 tabWidget
->addTab(c
, "&Pieces");
140 c
= new Category(NULL
, this);
141 m_categories
["squares"] = c
;
142 tabWidget
->addTab(c
, "&Squares");
144 c
= new Category(NULL
, this);
145 m_categories
["controls"] = c
;
146 tabWidget
->addTab(c
, "&Controls");
148 MasterSettings
cached_theme_info("tagua_config_cache.xml");
149 connect(comboVariant
, SIGNAL(currentIndexChanged(int)), this, SLOT(variantChanged()));
151 for(CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
152 Category
* c
= cit
->second
;
154 c
->m_list
->setSelectionMode(QAbstractItemView::SingleSelection
);
155 connect(c
->m_list
, SIGNAL(itemSelectionChanged()), c
, SLOT(themeChanged()));
156 connect(c
->m_check
, SIGNAL(toggled(bool)), c
, SLOT(themeChecked(bool)));
157 c
->m_opt_layout
= new QHBoxLayout(c
->m_widget
);
158 c
->m_opt_layout
->setMargin(0);
160 c
->m_themes
= to_theme_info_list(
161 KGlobal::dirs()->findAllResources("appdata",
162 "themes/"+cit
->first
+"/*.desktop",
163 KStandardDirs::Recursive
),
164 cached_theme_info
.group(cit
->first
)
167 //std::cout << "loaded " << c->m_themes.size() << " themes" << std::endl;
170 KService::List all
= Variants::self().all();
173 foreach (KService::Ptr service
, all
) {
174 if (service
->name() == currentVariant
) {
177 comboVariant
->addItem(service
->name(), QVariant(service
->name()));
182 comboVariant
->setCurrentIndex(current
);
187 PrefTheme::~PrefTheme() {
191 void PrefTheme::apply() {
192 SettingMap
<QString
> variants
= settings().group("variants").map
<QString
>("variant", "name");
194 for(CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
195 Category
* c
= cit
->second
;
197 for(std::map
<QString
, QString
>::iterator it
= c
->m_new_themes
.begin();
198 it
!= c
->m_new_themes
.end(); ++it
) {
199 Settings var
= variants
.insert(it
->first
);
200 var
[cit
->first
+"-theme"] = it
->second
;
202 for(std::map
<QString
, bool>::iterator it
= c
->m_new_use_def
.begin();
203 it
!= c
->m_new_use_def
.end(); ++it
) {
204 Settings var
= variants
.insert(it
->first
);
205 var
[cit
->first
+"-use-def"] = it
->second
;
209 for(std::map
<QString
, OptList
>::iterator it
= m_new_theme_options
.begin();
210 it
!= m_new_theme_options
.end(); ++it
) {
211 SettingMap
<QString
> s_lua
= settings().group("lua-settings").map
<QString
>("entry", "file-name");
212 Settings entry
= s_lua
.insert(it
->first
);
213 options_list_save_to_settings(it
->second
, entry
.group("options"));
217 void PrefTheme::update_list_view(QListWidget
* list
, const ThemeInfoList
& themes
,
218 QString variant_name
, QString settings_theme
) {
222 QListWidgetItem
*item_to_select
= NULL
;
224 for (int i
= 0; i
< themes
.size(); i
++) {
225 int ok
= theme_ok_for_variant(themes
[i
], variant_name
);
229 ok
= (themes
[i
].desktopFile
== settings_theme
) ? 5 : ok
;
230 QListWidgetItem
*list_item
= new QListWidgetItem(themes
[i
].name
, list
);
232 list_item
->setData(Qt::UserRole
, i
);
233 if(ok
> selected_ok
) {
234 item_to_select
= list_item
;
240 list
->setItemSelected(item_to_select
, true);
243 void PrefTheme::variantChanged() {
244 QString category
= comboVariant
->itemData(comboVariant
->currentIndex()).toString();
245 KService::Ptr service
= Variants::self().get(category
);
248 for (CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
249 Category
* c
= cit
->second
;
253 c
->m_list
->setEnabled(false);
254 c
->m_label
->setText(QString());
255 c
->m_label
->setEnabled(false);
261 QString variant_name
= service
->name();
262 QString variant_proxy
= service
->property("X-Tagua-Proxy").toString();
263 SettingMap
<QString
> variants
= settings().group("variants").map
<QString
>("variant", "name");
264 Settings var
= variants
.insert(variant_name
);
265 bool check_proxy
= variant_name
!= variant_proxy
;
267 for(CategoryMap::iterator cit
= m_categories
.begin(); cit
!= m_categories
.end(); ++cit
) {
268 Category
* c
= cit
->second
;
270 c
->m_check
->setVisible(check_proxy
);
272 bool use_def
= c
->m_new_use_def
.count(variant_name
)
273 ? c
->m_new_use_def
[variant_name
]
274 : (var
[cit
->first
+"-use-def"] | true).value();
275 c
->m_check
->setText("Same as "+variant_proxy
);
276 c
->m_check
->setChecked(use_def
);
277 c
->m_list
->setEnabled(!use_def
);
278 c
->m_label
->setEnabled(!use_def
);
281 c
->m_list
->setEnabled(true);
282 c
->m_label
->setEnabled(true);
285 QString settings_theme
= c
->m_new_themes
.count(variant_name
)
286 ? c
->m_new_themes
[variant_name
]
287 : (var
[cit
->first
+"-theme"] | QString()).value();
288 update_list_view(c
->m_list
, c
->m_themes
, variant_proxy
, settings_theme
);
292 ThemeInfo
PrefTheme::getBestTheme(Variant
* vi
, const QString
& category
) {
293 QString tag
= category
+ "-theme";
294 QString deftag
= category
+ "-use-def";
295 QString variant_name
= vi
->name();
296 QString variant_proxy_name
= vi
->proxy();
297 SettingMap
<QString
> variants
= settings().group("variants").map
<QString
>("variant", "name");
298 if (variant_name
!= vi
->proxy() &&
299 (variants
.insert(variant_name
)[deftag
] | true) )
300 variant_name
= vi
->proxy();
302 Settings var_settings
= variants
.insert(variant_name
);
303 if (var_settings
[tag
] && QFile::exists(var_settings
[tag
].value
<QString
>()) ) {
305 // there is a theme in the settings, so pick this
306 ThemeInfo res
= ThemeInfo::fromDesktopFile(var_settings
[tag
].value
<QString
>());
307 if(theme_ok_for_variant(res
, variant_proxy_name
))
311 MasterSettings
cached_theme_info("tagua_config_cache.xml");
312 KStandardDirs
* std_dirs
= KGlobal::dirs();
313 ThemeInfoList themes
= to_theme_info_list(std_dirs
->findAllResources("appdata",
314 "themes/" + category
+ "/*.desktop",
315 KStandardDirs::Recursive
),
316 cached_theme_info
.group(category
));
320 for(int i
= 0; i
< themes
.size(); i
++) {
321 int ok
= theme_ok_for_variant(themes
[i
], variant_proxy_name
);
333 var_settings
[tag
] = retv
->desktopFile
;
336 return retv
? *retv
: ThemeInfo();
339 PrefThemeCategory::PrefThemeCategory(QWidget
* parent
, PrefTheme
* owner
)
343 , m_opt_widget(NULL
) {
345 m_reset
= new QAction(KIcon("eraser"), "&Reset to default", this);
346 m_reset
->setShortcut(Qt::CTRL
+Qt::Key_Z
);
347 connect(m_reset
, SIGNAL(triggered()), this, SLOT(reset()));
348 m_resetButton
->setDefaultAction(m_reset
);
349 m_resetButton
->setToolButtonStyle(Qt::ToolButtonIconOnly
);
352 void PrefThemeCategory::reset() {
356 QList
<QListWidgetItem
*> l
= m_list
->selectedItems();
360 int i
= l
[0]->data(Qt::UserRole
).toInt();
361 if (i
>= 0 && i
< m_themes
.size()) {
362 OptList ol
= m_parent
->get_file_options(m_themes
[i
].file_name
, true);
363 qobject_cast
<OptionWidget
*>(m_opt_widget
)->setValues(ol
);
367 void PrefThemeCategory::themeChanged() {
368 QList
<QListWidgetItem
*> l
= m_list
->selectedItems();
370 int i
= l
[0]->data(Qt::UserRole
).toInt();
371 if(i
>=0 && i
<m_themes
.size()) {
372 m_label
->setText(m_themes
[i
].description
);
374 QString c
= m_parent
->comboVariant
->itemData(m_parent
->comboVariant
->currentIndex()).toString();
375 KService::Ptr
service(Variants::self().get(c
));
377 m_new_themes
[service
->name()] = m_themes
[i
].desktopFile
;
383 OptList ol
= m_parent
->get_file_options(m_themes
[i
].file_name
);
384 if (ol
.size() != 0 && m_list
->isEnabled()) {
385 m_opt_widget
= new OptionWidget(ol
, m_widget
);
386 m_opt_layout
->addWidget(m_opt_widget
);
387 m_reset
->setEnabled(true);
390 m_reset
->setEnabled(false);
394 m_label
->setText(QString());
397 void PrefThemeCategory::themeChecked(bool ck
) {
398 m_list
->setEnabled(!ck
);
399 m_label
->setEnabled(!ck
);
401 QString c
= m_parent
->comboVariant
->itemData(m_parent
->comboVariant
->currentIndex()).toString();
402 KService::Ptr service
= Variants::self().get(c
);
404 m_new_use_def
[service
->name()] = ck
;