2 * <one line to give the library's name and an idea of what it does.>
3 * Copyright (C) 2014 Todor <email>
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 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "themeloader.h"
22 #include <QMessageBox>
25 #include <QtXml/qdom.h>
30 #include <KUniqueApplication>
31 #include <KStandardDirs>
34 #include <KToggleAction>
40 int defaultWidth = 25;
41 int defaultHeight = 25;
43 #define DEFAULT_CSS ":/theme/standart.css"
45 ThemeLoader::ThemeLoader(QWidget *parent) : QObject(parent)
50 ThemeLoader::~ThemeLoader()
54 void ThemeLoader::loadTheme(QString& themeName)
58 int ret = this->loadLayout(themeName, ":/theme/");
65 if (QString::compare(themeName, "standart")==0) {
75 void ThemeLoader::loadColorFile(const QString& fileName)
79 themeFile.setFileName(fileName);
81 if (!themeFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
83 QMessageBox::information(0, "Error", QString("Unable to open css file: %1").arg(themeFile.fileName()));
87 ((QWidget*)parent())->setStyleSheet(themeFile.readAll());
88 ((QWidget*)parent())->setProperty("colors", fileName);
91 ((QWidget*)parent())->repaint();
93 emit colorStyleChanged();
97 void ThemeLoader::loadColorStyle()
100 QAction *action = (QAction*)QObject::sender();
102 QFileInfo info(action->data().toString());
104 this->loadColorFile(info.absoluteFilePath());
107 void ThemeLoader::findColorStyles(QMenu *colors, const QString& configSelectedStyle)
110 QStringList dirs = kdirs.findDirs("data", "kvkbd");
112 QActionGroup *color_group = new QActionGroup(colors);
113 color_group->setExclusive(true);
116 QAction *item = new QAction(colors);
117 item->setCheckable(true);
118 item->setText("standart");
119 item->setData(":/theme/standart.css");
120 colors->addAction(item);
121 color_group->addAction(item);
127 colors->setTitle("Color Style");
128 colors->setIcon(KIcon("preferences-desktop-color"));
129 QListIterator<QString> itr(dirs);
130 while (itr.hasNext()) {
131 QString data_path = itr.next() + "colors";
133 QFileInfo info(data_path);
134 if (info.isDir() && info.isReadable()) {
135 QDir colors_dir(info.absoluteFilePath(), "*.css");
136 QFileInfoList list = colors_dir.entryInfoList();
138 QListIterator<QFileInfo> itr(list);
139 while (itr.hasNext()) {
140 QFileInfo fileInfo = itr.next();
141 //std::cout << qPrintable(QString("%1 %2").arg(fileInfo.size(), 10)
142 // .arg(fileInfo.fileName()));
143 //std::cout << std::endl;
145 QAction *item = new QAction(this);
146 item->setCheckable(true);
148 item->setText(fileInfo.baseName());
149 item->setData(fileInfo.absoluteFilePath());
150 colors->addAction(item);
151 color_group->addAction(item);
160 QString selectedStyle = configSelectedStyle;
161 if (selectedStyle.length()<1) {
162 selectedStyle = DEFAULT_CSS;
164 QAction *selectedAction = 0;
166 QListIterator<QAction*> itrActions(color_group->actions());
167 while (itrActions.hasNext()) {
168 QAction *item = itrActions.next();
170 if (item->data().toString() == selectedStyle) {
171 item->setChecked(true);
172 selectedAction = item;
176 connect(item, SIGNAL(triggered(bool)), this, SLOT(loadColorStyle()));
179 if (selectedAction) {
180 selectedAction->trigger();
186 int ThemeLoader::loadLayout(const QString& themeName, const QString& path)
189 // const KArchiveDirectory * KArchive::directory ( ) const
198 themeFile.setFileName(QString(path + "%1.xml").arg(themeName));
200 if (!themeFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
201 QMessageBox::information(0, "Error", QString("Unable to open theme xml file: %1").arg(themeFile.fileName()));
204 if (!doc.setContent(&themeFile)) {
205 QMessageBox::information(0, "Error", QString("Unable to parse theme xml file: %1").arg(themeFile.fileName()));
211 QDomElement docElem = doc.documentElement();
213 QDomNodeList wList = docElem.elementsByTagName("buttonWidth");
214 QDomNode wNode = wList.at(0);
216 //read default button width
217 defaultWidth = wNode.attributes().namedItem("width").toAttr().value().toInt();
219 QDomNodeList nList = (wNode.toElement()).elementsByTagName("item");
220 for (int a=0; a<nList.count(); a++) {
221 QDomNode node = nList.at(a);
222 int width = node.attributes().namedItem("width").toAttr().value().toInt();
223 QString hintName = node.attributes().namedItem("name").toAttr().value();
224 widthMap.insert(hintName, width);
225 //cout << "widths[" << qPrintable(hintName) << "]=>"<< width << endl;
228 wList = docElem.elementsByTagName("buttonHeight");
230 nList = (wNode.toElement()).elementsByTagName("item");
231 for (int a=0; a<nList.count(); a++) {
232 QDomNode node = nList.at(a);
233 int height = node.attributes().namedItem("height").toAttr().value().toInt();
234 QString hintName = node.attributes().namedItem("name").toAttr().value();
235 heightMap.insert(hintName, height);
236 //cout << "heights[" << qPrintable(hintName) << "]=>"<< height << endl;
240 wList = docElem.elementsByTagName("spacingHints");
242 nList = (wNode.toElement()).elementsByTagName("item");
243 for (int a=0; a<nList.count(); a++) {
244 QDomNode node = nList.at(a);
245 int width = node.attributes().namedItem("width").toAttr().value().toInt();
246 QString hintName = node.attributes().namedItem("name").toAttr().value();
247 spacingMap.insert(hintName, width);
248 //cout << "spacing[" << qPrintable(hintName) << "]=>"<< width << endl;
252 wList = docElem.elementsByTagName("part");
255 //insert main part to widget
256 QString partName = wNode.attributes().namedItem("name").toAttr().value();
258 MainWidget *part = new MainWidget((QWidget*)parent());
259 part->setProperty("part", "main");
262 loadKeys(part, wNode);
264 wList = wNode.childNodes();
266 for (int a=0; a<wList.size(); a++) {
268 QDomNode wNode = wList.at(a);
269 if (wNode.toElement().tagName() == "extension") {
270 MainWidget *widget1 = new MainWidget((QWidget*)parent());
271 widget1->setProperty("part", "extension");
272 loadKeys(widget1, wNode);
281 bool ThemeLoader::applyProperty(VButton *btn, const QString& attributeName, QDomNamedNodeMap *attributes, QVariant defaultValue)
285 QString attributeValue = attributes->namedItem(attributeName).toAttr().value();
286 if (attributeValue.length()>0) {
287 btn->setProperty(qPrintable(attributeName), attributeValue);
291 if (defaultValue.toString().length()>0) {
292 btn->setProperty(qPrintable(attributeName), defaultValue);
298 void ThemeLoader::loadKeys(MainWidget *vPart, const QDomNode& wNode)
305 int rowMarginLeft = 0;
312 QDomNodeList nList = wNode.childNodes();
314 //(wNode.toElement()).elementsByTagName("row");
316 for (int a=0; a<nList.size(); a++) {
318 QDomNode wNode = nList.at(a);
319 if (wNode.toElement().tagName() != "row") continue;
323 int rowHeight = defaultHeight;
328 QDomNodeList key_list = wNode.childNodes();
330 QString rowHeightHint = wNode.attributes().namedItem("height").toAttr().value();
331 if (heightMap.contains(rowHeightHint)) {
332 rowHeight = heightMap.value(rowHeightHint);
336 for (int b=0; b<key_list.count(); b++) {
337 QDomNode node = key_list.at(b);
338 QDomNamedNodeMap attributes = node.attributes();
340 if (node.toElement().tagName()== "key") {
342 VButton *btn = new VButton(vPart);
346 int buttonWidth = defaultWidth;
347 int buttonHeight = defaultHeight;
349 QString widthHint = attributes.namedItem("width").toAttr().value();
350 if (widthMap.contains(widthHint)) {
351 buttonWidth = widthMap.value(widthHint);
354 QString heightHint = attributes.namedItem("height").toAttr().value();
355 if (heightMap.contains(heightHint)) {
356 buttonHeight = heightMap.value(heightHint);
360 QString button_name = attributes.namedItem("name").toAttr().value();
361 if (button_name.length()>0) {
362 btn->setObjectName(button_name);
366 if (applyProperty(btn, "label", &attributes)) {
367 btn->setText(btn->property("label").toString());
371 applyProperty(btn, "group_label", &attributes);
373 applyProperty(btn, "group_toggle", &attributes);
375 applyProperty(btn, "group_name", &attributes);
377 applyProperty(btn, "colorGroup", &attributes, "normal");
379 applyProperty(btn, "tooltip", &attributes);
381 QString modifier = attributes.namedItem("modifier").toAttr().value();
382 if (modifier.toInt()>0) {
383 btn->setProperty("modifier", true);
384 btn->setCheckable(true);
387 unsigned int key_code = attributes.namedItem("code").toAttr().value().toInt();
389 btn->setKeyCode(key_code);
392 if (applyProperty(btn, "action", &attributes)) {
393 btn->setProperty("action", btn->property("action").toString());
398 int is_checkable = attributes.namedItem("checkable").toAttr().value().toInt();
399 if (is_checkable>0) {
400 btn->setCheckable(true);
401 btn->setChecked(false);
405 btn->resize(buttonWidth, buttonHeight);
408 // btn->setNode(node);
409 // cout << "ColorGroup: " << qPrintable(colorGroup) << endl;
411 sx+=buttonWidth+rowSpacingX;
413 emit buttonLoaded(btn);
415 else if (node.toElement().tagName()=="spacing") {
417 QString widthHint = attributes.namedItem("width").toAttr().value();
418 QString heightHint = attributes.namedItem("height").toAttr().value();
421 if (spacingMap.contains(widthHint)) {
422 int spacingWidth = spacingMap.value(widthHint);
428 if (heightMap.contains(heightHint)) {
429 int spacingHeight = heightMap.value(heightHint);
431 if (spacingHeight>rowHeight) rowHeight = spacingHeight;
437 //cout << "X=>"<<sx<<" | Y=>"<<sy<<endl;
441 if (sx>max_sx)max_sx = sx;
443 sy+=(rowHeight+rowSpacingY);
446 if (row_buttons>total_cols)total_cols=row_buttons;
449 if (sy>max_sy) max_sy = sy;
451 vPart->setBaseSize(max_sx, max_sy);
453 emit partLoaded(vPart, total_rows, total_cols);
459 #include "moc_themeloader.cpp"