summaryrefslogtreecommitdiff
path: root/utils/rbutilqt/themesinstallwindow.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/rbutilqt/themesinstallwindow.cpp')
-rw-r--r--utils/rbutilqt/themesinstallwindow.cpp393
1 files changed, 393 insertions, 0 deletions
diff --git a/utils/rbutilqt/themesinstallwindow.cpp b/utils/rbutilqt/themesinstallwindow.cpp
new file mode 100644
index 0000000000..c1a54feb74
--- /dev/null
+++ b/utils/rbutilqt/themesinstallwindow.cpp
@@ -0,0 +1,393 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 * Copyright (C) 2007 by Dominik Riebeling
10 *
11 * All files in this archive are subject to the GNU General Public License.
12 * See the file COPYING in the source tree root for full license agreement.
13 *
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
16 *
17 ****************************************************************************/
18
19#include <QDialog>
20#include <QMessageBox>
21#include <QTextCodec>
22
23#include "ui_themesinstallfrm.h"
24#include "themesinstallwindow.h"
25#include "zipinstaller.h"
26#include "progressloggergui.h"
27#include "utils.h"
28#include "rbsettings.h"
29#include "playerbuildinfo.h"
30#include "rockboxinfo.h"
31#include "version.h"
32#include "Logger.h"
33
34ThemesInstallWindow::ThemesInstallWindow(QWidget *parent) : QDialog(parent)
35{
36 ui.setupUi(this);
37 ui.listThemes->setAlternatingRowColors(true);
38 ui.listThemes->setSelectionMode(QAbstractItemView::ExtendedSelection);
39 ui.listThemes->setSortingEnabled(true);
40 ui.themePreview->clear();
41 ui.themePreview->setText(tr("no theme selected"));
42 ui.labelSize->setText(tr("no selection"));
43 ui.listThemes->setLayoutDirection(Qt::LeftToRight);
44 ui.themeDescription->setLayoutDirection(Qt::LeftToRight);
45
46 connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(close()));
47 connect(ui.buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
48 connect(ui.listThemes, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)),
49 this, SLOT(updateDetails(QListWidgetItem*, QListWidgetItem*)));
50 connect(ui.listThemes, SIGNAL(itemSelectionChanged()), this, SLOT(updateSize()));
51 connect(&igetter, SIGNAL(done(bool)), this, SLOT(updateImage(bool)));
52
53 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
54 igetter.setCache(true);
55 else
56 {
57 if(infocachedir.isEmpty())
58 {
59 infocachedir = QDir::tempPath() + "rbutil-themeinfo";
60 QDir d = QDir::temp();
61 d.mkdir("rbutil-themeinfo");
62 }
63 igetter.setCache(infocachedir);
64 }
65
66 logger = nullptr;
67}
68
69ThemesInstallWindow::~ThemesInstallWindow()
70{
71 if(!infocachedir.isEmpty())
72 Utils::recursiveRmdir(infocachedir);
73}
74
75
76void ThemesInstallWindow::downloadInfo()
77{
78 // try to get the current build information
79 getter = new HttpGet(this);
80 RockboxInfo installInfo
81 = RockboxInfo(RbSettings::value(RbSettings::Mountpoint).toString());
82
83 themesInfo.open();
84 LOG_INFO() << "downloading info to" << themesInfo.fileName();
85 themesInfo.close();
86
87 QString infoUrl = PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesInfoUrl).toString();
88 infoUrl.replace("%TARGET%",
89 RbSettings::value(RbSettings::CurrentPlatform).toString().split(".").at(0));
90 infoUrl.replace("%REVISION%", installInfo.revision());
91 infoUrl.replace("%RELEASE%", installInfo.release());
92 infoUrl.replace("%RBUTILVER%", VERSION);
93 QUrl url = QUrl(infoUrl);
94 LOG_INFO() << "Info URL:" << url;
95 getter->setFile(&themesInfo);
96
97 connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
98 connect(logger, SIGNAL(aborted()), getter, SLOT(abort()));
99 getter->getFile(url);
100}
101
102
103void ThemesInstallWindow::downloadDone(int id, bool error)
104{
105 downloadDone(error);
106 LOG_INFO() << "Download" << id << "done, error:" << error;
107}
108
109
110void ThemesInstallWindow::downloadDone(bool error)
111{
112 LOG_INFO() << "Download done, error:" << error;
113
114 disconnect(logger, SIGNAL(aborted()), getter, SLOT(abort()));
115 disconnect(logger, SIGNAL(aborted()), this, SLOT(close()));
116 themesInfo.open();
117
118 QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this);
119 iniDetails.setIniCodec(QTextCodec::codecForName("UTF-8"));
120 QStringList tl = iniDetails.childGroups();
121 LOG_INFO() << "Theme site result:"
122 << iniDetails.value("error/code").toString()
123 << iniDetails.value("error/description").toString()
124 << iniDetails.value("error/query").toString();
125
126 if(error) {
127 logger->addItem(tr("Network error: %1.\n"
128 "Please check your network and proxy settings.")
129 .arg(getter->errorString()), LOGERROR);
130 getter->abort();
131 logger->setFinished();
132 disconnect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
133 connect(logger, SIGNAL(closed()), this, SLOT(close()));
134 return;
135 }
136 // handle possible error codes
137 if(iniDetails.value("error/code").toInt() != 0 || !iniDetails.contains("error/code")) {
138 LOG_ERROR() << "Theme site returned an error:"
139 << iniDetails.value("error/code");
140 logger->addItem(tr("the following error occured:\n%1")
141 .arg(iniDetails.value("error/description", "unknown error").toString()), LOGERROR);
142 logger->setFinished();
143 connect(logger, SIGNAL(closed()), this, SLOT(close()));
144 return;
145 }
146 logger->addItem(tr("done."), LOGOK);
147 logger->setFinished();
148 logger->close();
149
150 // setup list
151 for(int i = 0; i < tl.size(); i++) {
152 iniDetails.beginGroup(tl.at(i));
153 // skip all themes without name field set (i.e. error section)
154 if(iniDetails.value("name").toString().isEmpty()) {
155 iniDetails.endGroup();
156 continue;
157 }
158 LOG_INFO() << "adding to list:" << tl.at(i);
159 // convert to unicode and replace HTML-specific entities
160 QByteArray raw = iniDetails.value("name").toByteArray();
161 QTextCodec* codec = QTextCodec::codecForHtml(raw);
162 QString name = codec->toUnicode(raw);
163 name.replace("&quot;", "\"").replace("&amp;", "&");
164 name.replace("&lt;", "<").replace("&gt;", ">");
165 QListWidgetItem *w = new QListWidgetItem;
166 w->setData(Qt::DisplayRole, name.trimmed());
167 w->setData(Qt::UserRole, tl.at(i));
168 ui.listThemes->addItem(w);
169
170 iniDetails.endGroup();
171 }
172 // check if there's a themes "MOTD" available
173 if(iniDetails.contains("status/msg")) {
174 // check if there's a localized msg available
175 QString lang = RbSettings::value(RbSettings::Language).toString().split("_").at(0);
176 QString msg;
177 if(iniDetails.contains("status/msg." + lang))
178 msg = iniDetails.value("status/msg." + lang).toString();
179 else
180 msg = iniDetails.value("status/msg").toString();
181 LOG_INFO() << "MOTD" << msg;
182 if(!msg.isEmpty())
183 QMessageBox::information(this, tr("Information"), msg);
184 }
185}
186
187
188void ThemesInstallWindow::updateSize(void)
189{
190 long size = 0;
191 // sum up size for all selected themes
192 QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this);
193 iniDetails.setIniCodec(QTextCodec::codecForName("UTF-8"));
194 int items = ui.listThemes->selectedItems().size();
195 for(int i = 0; i < items; i++) {
196 iniDetails.beginGroup(ui.listThemes->selectedItems()
197 .at(i)->data(Qt::UserRole).toString());
198 size += iniDetails.value("size").toInt();
199 iniDetails.endGroup();
200 }
201 ui.labelSize->setText(tr("Download size %L1 kiB (%n item(s))", "", items)
202 .arg((size + 512) / 1024));
203}
204
205
206void ThemesInstallWindow::updateDetails(QListWidgetItem* cur, QListWidgetItem* prev)
207{
208 if(cur == prev)
209 return;
210
211 QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this);
212 iniDetails.setIniCodec(QTextCodec::codecForName("UTF-8"));
213
214 QCoreApplication::processEvents();
215 ui.themeDescription->setText(tr("fetching details for %1")
216 .arg(cur->data(Qt::DisplayRole).toString()));
217 ui.themePreview->clear();
218 ui.themePreview->setText(tr("fetching preview ..."));
219 imgData.clear();
220
221 iniDetails.beginGroup(cur->data(Qt::UserRole).toString());
222
223 QUrl img, txt;
224 txt = QUrl(QString(PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesUrl).toString() + "/"
225 + iniDetails.value("descriptionfile").toString()));
226 img = QUrl(QString(PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesUrl).toString() + "/"
227 + iniDetails.value("image").toString()));
228
229 QString text;
230 QTextCodec* codec = QTextCodec::codecForName("UTF-8");
231 text = tr("<b>Author:</b> %1<hr/>").arg(codec->toUnicode(iniDetails
232 .value("author", tr("unknown")).toByteArray()));
233 text += tr("<b>Version:</b> %1<hr/>").arg(codec->toUnicode(iniDetails
234 .value("version", tr("unknown")).toByteArray()));
235 text += tr("<b>Description:</b> %1<hr/>").arg(codec->toUnicode(iniDetails
236 .value("about", tr("no description")).toByteArray()));
237
238 text.replace("\n", "<br/>");
239 ui.themeDescription->setHtml(text);
240 iniDetails.endGroup();
241 igetter.abort();
242 igetter.getFile(img);
243}
244
245
246void ThemesInstallWindow::updateImage(bool error)
247{
248 LOG_INFO() << "Updating image:"<< !error;
249
250 if(error) {
251 ui.themePreview->clear();
252 ui.themePreview->setText(tr("Retrieving theme preview failed.\n"
253 "HTTP response code: %1").arg(igetter.httpResponse()));
254 return;
255 }
256
257 QPixmap p;
258 if(!error) {
259 imgData = igetter.readAll();
260 if(imgData.isNull()) return;
261 p.loadFromData(imgData);
262 if(p.isNull()) {
263 ui.themePreview->clear();
264 ui.themePreview->setText(tr("no theme preview"));
265 }
266 else
267 ui.themePreview->setPixmap(p);
268 }
269}
270
271
272void ThemesInstallWindow::resizeEvent(QResizeEvent* e)
273{
274 (void)e;
275 QPixmap p, q;
276 QSize img;
277 img.setHeight(ui.themePreview->height());
278 img.setWidth(ui.themePreview->width());
279
280 p.loadFromData(imgData);
281 if(p.isNull()) return;
282 q = p.scaled(img, Qt::KeepAspectRatio, Qt::SmoothTransformation);
283 ui.themePreview->setScaledContents(false);
284 ui.themePreview->setPixmap(p);
285}
286
287
288
289void ThemesInstallWindow::show()
290{
291 QDialog::show();
292 if(windowSelectOnly)
293 ui.buttonOk->setText(tr("Select"));
294
295 if(!logger)
296 logger = new ProgressLoggerGui(this);
297
298 if(ui.listThemes->count() == 0) {
299 logger->show();
300 logger->addItem(tr("getting themes information ..."), LOGINFO);
301
302 connect(logger, SIGNAL(aborted()), this, SLOT(close()));
303
304 downloadInfo();
305 }
306
307}
308
309
310void ThemesInstallWindow::abort()
311{
312 igetter.abort();
313 logger->setFinished();
314 this->close();
315}
316
317
318void ThemesInstallWindow::accept(void)
319{
320 if(!windowSelectOnly)
321 install();
322 else
323 close();
324}
325
326
327void ThemesInstallWindow::install()
328{
329 if(ui.listThemes->selectedItems().size() == 0) {
330 logger->addItem(tr("No themes selected, skipping"), LOGINFO);
331 emit done(false);
332 return;
333 }
334 QStringList themes;
335 QStringList names;
336 QStringList version;
337 QString zip;
338 QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this);
339 for(int i = 0; i < ui.listThemes->selectedItems().size(); i++) {
340 iniDetails.beginGroup(ui.listThemes->selectedItems().at(i)->data(Qt::UserRole).toString());
341 zip = PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesUrl).toString()
342 + "/" + iniDetails.value("archive").toString();
343 themes.append(zip);
344 names.append("Theme: " +
345 ui.listThemes->selectedItems().at(i)->data(Qt::DisplayRole).toString());
346 // if no version info is available use installation (current) date
347 version.append(iniDetails.value("version",
348 QDate().currentDate().toString("yyyyMMdd")).toString());
349 iniDetails.endGroup();
350 }
351 LOG_INFO() << "installing:" << themes;
352
353 if(logger == nullptr)
354 logger = new ProgressLoggerGui(this);
355 logger->show();
356 QString mountPoint = RbSettings::value(RbSettings::Mountpoint).toString();
357 LOG_INFO() << "mountpoint:" << mountPoint;
358 // show dialog with error if mount point is wrong
359 if(!QFileInfo(mountPoint).isDir()) {
360 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
361 logger->setFinished();
362 return;
363 }
364
365 installer = new ZipInstaller(this);
366 installer->setUrl(themes);
367 installer->setLogSection(names);
368 installer->setLogVersion(version);
369 installer->setMountPoint(mountPoint);
370 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
371 installer->setCache(true);
372
373 if(!windowSelectOnly) {
374 connect(logger, SIGNAL(closed()), this, SLOT(close()));
375 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
376 }
377 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
378 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
379 connect(installer, SIGNAL(done(bool)), this, SIGNAL(done(bool)));
380 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
381 installer->install();
382}
383
384
385void ThemesInstallWindow::changeEvent(QEvent *e)
386{
387 if(e->type() == QEvent::LanguageChange) {
388 ui.retranslateUi(this);
389 } else {
390 QWidget::changeEvent(e);
391 }
392}
393