diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/rbutilqt/themesinstallwindow.cpp | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/rbutilqt/themesinstallwindow.cpp')
-rw-r--r-- | utils/rbutilqt/themesinstallwindow.cpp | 393 |
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 | |||
34 | ThemesInstallWindow::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 | |||
69 | ThemesInstallWindow::~ThemesInstallWindow() | ||
70 | { | ||
71 | if(!infocachedir.isEmpty()) | ||
72 | Utils::recursiveRmdir(infocachedir); | ||
73 | } | ||
74 | |||
75 | |||
76 | void 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 | |||
103 | void ThemesInstallWindow::downloadDone(int id, bool error) | ||
104 | { | ||
105 | downloadDone(error); | ||
106 | LOG_INFO() << "Download" << id << "done, error:" << error; | ||
107 | } | ||
108 | |||
109 | |||
110 | void 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(""", "\"").replace("&", "&"); | ||
164 | name.replace("<", "<").replace(">", ">"); | ||
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 | |||
188 | void 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 | |||
206 | void 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 | |||
246 | void 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 | |||
272 | void 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 | |||
289 | void 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 | |||
310 | void ThemesInstallWindow::abort() | ||
311 | { | ||
312 | igetter.abort(); | ||
313 | logger->setFinished(); | ||
314 | this->close(); | ||
315 | } | ||
316 | |||
317 | |||
318 | void ThemesInstallWindow::accept(void) | ||
319 | { | ||
320 | if(!windowSelectOnly) | ||
321 | install(); | ||
322 | else | ||
323 | close(); | ||
324 | } | ||
325 | |||
326 | |||
327 | void 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 | |||
385 | void ThemesInstallWindow::changeEvent(QEvent *e) | ||
386 | { | ||
387 | if(e->type() == QEvent::LanguageChange) { | ||
388 | ui.retranslateUi(this); | ||
389 | } else { | ||
390 | QWidget::changeEvent(e); | ||
391 | } | ||
392 | } | ||
393 | |||