test test test
[kugel-rb.git] / rbutil / rbutilqt / rbutilqt.cpp
blobc8513b11875e9931beddfcf8d1ae83d931ea1370
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 // startup log
63 qDebug() << "======================================";
64 qDebug() << "[System] Rockbox Utility " VERSION;
65 qDebug() << "[System] Qt version:" << qVersion();
66 qDebug() << "======================================";
68 absolutePath = qApp->applicationDirPath();
70 HttpGet::setGlobalUserAgent("rbutil/"VERSION);
71 // init startup & autodetection
72 ui.setupUi(this);
73 updateSettings();
74 downloadInfo();
76 m_gotInfo = false;
77 m_auto = false;
79 // manual tab
80 ui.radioPdf->setChecked(true);
82 // info tab
83 ui.treeInfo->setAlternatingRowColors(true);
84 ui.treeInfo->setHeaderLabels(QStringList() << tr("File") << tr("Version"));
85 ui.treeInfo->expandAll();
86 ui.treeInfo->setColumnCount(2);
87 // disable quick install until version info is available
88 ui.buttonSmall->setEnabled(false);
89 ui.buttonComplete->setEnabled(false);
91 connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateTabs(int)));
92 connect(ui.actionAbout_Qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
93 connect(ui.action_About, SIGNAL(triggered()), this, SLOT(about()));
94 connect(ui.action_Help, SIGNAL(triggered()), this, SLOT(help()));
95 connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog()));
96 connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog()));
97 connect(ui.buttonRockbox, SIGNAL(clicked()), this, SLOT(installBtn()));
98 connect(ui.buttonBootloader, SIGNAL(clicked()), this, SLOT(installBootloaderBtn()));
99 connect(ui.buttonFonts, SIGNAL(clicked()), this, SLOT(installFontsBtn()));
100 connect(ui.buttonGames, SIGNAL(clicked()), this, SLOT(installDoomBtn()));
101 connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles()));
102 connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile()));
103 connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice()));
104 connect(ui.buttonThemes, SIGNAL(clicked()), this, SLOT(installThemes()));
105 connect(ui.buttonRemoveRockbox, SIGNAL(clicked()), this, SLOT(uninstall()));
106 connect(ui.buttonRemoveBootloader, SIGNAL(clicked()), this, SLOT(uninstallBootloader()));
107 connect(ui.buttonDownloadManual, SIGNAL(clicked()), this, SLOT(downloadManual()));
108 connect(ui.buttonSmall, SIGNAL(clicked()), this, SLOT(smallInstall()));
109 connect(ui.buttonComplete, SIGNAL(clicked()), this, SLOT(completeInstall()));
111 // actions accessible from the menu
112 connect(ui.actionComplete_Installation, SIGNAL(triggered()), this, SLOT(completeInstall()));
113 connect(ui.actionSmall_Installation, SIGNAL(triggered()), this, SLOT(smallInstall()));
114 connect(ui.actionInstall_Bootloader, SIGNAL(triggered()), this, SLOT(installBootloaderBtn()));
115 connect(ui.actionInstall_Rockbox, SIGNAL(triggered()), this, SLOT(installBtn()));
116 connect(ui.actionFonts_Package, SIGNAL(triggered()), this, SLOT(installFontsBtn()));
117 connect(ui.actionInstall_Themes, SIGNAL(triggered()), this, SLOT(installThemes()));
118 connect(ui.actionInstall_Game_Files, SIGNAL(triggered()), this, SLOT(installDoomBtn()));
119 connect(ui.actionInstall_Voice_File, SIGNAL(triggered()), this, SLOT(installVoice()));
120 connect(ui.actionCreate_Voice_File, SIGNAL(triggered()), this, SLOT(createVoiceFile()));
121 connect(ui.actionCreate_Talk_Files, SIGNAL(triggered()), this, SLOT(createTalkFiles()));
122 connect(ui.actionRemove_bootloader, SIGNAL(triggered()), this, SLOT(uninstallBootloader()));
123 connect(ui.actionUninstall_Rockbox, SIGNAL(triggered()), this, SLOT(uninstall()));
124 connect(ui.action_System_Info, SIGNAL(triggered()), this, SLOT(sysinfo()));
126 #if !defined(STATIC)
127 ui.actionInstall_Rockbox_Utility_on_player->setEnabled(false);
128 #else
129 connect(ui.actionInstall_Rockbox_Utility_on_player, SIGNAL(triggered()), this, SLOT(installPortable()));
130 #endif
135 void RbUtilQt::sysinfo(void)
137 Sysinfo *info = new Sysinfo(this);
138 info->show();
141 void RbUtilQt::updateTabs(int count)
143 switch(count) {
144 case 6:
145 updateInfo();
146 break;
147 default:
148 break;
153 void RbUtilQt::downloadInfo()
155 // make sure the version map is repopulated correctly later.
156 versmap.clear();
157 // try to get the current build information
158 daily = new HttpGet(this);
159 connect(daily, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
160 connect(daily, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
161 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
162 if(RbSettings::value(RbSettings::CacheOffline).toBool())
163 daily->setCache(true);
164 else
165 daily->setCache(false);
166 qDebug() << "[RbUtil] downloading build info";
167 daily->setFile(&buildInfo);
168 daily->getFile(QUrl(RbSettings::value(RbSettings::ServerConfUrl).toString()));
172 void RbUtilQt::downloadDone(bool error)
174 if(error) {
175 qDebug() << "[RbUtil] network error:" << daily->error();
176 QMessageBox::critical(this, tr("Network error"),
177 tr("Can't get version information."));
178 return;
180 qDebug() << "[RbUtil] network status:" << daily->error();
182 buildInfo.open();
183 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
184 buildInfo.close();
185 versmap.insert("arch_rev", info.value("dailies/rev").toString());
186 versmap.insert("arch_date", info.value("dailies/date").toString());
188 info.beginGroup("release");
189 versmap.insert("rel_rev", info.value(RbSettings::value(RbSettings::CurBuildserverModel).toString()).toString());
190 info.endGroup();
192 if(versmap.value("rel_rev").isEmpty()) {
193 ui.buttonSmall->setEnabled(false);
194 ui.buttonComplete->setEnabled(false);
196 else {
197 ui.buttonSmall->setEnabled(true);
198 ui.buttonComplete->setEnabled(true);
201 bleeding = new HttpGet(this);
202 connect(bleeding, SIGNAL(done(bool)), this, SLOT(downloadBleedingDone(bool)));
203 connect(bleeding, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
204 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
205 if(RbSettings::value(RbSettings::CacheOffline).toBool())
206 bleeding->setCache(true);
207 bleeding->setFile(&bleedingInfo);
208 bleeding->getFile(QUrl(RbSettings::value(RbSettings::BleedingInfo).toString()));
210 if(RbSettings::value(RbSettings::RbutilVersion) != PUREVERSION) {
211 QApplication::processEvents();
212 QMessageBox::information(this, tr("New installation"),
213 tr("This is a new installation of Rockbox Utility, or a new version. "
214 "The configuration dialog will now open to allow you to setup the program, "
215 " or review your settings."));
216 configDialog();
218 else if(chkConfig(false)) {
219 QApplication::processEvents();
220 QMessageBox::critical(this, tr("Configuration error"),
221 tr("Your configuration is invalid. This is most likely due "
222 "to a changed device path. The configuration dialog will "
223 "now open to allow you to correct the problem."));
224 configDialog();
229 void RbUtilQt::downloadBleedingDone(bool error)
231 if(error) {
232 qDebug() << "[RbUtil] network error:" << bleeding->error();
234 else {
235 bleedingInfo.open();
236 QSettings info(bleedingInfo.fileName(), QSettings::IniFormat, this);
237 bleedingInfo.close();
238 versmap.insert("bleed_rev", info.value("bleeding/rev").toString());
239 versmap.insert("bleed_date", info.value("bleeding/timestamp").toString());
240 qDebug() << "[RbUtil] version map:" << versmap;
242 m_gotInfo = true;
247 void RbUtilQt::downloadDone(int id, bool error)
249 QString errorString;
250 errorString = tr("Network error: %1. Please check your network and proxy settings.")
251 .arg(daily->errorString());
252 if(error) {
253 QMessageBox::about(this, "Network Error", errorString);
254 m_networkerror = daily->errorString();
256 qDebug() << "[RbUtil] downloadDone:" << id << "error:" << error;
260 void RbUtilQt::about()
262 QDialog *window = new QDialog(this);
263 Ui::aboutBox about;
264 about.setupUi(window);
265 window->setModal(true);
267 QFile licence(":/docs/gpl-2.0.html");
268 licence.open(QIODevice::ReadOnly);
269 QTextStream c(&licence);
270 QString cline = c.readAll();
271 about.browserLicense->insertHtml(cline);
272 about.browserLicense->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
273 QFile credits(":/docs/CREDITS");
274 credits.open(QIODevice::ReadOnly);
275 QTextStream r(&credits);
276 r.setCodec(QTextCodec::codecForName("UTF-8"));
277 QString rline = r.readAll();
278 about.browserCredits->insertPlainText(rline);
279 about.browserCredits->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
280 QString title = QString("<b>The Rockbox Utility</b><br/>Version %1").arg(FULLVERSION);
281 about.labelTitle->setText(title);
282 about.labelHomepage->setText("<a href='http://www.rockbox.org'>http://www.rockbox.org</a>");
284 window->show();
289 void RbUtilQt::help()
291 QUrl helpurl("http://www.rockbox.org/wiki/RockboxUtility");
292 QDesktopServices::openUrl(helpurl);
296 void RbUtilQt::configDialog()
298 Config *cw = new Config(this);
299 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
300 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
301 cw->show();
305 void RbUtilQt::updateSettings()
307 qDebug() << "[RbUtil] updating current settings";
308 updateDevice();
309 updateManual();
310 if(RbSettings::value(RbSettings::ProxyType) == "system") {
311 HttpGet::setGlobalProxy(Detect::systemProxy());
313 else if(RbSettings::value(RbSettings::ProxyType) == "manual") {
314 HttpGet::setGlobalProxy(RbSettings::value(RbSettings::Proxy).toString());
316 else {
317 HttpGet::setGlobalProxy(QUrl(""));
319 HttpGet::setGlobalCache(RbSettings::value(RbSettings::CachePath).toString());
320 HttpGet::setGlobalDumbCache(RbSettings::value(RbSettings::CacheOffline).toBool());
324 void RbUtilQt::updateDevice()
326 if(RbSettings::value(RbSettings::CurBootloaderMethod) == "none" ) {
327 ui.buttonBootloader->setEnabled(false);
328 ui.buttonRemoveBootloader->setEnabled(false);
329 ui.labelBootloader->setEnabled(false);
330 ui.labelRemoveBootloader->setEnabled(false);
332 else {
333 ui.buttonBootloader->setEnabled(true);
334 ui.labelBootloader->setEnabled(true);
335 if(RbSettings::value(RbSettings::CurBootloaderMethod) == "fwpatcher") {
336 ui.labelRemoveBootloader->setEnabled(false);
337 ui.buttonRemoveBootloader->setEnabled(false);
339 else {
340 ui.labelRemoveBootloader->setEnabled(true);
341 ui.buttonRemoveBootloader->setEnabled(true);
345 // displayed device info
346 QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
347 QString brand = RbSettings::value(RbSettings::CurBrand).toString();
348 QString name = RbSettings::value(RbSettings::CurName).toString();
349 if(name.isEmpty()) name = "&lt;none&gt;";
350 if(mountpoint.isEmpty()) mountpoint = "&lt;invalid&gt;";
351 ui.labelDevice->setText(tr("<b>%1 %2</b> at <b>%3</b>")
352 .arg(brand, name, QDir::toNativeSeparators(mountpoint)));
356 void RbUtilQt::updateManual()
358 if(RbSettings::value(RbSettings::Platform) != "")
360 QString manual= RbSettings::value(RbSettings::CurManual).toString();
362 if(manual == "")
363 manual = "rockbox-" + RbSettings::value(RbSettings::Platform).toString();
364 QString pdfmanual;
365 pdfmanual = RbSettings::value(RbSettings::ManualUrl).toString()
366 + "/" + manual + ".pdf";
367 QString htmlmanual;
368 htmlmanual = RbSettings::value(RbSettings::ManualUrl).toString()
369 + "/" + manual + "/rockbox-build.html";
370 ui.labelPdfManual->setText(tr("<a href='%1'>PDF Manual</a>")
371 .arg(pdfmanual));
372 ui.labelHtmlManual->setText(tr("<a href='%1'>HTML Manual (opens in browser)</a>")
373 .arg(htmlmanual));
375 else {
376 ui.labelPdfManual->setText(tr("Select a device for a link to the correct manual"));
377 ui.labelHtmlManual->setText(tr("<a href='%1'>Manual Overview</a>")
378 .arg("http://www.rockbox.org/manual.shtml"));
383 void RbUtilQt::completeInstall()
385 if(chkConfig(true)) return;
386 if(QMessageBox::question(this, tr("Confirm Installation"),
387 tr("Do you really want to perform a complete installation?\n\n"
388 "This will install Rockbox %1. To install the most recent "
389 "development build available press \"Cancel\" and "
390 "use the \"Installation\" tab.")
391 .arg(versmap.value("rel_rev")),
392 QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok)
393 return;
394 // create logger
395 logger = new ProgressLoggerGui(this);
396 logger->show();
398 if(smallInstallInner())
399 return;
400 logger->setRunning();
401 // Fonts
402 m_error = false;
403 m_installed = false;
404 if(!installFontsAuto())
405 return;
406 else
408 // wait for installation finished
409 while(!m_installed)
410 QApplication::processEvents();
412 if(m_error) return;
413 logger->setRunning();
415 // Doom
416 if(hasDoom())
418 m_error = false;
419 m_installed = false;
420 if(!installDoomAuto())
421 return;
422 else
424 // wait for installation finished
425 while(!m_installed)
426 QApplication::processEvents();
428 if(m_error) return;
431 // theme
432 // this is a window
433 // it has its own logger window,so close our.
434 logger->close();
435 installThemes();
439 void RbUtilQt::smallInstall()
441 if(chkConfig(true)) return;
442 if(QMessageBox::question(this, tr("Confirm Installation"),
443 tr("Do you really want to perform a minimal installation? "
444 "A minimal installation will contain only the absolutely "
445 "necessary parts to run Rockbox.\n\n"
446 "This will install Rockbox %1. To install the most recent "
447 "development build available press \"Cancel\" and "
448 "use the \"Installation\" tab.")
449 .arg(versmap.value("rel_rev")),
450 QMessageBox::Ok | QMessageBox::Cancel) != QMessageBox::Ok)
451 return;
453 // create logger
454 logger = new ProgressLoggerGui(this);
455 logger->show();
457 smallInstallInner();
460 bool RbUtilQt::smallInstallInner()
462 QString mountpoint = RbSettings::value(RbSettings::Mountpoint).toString();
463 // show dialog with error if mount point is wrong
464 if(!QFileInfo(mountpoint).isDir()) {
465 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
466 logger->setFinished();
467 return true;
469 // Bootloader
470 if(RbSettings::value(RbSettings::CurBootloaderMethod) != "none")
472 m_error = false;
473 m_installed = false;
474 m_auto = true;
475 if(!installBootloaderAuto()) {
476 logger->setFinished();
477 return true;
479 else
481 // wait for boot loader installation finished
482 while(!m_installed)
483 QApplication::processEvents();
485 m_auto = false;
486 if(m_error) return true;
487 logger->setRunning();
490 // Rockbox
491 m_error = false;
492 m_installed = false;
493 if(!installAuto())
494 return true;
495 else
497 // wait for installation finished
498 while(!m_installed)
499 QApplication::processEvents();
502 installBootloaderPost(false);
503 return false;
506 void RbUtilQt::installdone(bool error)
508 qDebug() << "[RbUtil] install done";
509 m_installed = true;
510 m_error = error;
513 void RbUtilQt::installBtn()
515 if(chkConfig(true)) return;
516 install();
519 bool RbUtilQt::installAuto()
521 QString file = QString("%1/%2/rockbox-%3-%4.zip")
522 .arg(RbSettings::value(RbSettings::ReleaseUrl).toString(),
523 versmap.value("rel_rev"),
524 RbSettings::value(RbSettings::CurBuildserverModel).toString(),
525 versmap.value("rel_rev"));
526 buildInfo.open();
527 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
528 buildInfo.close();
530 // check installed Version and Target
531 QString rbVersion = Detect::installedVersion(RbSettings::value(RbSettings::Mountpoint).toString());
532 QString warning = Detect::check(false);
534 if(!warning.isEmpty())
536 if(QMessageBox::warning(this, tr("Really continue?"), warning,
537 QMessageBox::Ok | QMessageBox::Abort, QMessageBox::Abort) == QMessageBox::Abort)
539 logger->addItem(tr("Aborted!"), LOGERROR);
540 logger->setFinished();
541 return false;
545 // check version
546 if(rbVersion != "")
548 if(QMessageBox::question(this, tr("Installed Rockbox detected"),
549 tr("Rockbox installation detected. Do you want to backup first?"),
550 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
552 logger->addItem(tr("Starting backup..."),LOGINFO);
553 QString backupName = RbSettings::value(RbSettings::Mountpoint).toString()
554 + "/.backup/rockbox-backup-" + rbVersion + ".zip";
556 //! create dir, if it doesnt exist
557 QFileInfo backupFile(backupName);
558 if(!QDir(backupFile.path()).exists())
560 QDir a;
561 a.mkpath(backupFile.path());
564 //! create backup
565 RbZip backup;
566 connect(&backup,SIGNAL(zipProgress(int,int)),logger, SLOT(setProgress(int,int)));
567 if(backup.createZip(backupName,
568 RbSettings::value(RbSettings::Mountpoint).toString() + "/.rockbox") == Zip::Ok)
570 logger->addItem(tr("Backup successful"),LOGOK);
572 else
574 logger->addItem(tr("Backup failed!"),LOGERROR);
575 logger->setFinished();
576 return false;
581 //! install current build
582 ZipInstaller* installer = new ZipInstaller(this);
583 installer->setUrl(file);
584 installer->setLogSection("Rockbox (Base)");
585 installer->setLogVersion(versmap.value("rel_rev"));
586 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
587 installer->setCache(true);
588 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
590 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
591 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
592 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
593 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
594 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
595 installer->install();
596 return true;
600 void RbUtilQt::install()
602 Install *installWindow = new Install(this);
604 buildInfo.open();
605 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
606 buildInfo.close();
607 installWindow->setVersionStrings(versmap);
609 installWindow->show();
612 bool RbUtilQt::installBootloaderAuto()
614 installBootloader();
615 return !m_error;
618 void RbUtilQt::installBootloaderBtn()
620 if(chkConfig(true)) return;
621 if(QMessageBox::question(this, tr("Confirm Installation"),
622 tr("Do you really want to install the Bootloader?"),
623 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
625 // create logger
626 logger = new ProgressLoggerGui(this);
627 logger->show();
628 installBootloader();
631 void RbUtilQt::installBootloader()
633 QString platform = RbSettings::value(RbSettings::Platform).toString();
634 QString backupDestination = "";
635 m_error = false;
637 // create installer
638 BootloaderInstallBase *bl;
639 QString type = RbSettings::value(RbSettings::CurBootloaderMethod).toString();
640 if(type == "mi4") {
641 bl = new BootloaderInstallMi4(this);
643 else if(type == "hex") {
644 bl = new BootloaderInstallHex(this);
646 else if(type == "sansa") {
647 bl = new BootloaderInstallSansa(this);
649 else if(type == "ipod") {
650 bl = new BootloaderInstallIpod(this);
652 else if(type == "file") {
653 bl = new BootloaderInstallFile(this);
655 else {
656 logger->addItem(tr("No install method known."), LOGERROR);
657 logger->setFinished();
658 return;
661 // set bootloader filename. Do this now as installed() needs it.
662 QString blfile;
663 blfile = RbSettings::value(RbSettings::Mountpoint).toString()
664 + RbSettings::value(RbSettings::CurBootloaderFile).toString();
665 // special case for H10 pure: this player can have a different
666 // bootloader file filename. This is handled here to keep the install
667 // class clean, though having it here is also not the nicest solution.
668 if(RbSettings::value(RbSettings::Platform).toString() == "h10_ums"
669 || RbSettings::value(RbSettings::Platform) == "h10_mtp") {
670 if(resolvePathCase(blfile).isEmpty())
671 blfile = RbSettings::value(RbSettings::Mountpoint).toString()
672 + RbSettings::value(RbSettings::CurBootloaderName).toString()
673 .replace("H10", "H10EMP", Qt::CaseInsensitive);
675 bl->setBlFile(blfile);
676 QUrl url(RbSettings::value(RbSettings::BootloaderUrl).toString()
677 + RbSettings::value(RbSettings::CurBootloaderName).toString());
678 bl->setBlUrl(url);
679 bl->setLogfile(RbSettings::value(RbSettings::Mountpoint).toString()
680 + "/.rockbox/rbutil.log");
682 if(bl->installed() == BootloaderInstallBase::BootloaderRockbox) {
683 if(QMessageBox::question(this, tr("Bootloader detected"),
684 tr("Bootloader already installed. Do you want to reinstall the bootloader?"),
685 QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
686 if(m_auto) {
687 // keep logger open for auto installs.
688 // don't consider abort as error in auto-mode.
689 logger->addItem(tr("Bootloader installation skipped"), LOGINFO);
690 installBootloaderPost(false);
692 else {
693 logger->close();
694 installBootloaderPost(true);
696 return;
699 else if(bl->installed() == BootloaderInstallBase::BootloaderOther
700 && bl->capabilities() & BootloaderInstallBase::Backup)
702 QString targetFolder = RbSettings::value(RbSettings::CurPlatformName).toString()
703 + " Firmware Backup";
704 // remove invalid character(s)
705 targetFolder.remove(QRegExp("[:/]"));
706 if(QMessageBox::question(this, tr("Create Bootloader backup"),
707 tr("You can create a backup of the original bootloader "
708 "file. Press \"Yes\" to select an output folder on your "
709 "computer to save the file to. The file will get placed "
710 "in a new folder \"%1\" created below the selected folder.\n"
711 "Press \"No\" to skip this step.").arg(targetFolder),
712 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
713 BrowseDirtree tree(this, tr("Browse backup folder"));
714 tree.setDir(QDir::home());
715 tree.exec();
717 backupDestination = tree.getSelected() + "/" + targetFolder;
718 qDebug() << "[RbUtil] backing up to" << backupDestination;
719 // backup needs to be done after the logger has been set up.
723 if(bl->capabilities() & BootloaderInstallBase::NeedsOf)
725 int ret;
726 ret = QMessageBox::information(this, tr("Prerequisites"),
727 bl->ofHint(),QMessageBox::Ok | QMessageBox::Abort);
728 if(ret != QMessageBox::Ok) {
729 // consider aborting an error to close window / abort automatic
730 // installation.
731 m_error = true;
732 logger->addItem(tr("Bootloader installation aborted"), LOGINFO);
733 logger->setFinished();
734 return;
736 // open dialog to browse to of file
737 QString offile;
738 offile = QFileDialog::getOpenFileName(this,
739 tr("Select firmware file"), QDir::homePath());
740 if(!QFileInfo(offile).isReadable()) {
741 logger->addItem(tr("Error opening firmware file"), LOGERROR);
742 logger->setFinished();
743 m_error = true;
744 return;
746 bl->setOfFile(offile);
749 // the bootloader install class does NOT use any GUI stuff.
750 // All messages are passed via signals.
751 connect(bl, SIGNAL(done(bool)), logger, SLOT(setFinished()));
752 connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool)));
753 connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
754 connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
756 // start install.
757 if(!backupDestination.isEmpty()) {
758 if(!bl->backup(backupDestination)) {
759 if(QMessageBox::warning(this, tr("Backup error"),
760 tr("Could not create backup file. Continue?"),
761 QMessageBox::No | QMessageBox::Yes)
762 == QMessageBox::No) {
763 logger->setFinished();
764 return;
768 bl->install();
771 void RbUtilQt::installBootloaderPost(bool error)
773 qDebug() << "[RbUtil] Bootloader Post-Installation, error state:" << error;
774 // if an error occured don't perform post install steps.
775 if(error) {
776 m_error = true;
777 return;
779 else
780 m_error = false;
782 m_installed = true;
783 // end here if automated install
784 if(m_auto)
785 return;
787 QString msg = BootloaderInstallBase::postinstallHints(
788 RbSettings::value(RbSettings::Platform).toString());
789 if(!msg.isEmpty()) {
790 QMessageBox::information(this, tr("Manual steps required"), msg);
791 logger->close();
796 void RbUtilQt::installFontsBtn()
798 if(chkConfig(true)) return;
799 if(QMessageBox::question(this, tr("Confirm Installation"),
800 tr("Do you really want to install the fonts package?"),
801 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
802 // create logger
803 logger = new ProgressLoggerGui(this);
804 logger->show();
805 installFonts();
808 bool RbUtilQt::installFontsAuto()
810 installFonts();
812 return !m_error;
815 void RbUtilQt::installFonts()
817 // create zip installer
818 installer = new ZipInstaller(this);
820 installer->setUrl(RbSettings::value(RbSettings::FontUrl).toString());
821 installer->setLogSection("Fonts");
822 installer->setLogVersion(versmap.value("arch_date"));
823 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
824 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
825 installer->setCache(true);
827 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
828 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
829 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
830 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
831 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
832 installer->install();
836 void RbUtilQt::installVoice()
838 if(chkConfig(true)) return;
840 if(m_gotInfo == false)
842 QMessageBox::warning(this, tr("Warning"),
843 tr("The Application is still downloading Information about new Builds."
844 " Please try again shortly."));
845 return;
848 if(QMessageBox::question(this, tr("Confirm Installation"),
849 tr("Do you really want to install the voice file?"),
850 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
851 // create logger
852 logger = new ProgressLoggerGui(this);
853 logger->show();
855 // create zip installer
856 installer = new ZipInstaller(this);
858 QString voiceurl = RbSettings::value(RbSettings::VoiceUrl).toString();
860 voiceurl += RbSettings::value(RbSettings::CurBuildserverModel).toString() + "-" +
861 versmap.value("arch_date") + "-english.zip";
862 qDebug() << "[RbUtil] voicefile URL:" << voiceurl;
864 installer->setUrl(voiceurl);
865 installer->setLogSection("Voice");
866 installer->setLogVersion(versmap.value("arch_date"));
867 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
868 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
869 installer->setCache(true);
870 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
871 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
872 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
873 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
874 installer->install();
878 void RbUtilQt::installDoomBtn()
880 if(chkConfig(true)) return;
881 if(!hasDoom()){
882 QMessageBox::critical(this, tr("Error"),
883 tr("Your device doesn't have a doom plugin. Aborting."));
884 return;
887 if(QMessageBox::question(this, tr("Confirm Installation"),
888 tr("Do you really want to install the game addon files?"),
889 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
890 // create logger
891 logger = new ProgressLoggerGui(this);
892 logger->show();
894 installDoom();
896 bool RbUtilQt::installDoomAuto()
898 installDoom();
899 return !m_error;
902 bool RbUtilQt::hasDoom()
904 QFile doomrock(RbSettings::value(RbSettings::Mountpoint).toString()
905 +"/.rockbox/rocks/games/doom.rock");
906 return doomrock.exists();
909 void RbUtilQt::installDoom()
911 // create zip installer
912 installer = new ZipInstaller(this);
914 installer->setUrl(RbSettings::value(RbSettings::DoomUrl).toString());
915 installer->setLogSection("Game Addons");
916 installer->setLogVersion(versmap.value("arch_date"));
917 installer->setMountPoint(RbSettings::value(RbSettings::Mountpoint).toString());
918 if(!RbSettings::value(RbSettings::CacheDisabled).toBool())
919 installer->setCache(true);
920 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
921 connect(installer, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
922 connect(installer, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
923 connect(installer, SIGNAL(done(bool)), logger, SLOT(setFinished()));
924 connect(logger, SIGNAL(aborted()), installer, SLOT(abort()));
925 installer->install();
929 void RbUtilQt::installThemes()
931 if(chkConfig(true)) return;
932 ThemesInstallWindow* tw = new ThemesInstallWindow(this);
933 tw->setModal(true);
934 tw->show();
937 void RbUtilQt::createTalkFiles(void)
939 if(chkConfig(true)) return;
940 InstallTalkWindow *installWindow = new InstallTalkWindow(this);
942 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
943 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
944 installWindow->show();
948 void RbUtilQt::createVoiceFile(void)
950 if(chkConfig(true)) return;
951 CreateVoiceWindow *installWindow = new CreateVoiceWindow(this);
953 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
954 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
955 installWindow->show();
958 void RbUtilQt::uninstall(void)
960 if(chkConfig(true)) return;
961 UninstallWindow *uninstallWindow = new UninstallWindow(this);
962 uninstallWindow->show();
966 void RbUtilQt::uninstallBootloader(void)
968 if(chkConfig(true)) return;
969 if(QMessageBox::question(this, tr("Confirm Uninstallation"),
970 tr("Do you really want to uninstall the Bootloader?"),
971 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
972 // create logger
973 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
974 logger->setProgressVisible(false);
975 logger->show();
977 QString platform = RbSettings::value(RbSettings::Platform).toString();
979 // create installer
980 BootloaderInstallBase *bl;
981 QString type = RbSettings::value(RbSettings::CurBootloaderMethod).toString();
982 if(type == "mi4") {
983 bl = new BootloaderInstallMi4(this);
985 else if(type == "hex") {
986 bl = new BootloaderInstallHex(this);
988 else if(type == "sansa") {
989 bl = new BootloaderInstallSansa(this);
991 else if(type == "ipod") {
992 bl = new BootloaderInstallIpod(this);
994 else if(type == "file") {
995 bl = new BootloaderInstallFile(this);
997 else {
998 logger->addItem(tr("No uninstall method known."), LOGERROR);
999 logger->setFinished();
1000 return;
1003 QString blfile = RbSettings::value(RbSettings::Mountpoint).toString()
1004 + RbSettings::value(RbSettings::CurBootloaderFile).toString();
1005 if(RbSettings::value(RbSettings::Platform).toString() == "h10_ums"
1006 || RbSettings::value(RbSettings::Platform).toString() == "h10_mtp") {
1007 if(resolvePathCase(blfile).isEmpty())
1008 blfile = RbSettings::value(RbSettings::Mountpoint).toString()
1009 + RbSettings::value(RbSettings::CurBootloaderName).toString()
1010 .replace("H10", "H10EMP", Qt::CaseInsensitive);
1012 bl->setBlFile(blfile);
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 Detect::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;