1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2012 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 "selectiveinstallwidget.h"
21 #include "ui_selectiveinstallwidgetfrm.h"
22 #include "serverinfo.h"
23 #include "rbsettings.h"
24 #include "rockboxinfo.h"
25 #include "systeminfo.h"
26 #include "progressloggergui.h"
27 #include "bootloaderinstallbase.h"
28 #include "bootloaderinstallhelper.h"
29 #include "themesinstallwindow.h"
32 SelectiveInstallWidget::SelectiveInstallWidget(QWidget
* parent
) : QWidget(parent
)
35 ui
.rockboxCheckbox
->setChecked(RbSettings::value(RbSettings::InstallRockbox
).toBool());
36 ui
.fontsCheckbox
->setChecked(RbSettings::value(RbSettings::InstallFonts
).toBool());
37 ui
.themesCheckbox
->setChecked(RbSettings::value(RbSettings::InstallThemes
).toBool());
38 ui
.gamefileCheckbox
->setChecked(RbSettings::value(RbSettings::InstallGamefiles
).toBool());
40 // check if Rockbox is installed by looking after rockbox-info.txt.
41 // If installed uncheck bootloader installation.
42 RockboxInfo
info(m_mountpoint
);
43 ui
.bootloaderCheckbox
->setChecked(!info
.success());
46 m_zipinstaller
= NULL
;
47 m_themesinstaller
= NULL
;
49 connect(ui
.installButton
, SIGNAL(clicked()), this, SLOT(startInstall()));
50 connect(this, SIGNAL(installSkipped(bool)), this, SLOT(continueInstall(bool)));
51 connect(ui
.themesCustomize
, SIGNAL(clicked()), this, SLOT(customizeThemes()));
52 connect(ui
.selectedVersion
, SIGNAL(currentIndexChanged(int)),
53 this, SLOT(selectedVersionChanged(int)));
54 // update version information. This also handles setting the previously
55 // selected build type and bootloader disabling.
60 void SelectiveInstallWidget::selectedVersionChanged(int index
)
62 QString current
= ui
.selectedVersion
->itemData(index
).toString();
63 if(current
== "release")
64 ui
.selectedDescription
->setText(tr("This is the latest stable "
65 "release available."));
66 if(current
== "current")
67 ui
.selectedDescription
->setText(tr("The development version is "
68 "updated on every code change. Last update was on %1").arg(
69 ServerInfo::value(ServerInfo::BleedingDate
).toString()));
71 ui
.selectedDescription
->setText(tr("This will eventually become the "
72 "next Rockbox version. Install it to help testing."));
76 void SelectiveInstallWidget::updateVersion(void)
78 // get some configuration values globally
79 m_mountpoint
= RbSettings::value(RbSettings::Mountpoint
).toString();
80 m_target
= RbSettings::value(RbSettings::CurrentPlatform
).toString();
81 m_blmethod
= SystemInfo::platformValue(m_target
,
82 SystemInfo::CurBootloaderMethod
).toString();
84 if(m_logger
!= NULL
) {
89 // re-populate all version items
91 m_versions
.insert("release", ServerInfo::value(ServerInfo::CurReleaseVersion
).toString());
92 m_versions
.insert("current", ServerInfo::value(ServerInfo::BleedingRevision
).toString());
93 m_versions
.insert("rc", ServerInfo::value(ServerInfo::RelCandidateVersion
).toString());
95 ui
.selectedVersion
->clear();
96 if(!m_versions
["release"].isEmpty()) {
97 ui
.selectedVersion
->addItem(tr("Stable Release (Version %1)").arg(
98 m_versions
["release"]), "release");
100 if(!m_versions
["current"].isEmpty()) {
101 ui
.selectedVersion
->addItem(tr("Development Version (Revison %1)").arg(
102 m_versions
["current"]), "current");
104 if(!m_versions
["rc"].isEmpty()) {
105 ui
.selectedVersion
->addItem(tr("Release Candidate (Revison %1)").arg(
106 m_versions
["rc"]), "rc");
109 // select previously selected version
110 int index
= ui
.selectedVersion
->findData(RbSettings::value(RbSettings::Build
).toString());
112 ui
.selectedVersion
->setCurrentIndex(index
);
115 index
= ui
.selectedVersion
->findData("release");
116 ui
.selectedVersion
->setCurrentIndex(index
);
118 // check if Rockbox is installed. If it is untick the bootloader option, as
119 // well as if the selected player doesn't need a bootloader.
120 if(m_blmethod
== "none") {
121 ui
.bootloaderCheckbox
->setEnabled(false);
122 ui
.bootloaderLabel
->setEnabled(false);
123 ui
.bootloaderLabel
->setText(tr("The selected player doesn't need a bootloader."));
126 ui
.bootloaderCheckbox
->setEnabled(true);
127 ui
.bootloaderLabel
->setEnabled(true);
128 ui
.bootloaderLabel
->setText(tr("The bootloader is required for starting "
129 "Rockbox. Installation of the bootloader is only necessary "
130 "on first time installation."));
133 // check if Rockbox is installed by looking after rockbox-info.txt.
134 // If installed uncheck bootloader installation.
135 RockboxInfo
info(m_mountpoint
);
136 ui
.bootloaderCheckbox
->setChecked(!info
.success());
141 void SelectiveInstallWidget::saveSettings(void)
143 qDebug() << "[SelectiveInstallWidget] saving current settings";
145 RbSettings::setValue(RbSettings::InstallRockbox
, ui
.rockboxCheckbox
->isChecked());
146 RbSettings::setValue(RbSettings::InstallFonts
, ui
.fontsCheckbox
->isChecked());
147 RbSettings::setValue(RbSettings::InstallThemes
, ui
.themesCheckbox
->isChecked());
148 RbSettings::setValue(RbSettings::InstallGamefiles
, ui
.gamefileCheckbox
->isChecked());
152 void SelectiveInstallWidget::startInstall(void)
154 qDebug() << "[SelectiveInstallWidget] starting installation";
157 if(m_logger
!= NULL
) delete m_logger
;
158 m_logger
= new ProgressLoggerGui(this);
160 if(!QFileInfo(m_mountpoint
).isDir()) {
161 m_logger
->addItem(tr("Mountpoint is wrong"), LOGERROR
);
162 m_logger
->setFinished();
165 // start installation. No errors until now.
166 continueInstall(false);
171 void SelectiveInstallWidget::continueInstall(bool error
)
173 qDebug() << "[SelectiveInstallWidget] continuing install with stage" << m_installStage
;
175 qDebug() << "[SelectiveInstallWidget] Last part returned error.";
176 m_logger
->setFinished();
180 switch(m_installStage
) {
181 case 0: qDebug() << "[SelectiveInstallWidget] Something wrong!"; break;
182 case 1: installBootloader(); break;
183 case 2: installRockbox(); break;
184 case 3: installFonts(); break;
185 case 4: installThemes(); break;
186 case 5: installGamefiles(); break;
187 case 6: installBootloaderPost(); break;
191 if(m_installStage
> 6) {
192 qDebug() << "[SelectiveInstallWidget] All install stages done.";
193 m_logger
->setFinished();
194 // check if Rockbox is installed by looking after rockbox-info.txt.
195 // If installed uncheck bootloader installation.
196 RockboxInfo
info(m_mountpoint
);
197 ui
.bootloaderCheckbox
->setChecked(!info
.success());
202 void SelectiveInstallWidget::installBootloader(void)
204 if(ui
.bootloaderCheckbox
->isChecked()) {
205 qDebug() << "[SelectiveInstallWidget] installing bootloader";
207 QString platform
= RbSettings::value(RbSettings::Platform
).toString();
208 QString backupDestination
= "";
211 BootloaderInstallBase
*bl
=
212 BootloaderInstallHelper::createBootloaderInstaller(this,
213 SystemInfo::value(SystemInfo::CurBootloaderMethod
).toString());
215 m_logger
->addItem(tr("No install method known."), LOGERROR
);
216 m_logger
->setFinished();
220 // the bootloader install class does NOT use any GUI stuff.
221 // All messages are passed via signals.
222 connect(bl
, SIGNAL(done(bool)), m_logger
, SLOT(setFinished()));
223 connect(bl
, SIGNAL(done(bool)), this, SLOT(continueInstall(bool)));
224 connect(bl
, SIGNAL(logItem(QString
, int)), m_logger
, SLOT(addItem(QString
, int)));
225 connect(bl
, SIGNAL(logProgress(int, int)), m_logger
, SLOT(setProgress(int, int)));
227 // set bootloader filename. Do this now as installed() needs it.
228 QStringList blfile
= SystemInfo::value(SystemInfo::CurBootloaderFile
).toStringList();
229 QStringList blfilepath
;
230 for(int a
= 0; a
< blfile
.size(); a
++) {
231 blfilepath
.append(RbSettings::value(RbSettings::Mountpoint
).toString()
234 bl
->setBlFile(blfilepath
);
235 QUrl
url(SystemInfo::value(SystemInfo::BootloaderUrl
).toString()
236 + SystemInfo::value(SystemInfo::CurBootloaderName
).toString());
238 bl
->setLogfile(RbSettings::value(RbSettings::Mountpoint
).toString()
239 + "/.rockbox/rbutil.log");
241 if(bl
->installed() == BootloaderInstallBase::BootloaderRockbox
) {
242 if(QMessageBox::question(this, tr("Bootloader detected"),
243 tr("Bootloader already installed. Do you want to reinstall the bootloader?"),
244 QMessageBox::Yes
| QMessageBox::No
) == QMessageBox::No
) {
245 // keep m_logger open for auto installs.
246 // don't consider abort as error in auto-mode.
247 m_logger
->addItem(tr("Bootloader installation skipped"), LOGINFO
);
249 emit
installSkipped(true);
253 else if(bl
->installed() == BootloaderInstallBase::BootloaderOther
254 && bl
->capabilities() & BootloaderInstallBase::Backup
)
256 QString targetFolder
= SystemInfo::value(SystemInfo::CurPlatformName
).toString()
257 + " Firmware Backup";
258 // remove invalid character(s)
259 targetFolder
.remove(QRegExp("[:/]"));
260 if(QMessageBox::question(this, tr("Create Bootloader backup"),
261 tr("You can create a backup of the original bootloader "
262 "file. Press \"Yes\" to select an output folder on your "
263 "computer to save the file to. The file will get placed "
264 "in a new folder \"%1\" created below the selected folder.\n"
265 "Press \"No\" to skip this step.").arg(targetFolder
),
266 QMessageBox::Yes
| QMessageBox::No
) == QMessageBox::Yes
) {
267 backupDestination
= QFileDialog::getExistingDirectory(this,
268 tr("Browse backup folder"), QDir::homePath());
269 if(!backupDestination
.isEmpty())
270 backupDestination
+= "/" + targetFolder
;
272 qDebug() << "[RbUtil] backing up to" << backupDestination
;
273 // backup needs to be done after the m_logger has been set up.
277 if(bl
->capabilities() & BootloaderInstallBase::NeedsOf
)
280 ret
= QMessageBox::information(this, tr("Prerequisites"),
281 bl
->ofHint(),QMessageBox::Ok
| QMessageBox::Abort
);
282 if(ret
!= QMessageBox::Ok
) {
283 // consider aborting an error to close window / abort automatic
285 m_logger
->addItem(tr("Bootloader installation aborted"), LOGINFO
);
286 m_logger
->setFinished();
287 emit
installSkipped(true);
290 // open dialog to browse to of file
293 = SystemInfo::value(SystemInfo::CurBootloaderFilter
).toString();
294 if(!filter
.isEmpty()) {
295 filter
= tr("Bootloader files (%1)").arg(filter
) + ";;";
297 filter
+= tr("All files (*)");
298 offile
= QFileDialog::getOpenFileName(this,
299 tr("Select firmware file"), QDir::homePath(), filter
);
300 if(!QFileInfo(offile
).isReadable()) {
301 m_logger
->addItem(tr("Error opening firmware file"), LOGERROR
);
302 m_logger
->setFinished();
303 emit
installSkipped(true);
306 if(!bl
->setOfFile(offile
, blfile
)) {
307 m_logger
->addItem(tr("Error reading firmware file"), LOGERROR
);
308 m_logger
->setFinished();
309 emit
installSkipped(true);
315 if(!backupDestination
.isEmpty()) {
316 if(!bl
->backup(backupDestination
)) {
317 if(QMessageBox::warning(this, tr("Backup error"),
318 tr("Could not create backup file. Continue?"),
319 QMessageBox::No
| QMessageBox::Yes
)
320 == QMessageBox::No
) {
321 m_logger
->setFinished();
330 qDebug() << "[SelectiveInstallWidget] Bootloader install disabled.";
331 emit
installSkipped(false);
335 void SelectiveInstallWidget::installBootloaderPost()
337 // don't do anything if no bootloader install has been done.
338 if(ui
.bootloaderCheckbox
->isChecked()) {
339 QString msg
= BootloaderInstallHelper::postinstallHints(
340 RbSettings::value(RbSettings::Platform
).toString());
342 QMessageBox::information(this, tr("Manual steps required"), msg
);
345 emit
installSkipped(false);
349 void SelectiveInstallWidget::installRockbox(void)
351 if(ui
.rockboxCheckbox
->isChecked()) {
352 qDebug() << "[SelectiveInstallWidget] installing Rockbox";
355 QString selected
= ui
.selectedVersion
->itemData(ui
.selectedVersion
->currentIndex()).toString();
356 RbSettings::setValue(RbSettings::Build
, selected
);
359 QString warning
= Utils::checkEnvironment(false);
360 if(!warning
.isEmpty())
362 warning
+= "<br/>" + tr("Continue with installation?");
363 if(QMessageBox::warning(this, tr("Really continue?"), warning
,
364 QMessageBox::Ok
| QMessageBox::Abort
, QMessageBox::Abort
)
365 == QMessageBox::Abort
)
367 m_logger
->addItem(tr("Aborted!"),LOGERROR
);
368 m_logger
->setFinished();
369 emit
installSkipped(true);
374 if(selected
== "release") url
= ServerInfo::platformValue(m_target
,
375 ServerInfo::CurReleaseUrl
).toString();
376 else if(selected
== "current") url
= ServerInfo::platformValue(m_target
,
377 ServerInfo::CurDevelUrl
).toString();
378 else if(selected
== "rc") url
= ServerInfo::platformValue(m_target
,
379 ServerInfo::RelCandidateUrl
).toString();
382 RockboxInfo
info(m_mountpoint
);
384 // existing installation found. Ask for backup.
385 QMessageBox::information(this, tr("Backup existing installation?"),
386 tr("Existing installation detected. Create a backup before installing?"),
387 QMessageBox::Yes
| QMessageBox::No
, QMessageBox::No
);
392 //! check if we should backup
393 if(ui
.backup
->isChecked())
395 m_logger
->addItem(tr("Beginning Backup..."),LOGINFO
);
396 QCoreApplication::processEvents();
398 //! create dir, if it doesnt exist
399 QFileInfo
backupFile(m_backupName
);
400 if(!QDir(backupFile
.path()).exists())
403 a
.mkpath(backupFile
.path());
409 connect(&zip
, SIGNAL(logProgress(int, int)), m_logger
, SLOT(setProgress(int, int)));
410 connect(&zip
, SIGNAL(logItem(QString
, int)), m_logger
, SLOT(addItem(QString
, int)));
411 zip
.open(m_backupName
, QuaZip::mdCreate
);
412 QString mp
= RbSettings::value(RbSettings::Mountpoint
).toString();
413 QString folder
= mp
+ "/.rockbox";
414 result
= zip
.appendDirToArchive(folder
, mp
);
417 m_logger
->addItem(tr("Backup finished."), LOGINFO
);
420 m_logger
->addItem(tr("Backup failed!"), LOGERROR
);
421 m_logger
->setFinished();
428 if(m_zipinstaller
!= NULL
) delete m_zipinstaller
;
429 m_zipinstaller
= new ZipInstaller(this);
430 m_zipinstaller
->setUrl(url
);
431 m_zipinstaller
->setLogSection("Rockbox (Base)");
432 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
433 m_zipinstaller
->setCache(true);
434 m_zipinstaller
->setLogVersion(m_versions
[selected
]);
435 m_zipinstaller
->setMountPoint(m_mountpoint
);
437 connect(m_zipinstaller
, SIGNAL(done(bool)), this, SLOT(continueInstall(bool)));
439 connect(m_zipinstaller
, SIGNAL(logItem(QString
, int)), m_logger
, SLOT(addItem(QString
, int)));
440 connect(m_zipinstaller
, SIGNAL(logProgress(int, int)), m_logger
, SLOT(setProgress(int, int)));
441 connect(m_logger
, SIGNAL(aborted()), m_zipinstaller
, SLOT(abort()));
442 m_zipinstaller
->install();
446 qDebug() << "[SelectiveInstallWidget] Rockbox install disabled.";
447 emit
installSkipped(false);
452 void SelectiveInstallWidget::installFonts(void)
454 if(ui
.fontsCheckbox
->isChecked()) {
455 qDebug() << "[SelectiveInstallWidget] installing Fonts";
457 RockboxInfo
installInfo(m_mountpoint
);
460 QString relversion
= installInfo
.release();
461 if(relversion
.isEmpty()) {
462 // release is empty for non-release versions (i.e. daily / current)
463 fontsurl
= SystemInfo::value(SystemInfo::DailyFontUrl
).toString();
466 fontsurl
= SystemInfo::value(SystemInfo::ReleaseFontUrl
).toString();
467 logversion
= installInfo
.release();
469 fontsurl
.replace("%RELEASEVER%", relversion
);
471 // create new zip installer
472 if(m_zipinstaller
!= NULL
) delete m_zipinstaller
;
473 m_zipinstaller
= new ZipInstaller(this);
474 m_zipinstaller
->setUrl(fontsurl
);
475 m_zipinstaller
->setLogSection("Fonts");
476 m_zipinstaller
->setLogVersion(logversion
);
477 m_zipinstaller
->setMountPoint(m_mountpoint
);
478 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
479 m_zipinstaller
->setCache(true);
481 connect(m_zipinstaller
, SIGNAL(done(bool)), this, SLOT(continueInstall(bool)));
482 connect(m_zipinstaller
, SIGNAL(logItem(QString
, int)), m_logger
, SLOT(addItem(QString
, int)));
483 connect(m_zipinstaller
, SIGNAL(logProgress(int, int)), m_logger
, SLOT(setProgress(int, int)));
484 connect(m_logger
, SIGNAL(aborted()), m_zipinstaller
, SLOT(abort()));
485 m_zipinstaller
->install();
488 qDebug() << "[SelectiveInstallWidget] Fonts install disabled.";
489 emit
installSkipped(false);
493 void SelectiveInstallWidget::customizeThemes(void)
495 if(m_themesinstaller
== NULL
)
496 m_themesinstaller
= new ThemesInstallWindow(this);
498 m_themesinstaller
->setSelectOnly(true);
499 m_themesinstaller
->show();
503 void SelectiveInstallWidget::installThemes(void)
505 if(ui
.themesCheckbox
->isChecked()) {
506 qDebug() << "[SelectiveInstallWidget] installing themes";
507 if(m_themesinstaller
== NULL
)
508 m_themesinstaller
= new ThemesInstallWindow(this);
510 m_themesinstaller
->setLogger(m_logger
);
511 m_themesinstaller
->setModal(true);
512 m_themesinstaller
->install();
513 connect(m_themesinstaller
, SIGNAL(done(bool)), this, SLOT(continueInstall(bool)));
516 qDebug() << "[SelectiveInstallWidget] Themes install disabled.";
517 emit
installSkipped(false);
522 void SelectiveInstallWidget::installGamefiles(void)
524 if(ui
.gamefileCheckbox
->isChecked()) {
525 // check if installed Rockbox has doom plugin. If not disable doom.
526 if(!QFileInfo(m_mountpoint
+ "/.rockbox/rocks/games/doom.rock").exists()) {
527 m_logger
->addItem(tr("Your installation doesn't require game files, skipping."), LOGINFO
);
528 emit
installSkipped(false);
530 qDebug() << "[SelectiveInstallWidget] installing gamefiles";
531 // create new zip installer
532 if(m_zipinstaller
!= NULL
) delete m_zipinstaller
;
533 m_zipinstaller
= new ZipInstaller(this);
535 m_zipinstaller
->setUrl(SystemInfo::value(SystemInfo::DoomUrl
).toString());
536 m_zipinstaller
->setLogSection("Game Addons");
537 m_zipinstaller
->setLogVersion();
538 m_zipinstaller
->setMountPoint(m_mountpoint
);
539 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
540 m_zipinstaller
->setCache(true);
541 connect(m_zipinstaller
, SIGNAL(done(bool)), this, SLOT(continueInstall(bool)));
542 connect(m_zipinstaller
, SIGNAL(logItem(QString
, int)), m_logger
, SLOT(addItem(QString
, int)));
543 connect(m_zipinstaller
, SIGNAL(logProgress(int, int)), m_logger
, SLOT(setProgress(int, int)));
544 connect(m_logger
, SIGNAL(aborted()), m_zipinstaller
, SLOT(abort()));
545 m_zipinstaller
->install();
548 qDebug() << "[SelectiveInstallWidget] Gamefile install disabled.";
549 emit
installSkipped(false);
553 void SelectiveInstallWidget::changeEvent(QEvent
*e
)
555 if(e
->type() == QEvent::LanguageChange
) {
556 ui
.retranslateUi(this);
558 QWidget::changeEvent(e
);