rbutil: enforce parents for bootloader install classes. and rework OF handling a...
[kugel-rb.git] / rbutil / rbutilqt / rbutilqt.cpp
blob3a594ef0adf9bbc787c28e07a9c87984169d4ab8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
9 * Copyright (C) 2007 by Dominik Riebeling
10 * $Id$
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 #include <QtGui>
22 #include "version.h"
23 #include "rbutilqt.h"
24 #include "ui_rbutilqtfrm.h"
25 #include "ui_aboutbox.h"
26 #include "configure.h"
27 #include "install.h"
28 #include "installtalkwindow.h"
29 #include "createvoicewindow.h"
30 #include "httpget.h"
31 #include "themesinstallwindow.h"
32 #include "uninstallwindow.h"
33 #include "utils.h"
34 #include "rbzip.h"
35 #include "sysinfo.h"
36 #include "detect.h"
37 #include "rbsettings.h"
39 #include "progressloggerinterface.h"
41 #include "bootloaderinstallbase.h"
42 #include "bootloaderinstallmi4.h"
43 #include "bootloaderinstallhex.h"
44 #include "bootloaderinstallipod.h"
45 #include "bootloaderinstallsansa.h"
46 #include "bootloaderinstallfile.h"
48 #if defined(Q_OS_LINUX)
49 #include <stdio.h>
50 #endif
51 #if defined(Q_OS_WIN32)
52 #if defined(UNICODE)
53 #define _UNICODE
54 #endif
55 #include <stdio.h>
56 #include <tchar.h>
57 #include <windows.h>
58 #endif
60 RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent)
62 absolutePath = qApp->applicationDirPath();
64 HttpGet::setGlobalUserAgent("rbutil/"VERSION);
65 // init startup & autodetection
66 ui.setupUi(this);
67 updateSettings();
68 downloadInfo();
70 m_gotInfo = false;
71 m_auto = false;
73 // manual tab
74 ui.radioPdf->setChecked(true);
76 // info tab
77 ui.treeInfo->setAlternatingRowColors(true);
78 ui.treeInfo->setHeaderLabels(QStringList() << tr("File") << tr("Version"));
79 ui.treeInfo->expandAll();
80 ui.treeInfo->setColumnCount(2);
81 // disable quick install until version info is available
82 ui.buttonSmall->setEnabled(false);
83 ui.buttonComplete->setEnabled(false);
85 connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateTabs(int)));
86 connect(ui.actionAbout_Qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
87 connect(ui.action_About, SIGNAL(triggered()), this, SLOT(about()));
88 connect(ui.action_Help, SIGNAL(triggered()), this, SLOT(help()));
89 connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog()));
90 connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog()));
91 connect(ui.buttonRockbox, SIGNAL(clicked()), this, SLOT(installBtn()));
92 connect(ui.buttonBootloader, SIGNAL(clicked()), this, SLOT(installBootloaderBtn()));
93 connect(ui.buttonFonts, SIGNAL(clicked()), this, SLOT(installFontsBtn()));
94 connect(ui.buttonGames, SIGNAL(clicked()), this, SLOT(installDoomBtn()));
95 connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles()));
96 connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile()));
97 connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice()));
98 connect(ui.buttonThemes, SIGNAL(clicked()), this, SLOT(installThemes()));
99 connect(ui.buttonRemoveRockbox, SIGNAL(clicked()), this, SLOT(uninstall()));
100 connect(ui.buttonRemoveBootloader, SIGNAL(clicked()), this, SLOT(uninstallBootloader()));
101 connect(ui.buttonDownloadManual, SIGNAL(clicked()), this, SLOT(downloadManual()));
102 connect(ui.buttonSmall, SIGNAL(clicked()), this, SLOT(smallInstall()));
103 connect(ui.buttonComplete, SIGNAL(clicked()), this, SLOT(completeInstall()));
105 // actions accessible from the menu
106 connect(ui.actionComplete_Installation, SIGNAL(triggered()), this, SLOT(completeInstall()));
107 connect(ui.actionSmall_Installation, SIGNAL(triggered()), this, SLOT(smallInstall()));
108 connect(ui.actionInstall_Bootloader, SIGNAL(triggered()), this, SLOT(installBootloaderBtn()));
109 connect(ui.actionInstall_Rockbox, SIGNAL(triggered()), this, SLOT(installBtn()));
110 connect(ui.actionFonts_Package, SIGNAL(triggered()), this, SLOT(installFontsBtn()));
111 connect(ui.actionInstall_Themes, SIGNAL(triggered()), this, SLOT(installThemes()));
112 connect(ui.actionInstall_Game_Files, SIGNAL(triggered()), this, SLOT(installDoomBtn()));
113 connect(ui.actionInstall_Voice_File, SIGNAL(triggered()), this, SLOT(installVoice()));
114 connect(ui.actionCreate_Voice_File, SIGNAL(triggered()), this, SLOT(createVoiceFile()));
115 connect(ui.actionCreate_Talk_Files, SIGNAL(triggered()), this, SLOT(createTalkFiles()));
116 connect(ui.actionRemove_bootloader, SIGNAL(triggered()), this, SLOT(uninstallBootloader()));
117 connect(ui.actionUninstall_Rockbox, SIGNAL(triggered()), this, SLOT(uninstall()));
118 connect(ui.action_System_Info, SIGNAL(triggered()), this, SLOT(sysinfo()));
120 #if !defined(STATIC)
121 ui.actionInstall_Rockbox_Utility_on_player->setEnabled(false);
122 #else
123 connect(ui.actionInstall_Rockbox_Utility_on_player, SIGNAL(triggered()), this, SLOT(installPortable()));
124 #endif
129 void RbUtilQt::sysinfo(void)
131 Sysinfo *info = new Sysinfo(this);
132 info->show();
135 void RbUtilQt::updateTabs(int count)
137 switch(count) {
138 case 6:
139 updateInfo();
140 break;
141 default:
142 break;
147 void RbUtilQt::downloadInfo()
149 // make sure the version map is repopulated correctly later.
150 versmap.clear();
151 // try to get the current build information
152 daily = new HttpGet(this);
153 connect(daily, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
154 connect(daily, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
155 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
156 if(RbSettings::value(RbSettings::CacheOffline).toBool())
157 daily->setCache(true);
158 else
159 daily->setCache(false);
160 qDebug() << "downloading build info";
161 daily->setFile(&buildInfo);
162 daily->getFile(QUrl(RbSettings::value(RbSettings::ServerConfUrl).toString()));
166 void RbUtilQt::downloadDone(bool error)
168 if(error) {
169 qDebug() << "network error:" << daily->error();
170 QMessageBox::critical(this, tr("Network error"),
171 tr("Can't get version information."));
172 return;
174 qDebug() << "network status:" << daily->error();
176 buildInfo.open();
177 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
178 buildInfo.close();
179 versmap.insert("arch_rev", info.value("dailies/rev").toString());
180 versmap.insert("arch_date", info.value("dailies/date").toString());
182 info.beginGroup("release");
183 versmap.insert("rel_rev", info.value(RbSettings::value(RbSettings::CurBuildserverModel).toString()).toString());
184 info.endGroup();
186 if(versmap.value("rel_rev").isEmpty()) {
187 ui.buttonSmall->setEnabled(false);
188 ui.buttonComplete->setEnabled(false);
190 else {
191 ui.buttonSmall->setEnabled(true);
192 ui.buttonComplete->setEnabled(true);
195 bleeding = new HttpGet(this);
196 connect(bleeding, SIGNAL(done(bool)), this, SLOT(downloadBleedingDone(bool)));
197 connect(bleeding, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
198 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
199 if(RbSettings::value(RbSettings::CacheOffline).toBool())
200 bleeding->setCache(true);
201 bleeding->setFile(&bleedingInfo);
202 bleeding->getFile(QUrl(RbSettings::value(RbSettings::BleedingInfo).toString()));
204 if(RbSettings::value(RbSettings::RbutilVersion) != PUREVERSION) {
205 QApplication::processEvents();
206 QMessageBox::information(this, tr("New installation"),
207 tr("This is a new installation of Rockbox Utility, or a new version. "
208 "The configuration dialog will now open to allow you to setup the program, "
209 " or review your settings."));
210 configDialog();
212 else if(chkConfig(false)) {
213 QApplication::processEvents();
214 QMessageBox::critical(this, tr("Configuration error"),
215 tr("Your configuration is invalid. This is most likely due "
216 "to a changed device path. The configuration dialog will "
217 "now open to allow you to correct the problem."));
218 configDialog();
223 void RbUtilQt::downloadBleedingDone(bool error)
225 if(error) {
226 qDebug() << "network error:" << bleeding->error();
228 else {
229 bleedingInfo.open();
230 QSettings info(bleedingInfo.fileName(), QSettings::IniFormat, this);
231 bleedingInfo.close();
232 versmap.insert("bleed_rev", info.value("bleeding/rev").toString());
233 versmap.insert("bleed_date", info.value("bleeding/timestamp").toString());
234 qDebug() << "versmap =" << versmap;
236 m_gotInfo = true;
241 void RbUtilQt::downloadDone(int id, bool error)
243 QString errorString;
244 errorString = tr("Network error: %1. Please check your network and proxy settings.")
245 .arg(daily->errorString());
246 if(error) {
247 QMessageBox::about(this, "Network Error", errorString);
248 m_networkerror = daily->errorString();
250 qDebug() << "downloadDone:" << id << "error:" << error;
254 void RbUtilQt::about()
256 QDialog *window = new QDialog(this);
257 Ui::aboutBox about;
258 about.setupUi(window);
259 window->setModal(true);
261 QFile licence(":/docs/gpl-2.0.html");
262 licence.open(QIODevice::ReadOnly);
263 QTextStream c(&licence);
264 QString cline = c.readAll();
265 about.browserLicense->insertHtml(cline);
266 about.browserLicense->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
267 QFile credits(":/docs/CREDITS");
268 credits.open(QIODevice::ReadOnly);
269 QTextStream r(&credits);
270 r.setCodec(QTextCodec::codecForName("UTF-8"));
271 QString rline = r.readAll();
272 about.browserCredits->insertPlainText(rline);
273 about.browserCredits->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
274 QString title = QString("<b>The Rockbox Utility</b><br/>Version %1").arg(FULLVERSION);
275 about.labelTitle->setText(title);
276 about.labelHomepage->setText("<a href='http://www.rockbox.org'>http://www.rockbox.org</a>");
278 window->show();
283 void RbUtilQt::help()
285 QUrl helpurl("http://www.rockbox.org/wiki/RockboxUtility");
286 QDesktopServices::openUrl(helpurl);
290 void RbUtilQt::configDialog()
292 Config *cw = new Config(this);
293 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
294 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
295 cw->show();
299 void RbUtilQt::updateSettings()
301 qDebug() << "updateSettings()";
302 updateDevice();
303 updateManual();
304 if(RbSettings::value(RbSettings::ProxyType) == "system") {
305 HttpGet::setGlobalProxy(Detect::systemProxy());
307 else if(RbSettings::value(RbSettings::ProxyType) == "manual") {
308 HttpGet::setGlobalProxy(RbSettings::value(RbSettings::Proxy).toString());
310 else {
311 HttpGet::setGlobalProxy(QUrl(""));
313 HttpGet::setGlobalCache(RbSettings::value(RbSettings::CachePath).toString());
314 HttpGet::setGlobalDumbCache(RbSettings::value(RbSettings::CacheOffline).toBool());
318 void RbUtilQt::updateDevice()
320 if(RbSettings::value(RbSettings::CurBootloaderMethod) == "none" ) {
321 ui.buttonBootloader->setEnabled(false);
322 ui.buttonRemoveBootloader->setEnabled(false);
323 ui.labelBootloader->setEnabled(false);
324 ui.labelRemoveBootloader->setEnabled(false);
326 else {
327 ui.buttonBootloader->setEnabled(true);
328 ui.labelBootloader->setEnabled(true);
329 if(RbSettings::value(RbSettings::CurBootloaderMethod) == "fwpatcher") {
330 ui.labelRemoveBootloader->setEnabled(false);
331 ui.buttonRemoveBootloader->setEnabled(false);
333 else {
334 ui.labelRemoveBootloader->setEnabled(true);
335 ui.buttonRemoveBootloader->setEnabled(true);
339 // displayed device info
340 QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
341 QString brand = RbSettings::value(RbSettings::CurBrand).toString();
342 QString name = RbSettings::value(RbSettings::CurName).toString();
343 if(name.isEmpty()) name = "&lt;none&gt;";
344 if(mountpoint.isEmpty()) mountpoint = "&lt;invalid&gt;";
345 ui.labelDevice->setText(tr("<b>%1 %2</b> at <b>%3</b>")
346 .arg(brand, name, QDir::toNativeSeparators(mountpoint)));
350 void RbUtilQt::updateManual()
352 if(RbSettings::value(RbSettings::Platform) != "")
354 QString manual= RbSettings::value(RbSettings::CurManual).toString();
356 if(manual == "")
357 manual = "rockbox-" + RbSettings::value(RbSettings::Platform).toString();
358 QString pdfmanual;
359 pdfmanual = RbSettings::value(RbSettings::ManualUrl).toString()
360 + "/" + manual + ".pdf";
361 QString htmlmanual;
362 htmlmanual = RbSettings::value(RbSettings::ManualUrl).toString()
363 + "/" + manual + "/rockbox-build.html";
364 ui.labelPdfManual->setText(tr("<a href='%1'>PDF Manual</a>")
365 .arg(pdfmanual));
366 ui.labelHtmlManual->setText(tr("<a href='%1'>HTML Manual (opens in browser)</a>")
367 .arg(htmlmanual));
369 else {
370 ui.labelPdfManual->setText(tr("Select a device for a link to the correct manual"));
371 ui.labelHtmlManual->setText(tr("<a href='%1'>Manual Overview</a>")
372 .arg("http://www.rockbox.org/manual.shtml"));
377 void RbUtilQt::completeInstall()
379 if(chkConfig(true)) return;
380 if(QMessageBox::question(this, tr("Confirm Installation"),
381 tr("Do you really want to perform a complete installation?\n\n"
382 "This will install Rockbox %1. To install the most recent "
383 "development build available press \"Cancel\" and "
384 "use the \"Installation\" tab.")
385 .arg(versmap.value("rel_rev")),
386 QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok)
387 return;
388 // create logger
389 logger = new ProgressLoggerGui(this);
390 logger->show();
392 if(smallInstallInner())
393 return;
394 logger->setRunning();
395 // Fonts
396 m_error = false;
397 m_installed = false;
398 if(!installFontsAuto())
399 return;
400 else
402 // wait for installation finished
403 while(!m_installed)
404 QApplication::processEvents();
406 if(m_error) return;
407 logger->setRunning();
409 // Doom
410 if(hasDoom())
412 m_error = false;
413 m_installed = false;
414 if(!installDoomAuto())
415 return;
416 else
418 // wait for installation finished
419 while(!m_installed)
420 QApplication::processEvents();
422 if(m_error) return;
425 // theme
426 // this is a window
427 // it has its own logger window,so close our.
428 logger->close();
429 installThemes();
433 void RbUtilQt::smallInstall()
435 if(chkConfig(true)) return;
436 if(QMessageBox::question(this, tr("Confirm Installation"),
437 tr("Do you really want to perform a minimal installation? "
438 "A minimal installation will contain only the absolutely "
439 "necessary parts to run Rockbox.\n\n"
440 "This will install Rockbox %1. To install the most recent "
441 "development build available press \"Cancel\" and "
442 "use the \"Installation\" tab.")
443 .arg(versmap.value("rel_rev")),
444 QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok)
445 return;
447 // create logger
448 logger = new ProgressLoggerGui(this);
449 logger->show();
451 smallInstallInner();
454 bool RbUtilQt::smallInstallInner()
456 QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
457 // show dialog with error if mount point is wrong
458 if(!QFileInfo(mountpoint).isDir()) {
459 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
460 logger->setFinished();
461 return true;
463 // Bootloader
464 if(RbSettings::value(RbSettings::CurBootloaderMethod) != "none")
466 m_error = false;
467 m_installed = false;
468 m_auto = true;
469 if(!installBootloaderAuto()) {
470 logger->setFinished();
471 return true;
473 else
475 // wait for boot loader installation finished
476 while(!m_installed)
477 QApplication::processEvents();
479 m_auto = false;
480 if(m_error) return true;
481 logger->setRunning();
484 // Rockbox
485 m_error = false;
486 m_installed = false;
487 if(!installAuto())
488 return true;
489 else
491 // wait for installation finished
492 while(!m_installed)
493 QApplication::processEvents();
496 installBootloaderPost(false);
497 return false;
500 void RbUtilQt::installdone(bool error)
502 qDebug() << "install done";
503 m_installed = true;
504 m_error = error;
507 void RbUtilQt::installBtn()
509 if(chkConfig(true)) return;
510 install();
513 bool RbUtilQt::installAuto()
515 QString file = QString("%1/%2/rockbox-%3-%4.zip")
516 .arg(RbSettings::value(RbSettings::ReleaseUrl).toString(),
517 versmap.value("rel_rev"),
518 RbSettings::value(RbSettings::CurBuildserverModel).toString(),
519 versmap.value("rel_rev"));
520 buildInfo.open();
521 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
522 buildInfo.close();
524 // check installed Version and Target
525 QString rbVersion = Detect::installedVersion(RbSettings::value(RbSettings::Mountpoint).toString());
526 QString warning = Detect::check(false);
528 if(!warning.isEmpty())
530 if(QMessageBox::warning(this, tr("Really continue?"), warning,
531 QMessageBox::Ok | QMessageBox::Abort, QMessageBox::Abort) == QMessageBox::Abort)
533 logger->addItem(tr("Aborted!"), LOGERROR);
534 logger->setFinished();
535 return false;
539 // check version
540 if(rbVersion != "")
542 if(QMessageBox::question(this, tr("Installed Rockbox detected"),
543 tr("Rockbox installation detected. Do you want to backup first?"),
544 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
546 logger->addItem(tr("Starting backup..."),LOGINFO);
547 QString backupName = RbSettings::value(RbSettings::Mountpoint).toString()
548 + "/.backup/rockbox-backup-" + rbVersion + ".zip";
550 //! create dir, if it doesnt exist
551 QFileInfo backupFile(backupName);
552 if(!QDir(backupFile.path()).exists())
554 QDir a;
555 a.mkpath(backupFile.path());
558 //! create backup
559 RbZip backup;
560 connect(&backup,SIGNAL(zipProgress(int,int)),logger, SLOT(setProgress(int,int)));
561 if(backup.createZip(backupName,
562 RbSettings::value(RbSettings::Mountpoint).toString() + "/.rockbox") == Zip::Ok)
564 logger->addItem(tr("Backup successful"),LOGOK);
566 else
568 logger->addItem(tr("Backup failed!"),LOGERROR);
569 logger->setFinished();
570 return false;
575 //! install current build
576 ZipInstaller* installer = new ZipInstaller(this);
577 installer->setUrl(file);
578 installer->setLogSection("Rockbox (Base)");
579 installer->setLogVersion(versmap.value("rel_rev"));
580 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
581 installer->setCache(true);
582 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
584 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
585 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
586 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
587 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
588 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
589 installer->install();
590 return true;
594 void RbUtilQt::install()
596 Install *installWindow = new Install(this);
598 buildInfo.open();
599 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
600 buildInfo.close();
601 installWindow->setVersionStrings(versmap);
603 installWindow->show();
606 bool RbUtilQt::installBootloaderAuto()
608 installBootloader();
609 return !m_error;
612 void RbUtilQt::installBootloaderBtn()
614 if(chkConfig(true)) return;
615 if(QMessageBox::question(this, tr("Confirm Installation"),
616 tr("Do you really want to install the Bootloader?"),
617 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
619 // create logger
620 logger = new ProgressLoggerGui(this);
622 installBootloader();
625 void RbUtilQt::installBootloader()
627 QString platform = RbSettings::value(RbSettings::Platform).toString();
628 QString backupDestination = "";
629 m_error = false;
631 // create installer
632 BootloaderInstallBase *bl;
633 QString type = RbSettings::value(RbSettings::CurBootloaderMethod).toString();
634 if(type == "mi4") {
635 bl = new BootloaderInstallMi4(this);
637 else if(type == "hex") {
638 bl = new BootloaderInstallHex(this);
640 else if(type == "sansa") {
641 bl = new BootloaderInstallSansa(this);
643 else if(type == "ipod") {
644 bl = new BootloaderInstallIpod(this);
646 else if(type == "file") {
647 bl = new BootloaderInstallFile(this);
649 else {
650 logger->addItem(tr("No install method known."), LOGERROR);
651 logger->setFinished();
652 return;
655 // set bootloader filename. Do this now as installed() needs it.
656 QString blfile;
657 blfile = RbSettings::value(RbSettings::Mountpoint).toString()
658 + RbSettings::value(RbSettings::CurBootloaderFile).toString();
659 // special case for H10 pure: this player can have a different
660 // bootloader file filename. This is handled here to keep the install
661 // class clean, though having it here is also not the nicest solution.
662 if(RbSettings::value(RbSettings::Platform).toString() == "h10_ums"
663 || RbSettings::value(RbSettings::Platform) == "h10_mtp") {
664 if(resolvePathCase(blfile).isEmpty())
665 blfile = RbSettings::value(RbSettings::Mountpoint).toString()
666 + RbSettings::value(RbSettings::CurBootloaderName).toString()
667 .replace("H10", "H10EMP", Qt::CaseInsensitive);
669 bl->setBlFile(blfile);
670 QUrl url(RbSettings::value(RbSettings::BootloaderUrl).toString()
671 + RbSettings::value(RbSettings::CurBootloaderName).toString());
672 bl->setBlUrl(url);
673 bl->setLogfile(RbSettings::value(RbSettings::Mountpoint).toString()
674 + "/.rockbox/rbutil.log");
676 if(bl->installed() == BootloaderInstallBase::BootloaderRockbox) {
677 if(QMessageBox::question(this, tr("Bootloader detected"),
678 tr("Bootloader already installed. Do you want to reinstall the bootloader?"),
679 QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
680 if(m_auto) {
681 // keep logger open for auto installs.
682 // don't consider abort as error in auto-mode.
683 logger->addItem(tr("Bootloader installation skipped"), LOGINFO);
684 installBootloaderPost(false);
686 else {
687 logger->close();
688 installBootloaderPost(true);
690 return;
693 else if(bl->installed() == BootloaderInstallBase::BootloaderOther
694 && bl->capabilities() & BootloaderInstallBase::Backup)
696 QString targetFolder = RbSettings::value(RbSettings::CurPlatformName).toString()
697 + " Firmware Backup";
698 // remove invalid character(s)
699 targetFolder.remove(QRegExp("[:/]"));
700 if(QMessageBox::question(this, tr("Create Bootloader backup"),
701 tr("You can create a backup of the original bootloader "
702 "file. Press \"Yes\" to select an output folder on your "
703 "computer to save the file to. The file will get placed "
704 "in a new folder \"%1\" created below the selected folder.\n"
705 "Press \"No\" to skip this step.").arg(targetFolder),
706 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
707 BrowseDirtree tree(this, tr("Browse backup folder"));
708 tree.setDir(QDir::home());
709 tree.exec();
711 backupDestination = tree.getSelected() + "/" + targetFolder;
712 qDebug() << backupDestination;
713 // backup needs to be done after the logger has been set up.
717 if(bl->capabilities() & BootloaderInstallBase::NeedsOf)
719 int ret;
720 ret = QMessageBox::information(this, tr("Prerequisites"),
721 bl->ofHint(),QMessageBox::Ok | QMessageBox::Abort);
722 if(ret != QMessageBox::Ok) {
723 // consider aborting an error to close window / abort automatic
724 // installation.
725 m_error = true;
726 logger->addItem(tr("Bootloader installation aborted"), LOGINFO);
727 return;
729 // open dialog to browse to of file
730 QString offile;
731 offile = QFileDialog::getOpenFileName(this,
732 tr("Select firmware file"), QDir::homePath());
733 if(!QFileInfo(offile).isReadable()) {
734 logger->addItem(tr("Error opening firmware file"), LOGERROR);
735 m_error = true;
736 return;
738 bl->setOfFile(offile);
741 // the bootloader install class does NOT use any GUI stuff.
742 // All messages are passed via signals.
743 connect(bl, SIGNAL(done(bool)), logger, SLOT(setFinished()));
744 connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool)));
745 connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
746 connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
748 // show logger and start install.
749 logger->show();
750 if(!backupDestination.isEmpty()) {
751 if(!bl->backup(backupDestination)) {
752 if(QMessageBox::warning(this, tr("Backup error"),
753 tr("Could not create backup file. Continue?"),
754 QMessageBox::No | QMessageBox::Yes)
755 == QMessageBox::No) {
756 logger->setFinished();
757 return;
761 bl->install();
764 void RbUtilQt::installBootloaderPost(bool error)
766 qDebug() << __func__ << error;
767 // if an error occured don't perform post install steps.
768 if(error) {
769 m_error = true;
770 return;
772 else
773 m_error = false;
775 m_installed = true;
776 // end here if automated install
777 if(m_auto)
778 return;
780 QString msg = BootloaderInstallBase::postinstallHints(
781 RbSettings::value(RbSettings::Platform).toString());
782 if(!msg.isEmpty()) {
783 QMessageBox::information(this, tr("Manual steps required"), msg);
784 logger->close();
789 void RbUtilQt::installFontsBtn()
791 if(chkConfig(true)) return;
792 if(QMessageBox::question(this, tr("Confirm Installation"),
793 tr("Do you really want to install the fonts package?"),
794 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
795 // create logger
796 logger = new ProgressLoggerGui(this);
797 logger->show();
798 installFonts();
801 bool RbUtilQt::installFontsAuto()
803 installFonts();
805 return !m_error;
808 void RbUtilQt::installFonts()
810 // create zip installer
811 installer = new ZipInstaller(this);
813 installer->setUrl(RbSettings::value(RbSettings::FontUrl).toString());
814 installer->setLogSection("Fonts");
815 installer->setLogVersion(versmap.value("arch_date"));
816 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
817 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
818 installer->setCache(true);
820 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
821 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
822 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
823 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
824 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
825 installer->install();
829 void RbUtilQt::installVoice()
831 if(chkConfig(true)) return;
833 if(m_gotInfo == false)
835 QMessageBox::warning(this, tr("Warning"),
836 tr("The Application is still downloading Information about new Builds."
837 " Please try again shortly."));
838 return;
841 if(QMessageBox::question(this, tr("Confirm Installation"),
842 tr("Do you really want to install the voice file?"),
843 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
844 // create logger
845 logger = new ProgressLoggerGui(this);
846 logger->show();
848 // create zip installer
849 installer = new ZipInstaller(this);
851 QString voiceurl = RbSettings::value(RbSettings::VoiceUrl).toString();
853 voiceurl += RbSettings::value(RbSettings::CurConfigureModel).toString() + "-" +
854 versmap.value("arch_date") + "-english.zip";
855 qDebug() << voiceurl;
857 installer->setUrl(voiceurl);
858 installer->setLogSection("Voice");
859 installer->setLogVersion(versmap.value("arch_date"));
860 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
861 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
862 installer->setCache(true);
863 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
864 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
865 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
866 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
867 installer->install();
871 void RbUtilQt::installDoomBtn()
873 if(chkConfig(true)) return;
874 if(!hasDoom()){
875 QMessageBox::critical(this, tr("Error"),
876 tr("Your device doesn't have a doom plugin. Aborting."));
877 return;
880 if(QMessageBox::question(this, tr("Confirm Installation"),
881 tr("Do you really want to install the game addon files?"),
882 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
883 // create logger
884 logger = new ProgressLoggerGui(this);
885 logger->show();
887 installDoom();
889 bool RbUtilQt::installDoomAuto()
891 installDoom();
892 return !m_error;
895 bool RbUtilQt::hasDoom()
897 QFile doomrock(RbSettings::value(RbSettings::Mountpoint).toString()
898 +"/.rockbox/rocks/games/doom.rock");
899 return doomrock.exists();
902 void RbUtilQt::installDoom()
904 // create zip installer
905 installer = new ZipInstaller(this);
907 installer->setUrl(RbSettings::value(RbSettings::DoomUrl).toString());
908 installer->setLogSection("Game Addons");
909 installer->setLogVersion(versmap.value("arch_date"));
910 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
911 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
912 installer->setCache(true);
913 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
914 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
915 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
916 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
917 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
918 installer->install();
922 void RbUtilQt::installThemes()
924 if(chkConfig(true)) return;
925 ThemesInstallWindow* tw = new ThemesInstallWindow(this);
926 tw->setModal(true);
927 tw->show();
930 void RbUtilQt::createTalkFiles(void)
932 if(chkConfig(true)) return;
933 InstallTalkWindow *installWindow = new InstallTalkWindow(this);
935 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
936 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
937 installWindow->show();
941 void RbUtilQt::createVoiceFile(void)
943 if(chkConfig(true)) return;
944 CreateVoiceWindow *installWindow = new CreateVoiceWindow(this);
946 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
947 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
948 installWindow->show();
951 void RbUtilQt::uninstall(void)
953 if(chkConfig(true)) return;
954 UninstallWindow *uninstallWindow = new UninstallWindow(this);
955 uninstallWindow->show();
959 void RbUtilQt::uninstallBootloader(void)
961 if(chkConfig(true)) return;
962 if(QMessageBox::question(this, tr("Confirm Uninstallation"),
963 tr("Do you really want to uninstall the Bootloader?"),
964 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
965 // create logger
966 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
967 logger->setProgressVisible(false);
968 logger->show();
970 QString platform = RbSettings::value(RbSettings::Platform).toString();
972 // create installer
973 BootloaderInstallBase *bl;
974 QString type = RbSettings::value(RbSettings::CurBootloaderMethod).toString();
975 if(type == "mi4") {
976 bl = new BootloaderInstallMi4(this);
978 else if(type == "hex") {
979 bl = new BootloaderInstallHex(this);
981 else if(type == "sansa") {
982 bl = new BootloaderInstallSansa(this);
984 else if(type == "ipod") {
985 bl = new BootloaderInstallIpod(this);
987 else if(type == "file") {
988 bl = new BootloaderInstallFile(this);
990 else {
991 logger->addItem(tr("No uninstall method known."), LOGERROR);
992 logger->setFinished();
993 return;
996 QString blfile = RbSettings::value(RbSettings::Mountpoint).toString()
997 + RbSettings::value(RbSettings::CurBootloaderFile).toString();
998 if(RbSettings::value(RbSettings::Platform).toString() == "h10_ums"
999 || RbSettings::value(RbSettings::Platform).toString() == "h10_mtp") {
1000 if(resolvePathCase(blfile).isEmpty())
1001 blfile = RbSettings::value(RbSettings::Mountpoint).toString()
1002 + RbSettings::value(RbSettings::CurBootloaderName).toString()
1003 .replace("H10", "H10EMP", Qt::CaseInsensitive);
1005 bl->setBlFile(blfile);
1007 connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
1008 connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
1010 int result;
1011 result = bl->uninstall();
1013 logger->setFinished();
1018 void RbUtilQt::downloadManual(void)
1020 if(chkConfig(true)) return;
1021 if(QMessageBox::question(this, tr("Confirm download"),
1022 tr("Do you really want to download the manual? The manual will be saved "
1023 "to the root folder of your player."),
1024 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
1025 return;
1027 buildInfo.open();
1028 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
1029 buildInfo.close();
1031 QString manual = RbSettings::value(RbSettings::CurManual).toString();
1033 QString date = (info.value("dailies/date").toString());
1035 QString manualurl;
1036 QString target;
1037 QString section;
1038 if(ui.radioPdf->isChecked()) {
1039 target = "/" + manual + ".pdf";
1040 section = "Manual (PDF)";
1042 else {
1043 target = "/" + manual + "-" + date + "-html.zip";
1044 section = "Manual (HTML)";
1046 manualurl = RbSettings::value(RbSettings::ManualUrl).toString() + "/" + target;
1047 qDebug() << "manualurl =" << manualurl;
1049 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
1050 logger->show();
1051 installer = new ZipInstaller(this);
1052 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
1053 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
1054 installer->setCache(true);
1055 installer->setLogSection(section);
1056 installer->setLogVersion(date);
1057 installer->setUrl(manualurl);
1058 installer->setUnzip(false);
1059 installer->setTarget(target);
1060 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
1061 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
1062 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
1063 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
1064 installer->install();
1068 void RbUtilQt::installPortable(void)
1070 if(QMessageBox::question(this, tr("Confirm installation"),
1071 tr("Do you really want to install Rockbox Utility to your player? "
1072 "After installation you can run it from the players hard drive."),
1073 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
1074 return;
1076 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
1077 logger->setProgressMax(0);
1078 logger->setProgressValue(0);
1079 logger->show();
1080 logger->addItem(tr("Installing Rockbox Utility"), LOGINFO);
1082 // check mountpoint
1083 if(!QFileInfo(RbSettings::value(RbSettings::Mountpoint).toString()).isDir()) {
1084 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
1085 logger->setFinished();
1086 return;
1089 // remove old files first.
1090 QFile::remove(RbSettings::value(RbSettings::Mountpoint).toString()
1091 + "/RockboxUtility.exe");
1092 QFile::remove(RbSettings::value(RbSettings::Mountpoint).toString()
1093 + "/RockboxUtility.ini");
1094 // copy currently running binary and currently used settings file
1095 if(!QFile::copy(qApp->applicationFilePath(),
1096 RbSettings::value(RbSettings::Mountpoint).toString()
1097 + "/RockboxUtility.exe")) {
1098 logger->addItem(tr("Error installing Rockbox Utility"), LOGERROR);
1099 logger->setFinished();
1100 return;
1102 logger->addItem(tr("Installing user configuration"), LOGINFO);
1103 if(!QFile::copy(RbSettings::userSettingFilename(),
1104 RbSettings::value(RbSettings::Mountpoint).toString()
1105 + "/RockboxUtility.ini")) {
1106 logger->addItem(tr("Error installing user configuration"), LOGERROR);
1107 logger->setFinished();
1108 return;
1110 logger->addItem(tr("Successfully installed Rockbox Utility."), LOGOK);
1111 logger->setFinished();
1112 logger->setProgressMax(1);
1113 logger->setProgressValue(1);
1118 void RbUtilQt::updateInfo()
1120 qDebug() << "RbUtilQt::updateInfo()";
1122 QSettings log(RbSettings::value(RbSettings::Mountpoint).toString()
1123 + "/.rockbox/rbutil.log", QSettings::IniFormat, this);
1124 QStringList groups = log.childGroups();
1125 QList<QTreeWidgetItem *> items;
1126 QTreeWidgetItem *w, *w2;
1127 QString min, max;
1128 int olditems = 0;
1130 // remove old list entries (if any)
1131 int l = ui.treeInfo->topLevelItemCount();
1132 while(l--) {
1133 QTreeWidgetItem *m;
1134 m = ui.treeInfo->takeTopLevelItem(l);
1135 // delete childs (single level deep, no recursion here)
1136 int n = m->childCount();
1137 while(n--)
1138 delete m->child(n);
1140 // get and populate new items
1141 for(int a = 0; a < groups.size(); a++) {
1142 log.beginGroup(groups.at(a));
1143 QStringList keys = log.allKeys();
1144 w = new QTreeWidgetItem;
1145 w->setFlags(Qt::ItemIsEnabled);
1146 w->setText(0, groups.at(a));
1147 items.append(w);
1148 // get minimum and maximum version information so we can hilight old files
1149 min = max = log.value(keys.at(0)).toString();
1150 for(int b = 0; b < keys.size(); b++) {
1151 if(log.value(keys.at(b)).toString() > max)
1152 max = log.value(keys.at(b)).toString();
1153 if(log.value(keys.at(b)).toString() < min)
1154 min = log.value(keys.at(b)).toString();
1157 for(int b = 0; b < keys.size(); b++) {
1158 QString file;
1159 file = RbSettings::value(RbSettings::Mountpoint).toString() + "/" + keys.at(b);
1160 if(QFileInfo(file).isDir())
1161 continue;
1162 w2 = new QTreeWidgetItem(w, QStringList() << "/"
1163 + keys.at(b) << log.value(keys.at(b)).toString());
1164 if(log.value(keys.at(b)).toString() != max) {
1165 w2->setForeground(0, QBrush(QColor(255, 0, 0)));
1166 w2->setForeground(1, QBrush(QColor(255, 0, 0)));
1167 olditems++;
1169 items.append(w2);
1171 log.endGroup();
1172 if(min != max)
1173 w->setData(1, Qt::DisplayRole, QString("%1 / %2").arg(min, max));
1174 else
1175 w->setData(1, Qt::DisplayRole, max);
1177 ui.treeInfo->insertTopLevelItems(0, items);
1178 ui.treeInfo->resizeColumnToContents(0);
1182 QUrl RbUtilQt::proxy()
1184 if(RbSettings::value(RbSettings::ProxyType) == "manual")
1185 return QUrl(RbSettings::value(RbSettings::Proxy).toString());
1186 else if(RbSettings::value(RbSettings::ProxyType) == "system")
1187 return Detect::systemProxy();
1188 return QUrl("");
1192 bool RbUtilQt::chkConfig(bool warn)
1194 bool error = false;
1195 if(RbSettings::value(RbSettings::Platform).toString().isEmpty()
1196 || RbSettings::value(RbSettings::Mountpoint).toString().isEmpty()
1197 || !QFileInfo(RbSettings::value(RbSettings::Mountpoint).toString()).isWritable()) {
1198 error = true;
1200 if(warn) QMessageBox::critical(this, tr("Configuration error"),
1201 tr("Your configuration is invalid. Please go to the configuration "
1202 "dialog and make sure the selected values are correct."));
1204 return error;