1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Riebeling
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.
14 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
15 * KIND, either express or implied.
17 ****************************************************************************/
20 #include <QMessageBox>
22 #include "ui_themesinstallfrm.h"
23 #include "themesinstallwindow.h"
24 #include "zipinstaller.h"
25 #include "progressloggergui.h"
27 #include "rbsettings.h"
28 #include "systeminfo.h"
29 #include "rockboxinfo.h"
32 ThemesInstallWindow::ThemesInstallWindow(QWidget
*parent
) : QDialog(parent
)
35 ui
.listThemes
->setAlternatingRowColors(true);
36 ui
.listThemes
->setSelectionMode(QAbstractItemView::ExtendedSelection
);
37 ui
.listThemes
->setSortingEnabled(true);
38 ui
.themePreview
->clear();
39 ui
.themePreview
->setText(tr("no theme selected"));
40 ui
.labelSize
->setText(tr("no selection"));
41 ui
.listThemes
->setLayoutDirection(Qt::LeftToRight
);
42 ui
.themeDescription
->setLayoutDirection(Qt::LeftToRight
);
44 connect(ui
.buttonCancel
, SIGNAL(clicked()), this, SLOT(close()));
45 connect(ui
.buttonOk
, SIGNAL(clicked()), this, SLOT(accept()));
46 connect(ui
.listThemes
, SIGNAL(currentItemChanged(QListWidgetItem
*, QListWidgetItem
*)),
47 this, SLOT(updateDetails(QListWidgetItem
*, QListWidgetItem
*)));
48 connect(ui
.listThemes
, SIGNAL(itemSelectionChanged()), this, SLOT(updateSize()));
49 connect(&igetter
, SIGNAL(done(bool)), this, SLOT(updateImage(bool)));
51 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
52 igetter
.setCache(true);
55 if(infocachedir
.isEmpty())
57 infocachedir
= QDir::tempPath() + "rbutil-themeinfo";
58 QDir d
= QDir::temp();
59 d
.mkdir("rbutil-themeinfo");
61 igetter
.setCache(infocachedir
);
67 ThemesInstallWindow::~ThemesInstallWindow()
69 if(!infocachedir
.isEmpty())
70 Utils::recursiveRmdir(infocachedir
);
74 void ThemesInstallWindow::downloadInfo()
76 // try to get the current build information
77 getter
= new HttpGet(this);
78 RockboxInfo installInfo
79 = RockboxInfo(RbSettings::value(RbSettings::Mountpoint
).toString());
82 qDebug() << "[Themes] downloading info to" << themesInfo
.fileName();
85 QString infoUrl
= SystemInfo::value(SystemInfo::ThemesInfoUrl
).toString();
86 infoUrl
.replace("%TARGET%",
87 SystemInfo::value(SystemInfo::CurConfigureModel
).toString());
88 infoUrl
.replace("%REVISION%", installInfo
.revision());
89 infoUrl
.replace("%RELEASE%", installInfo
.release());
90 infoUrl
.replace("%RBUTILVER%", VERSION
);
91 QUrl url
= QUrl(infoUrl
);
92 qDebug() << "[Themes] Info URL:" << url
;
93 getter
->setFile(&themesInfo
);
95 connect(getter
, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
96 connect(logger
, SIGNAL(aborted()), getter
, SLOT(abort()));
101 void ThemesInstallWindow::downloadDone(int id
, bool error
)
104 qDebug() << "[Themes] Download" << id
<< "done, error:" << error
;
108 void ThemesInstallWindow::downloadDone(bool error
)
110 qDebug() << "[Themes] Download done, error:" << error
;
112 disconnect(logger
, SIGNAL(aborted()), getter
, SLOT(abort()));
113 disconnect(logger
, SIGNAL(aborted()), this, SLOT(close()));
116 QSettings
iniDetails(themesInfo
.fileName(), QSettings::IniFormat
, this);
117 QStringList tl
= iniDetails
.childGroups();
118 qDebug() << "[Themes] Theme site result:"
119 << iniDetails
.value("error/code").toString()
120 << iniDetails
.value("error/description").toString()
121 << iniDetails
.value("error/query").toString();
124 logger
->addItem(tr("Network error: %1.\n"
125 "Please check your network and proxy settings.")
126 .arg(getter
->errorString()), LOGERROR
);
128 logger
->setFinished();
129 disconnect(getter
, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
130 connect(logger
, SIGNAL(closed()), this, SLOT(close()));
133 // handle possible error codes
134 if(iniDetails
.value("error/code").toInt() != 0 || !iniDetails
.contains("error/code")) {
135 qDebug() << "[Themes] Theme site returned an error:"
136 << iniDetails
.value("error/code");
137 logger
->addItem(tr("the following error occured:\n%1")
138 .arg(iniDetails
.value("error/description", "unknown error").toString()), LOGERROR
);
139 logger
->setFinished();
140 connect(logger
, SIGNAL(closed()), this, SLOT(close()));
143 logger
->addItem(tr("done."), LOGOK
);
144 logger
->setFinished();
148 for(int i
= 0; i
< tl
.size(); i
++) {
149 iniDetails
.beginGroup(tl
.at(i
));
150 // skip all themes without name field set (i.e. error section)
151 if(iniDetails
.value("name").toString().isEmpty()) {
152 iniDetails
.endGroup();
155 qDebug() << "[Themes] adding to list:" << tl
.at(i
);
156 // convert to unicode and replace HTML-specific entities
157 QByteArray raw
= iniDetails
.value("name").toByteArray();
158 QTextCodec
* codec
= QTextCodec::codecForHtml(raw
);
159 QString name
= codec
->toUnicode(raw
);
160 name
.replace(""", "\"").replace("&", "&");
161 name
.replace("<", "<").replace(">", ">");
162 QListWidgetItem
*w
= new QListWidgetItem
;
163 w
->setData(Qt::DisplayRole
, name
.trimmed());
164 w
->setData(Qt::UserRole
, tl
.at(i
));
165 ui
.listThemes
->addItem(w
);
167 iniDetails
.endGroup();
169 // check if there's a themes "MOTD" available
170 if(iniDetails
.contains("status/msg")) {
171 // check if there's a localized msg available
172 QString lang
= RbSettings::value(RbSettings::Language
).toString().split("_").at(0);
174 if(iniDetails
.contains("status/msg." + lang
))
175 msg
= iniDetails
.value("status/msg." + lang
).toString();
177 msg
= iniDetails
.value("status/msg").toString();
178 qDebug() << "[Themes] MOTD" << msg
;
180 QMessageBox::information(this, tr("Information"), msg
);
185 void ThemesInstallWindow::updateSize(void)
188 // sum up size for all selected themes
189 QSettings
iniDetails(themesInfo
.fileName(), QSettings::IniFormat
, this);
190 int items
= ui
.listThemes
->selectedItems().size();
191 for(int i
= 0; i
< items
; i
++) {
192 iniDetails
.beginGroup(ui
.listThemes
->selectedItems()
193 .at(i
)->data(Qt::UserRole
).toString());
194 size
+= iniDetails
.value("size").toInt();
195 iniDetails
.endGroup();
197 ui
.labelSize
->setText(tr("Download size %L1 kiB (%n item(s))", "", items
)
198 .arg((size
+ 512) / 1024));
202 void ThemesInstallWindow::updateDetails(QListWidgetItem
* cur
, QListWidgetItem
* prev
)
207 QSettings
iniDetails(themesInfo
.fileName(), QSettings::IniFormat
, this);
209 QCoreApplication::processEvents();
210 ui
.themeDescription
->setText(tr("fetching details for %1")
211 .arg(cur
->data(Qt::DisplayRole
).toString()));
212 ui
.themePreview
->clear();
213 ui
.themePreview
->setText(tr("fetching preview ..."));
216 iniDetails
.beginGroup(cur
->data(Qt::UserRole
).toString());
219 txt
= QUrl(QString(SystemInfo::value(SystemInfo::ThemesUrl
).toString() + "/"
220 + iniDetails
.value("descriptionfile").toString()));
221 img
= QUrl(QString(SystemInfo::value(SystemInfo::ThemesUrl
).toString() + "/"
222 + iniDetails
.value("image").toString()));
225 QTextCodec
* codec
= QTextCodec::codecForName("UTF-8");
226 text
= tr("<b>Author:</b> %1<hr/>").arg(codec
->toUnicode(iniDetails
227 .value("author", tr("unknown")).toByteArray()));
228 text
+= tr("<b>Version:</b> %1<hr/>").arg(codec
->toUnicode(iniDetails
229 .value("version", tr("unknown")).toByteArray()));
230 text
+= tr("<b>Description:</b> %1<hr/>").arg(codec
->toUnicode(iniDetails
231 .value("about", tr("no description")).toByteArray()));
233 text
.replace("\n", "<br/>");
234 ui
.themeDescription
->setHtml(text
);
235 iniDetails
.endGroup();
237 igetter
.getFile(img
);
241 void ThemesInstallWindow::updateImage(bool error
)
243 qDebug() << "[Themes] Updating image:"<< !error
;
246 ui
.themePreview
->clear();
247 ui
.themePreview
->setText(tr("Retrieving theme preview failed.\n"
248 "HTTP response code: %1").arg(igetter
.httpResponse()));
254 imgData
= igetter
.readAll();
255 if(imgData
.isNull()) return;
256 p
.loadFromData(imgData
);
258 ui
.themePreview
->clear();
259 ui
.themePreview
->setText(tr("no theme preview"));
262 ui
.themePreview
->setPixmap(p
);
267 void ThemesInstallWindow::resizeEvent(QResizeEvent
* e
)
269 qDebug() << "[Themes]" << e
;
273 img
.setHeight(ui
.themePreview
->height());
274 img
.setWidth(ui
.themePreview
->width());
276 p
.loadFromData(imgData
);
277 if(p
.isNull()) return;
278 q
= p
.scaled(img
, Qt::KeepAspectRatio
, Qt::SmoothTransformation
);
279 ui
.themePreview
->setScaledContents(false);
280 ui
.themePreview
->setPixmap(p
);
285 void ThemesInstallWindow::show()
289 ui
.buttonOk
->setText(tr("Select"));
292 logger
= new ProgressLoggerGui(this);
294 if(ui
.listThemes
->count() == 0) {
296 logger
->addItem(tr("getting themes information ..."), LOGINFO
);
298 connect(logger
, SIGNAL(aborted()), this, SLOT(close()));
306 void ThemesInstallWindow::abort()
309 logger
->setFinished();
314 void ThemesInstallWindow::accept(void)
316 if(!windowSelectOnly
)
323 void ThemesInstallWindow::install()
325 if(ui
.listThemes
->selectedItems().size() == 0) {
326 logger
->addItem(tr("No themes selected, skipping"), LOGINFO
);
334 QSettings
iniDetails(themesInfo
.fileName(), QSettings::IniFormat
, this);
335 for(int i
= 0; i
< ui
.listThemes
->selectedItems().size(); i
++) {
336 iniDetails
.beginGroup(ui
.listThemes
->selectedItems().at(i
)->data(Qt::UserRole
).toString());
337 zip
= SystemInfo::value(SystemInfo::ThemesUrl
).toString()
338 + "/" + iniDetails
.value("archive").toString();
340 names
.append("Theme: " +
341 ui
.listThemes
->selectedItems().at(i
)->data(Qt::DisplayRole
).toString());
342 // if no version info is available use installation (current) date
343 version
.append(iniDetails
.value("version",
344 QDate().currentDate().toString("yyyyMMdd")).toString());
345 iniDetails
.endGroup();
347 qDebug() << "[Themes] installing:" << themes
;
350 logger
= new ProgressLoggerGui(this);
352 QString mountPoint
= RbSettings::value(RbSettings::Mountpoint
).toString();
353 qDebug() << "[Themes] mountpoint:" << mountPoint
;
354 // show dialog with error if mount point is wrong
355 if(!QFileInfo(mountPoint
).isDir()) {
356 logger
->addItem(tr("Mount point is wrong!"),LOGERROR
);
357 logger
->setFinished();
361 installer
= new ZipInstaller(this);
362 installer
->setUrl(themes
);
363 installer
->setLogSection(names
);
364 installer
->setLogVersion(version
);
365 installer
->setMountPoint(mountPoint
);
366 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
367 installer
->setCache(true);
369 if(!windowSelectOnly
) {
370 connect(logger
, SIGNAL(closed()), this, SLOT(close()));
371 connect(installer
, SIGNAL(done(bool)), logger
, SLOT(setFinished()));
373 connect(installer
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
374 connect(installer
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
375 connect(installer
, SIGNAL(done(bool)), this, SIGNAL(done(bool)));
376 connect(logger
, SIGNAL(aborted()), installer
, SLOT(abort()));
377 installer
->install();
381 void ThemesInstallWindow::changeEvent(QEvent
*e
)
383 if(e
->type() == QEvent::LanguageChange
) {
384 ui
.retranslateUi(this);
386 QWidget::changeEvent(e
);