Added zpos attribute to all elements. Changed architecture to allow detailscreen...
[jspeed] / src / themeloader.cpp
1 /*
2  * This file is part of jSpeed.
3  *
4  * jSpeed is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * jSpeed is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with jSpeed.  If not, see <http://www.gnu.org/licenses/>.
16  *
17  */
18
19 #include <QtCore/QDir>
20 #include <QtCore/QString>
21 #include <QtCore/QDebug>
22 #include <QtCore/QTimer>
23 #include <QtGui/QStackedWidget>
24 #include <QtXml/QDomNode>
25 #include <QtXml/QDomDocument>
26 #include <QtXml/QDomAttr>
27 #include <QMaemo5InformationBox>
28 #include "themeloader.h"
29 #include "reader.h"
30 #include "zipreader.h"
31 #include "filereader.h"
32 #include "themescreen.h"
33 #include "detailscreen.h"
34 #include "settings.h"
35 #include "widgetscreen.h"
36
37 namespace
38 {
39     QString const RESOURCE_DIR = ":/resources/themes/";
40     QString const THEME_SUFFIX = ".jspeed";
41 }
42
43 ThemeLoader::ThemeLoader(WidgetScreen* mainScreen, WidgetScreen* detailScreen, QObject* parent): QObject(parent),
44 reader_(0), mainScreen_(mainScreen), detailScreen_(detailScreen)
45 {
46 }
47
48 ThemeLoader::~ThemeLoader()
49 {
50 }
51
52 bool ThemeLoader::load()
53 {
54     QString theme = Settings::instance().value("theme", "default").toString();
55
56     QString themeDir = getThemeDir();
57
58     if(QFile::exists(themeDir + theme + THEME_SUFFIX))
59     {
60         reader_ = new ZipReader(themeDir + theme + THEME_SUFFIX);
61
62         if(read())
63         {
64             return true;
65         }
66         else
67         {
68             QMaemo5InformationBox::information(mainScreen_,
69                                                tr("Unable to load theme: %1.").arg(error_),
70                                                QMaemo5InformationBox::NoTimeout);
71         }
72     }
73
74     theme = "default";
75     Settings::instance().setValue("theme", theme);
76
77     if(QFile::exists(RESOURCE_DIR + theme))
78     {
79         if(reader_)
80         {
81             delete reader_;
82         }
83
84         reader_ = new FileReader(RESOURCE_DIR + theme);
85         return read();
86     }
87
88     error_ = "No themes found";
89
90     return false;
91 }
92
93 bool ThemeLoader::read()
94 {
95     Q_ASSERT(reader_ != 0);
96
97     if(!reader_->open())
98     {
99         error_ = reader_->errorString();
100         return false;
101     }
102
103     QByteArray xmlData;
104
105     if(!reader_->readFile("theme.xml", xmlData))
106     {
107         error_ = "Unable to find <b>theme.xml</b> from theme file";
108         return false;
109     }
110
111     QDomDocument doc;
112     int line = 0;
113     int column = 0;
114     QString msg;
115
116     if(!doc.setContent(xmlData, false, &msg, &line, &column))
117     {
118         error_ = "Invalid xml file, " + msg + " (line " + QString::number(line)+", column " + QString::number(column) + ")";
119         return false;
120     }
121
122     detailScreen_->clear();
123     detailScreen_->addScreen(new DetailScreen, WidgetScreen::LANDSCAPE);
124     detailScreen_->addScreen(new DetailScreen, WidgetScreen::PORTRAIT);
125     loadScreen("detailscreen", doc, detailScreen_);
126
127     mainScreen_->clear();
128     mainScreen_->addScreen(new ThemeScreen, WidgetScreen::LANDSCAPE);
129     mainScreen_->addScreen(new ThemeScreen, WidgetScreen::PORTRAIT);
130     bool ret = loadScreen("mainscreen", doc, mainScreen_);
131     mainScreen_->removeUnloaded();
132
133     reader_->close();
134
135     return ret;
136 }
137
138 bool ThemeLoader::loadScreen(QString const& tag, QDomDocument const& doc, WidgetScreen* screen)
139 {
140     QDomNodeList orientations = doc.elementsByTagName(tag);
141
142     if(orientations.isEmpty())
143     {
144         error_ = "No <"+tag+"> tags found";
145         return false;
146     }
147
148     bool ok = true;
149
150     for(int i = 0; i < orientations.size(); i++)
151     {
152         QDomNode data = orientations.at(i);
153         QString type = data.attributes().namedItem("orientation").toAttr().value();
154         QDomNode color = data.attributes().namedItem("color");
155
156         if(type == "landscape")
157         {
158             if(screen->orientationLoaded(WidgetScreen::LANDSCAPE))
159             {
160                 error_ = "More than one <"+tag+" orientation=\"landscape\"> specified";
161                 ok = false;
162             }
163
164             ok = ok && screen->load(WidgetScreen::LANDSCAPE, data, reader_);
165
166         }
167         else if(type == "portrait")
168         {
169             if(screen->orientationLoaded(WidgetScreen::PORTRAIT))
170             {
171                 error_ = "More than one <"+tag+" orientation=\"portrait\"> specified";
172                 ok = false;
173             }
174
175             ok = ok && screen->load(WidgetScreen::PORTRAIT, data, reader_);
176         }
177         else if(type == "both")
178         {
179             if(screen->orientationLoaded(WidgetScreen::PORTRAIT) ||
180                screen->orientationLoaded(WidgetScreen::LANDSCAPE))
181             {
182                 error_ = "Multiple orientations specified for same screen";
183                 ok = false;
184             }
185
186             ok = ok && screen->load(WidgetScreen::PORTRAIT, data, reader_);
187             ok = ok && screen->load(WidgetScreen::LANDSCAPE, data, reader_);
188         }
189         else
190         {
191             error_ = "Invalid orientation: " + type;
192             ok = false;
193         }
194
195         if(ok && !color.isNull())
196         {
197             screen->setColor(color.toAttr().value());
198         }
199     }
200
201     return ok;
202 }
203
204 QString ThemeLoader::getThemeDir()
205 {
206     return Settings::getDir() + "themes" + QDir::separator();
207 }
208
209 QString const& ThemeLoader::getThemeSuffix()
210 {
211     return THEME_SUFFIX;
212 }
213
214 QString const& ThemeLoader::error() const
215 {
216     return error_;
217 }
218