From c876d3bbefe0dc00c27ca0c12d29da5874946962 Mon Sep 17 00:00:00 2001 From: Dominik Riebeling Date: Wed, 15 Dec 2021 21:04:28 +0100 Subject: 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 --- utils/rbutilqt/themesinstallwindow.cpp | 393 +++++++++++++++++++++++++++++++++ 1 file changed, 393 insertions(+) create mode 100644 utils/rbutilqt/themesinstallwindow.cpp (limited to 'utils/rbutilqt/themesinstallwindow.cpp') 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 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * Copyright (C) 2007 by Dominik Riebeling + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include + +#include "ui_themesinstallfrm.h" +#include "themesinstallwindow.h" +#include "zipinstaller.h" +#include "progressloggergui.h" +#include "utils.h" +#include "rbsettings.h" +#include "playerbuildinfo.h" +#include "rockboxinfo.h" +#include "version.h" +#include "Logger.h" + +ThemesInstallWindow::ThemesInstallWindow(QWidget *parent) : QDialog(parent) +{ + ui.setupUi(this); + ui.listThemes->setAlternatingRowColors(true); + ui.listThemes->setSelectionMode(QAbstractItemView::ExtendedSelection); + ui.listThemes->setSortingEnabled(true); + ui.themePreview->clear(); + ui.themePreview->setText(tr("no theme selected")); + ui.labelSize->setText(tr("no selection")); + ui.listThemes->setLayoutDirection(Qt::LeftToRight); + ui.themeDescription->setLayoutDirection(Qt::LeftToRight); + + connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(close())); + connect(ui.buttonOk, SIGNAL(clicked()), this, SLOT(accept())); + connect(ui.listThemes, SIGNAL(currentItemChanged(QListWidgetItem*, QListWidgetItem*)), + this, SLOT(updateDetails(QListWidgetItem*, QListWidgetItem*))); + connect(ui.listThemes, SIGNAL(itemSelectionChanged()), this, SLOT(updateSize())); + connect(&igetter, SIGNAL(done(bool)), this, SLOT(updateImage(bool))); + + if(!RbSettings::value(RbSettings::CacheDisabled).toBool()) + igetter.setCache(true); + else + { + if(infocachedir.isEmpty()) + { + infocachedir = QDir::tempPath() + "rbutil-themeinfo"; + QDir d = QDir::temp(); + d.mkdir("rbutil-themeinfo"); + } + igetter.setCache(infocachedir); + } + + logger = nullptr; +} + +ThemesInstallWindow::~ThemesInstallWindow() +{ + if(!infocachedir.isEmpty()) + Utils::recursiveRmdir(infocachedir); +} + + +void ThemesInstallWindow::downloadInfo() +{ + // try to get the current build information + getter = new HttpGet(this); + RockboxInfo installInfo + = RockboxInfo(RbSettings::value(RbSettings::Mountpoint).toString()); + + themesInfo.open(); + LOG_INFO() << "downloading info to" << themesInfo.fileName(); + themesInfo.close(); + + QString infoUrl = PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesInfoUrl).toString(); + infoUrl.replace("%TARGET%", + RbSettings::value(RbSettings::CurrentPlatform).toString().split(".").at(0)); + infoUrl.replace("%REVISION%", installInfo.revision()); + infoUrl.replace("%RELEASE%", installInfo.release()); + infoUrl.replace("%RBUTILVER%", VERSION); + QUrl url = QUrl(infoUrl); + LOG_INFO() << "Info URL:" << url; + getter->setFile(&themesInfo); + + connect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool))); + connect(logger, SIGNAL(aborted()), getter, SLOT(abort())); + getter->getFile(url); +} + + +void ThemesInstallWindow::downloadDone(int id, bool error) +{ + downloadDone(error); + LOG_INFO() << "Download" << id << "done, error:" << error; +} + + +void ThemesInstallWindow::downloadDone(bool error) +{ + LOG_INFO() << "Download done, error:" << error; + + disconnect(logger, SIGNAL(aborted()), getter, SLOT(abort())); + disconnect(logger, SIGNAL(aborted()), this, SLOT(close())); + themesInfo.open(); + + QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this); + iniDetails.setIniCodec(QTextCodec::codecForName("UTF-8")); + QStringList tl = iniDetails.childGroups(); + LOG_INFO() << "Theme site result:" + << iniDetails.value("error/code").toString() + << iniDetails.value("error/description").toString() + << iniDetails.value("error/query").toString(); + + if(error) { + logger->addItem(tr("Network error: %1.\n" + "Please check your network and proxy settings.") + .arg(getter->errorString()), LOGERROR); + getter->abort(); + logger->setFinished(); + disconnect(getter, SIGNAL(done(bool)), this, SLOT(downloadDone(bool))); + connect(logger, SIGNAL(closed()), this, SLOT(close())); + return; + } + // handle possible error codes + if(iniDetails.value("error/code").toInt() != 0 || !iniDetails.contains("error/code")) { + LOG_ERROR() << "Theme site returned an error:" + << iniDetails.value("error/code"); + logger->addItem(tr("the following error occured:\n%1") + .arg(iniDetails.value("error/description", "unknown error").toString()), LOGERROR); + logger->setFinished(); + connect(logger, SIGNAL(closed()), this, SLOT(close())); + return; + } + logger->addItem(tr("done."), LOGOK); + logger->setFinished(); + logger->close(); + + // setup list + for(int i = 0; i < tl.size(); i++) { + iniDetails.beginGroup(tl.at(i)); + // skip all themes without name field set (i.e. error section) + if(iniDetails.value("name").toString().isEmpty()) { + iniDetails.endGroup(); + continue; + } + LOG_INFO() << "adding to list:" << tl.at(i); + // convert to unicode and replace HTML-specific entities + QByteArray raw = iniDetails.value("name").toByteArray(); + QTextCodec* codec = QTextCodec::codecForHtml(raw); + QString name = codec->toUnicode(raw); + name.replace(""", "\"").replace("&", "&"); + name.replace("<", "<").replace(">", ">"); + QListWidgetItem *w = new QListWidgetItem; + w->setData(Qt::DisplayRole, name.trimmed()); + w->setData(Qt::UserRole, tl.at(i)); + ui.listThemes->addItem(w); + + iniDetails.endGroup(); + } + // check if there's a themes "MOTD" available + if(iniDetails.contains("status/msg")) { + // check if there's a localized msg available + QString lang = RbSettings::value(RbSettings::Language).toString().split("_").at(0); + QString msg; + if(iniDetails.contains("status/msg." + lang)) + msg = iniDetails.value("status/msg." + lang).toString(); + else + msg = iniDetails.value("status/msg").toString(); + LOG_INFO() << "MOTD" << msg; + if(!msg.isEmpty()) + QMessageBox::information(this, tr("Information"), msg); + } +} + + +void ThemesInstallWindow::updateSize(void) +{ + long size = 0; + // sum up size for all selected themes + QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this); + iniDetails.setIniCodec(QTextCodec::codecForName("UTF-8")); + int items = ui.listThemes->selectedItems().size(); + for(int i = 0; i < items; i++) { + iniDetails.beginGroup(ui.listThemes->selectedItems() + .at(i)->data(Qt::UserRole).toString()); + size += iniDetails.value("size").toInt(); + iniDetails.endGroup(); + } + ui.labelSize->setText(tr("Download size %L1 kiB (%n item(s))", "", items) + .arg((size + 512) / 1024)); +} + + +void ThemesInstallWindow::updateDetails(QListWidgetItem* cur, QListWidgetItem* prev) +{ + if(cur == prev) + return; + + QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this); + iniDetails.setIniCodec(QTextCodec::codecForName("UTF-8")); + + QCoreApplication::processEvents(); + ui.themeDescription->setText(tr("fetching details for %1") + .arg(cur->data(Qt::DisplayRole).toString())); + ui.themePreview->clear(); + ui.themePreview->setText(tr("fetching preview ...")); + imgData.clear(); + + iniDetails.beginGroup(cur->data(Qt::UserRole).toString()); + + QUrl img, txt; + txt = QUrl(QString(PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesUrl).toString() + "/" + + iniDetails.value("descriptionfile").toString())); + img = QUrl(QString(PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesUrl).toString() + "/" + + iniDetails.value("image").toString())); + + QString text; + QTextCodec* codec = QTextCodec::codecForName("UTF-8"); + text = tr("Author: %1
").arg(codec->toUnicode(iniDetails + .value("author", tr("unknown")).toByteArray())); + text += tr("Version: %1
").arg(codec->toUnicode(iniDetails + .value("version", tr("unknown")).toByteArray())); + text += tr("Description: %1
").arg(codec->toUnicode(iniDetails + .value("about", tr("no description")).toByteArray())); + + text.replace("\n", "
"); + ui.themeDescription->setHtml(text); + iniDetails.endGroup(); + igetter.abort(); + igetter.getFile(img); +} + + +void ThemesInstallWindow::updateImage(bool error) +{ + LOG_INFO() << "Updating image:"<< !error; + + if(error) { + ui.themePreview->clear(); + ui.themePreview->setText(tr("Retrieving theme preview failed.\n" + "HTTP response code: %1").arg(igetter.httpResponse())); + return; + } + + QPixmap p; + if(!error) { + imgData = igetter.readAll(); + if(imgData.isNull()) return; + p.loadFromData(imgData); + if(p.isNull()) { + ui.themePreview->clear(); + ui.themePreview->setText(tr("no theme preview")); + } + else + ui.themePreview->setPixmap(p); + } +} + + +void ThemesInstallWindow::resizeEvent(QResizeEvent* e) +{ + (void)e; + QPixmap p, q; + QSize img; + img.setHeight(ui.themePreview->height()); + img.setWidth(ui.themePreview->width()); + + p.loadFromData(imgData); + if(p.isNull()) return; + q = p.scaled(img, Qt::KeepAspectRatio, Qt::SmoothTransformation); + ui.themePreview->setScaledContents(false); + ui.themePreview->setPixmap(p); +} + + + +void ThemesInstallWindow::show() +{ + QDialog::show(); + if(windowSelectOnly) + ui.buttonOk->setText(tr("Select")); + + if(!logger) + logger = new ProgressLoggerGui(this); + + if(ui.listThemes->count() == 0) { + logger->show(); + logger->addItem(tr("getting themes information ..."), LOGINFO); + + connect(logger, SIGNAL(aborted()), this, SLOT(close())); + + downloadInfo(); + } + +} + + +void ThemesInstallWindow::abort() +{ + igetter.abort(); + logger->setFinished(); + this->close(); +} + + +void ThemesInstallWindow::accept(void) +{ + if(!windowSelectOnly) + install(); + else + close(); +} + + +void ThemesInstallWindow::install() +{ + if(ui.listThemes->selectedItems().size() == 0) { + logger->addItem(tr("No themes selected, skipping"), LOGINFO); + emit done(false); + return; + } + QStringList themes; + QStringList names; + QStringList version; + QString zip; + QSettings iniDetails(themesInfo.fileName(), QSettings::IniFormat, this); + for(int i = 0; i < ui.listThemes->selectedItems().size(); i++) { + iniDetails.beginGroup(ui.listThemes->selectedItems().at(i)->data(Qt::UserRole).toString()); + zip = PlayerBuildInfo::instance()->value(PlayerBuildInfo::ThemesUrl).toString() + + "/" + iniDetails.value("archive").toString(); + themes.append(zip); + names.append("Theme: " + + ui.listThemes->selectedItems().at(i)->data(Qt::DisplayRole).toString()); + // if no version info is available use installation (current) date + version.append(iniDetails.value("version", + QDate().currentDate().toString("yyyyMMdd")).toString()); + iniDetails.endGroup(); + } + LOG_INFO() << "installing:" << themes; + + if(logger == nullptr) + logger = new ProgressLoggerGui(this); + logger->show(); + QString mountPoint = RbSettings::value(RbSettings::Mountpoint).toString(); + LOG_INFO() << "mountpoint:" << mountPoint; + // show dialog with error if mount point is wrong + if(!QFileInfo(mountPoint).isDir()) { + logger->addItem(tr("Mount point is wrong!"),LOGERROR); + logger->setFinished(); + return; + } + + installer = new ZipInstaller(this); + installer->setUrl(themes); + installer->setLogSection(names); + installer->setLogVersion(version); + installer->setMountPoint(mountPoint); + if(!RbSettings::value(RbSettings::CacheDisabled).toBool()) + installer->setCache(true); + + if(!windowSelectOnly) { + connect(logger, SIGNAL(closed()), this, SLOT(close())); + connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished())); + } + connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int))); + connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int))); + connect(installer, SIGNAL(done(bool)), this, SIGNAL(done(bool))); + connect(logger, SIGNAL(aborted()), installer, SLOT(abort())); + installer->install(); +} + + +void ThemesInstallWindow::changeEvent(QEvent *e) +{ + if(e->type() == QEvent::LanguageChange) { + ui.retranslateUi(this); + } else { + QWidget::changeEvent(e); + } +} + -- cgit v1.2.3