Add Save icon and add a note to the about dialog about the origin of the icons. Shoul...
[kugel-rb/myfork.git] / rbutil / rbutilqt / rbutilqt.cpp
blobb0684f7ef7a718e53e6fb1eec8dbc4b80e8219ca
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 "system.h"
37 #include "systrace.h"
38 #include "rbsettings.h"
40 #include "progressloggerinterface.h"
42 #include "bootloaderinstallbase.h"
43 #include "bootloaderinstallmi4.h"
44 #include "bootloaderinstallhex.h"
45 #include "bootloaderinstallipod.h"
46 #include "bootloaderinstallsansa.h"
47 #include "bootloaderinstallfile.h"
48 #include "bootloaderinstallams.h"
51 #if defined(Q_OS_LINUX)
52 #include <stdio.h>
53 #endif
54 #if defined(Q_OS_WIN32)
55 #if defined(UNICODE)
56 #define _UNICODE
57 #endif
58 #include <stdio.h>
59 #include <tchar.h>
60 #include <windows.h>
61 #endif
63 RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent)
65 // startup log
66 qDebug() << "======================================";
67 qDebug() << "[System] Rockbox Utility " VERSION;
68 qDebug() << "[System] Qt version:" << qVersion();
69 qDebug() << "======================================";
71 absolutePath = qApp->applicationDirPath();
73 HttpGet::setGlobalUserAgent("rbutil/"VERSION);
74 // init startup & autodetection
75 ui.setupUi(this);
76 updateSettings();
77 downloadInfo();
79 m_gotInfo = false;
80 m_auto = false;
82 // manual tab
83 ui.radioPdf->setChecked(true);
85 // info tab
86 ui.treeInfo->setAlternatingRowColors(true);
87 ui.treeInfo->setHeaderLabels(QStringList() << tr("File") << tr("Version"));
88 ui.treeInfo->expandAll();
89 ui.treeInfo->setColumnCount(2);
90 // disable quick install until version info is available
91 ui.buttonSmall->setEnabled(false);
92 ui.buttonComplete->setEnabled(false);
94 connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateTabs(int)));
95 connect(ui.actionAbout_Qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
96 connect(ui.action_About, SIGNAL(triggered()), this, SLOT(about()));
97 connect(ui.action_Help, SIGNAL(triggered()), this, SLOT(help()));
98 connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog()));
99 connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog()));
100 connect(ui.buttonRockbox, SIGNAL(clicked()), this, SLOT(installBtn()));
101 connect(ui.buttonBootloader, SIGNAL(clicked()), this, SLOT(installBootloaderBtn()));
102 connect(ui.buttonFonts, SIGNAL(clicked()), this, SLOT(installFontsBtn()));
103 connect(ui.buttonGames, SIGNAL(clicked()), this, SLOT(installDoomBtn()));
104 connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles()));
105 connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile()));
106 connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice()));
107 connect(ui.buttonThemes, SIGNAL(clicked()), this, SLOT(installThemes()));
108 connect(ui.buttonRemoveRockbox, SIGNAL(clicked()), this, SLOT(uninstall()));
109 connect(ui.buttonRemoveBootloader, SIGNAL(clicked()), this, SLOT(uninstallBootloader()));
110 connect(ui.buttonDownloadManual, SIGNAL(clicked()), this, SLOT(downloadManual()));
111 connect(ui.buttonSmall, SIGNAL(clicked()), this, SLOT(smallInstall()));
112 connect(ui.buttonComplete, SIGNAL(clicked()), this, SLOT(completeInstall()));
114 // actions accessible from the menu
115 connect(ui.actionComplete_Installation, SIGNAL(triggered()), this, SLOT(completeInstall()));
116 connect(ui.actionSmall_Installation, SIGNAL(triggered()), this, SLOT(smallInstall()));
117 connect(ui.actionInstall_Bootloader, SIGNAL(triggered()), this, SLOT(installBootloaderBtn()));
118 connect(ui.actionInstall_Rockbox, SIGNAL(triggered()), this, SLOT(installBtn()));
119 connect(ui.actionFonts_Package, SIGNAL(triggered()), this, SLOT(installFontsBtn()));
120 connect(ui.actionInstall_Themes, SIGNAL(triggered()), this, SLOT(installThemes()));
121 connect(ui.actionInstall_Game_Files, SIGNAL(triggered()), this, SLOT(installDoomBtn()));
122 connect(ui.actionInstall_Voice_File, SIGNAL(triggered()), this, SLOT(installVoice()));
123 connect(ui.actionCreate_Voice_File, SIGNAL(triggered()), this, SLOT(createVoiceFile()));
124 connect(ui.actionCreate_Talk_Files, SIGNAL(triggered()), this, SLOT(createTalkFiles()));
125 connect(ui.actionRemove_bootloader, SIGNAL(triggered()), this, SLOT(uninstallBootloader()));
126 connect(ui.actionUninstall_Rockbox, SIGNAL(triggered()), this, SLOT(uninstall()));
127 connect(ui.action_System_Info, SIGNAL(triggered()), this, SLOT(sysinfo()));
128 connect(ui.action_Trace, SIGNAL(triggered()), this, SLOT(trace()));
130 #if !defined(STATIC)
131 ui.actionInstall_Rockbox_Utility_on_player->setEnabled(false);
132 #else
133 connect(ui.actionInstall_Rockbox_Utility_on_player, SIGNAL(triggered()), this, SLOT(installPortable()));
134 #endif
139 void RbUtilQt::trace(void)
141 SysTrace wnd(this);
142 wnd.exec();
145 void RbUtilQt::sysinfo(void)
147 Sysinfo info(this);
148 info.exec();
151 void RbUtilQt::updateTabs(int count)
153 switch(count) {
154 case 6:
155 updateInfo();
156 break;
157 default:
158 break;
163 void RbUtilQt::downloadInfo()
165 // make sure the version map is repopulated correctly later.
166 versmap.clear();
167 // try to get the current build information
168 daily = new HttpGet(this);
169 connect(daily, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
170 connect(daily, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
171 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
172 if(RbSettings::value(RbSettings::CacheOffline).toBool())
173 daily->setCache(true);
174 else
175 daily->setCache(false);
176 qDebug() << "[RbUtil] downloading build info";
177 daily->setFile(&buildInfo);
178 daily->getFile(QUrl(RbSettings::value(RbSettings::ServerConfUrl).toString()));
182 void RbUtilQt::downloadDone(bool error)
184 if(error) {
185 qDebug() << "[RbUtil] network error:" << daily->error();
186 QMessageBox::critical(this, tr("Network error"),
187 tr("Can't get version information."));
188 return;
190 qDebug() << "[RbUtil] network status:" << daily->error();
192 buildInfo.open();
193 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
194 buildInfo.close();
195 versmap.insert("arch_rev", info.value("dailies/rev").toString());
196 versmap.insert("arch_date", info.value("dailies/date").toString());
198 info.beginGroup("release");
199 versmap.insert("rel_rev", info.value(RbSettings::value(RbSettings::CurBuildserverModel).toString()).toString());
200 info.endGroup();
202 if(versmap.value("rel_rev").isEmpty()) {
203 ui.buttonSmall->setEnabled(false);
204 ui.buttonComplete->setEnabled(false);
206 else {
207 ui.buttonSmall->setEnabled(true);
208 ui.buttonComplete->setEnabled(true);
211 bleeding = new HttpGet(this);
212 connect(bleeding, SIGNAL(done(bool)), this, SLOT(downloadBleedingDone(bool)));
213 connect(bleeding, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
214 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
215 if(RbSettings::value(RbSettings::CacheOffline).toBool())
216 bleeding->setCache(true);
217 bleeding->setFile(&bleedingInfo);
218 bleeding->getFile(QUrl(RbSettings::value(RbSettings::BleedingInfo).toString()));
220 if(RbSettings::value(RbSettings::RbutilVersion) != PUREVERSION) {
221 QApplication::processEvents();
222 QMessageBox::information(this, tr("New installation"),
223 tr("This is a new installation of Rockbox Utility, or a new version. "
224 "The configuration dialog will now open to allow you to setup the program, "
225 " or review your settings."));
226 configDialog();
228 else if(chkConfig(false)) {
229 QApplication::processEvents();
230 QMessageBox::critical(this, tr("Configuration error"),
231 tr("Your configuration is invalid. This is most likely due "
232 "to a changed device path. The configuration dialog will "
233 "now open to allow you to correct the problem."));
234 configDialog();
239 void RbUtilQt::downloadBleedingDone(bool error)
241 if(error) {
242 qDebug() << "[RbUtil] network error:" << bleeding->error();
244 else {
245 bleedingInfo.open();
246 QSettings info(bleedingInfo.fileName(), QSettings::IniFormat, this);
247 bleedingInfo.close();
248 versmap.insert("bleed_rev", info.value("bleeding/rev").toString());
249 versmap.insert("bleed_date", info.value("bleeding/timestamp").toString());
250 qDebug() << "[RbUtil] version map:" << versmap;
252 m_gotInfo = true;
257 void RbUtilQt::downloadDone(int id, bool error)
259 QString errorString;
260 errorString = tr("Network error: %1. Please check your network and proxy settings.")
261 .arg(daily->errorString());
262 if(error) {
263 QMessageBox::about(this, "Network Error", errorString);
264 m_networkerror = daily->errorString();
266 qDebug() << "[RbUtil] downloadDone:" << id << "error:" << error;
270 void RbUtilQt::about()
272 QDialog *window = new QDialog(this);
273 Ui::aboutBox about;
274 about.setupUi(window);
275 window->setModal(true);
277 QFile licence(":/docs/gpl-2.0.html");
278 licence.open(QIODevice::ReadOnly);
279 QTextStream c(&licence);
280 QString cline = c.readAll();
281 about.browserLicense->insertHtml(cline);
282 about.browserLicense->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
283 QFile credits(":/docs/CREDITS");
284 credits.open(QIODevice::ReadOnly);
285 QTextStream r(&credits);
286 r.setCodec(QTextCodec::codecForName("UTF-8"));
287 QString rline = r.readAll();
288 about.browserCredits->insertPlainText(rline);
289 about.browserCredits->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
290 QString title = QString("<b>The Rockbox Utility</b><br/>Version %1").arg(FULLVERSION);
291 about.labelTitle->setText(title);
293 window->show();
298 void RbUtilQt::help()
300 QUrl helpurl("http://www.rockbox.org/wiki/RockboxUtility");
301 QDesktopServices::openUrl(helpurl);
305 void RbUtilQt::configDialog()
307 Config *cw = new Config(this);
308 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
309 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
310 cw->show();
314 void RbUtilQt::updateSettings()
316 qDebug() << "[RbUtil] updating current settings";
317 updateDevice();
318 updateManual();
319 if(RbSettings::value(RbSettings::ProxyType) == "system") {
320 HttpGet::setGlobalProxy(System::systemProxy());
322 else if(RbSettings::value(RbSettings::ProxyType) == "manual") {
323 HttpGet::setGlobalProxy(RbSettings::value(RbSettings::Proxy).toString());
325 else {
326 HttpGet::setGlobalProxy(QUrl(""));
328 HttpGet::setGlobalCache(RbSettings::value(RbSettings::CachePath).toString());
329 HttpGet::setGlobalDumbCache(RbSettings::value(RbSettings::CacheOffline).toBool());
333 void RbUtilQt::updateDevice()
335 if(RbSettings::value(RbSettings::CurBootloaderMethod) == "none" ) {
336 ui.buttonBootloader->setEnabled(false);
337 ui.buttonRemoveBootloader->setEnabled(false);
338 ui.labelBootloader->setEnabled(false);
339 ui.labelRemoveBootloader->setEnabled(false);
341 else {
342 ui.buttonBootloader->setEnabled(true);
343 ui.labelBootloader->setEnabled(true);
344 if(RbSettings::value(RbSettings::CurBootloaderMethod) == "fwpatcher") {
345 ui.labelRemoveBootloader->setEnabled(false);
346 ui.buttonRemoveBootloader->setEnabled(false);
348 else {
349 ui.labelRemoveBootloader->setEnabled(true);
350 ui.buttonRemoveBootloader->setEnabled(true);
354 // displayed device info
355 QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
356 QString brand = RbSettings::value(RbSettings::CurBrand).toString();
357 QString name = RbSettings::value(RbSettings::CurName).toString();
358 if(name.isEmpty()) name = "&lt;none&gt;";
359 if(mountpoint.isEmpty()) mountpoint = "&lt;invalid&gt;";
360 ui.labelDevice->setText(tr("<b>%1 %2</b> at <b>%3</b>")
361 .arg(brand, name, QDir::toNativeSeparators(mountpoint)));
365 void RbUtilQt::updateManual()
367 if(RbSettings::value(RbSettings::Platform) != "")
369 QString manual= RbSettings::value(RbSettings::CurManual).toString();
371 if(manual == "")
372 manual = "rockbox-" + RbSettings::value(RbSettings::Platform).toString();
373 QString pdfmanual;
374 pdfmanual = RbSettings::value(RbSettings::ManualUrl).toString()
375 + "/" + manual + ".pdf";
376 QString htmlmanual;
377 htmlmanual = RbSettings::value(RbSettings::ManualUrl).toString()
378 + "/" + manual + "/rockbox-build.html";
379 ui.labelPdfManual->setText(tr("<a href='%1'>PDF Manual</a>")
380 .arg(pdfmanual));
381 ui.labelHtmlManual->setText(tr("<a href='%1'>HTML Manual (opens in browser)</a>")
382 .arg(htmlmanual));
384 else {
385 ui.labelPdfManual->setText(tr("Select a device for a link to the correct manual"));
386 ui.labelHtmlManual->setText(tr("<a href='%1'>Manual Overview</a>")
387 .arg("http://www.rockbox.org/manual.shtml"));
392 void RbUtilQt::completeInstall()
394 if(chkConfig(true)) return;
395 if(QMessageBox::question(this, tr("Confirm Installation"),
396 tr("Do you really want to perform a complete installation?\n\n"
397 "This will install Rockbox %1. To install the most recent "
398 "development build available press \"Cancel\" and "
399 "use the \"Installation\" tab.")
400 .arg(versmap.value("rel_rev")),
401 QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok)
402 return;
403 // create logger
404 logger = new ProgressLoggerGui(this);
405 logger->show();
407 if(smallInstallInner())
408 return;
409 logger->setRunning();
410 // Fonts
411 m_error = false;
412 m_installed = false;
413 if(!installFontsAuto())
414 return;
415 else
417 // wait for installation finished
418 while(!m_installed)
419 QApplication::processEvents();
421 if(m_error) return;
422 logger->setRunning();
424 // Doom
425 if(hasDoom())
427 m_error = false;
428 m_installed = false;
429 if(!installDoomAuto())
430 return;
431 else
433 // wait for installation finished
434 while(!m_installed)
435 QApplication::processEvents();
437 if(m_error) return;
440 // theme
441 // this is a window
442 // it has its own logger window,so close our.
443 logger->close();
444 installThemes();
448 void RbUtilQt::smallInstall()
450 if(chkConfig(true)) return;
451 if(QMessageBox::question(this, tr("Confirm Installation"),
452 tr("Do you really want to perform a minimal installation? "
453 "A minimal installation will contain only the absolutely "
454 "necessary parts to run Rockbox.\n\n"
455 "This will install Rockbox %1. To install the most recent "
456 "development build available press \"Cancel\" and "
457 "use the \"Installation\" tab.")
458 .arg(versmap.value("rel_rev")),
459 QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok)
460 return;
462 // create logger
463 logger = new ProgressLoggerGui(this);
464 logger->show();
466 smallInstallInner();
469 bool RbUtilQt::smallInstallInner()
471 QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
472 // show dialog with error if mount point is wrong
473 if(!QFileInfo(mountpoint).isDir()) {
474 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
475 logger->setFinished();
476 return true;
478 // Bootloader
479 if(RbSettings::value(RbSettings::CurBootloaderMethod) != "none")
481 m_error = false;
482 m_installed = false;
483 m_auto = true;
484 if(!installBootloaderAuto()) {
485 logger->setFinished();
486 return true;
488 else
490 // wait for boot loader installation finished
491 while(!m_installed)
492 QApplication::processEvents();
494 m_auto = false;
495 if(m_error) return true;
496 logger->setRunning();
499 // Rockbox
500 m_error = false;
501 m_installed = false;
502 if(!installAuto())
503 return true;
504 else
506 // wait for installation finished
507 while(!m_installed)
508 QApplication::processEvents();
511 installBootloaderPost(false);
512 return false;
515 void RbUtilQt::installdone(bool error)
517 qDebug() << "[RbUtil] install done";
518 m_installed = true;
519 m_error = error;
522 void RbUtilQt::installBtn()
524 if(chkConfig(true)) return;
525 install();
528 bool RbUtilQt::installAuto()
530 QString file = RbSettings::value(RbSettings::ReleaseUrl).toString();
531 file.replace("%MODEL%", RbSettings::value(RbSettings::CurBuildserverModel).toString());
532 file.replace("%RELVERSION%", versmap.value("rel_rev"));
533 buildInfo.open();
534 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
535 buildInfo.close();
537 // check installed Version and Target
538 QString warning = check(false);
539 if(!warning.isEmpty())
541 if(QMessageBox::warning(this, tr("Really continue?"), warning,
542 QMessageBox::Ok | QMessageBox::Abort, QMessageBox::Abort)
543 == QMessageBox::Abort)
545 logger->addItem(tr("Aborted!"), LOGERROR);
546 logger->setFinished();
547 return false;
551 // check version
552 RockboxInfo rbinfo(RbSettings::value(RbSettings::Mountpoint).toString());
553 if(rbinfo.version() != "")
555 if(QMessageBox::question(this, tr("Installed Rockbox detected"),
556 tr("Rockbox installation detected. Do you want to backup first?"),
557 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
559 logger->addItem(tr("Starting backup..."),LOGINFO);
560 QString backupName = RbSettings::value(RbSettings::Mountpoint).toString()
561 + "/.backup/rockbox-backup-" + rbinfo.version() + ".zip";
563 //! create dir, if it doesnt exist
564 QFileInfo backupFile(backupName);
565 if(!QDir(backupFile.path()).exists())
567 QDir a;
568 a.mkpath(backupFile.path());
571 //! create backup
572 RbZip backup;
573 connect(&backup,SIGNAL(zipProgress(int,int)),logger, SLOT(setProgress(int,int)));
574 if(backup.createZip(backupName,
575 RbSettings::value(RbSettings::Mountpoint).toString() + "/.rockbox") == Zip::Ok)
577 logger->addItem(tr("Backup successful"),LOGOK);
579 else
581 logger->addItem(tr("Backup failed!"),LOGERROR);
582 logger->setFinished();
583 return false;
588 //! install current build
589 ZipInstaller* installer = new ZipInstaller(this);
590 installer->setUrl(file);
591 installer->setLogSection("Rockbox (Base)");
592 installer->setLogVersion(versmap.value("rel_rev"));
593 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
594 installer->setCache(true);
595 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
597 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
598 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
599 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
600 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
601 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
602 installer->install();
603 return true;
607 void RbUtilQt::install()
609 Install *installWindow = new Install(this);
611 buildInfo.open();
612 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
613 buildInfo.close();
614 installWindow->setVersionStrings(versmap);
616 installWindow->show();
619 bool RbUtilQt::installBootloaderAuto()
621 installBootloader();
622 return !m_error;
625 void RbUtilQt::installBootloaderBtn()
627 if(chkConfig(true)) return;
628 if(QMessageBox::question(this, tr("Confirm Installation"),
629 tr("Do you really want to install the Bootloader?"),
630 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
632 // create logger
633 logger = new ProgressLoggerGui(this);
634 logger->show();
635 installBootloader();
638 void RbUtilQt::installBootloader()
640 QString platform = RbSettings::value(RbSettings::Platform).toString();
641 QString backupDestination = "";
642 m_error = false;
644 // create installer
645 BootloaderInstallBase *bl;
646 QString type = RbSettings::value(RbSettings::CurBootloaderMethod).toString();
647 if(type == "mi4") {
648 bl = new BootloaderInstallMi4(this);
650 else if(type == "hex") {
651 bl = new BootloaderInstallHex(this);
653 else if(type == "sansa") {
654 bl = new BootloaderInstallSansa(this);
656 else if(type == "ipod") {
657 bl = new BootloaderInstallIpod(this);
659 else if(type == "file") {
660 bl = new BootloaderInstallFile(this);
662 else if(type == "ams") {
663 bl = new BootloaderInstallAms(this);
665 else {
666 logger->addItem(tr("No install method known."), LOGERROR);
667 logger->setFinished();
668 return;
671 // set bootloader filename. Do this now as installed() needs it.
672 QStringList blfile = RbSettings::value(RbSettings::CurBootloaderFile).toStringList();
673 QStringList blfilepath;
674 for(int a = 0; a < blfile.size(); a++) {
675 blfilepath.append(RbSettings::value(RbSettings::Mountpoint).toString()
676 + blfile.at(a));
678 bl->setBlFile(blfilepath);
679 QUrl url(RbSettings::value(RbSettings::BootloaderUrl).toString()
680 + RbSettings::value(RbSettings::CurBootloaderName).toString());
681 bl->setBlUrl(url);
682 bl->setLogfile(RbSettings::value(RbSettings::Mountpoint).toString()
683 + "/.rockbox/rbutil.log");
685 if(bl->installed() == BootloaderInstallBase::BootloaderRockbox) {
686 if(QMessageBox::question(this, tr("Bootloader detected"),
687 tr("Bootloader already installed. Do you want to reinstall the bootloader?"),
688 QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
689 if(m_auto) {
690 // keep logger open for auto installs.
691 // don't consider abort as error in auto-mode.
692 logger->addItem(tr("Bootloader installation skipped"), LOGINFO);
693 installBootloaderPost(false);
695 else {
696 logger->close();
697 installBootloaderPost(true);
699 return;
702 else if(bl->installed() == BootloaderInstallBase::BootloaderOther
703 && bl->capabilities() & BootloaderInstallBase::Backup)
705 QString targetFolder = RbSettings::value(RbSettings::CurPlatformName).toString()
706 + " Firmware Backup";
707 // remove invalid character(s)
708 targetFolder.remove(QRegExp("[:/]"));
709 if(QMessageBox::question(this, tr("Create Bootloader backup"),
710 tr("You can create a backup of the original bootloader "
711 "file. Press \"Yes\" to select an output folder on your "
712 "computer to save the file to. The file will get placed "
713 "in a new folder \"%1\" created below the selected folder.\n"
714 "Press \"No\" to skip this step.").arg(targetFolder),
715 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
716 BrowseDirtree tree(this, tr("Browse backup folder"));
717 tree.setDir(QDir::home());
718 tree.exec();
720 backupDestination = tree.getSelected() + "/" + targetFolder;
721 qDebug() << "[RbUtil] backing up to" << backupDestination;
722 // backup needs to be done after the logger has been set up.
726 if(bl->capabilities() & BootloaderInstallBase::NeedsOf)
728 int ret;
729 ret = QMessageBox::information(this, tr("Prerequisites"),
730 bl->ofHint(),QMessageBox::Ok | QMessageBox::Abort);
731 if(ret != QMessageBox::Ok) {
732 // consider aborting an error to close window / abort automatic
733 // installation.
734 m_error = true;
735 logger->addItem(tr("Bootloader installation aborted"), LOGINFO);
736 logger->setFinished();
737 return;
739 // open dialog to browse to of file
740 QString offile;
741 offile = QFileDialog::getOpenFileName(this,
742 tr("Select firmware file"), QDir::homePath());
743 if(!QFileInfo(offile).isReadable()) {
744 logger->addItem(tr("Error opening firmware file"), LOGERROR);
745 logger->setFinished();
746 m_error = true;
747 return;
749 bl->setOfFile(offile);
752 // the bootloader install class does NOT use any GUI stuff.
753 // All messages are passed via signals.
754 connect(bl, SIGNAL(done(bool)), logger, SLOT(setFinished()));
755 connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool)));
756 connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
757 connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
759 // start install.
760 if(!backupDestination.isEmpty()) {
761 if(!bl->backup(backupDestination)) {
762 if(QMessageBox::warning(this, tr("Backup error"),
763 tr("Could not create backup file. Continue?"),
764 QMessageBox::No | QMessageBox::Yes)
765 == QMessageBox::No) {
766 logger->setFinished();
767 return;
771 bl->install();
774 void RbUtilQt::installBootloaderPost(bool error)
776 qDebug() << "[RbUtil] Bootloader Post-Installation, error state:" << error;
777 // if an error occured don't perform post install steps.
778 if(error) {
779 m_error = true;
780 return;
782 else
783 m_error = false;
785 m_installed = true;
786 // end here if automated install
787 if(m_auto)
788 return;
790 QString msg = BootloaderInstallBase::postinstallHints(
791 RbSettings::value(RbSettings::Platform).toString());
792 if(!msg.isEmpty()) {
793 QMessageBox::information(this, tr("Manual steps required"), msg);
794 logger->close();
799 void RbUtilQt::installFontsBtn()
801 if(chkConfig(true)) return;
802 if(QMessageBox::question(this, tr("Confirm Installation"),
803 tr("Do you really want to install the fonts package?"),
804 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
805 // create logger
806 logger = new ProgressLoggerGui(this);
807 logger->show();
808 installFonts();
811 bool RbUtilQt::installFontsAuto()
813 installFonts();
815 return !m_error;
818 void RbUtilQt::installFonts()
820 // create zip installer
821 installer = new ZipInstaller(this);
823 installer->setUrl(RbSettings::value(RbSettings::FontUrl).toString());
824 installer->setLogSection("Fonts");
825 installer->setLogVersion(versmap.value("arch_date"));
826 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
827 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
828 installer->setCache(true);
830 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
831 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
832 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
833 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
834 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
835 installer->install();
839 void RbUtilQt::installVoice()
841 if(chkConfig(true)) return;
843 if(m_gotInfo == false)
845 QMessageBox::warning(this, tr("Warning"),
846 tr("The Application is still downloading Information about new Builds."
847 " Please try again shortly."));
848 return;
851 if(QMessageBox::question(this, tr("Confirm Installation"),
852 tr("Do you really want to install the voice file?"),
853 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
854 // create logger
855 logger = new ProgressLoggerGui(this);
856 logger->show();
858 // create zip installer
859 installer = new ZipInstaller(this);
861 QString voiceurl = RbSettings::value(RbSettings::VoiceUrl).toString();
863 voiceurl += RbSettings::value(RbSettings::CurBuildserverModel).toString() + "-" +
864 versmap.value("arch_date") + "-english.zip";
865 qDebug() << "[RbUtil] voicefile URL:" << voiceurl;
867 installer->setUrl(voiceurl);
868 installer->setLogSection("Voice");
869 installer->setLogVersion(versmap.value("arch_date"));
870 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
871 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
872 installer->setCache(true);
873 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
874 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
875 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
876 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
877 installer->install();
881 void RbUtilQt::installDoomBtn()
883 if(chkConfig(true)) return;
884 if(!hasDoom()){
885 QMessageBox::critical(this, tr("Error"),
886 tr("Your device doesn't have a doom plugin. Aborting."));
887 return;
890 if(QMessageBox::question(this, tr("Confirm Installation"),
891 tr("Do you really want to install the game addon files?"),
892 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
893 // create logger
894 logger = new ProgressLoggerGui(this);
895 logger->show();
897 installDoom();
899 bool RbUtilQt::installDoomAuto()
901 installDoom();
902 return !m_error;
905 bool RbUtilQt::hasDoom()
907 QFile doomrock(RbSettings::value(RbSettings::Mountpoint).toString()
908 +"/.rockbox/rocks/games/doom.rock");
909 return doomrock.exists();
912 void RbUtilQt::installDoom()
914 // create zip installer
915 installer = new ZipInstaller(this);
917 installer->setUrl(RbSettings::value(RbSettings::DoomUrl).toString());
918 installer->setLogSection("Game Addons");
919 installer->setLogVersion(versmap.value("arch_date"));
920 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
921 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
922 installer->setCache(true);
923 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
924 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
925 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
926 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
927 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
928 installer->install();
932 void RbUtilQt::installThemes()
934 if(chkConfig(true)) return;
935 ThemesInstallWindow* tw = new ThemesInstallWindow(this);
936 tw->setModal(true);
937 tw->show();
940 void RbUtilQt::createTalkFiles(void)
942 if(chkConfig(true)) return;
943 InstallTalkWindow *installWindow = new InstallTalkWindow(this);
945 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
946 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
947 installWindow->show();
951 void RbUtilQt::createVoiceFile(void)
953 if(chkConfig(true)) return;
954 CreateVoiceWindow *installWindow = new CreateVoiceWindow(this);
956 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
957 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
958 installWindow->show();
961 void RbUtilQt::uninstall(void)
963 if(chkConfig(true)) return;
964 UninstallWindow *uninstallWindow = new UninstallWindow(this);
965 uninstallWindow->show();
969 void RbUtilQt::uninstallBootloader(void)
971 if(chkConfig(true)) return;
972 if(QMessageBox::question(this, tr("Confirm Uninstallation"),
973 tr("Do you really want to uninstall the Bootloader?"),
974 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
975 // create logger
976 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
977 logger->setProgressVisible(false);
978 logger->show();
980 QString platform = RbSettings::value(RbSettings::Platform).toString();
982 // create installer
983 BootloaderInstallBase *bl;
984 QString type = RbSettings::value(RbSettings::CurBootloaderMethod).toString();
985 if(type == "mi4") {
986 bl = new BootloaderInstallMi4(this);
988 else if(type == "hex") {
989 bl = new BootloaderInstallHex(this);
991 else if(type == "sansa") {
992 bl = new BootloaderInstallSansa(this);
994 else if(type == "ipod") {
995 bl = new BootloaderInstallIpod(this);
997 else if(type == "file") {
998 bl = new BootloaderInstallFile(this);
1000 else {
1001 logger->addItem(tr("No uninstall method known."), LOGERROR);
1002 logger->setFinished();
1003 return;
1006 QStringList blfile = RbSettings::value(RbSettings::CurBootloaderFile).toStringList();
1007 QStringList blfilepath;
1008 for(int a = 0; a < blfile.size(); a++) {
1009 blfilepath.append(RbSettings::value(RbSettings::Mountpoint).toString()
1010 + blfile.at(a));
1012 bl->setBlFile(blfilepath);
1014 connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
1015 connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
1017 int result;
1018 result = bl->uninstall();
1020 logger->setFinished();
1025 void RbUtilQt::downloadManual(void)
1027 if(chkConfig(true)) return;
1028 if(QMessageBox::question(this, tr("Confirm download"),
1029 tr("Do you really want to download the manual? The manual will be saved "
1030 "to the root folder of your player."),
1031 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
1032 return;
1034 buildInfo.open();
1035 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
1036 buildInfo.close();
1038 QString manual = RbSettings::value(RbSettings::CurManual).toString();
1039 if(manual.isEmpty())
1040 manual = "rockbox-" + RbSettings::value(RbSettings::Platform).toString();
1042 QString date = (info.value("dailies/date").toString());
1044 QString manualurl;
1045 QString target;
1046 QString section;
1047 if(ui.radioPdf->isChecked()) {
1048 target = "/" + manual + ".pdf";
1049 section = "Manual (PDF)";
1051 else {
1052 target = "/" + manual + "-" + date + "-html.zip";
1053 section = "Manual (HTML)";
1055 manualurl = RbSettings::value(RbSettings::ManualUrl).toString() + "/" + target;
1056 qDebug() << "[RbUtil] Manual URL:" << manualurl;
1058 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
1059 logger->show();
1060 installer = new ZipInstaller(this);
1061 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
1062 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
1063 installer->setCache(true);
1064 installer->setLogSection(section);
1065 installer->setLogVersion(date);
1066 installer->setUrl(manualurl);
1067 installer->setUnzip(false);
1068 installer->setTarget(target);
1069 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
1070 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
1071 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
1072 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
1073 installer->install();
1077 void RbUtilQt::installPortable(void)
1079 if(QMessageBox::question(this, tr("Confirm installation"),
1080 tr("Do you really want to install Rockbox Utility to your player? "
1081 "After installation you can run it from the players hard drive."),
1082 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
1083 return;
1085 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
1086 logger->setProgressMax(0);
1087 logger->setProgressValue(0);
1088 logger->show();
1089 logger->addItem(tr("Installing Rockbox Utility"), LOGINFO);
1091 // check mountpoint
1092 if(!QFileInfo(RbSettings::value(RbSettings::Mountpoint).toString()).isDir()) {
1093 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
1094 logger->setFinished();
1095 return;
1098 // remove old files first.
1099 QFile::remove(RbSettings::value(RbSettings::Mountpoint).toString()
1100 + "/RockboxUtility.exe");
1101 QFile::remove(RbSettings::value(RbSettings::Mountpoint).toString()
1102 + "/RockboxUtility.ini");
1103 // copy currently running binary and currently used settings file
1104 if(!QFile::copy(qApp->applicationFilePath(),
1105 RbSettings::value(RbSettings::Mountpoint).toString()
1106 + "/RockboxUtility.exe")) {
1107 logger->addItem(tr("Error installing Rockbox Utility"), LOGERROR);
1108 logger->setFinished();
1109 return;
1111 logger->addItem(tr("Installing user configuration"), LOGINFO);
1112 if(!QFile::copy(RbSettings::userSettingFilename(),
1113 RbSettings::value(RbSettings::Mountpoint).toString()
1114 + "/RockboxUtility.ini")) {
1115 logger->addItem(tr("Error installing user configuration"), LOGERROR);
1116 logger->setFinished();
1117 return;
1119 logger->addItem(tr("Successfully installed Rockbox Utility."), LOGOK);
1120 logger->setFinished();
1121 logger->setProgressMax(1);
1122 logger->setProgressValue(1);
1127 void RbUtilQt::updateInfo()
1129 qDebug() << "[RbUtil] updating server info";
1131 QSettings log(RbSettings::value(RbSettings::Mountpoint).toString()
1132 + "/.rockbox/rbutil.log", QSettings::IniFormat, this);
1133 QStringList groups = log.childGroups();
1134 QList<QTreeWidgetItem *> items;
1135 QTreeWidgetItem *w, *w2;
1136 QString min, max;
1137 int olditems = 0;
1139 // remove old list entries (if any)
1140 int l = ui.treeInfo->topLevelItemCount();
1141 while(l--) {
1142 QTreeWidgetItem *m;
1143 m = ui.treeInfo->takeTopLevelItem(l);
1144 // delete childs (single level deep, no recursion here)
1145 int n = m->childCount();
1146 while(n--)
1147 delete m->child(n);
1149 // get and populate new items
1150 for(int a = 0; a < groups.size(); a++) {
1151 log.beginGroup(groups.at(a));
1152 QStringList keys = log.allKeys();
1153 w = new QTreeWidgetItem;
1154 w->setFlags(Qt::ItemIsEnabled);
1155 w->setText(0, groups.at(a));
1156 items.append(w);
1157 // get minimum and maximum version information so we can hilight old files
1158 min = max = log.value(keys.at(0)).toString();
1159 for(int b = 0; b < keys.size(); b++) {
1160 if(log.value(keys.at(b)).toString() > max)
1161 max = log.value(keys.at(b)).toString();
1162 if(log.value(keys.at(b)).toString() < min)
1163 min = log.value(keys.at(b)).toString();
1166 for(int b = 0; b < keys.size(); b++) {
1167 QString file;
1168 file = RbSettings::value(RbSettings::Mountpoint).toString() + "/" + keys.at(b);
1169 if(QFileInfo(file).isDir())
1170 continue;
1171 w2 = new QTreeWidgetItem(w, QStringList() << "/"
1172 + keys.at(b) << log.value(keys.at(b)).toString());
1173 if(log.value(keys.at(b)).toString() != max) {
1174 w2->setForeground(0, QBrush(QColor(255, 0, 0)));
1175 w2->setForeground(1, QBrush(QColor(255, 0, 0)));
1176 olditems++;
1178 items.append(w2);
1180 log.endGroup();
1181 if(min != max)
1182 w->setData(1, Qt::DisplayRole, QString("%1 / %2").arg(min, max));
1183 else
1184 w->setData(1, Qt::DisplayRole, max);
1186 ui.treeInfo->insertTopLevelItems(0, items);
1187 ui.treeInfo->resizeColumnToContents(0);
1191 QUrl RbUtilQt::proxy()
1193 if(RbSettings::value(RbSettings::ProxyType) == "manual")
1194 return QUrl(RbSettings::value(RbSettings::Proxy).toString());
1195 else if(RbSettings::value(RbSettings::ProxyType) == "system")
1196 return System::systemProxy();
1197 return QUrl("");
1201 bool RbUtilQt::chkConfig(bool warn)
1203 bool error = false;
1204 if(RbSettings::value(RbSettings::Platform).toString().isEmpty()
1205 || RbSettings::value(RbSettings::Mountpoint).toString().isEmpty()
1206 || !QFileInfo(RbSettings::value(RbSettings::Mountpoint).toString()).isWritable()) {
1207 error = true;
1209 if(warn) QMessageBox::critical(this, tr("Configuration error"),
1210 tr("Your configuration is invalid. Please go to the configuration "
1211 "dialog and make sure the selected values are correct."));
1213 return error;