Changelog fixed.
[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     detailScreen_->reArrange();
134     mainScreen_->reArrange();
135
136     reader_->close();
137
138     return ret;
139 }
140
141 bool ThemeLoader::loadScreen(QString const& tag, QDomDocument const& doc, WidgetScreen* screen)
142 {
143     QDomNodeList orientations = doc.elementsByTagName(tag);
144
145     if(orientations.isEmpty())
146     {
147         error_ = "No <"+tag+"> tags found";
148         return false;
149     }
150
151     bool ok = true;
152
153     for(int i = 0; i < orientations.size(); i++)
154     {
155         QDomNode data = orientations.at(i);
156         QString type = data.attributes().namedItem("orientation").toAttr().value();
157         QDomNode color = data.attributes().namedItem("color");
158
159         if(type == "landscape")
160         {
161             if(screen->orientationLoaded(WidgetScreen::LANDSCAPE))
162             {
163                 error_ = "More than one <"+tag+" orientation=\"landscape\"> specified";
164                 ok = false;
165             }
166
167             ok = ok && screen->load(WidgetScreen::LANDSCAPE, data, reader_);
168
169             if(ok && !color.isNull())
170             {
171                 screen->setColor(WidgetScreen::LANDSCAPE, color.toAttr().value());
172             }
173
174         }
175         else if(type == "portrait")
176         {
177             if(screen->orientationLoaded(WidgetScreen::PORTRAIT))
178             {
179                 error_ = "More than one <"+tag+" orientation=\"portrait\"> specified";
180                 ok = false;
181             }
182
183             ok = ok && screen->load(WidgetScreen::PORTRAIT, data, reader_);
184
185             if(ok && !color.isNull())
186             {
187                 screen->setColor(WidgetScreen::PORTRAIT, color.toAttr().value());
188             }
189         }
190         else if(type == "both")
191         {
192             if(screen->orientationLoaded(WidgetScreen::PORTRAIT) ||
193                screen->orientationLoaded(WidgetScreen::LANDSCAPE))
194             {
195                 error_ = "Multiple orientations specified for same screen";
196                 ok = false;
197             }
198
199             ok = ok && screen->load(data, reader_);
200
201             if(ok && !color.isNull())
202             {
203                 screen->setColor(color.toAttr().value());
204             }
205         }
206         else
207         {
208             error_ = "Invalid orientation: " + type;
209             ok = false;
210         }
211     }
212
213     return ok;
214 }
215
216 QString ThemeLoader::getThemeDir()
217 {
218     return Settings::getDir() + "themes" + QDir::separator();
219 }
220
221 QString const& ThemeLoader::getThemeSuffix()
222 {
223     return THEME_SUFFIX;
224 }
225
226 QString const& ThemeLoader::error() const
227 {
228     return error_;
229 }
230