codec.link must be created with -DCODEC
[kugel-rb.git] / rbutil / rbutilqt / rbutilqt.cpp
blob8c0691c52b0387a084bfc500dffb8e8e6c60695d
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 "installthemes.h"
32 #include "uninstallwindow.h"
33 #include "utils.h"
34 #include "rbzip.h"
35 #include "sysinfo.h"
36 #include "detect.h"
38 #include "progressloggerinterface.h"
40 #include "bootloaderinstallbase.h"
41 #include "bootloaderinstallmi4.h"
42 #include "bootloaderinstallhex.h"
43 #include "bootloaderinstallipod.h"
44 #include "bootloaderinstallsansa.h"
45 #include "bootloaderinstallfile.h"
47 #if defined(Q_OS_LINUX)
48 #include <stdio.h>
49 #endif
50 #if defined(Q_OS_WIN32)
51 #if defined(UNICODE)
52 #define _UNICODE
53 #endif
54 #include <stdio.h>
55 #include <tchar.h>
56 #include <windows.h>
57 #endif
59 RbUtilQt::RbUtilQt(QWidget *parent) : QMainWindow(parent)
61 absolutePath = qApp->applicationDirPath();
63 settings = new RbSettings();
64 settings->open();
65 HttpGet::setGlobalUserAgent("rbutil/"VERSION);
66 // init startup & autodetection
67 ui.setupUi(this);
68 updateSettings();
69 downloadInfo();
71 m_gotInfo = false;
72 m_auto = false;
74 // manual tab
75 ui.radioPdf->setChecked(true);
77 // info tab
78 ui.treeInfo->setAlternatingRowColors(true);
79 ui.treeInfo->setHeaderLabels(QStringList() << tr("File") << tr("Version"));
80 ui.treeInfo->expandAll();
81 ui.treeInfo->setColumnCount(2);
83 connect(ui.tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateTabs(int)));
84 connect(ui.actionAbout_Qt, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
85 connect(ui.action_About, SIGNAL(triggered()), this, SLOT(about()));
86 connect(ui.action_Help, SIGNAL(triggered()), this, SLOT(help()));
87 connect(ui.action_Configure, SIGNAL(triggered()), this, SLOT(configDialog()));
88 connect(ui.buttonChangeDevice, SIGNAL(clicked()), this, SLOT(configDialog()));
89 connect(ui.buttonRockbox, SIGNAL(clicked()), this, SLOT(installBtn()));
90 connect(ui.buttonBootloader, SIGNAL(clicked()), this, SLOT(installBootloaderBtn()));
91 connect(ui.buttonFonts, SIGNAL(clicked()), this, SLOT(installFontsBtn()));
92 connect(ui.buttonGames, SIGNAL(clicked()), this, SLOT(installDoomBtn()));
93 connect(ui.buttonTalk, SIGNAL(clicked()), this, SLOT(createTalkFiles()));
94 connect(ui.buttonCreateVoice, SIGNAL(clicked()), this, SLOT(createVoiceFile()));
95 connect(ui.buttonVoice, SIGNAL(clicked()), this, SLOT(installVoice()));
96 connect(ui.buttonThemes, SIGNAL(clicked()), this, SLOT(installThemes()));
97 connect(ui.buttonRemoveRockbox, SIGNAL(clicked()), this, SLOT(uninstall()));
98 connect(ui.buttonRemoveBootloader, SIGNAL(clicked()), this, SLOT(uninstallBootloader()));
99 connect(ui.buttonDownloadManual, SIGNAL(clicked()), this, SLOT(downloadManual()));
100 connect(ui.buttonSmall, SIGNAL(clicked()), this, SLOT(smallInstall()));
101 connect(ui.buttonComplete, SIGNAL(clicked()), this, SLOT(completeInstall()));
103 // actions accessible from the menu
104 connect(ui.actionComplete_Installation, SIGNAL(triggered()), this, SLOT(completeInstall()));
105 connect(ui.actionSmall_Installation, SIGNAL(triggered()), this, SLOT(smallInstall()));
106 connect(ui.actionInstall_Bootloader, SIGNAL(triggered()), this, SLOT(installBootloaderBtn()));
107 connect(ui.actionInstall_Rockbox, SIGNAL(triggered()), this, SLOT(installBtn()));
108 connect(ui.actionFonts_Package, SIGNAL(triggered()), this, SLOT(installFontsBtn()));
109 connect(ui.actionInstall_Themes, SIGNAL(triggered()), this, SLOT(installThemes()));
110 connect(ui.actionInstall_Game_Files, SIGNAL(triggered()), this, SLOT(installDoomBtn()));
111 connect(ui.actionInstall_Voice_File, SIGNAL(triggered()), this, SLOT(installVoice()));
112 connect(ui.actionCreate_Voice_File, SIGNAL(triggered()), this, SLOT(createVoiceFile()));
113 connect(ui.actionCreate_Talk_Files, SIGNAL(triggered()), this, SLOT(createTalkFiles()));
114 connect(ui.actionRemove_bootloader, SIGNAL(triggered()), this, SLOT(uninstallBootloader()));
115 connect(ui.actionUninstall_Rockbox, SIGNAL(triggered()), this, SLOT(uninstall()));
116 connect(ui.action_System_Info, SIGNAL(triggered()), this, SLOT(sysinfo()));
118 #if !defined(STATIC)
119 ui.actionInstall_Rockbox_Utility_on_player->setEnabled(false);
120 #else
121 connect(ui.actionInstall_Rockbox_Utility_on_player, SIGNAL(triggered()), this, SLOT(installPortable()));
122 #endif
127 void RbUtilQt::sysinfo(void)
129 Sysinfo *info = new Sysinfo(this);
130 info->show();
133 void RbUtilQt::updateTabs(int count)
135 switch(count) {
136 case 6:
137 updateInfo();
138 break;
139 default:
140 break;
145 void RbUtilQt::downloadInfo()
147 // try to get the current build information
148 daily = new HttpGet(this);
149 connect(daily, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
150 connect(daily, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
151 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
152 if(settings->cacheOffline())
153 daily->setCache(true);
154 else
155 daily->setCache(false);
156 qDebug() << "downloading build info";
157 daily->setFile(&buildInfo);
158 daily->getFile(QUrl(settings->serverConfUrl()));
162 void RbUtilQt::downloadDone(bool error)
164 if(error) {
165 qDebug() << "network error:" << daily->error();
166 QMessageBox::critical(this, tr("Network error"),
167 tr("Can't get version information."));
168 return;
170 qDebug() << "network status:" << daily->error();
172 buildInfo.open();
173 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
174 buildInfo.close();
175 versmap.insert("arch_rev", info.value("dailies/rev").toString());
176 versmap.insert("arch_date", info.value("dailies/date").toString());
178 bleeding = new HttpGet(this);
179 connect(bleeding, SIGNAL(done(bool)), this, SLOT(downloadBleedingDone(bool)));
180 connect(bleeding, SIGNAL(requestFinished(int, bool)), this, SLOT(downloadDone(int, bool)));
181 connect(qApp, SIGNAL(lastWindowClosed()), daily, SLOT(abort()));
182 if(settings->cacheOffline())
183 bleeding->setCache(true);
184 bleeding->setFile(&bleedingInfo);
185 bleeding->getFile(QUrl(settings->bleedingInfo()));
187 if(settings->curVersion() != PUREVERSION) {
188 QApplication::processEvents();
189 QMessageBox::information(this, tr("New installation"),
190 tr("This is a new installation of Rockbox Utility, or a new version. "
191 "The configuration dialog will now open to allow you to setup the program, "
192 " or review your settings."));
193 configDialog();
195 else if(chkConfig(false)) {
196 QApplication::processEvents();
197 QMessageBox::critical(this, tr("Configuration error"),
198 tr("Your configuration is invalid. This is most likely due "
199 "to a changed device path. The configuration dialog will "
200 "now open to allow you to correct the problem."));
201 configDialog();
206 void RbUtilQt::downloadBleedingDone(bool error)
208 if(error) qDebug() << "network error:" << bleeding->error();
210 bleedingInfo.open();
211 QSettings info(bleedingInfo.fileName(), QSettings::IniFormat, this);
212 bleedingInfo.close();
213 versmap.insert("bleed_rev", info.value("bleeding/rev").toString());
214 versmap.insert("bleed_date", info.value("bleeding/timestamp").toString());
215 qDebug() << "versmap =" << versmap;
217 m_gotInfo = true;
221 void RbUtilQt::downloadDone(int id, bool error)
223 QString errorString;
224 errorString = tr("Network error: %1. Please check your network and proxy settings.")
225 .arg(daily->errorString());
226 if(error) {
227 QMessageBox::about(this, "Network Error", errorString);
228 m_networkerror = daily->errorString();
230 qDebug() << "downloadDone:" << id << "error:" << error;
234 void RbUtilQt::about()
236 QDialog *window = new QDialog(this);
237 Ui::aboutBox about;
238 about.setupUi(window);
239 window->setModal(true);
241 QFile licence(":/docs/gpl-2.0.html");
242 licence.open(QIODevice::ReadOnly);
243 QTextStream c(&licence);
244 QString cline = c.readAll();
245 about.browserLicense->insertHtml(cline);
246 about.browserLicense->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
247 QFile credits(":/docs/CREDITS");
248 credits.open(QIODevice::ReadOnly);
249 QTextStream r(&credits);
250 QString rline = r.readAll();
251 about.browserCredits->insertPlainText(rline);
252 about.browserCredits->moveCursor(QTextCursor::Start, QTextCursor::MoveAnchor);
253 QString title = QString("<b>The Rockbox Utility</b><br/>Version %1").arg(FULLVERSION);
254 about.labelTitle->setText(title);
255 about.labelHomepage->setText("<a href='http://www.rockbox.org'>http://www.rockbox.org</a>");
257 window->show();
262 void RbUtilQt::help()
264 QUrl helpurl("http://www.rockbox.org/wiki/RockboxUtility");
265 QDesktopServices::openUrl(helpurl);
269 void RbUtilQt::configDialog()
271 Config *cw = new Config(this);
272 cw->setSettings(settings);
273 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
274 connect(cw, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
275 cw->show();
279 void RbUtilQt::updateSettings()
281 qDebug() << "updateSettings()";
282 updateDevice();
283 updateManual();
284 if(settings->proxyType() == "system") {
285 HttpGet::setGlobalProxy(Detect::systemProxy());
287 else if(settings->proxyType() == "manual") {
288 HttpGet::setGlobalProxy(settings->proxy());
290 else {
291 HttpGet::setGlobalProxy(QUrl(""));
293 HttpGet::setGlobalCache(settings->cachePath());
294 HttpGet::setGlobalDumbCache(settings->cacheOffline());
298 void RbUtilQt::updateDevice()
300 if(!settings->curNeedsBootloader() ) {
301 ui.buttonBootloader->setEnabled(false);
302 ui.buttonRemoveBootloader->setEnabled(false);
303 ui.labelBootloader->setEnabled(false);
304 ui.labelRemoveBootloader->setEnabled(false);
306 else {
307 ui.buttonBootloader->setEnabled(true);
308 ui.labelBootloader->setEnabled(true);
309 if(settings->curBootloaderMethod() == "fwpatcher") {
310 ui.labelRemoveBootloader->setEnabled(false);
311 ui.buttonRemoveBootloader->setEnabled(false);
313 else {
314 ui.labelRemoveBootloader->setEnabled(true);
315 ui.buttonRemoveBootloader->setEnabled(true);
319 // displayed device info
320 QString mountpoint = settings->mountpoint();
321 QString brand = settings->curBrand();
322 QString name = settings->curName();
323 if(name.isEmpty()) name = "&lt;none&gt;";
324 if(mountpoint.isEmpty()) mountpoint = "&lt;invalid&gt;";
325 ui.labelDevice->setText(tr("<b>%1 %2</b> at <b>%3</b>")
326 .arg(brand, name, QDir::toNativeSeparators(mountpoint)));
330 void RbUtilQt::updateManual()
332 if(settings->curPlatform() != "")
334 QString manual= settings->curManual();
336 if(manual == "")
337 manual = "rockbox-" + settings->curPlatform();
338 QString pdfmanual;
339 pdfmanual = settings->manualUrl() + "/" + manual + ".pdf";
340 QString htmlmanual;
341 htmlmanual = settings->manualUrl() + "/" + manual + "/rockbox-build.html";
342 ui.labelPdfManual->setText(tr("<a href='%1'>PDF Manual</a>")
343 .arg(pdfmanual));
344 ui.labelHtmlManual->setText(tr("<a href='%1'>HTML Manual (opens in browser)</a>")
345 .arg(htmlmanual));
347 else {
348 ui.labelPdfManual->setText(tr("Select a device for a link to the correct manual"));
349 ui.labelHtmlManual->setText(tr("<a href='%1'>Manual Overview</a>")
350 .arg("http://www.rockbox.org/manual.shtml"));
355 void RbUtilQt::completeInstall()
357 if(chkConfig(true)) return;
358 if(QMessageBox::question(this, tr("Confirm Installation"),
359 tr("Do you really want to make a complete Installation? "
360 "This will install the latest build available, not the latest "
361 "released version."),
362 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
364 // create logger
365 logger = new ProgressLoggerGui(this);
366 logger->show();
368 if(smallInstallInner())
369 return;
370 logger->undoAbort();
371 // Fonts
372 m_error = false;
373 m_installed = false;
374 if(!installFontsAuto())
375 return;
376 else
378 // wait for installation finished
379 while(!m_installed)
380 QApplication::processEvents();
382 if(m_error) return;
383 logger->undoAbort();
385 // Doom
386 if(hasDoom())
388 m_error = false;
389 m_installed = false;
390 if(!installDoomAuto())
391 return;
392 else
394 // wait for installation finished
395 while(!m_installed)
396 QApplication::processEvents();
398 if(m_error) return;
401 // theme
402 // this is a window
403 // it has its own logger window,so close our.
404 logger->close();
405 installThemes();
409 void RbUtilQt::smallInstall()
411 if(chkConfig(true)) return;
412 if(QMessageBox::question(this, tr("Confirm Installation"),
413 tr("Do you really want to make a small Installation? "
414 "This will install the latest build available, not the latest "
415 "released version."),
416 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
418 // create logger
419 logger = new ProgressLoggerGui(this);
420 logger->show();
422 smallInstallInner();
425 bool RbUtilQt::smallInstallInner()
427 QString mountpoint = settings->mountpoint();
428 // show dialog with error if mount point is wrong
429 if(!QFileInfo(mountpoint).isDir()) {
430 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
431 logger->abort();
432 return true;
434 // Bootloader
435 if(settings->curNeedsBootloader())
437 m_error = false;
438 m_installed = false;
439 m_auto = true;
440 if(!installBootloaderAuto())
441 return true;
442 else
444 // wait for boot loader installation finished
445 while(!m_installed)
446 QApplication::processEvents();
448 m_auto = false;
449 if(m_error) return true;
450 logger->undoAbort();
453 // Rockbox
454 m_error = false;
455 m_installed = false;
456 if(!installAuto())
457 return true;
458 else
460 // wait for installation finished
461 while(!m_installed)
462 QApplication::processEvents();
465 installBootloaderPost(false);
466 return false;
469 void RbUtilQt::installdone(bool error)
471 qDebug() << "install done";
472 m_installed = true;
473 m_error = error;
476 void RbUtilQt::installBtn()
478 if(chkConfig(true)) return;
479 install();
482 bool RbUtilQt::installAuto()
484 QString file = QString("%1%2/rockbox.zip")
485 .arg(settings->bleedingUrl(), settings->curPlatformName());
487 buildInfo.open();
488 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
489 buildInfo.close();
491 if(settings->curReleased()) {
492 // only set the keys if needed -- querying will yield an empty string
493 // if not set.
494 versmap.insert("rel_rev", settings->lastRelease(settings->curPlatform()));
495 versmap.insert("rel_date", ""); // FIXME: provide the release timestamp
498 QString myversion = "r" + versmap.value("bleed_rev");
500 // check installed Version and Target
501 QString rbVersion = Detect::installedVersion(settings->mountpoint());
502 QString warning = Detect::check(settings, false, settings->curTargetId());
504 if(!warning.isEmpty())
506 if(QMessageBox::warning(this, tr("Really continue?"), warning,
507 QMessageBox::Ok | QMessageBox::Abort, QMessageBox::Abort) == QMessageBox::Abort)
509 logger->addItem(tr("Aborted!"), LOGERROR);
510 logger->abort();
511 return false;
515 // check version
516 if(rbVersion != "")
518 if(QMessageBox::question(this, tr("Installed Rockbox detected"),
519 tr("Rockbox installation detected. Do you want to backup first?"),
520 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes)
522 logger->addItem(tr("Starting backup..."),LOGINFO);
523 QString backupName = settings->mountpoint() + "/.backup/rockbox-backup-"+rbVersion+".zip";
525 //! create dir, if it doesnt exist
526 QFileInfo backupFile(backupName);
527 if(!QDir(backupFile.path()).exists())
529 QDir a;
530 a.mkpath(backupFile.path());
533 //! create backup
534 RbZip backup;
535 connect(&backup,SIGNAL(zipProgress(int,int)),logger, SLOT(setProgress(int,int)));
536 if(backup.createZip(backupName,settings->mountpoint() + "/.rockbox") == Zip::Ok)
538 logger->addItem(tr("Backup successful"),LOGOK);
540 else
542 logger->addItem(tr("Backup failed!"),LOGERROR);
543 logger->abort();
544 return false;
549 //! install current build
550 ZipInstaller* installer = new ZipInstaller(this);
551 installer->setUrl(file);
552 installer->setLogSection("Rockbox (Base)");
553 installer->setLogVersion(myversion);
554 if(!settings->cacheDisabled())
555 installer->setCache(true);
556 installer->setMountPoint(settings->mountpoint());
558 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
560 installer->install(logger);
561 return true;
565 void RbUtilQt::install()
567 Install *installWindow = new Install(settings,this);
569 buildInfo.open();
570 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
571 buildInfo.close();
573 if(settings->curReleased()) {
574 // only set the keys if needed -- querying will yield an empty string
575 // if not set.
576 versmap.insert("rel_rev", settings->lastRelease(settings->curPlatform()));
577 versmap.insert("rel_date", ""); // FIXME: provide the release timestamp
579 installWindow->setVersionStrings(versmap);
581 installWindow->show();
584 bool RbUtilQt::installBootloaderAuto()
586 installBootloader();
587 return !m_error;
590 void RbUtilQt::installBootloaderBtn()
592 if(chkConfig(true)) return;
593 if(QMessageBox::question(this, tr("Confirm Installation"),
594 tr("Do you really want to install the Bootloader?"),
595 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
597 // create logger
598 logger = new ProgressLoggerGui(this);
600 installBootloader();
603 void RbUtilQt::installBootloader()
605 QString platform = settings->curPlatform();
606 QString backupDestination = "";
607 m_error = false;
609 // create installer
610 BootloaderInstallBase *bl;
611 QString type = settings->curBootloaderMethod();
612 if(type == "mi4") {
613 bl = new BootloaderInstallMi4(this);
615 else if(type == "hex") {
616 bl = new BootloaderInstallHex(this);
618 else if(type == "sansa") {
619 bl = new BootloaderInstallSansa(this);
621 else if(type == "ipod") {
622 bl = new BootloaderInstallIpod(this);
624 else if(type == "file") {
625 bl = new BootloaderInstallFile(this);
627 else {
628 logger->addItem(tr("No install method known."), LOGERROR);
629 logger->abort();
630 return;
633 // set bootloader filename. Do this now as installed() needs it.
634 QString blfile;
635 blfile = settings->mountpoint() + settings->curBootloaderFile();
636 // special case for H10 pure: this player can have a different
637 // bootloader file filename. This is handled here to keep the install
638 // class clean, though having it here is also not the nicest solution.
639 if(settings->curPlatformName() == "h10_ums"
640 || settings->curPlatformName() == "h10_mtp") {
641 if(resolvePathCase(blfile).isEmpty())
642 blfile = settings->mountpoint()
643 + settings->curBootloaderName().replace("H10",
644 "H10EMP", Qt::CaseInsensitive);
646 bl->setBlFile(blfile);
647 QUrl url(settings->bootloaderUrl() + settings->curBootloaderName());
648 bl->setBlUrl(url);
649 bl->setLogfile(settings->mountpoint() + "/.rockbox/rbutil.log");
651 if(bl->installed() == BootloaderInstallBase::BootloaderRockbox) {
652 if(QMessageBox::question(this, tr("Bootloader detected"),
653 tr("Bootloader already installed. Do you want to reinstall the bootloader?"),
654 QMessageBox::Yes | QMessageBox::No) == QMessageBox::No) {
655 logger->close();
656 m_error = true;
657 return;
660 else if(bl->installed() == BootloaderInstallBase::BootloaderOther
661 && bl->capabilities() & BootloaderInstallBase::Backup)
663 QString targetFolder = settings->name(settings->curPlatform())
664 + " Firmware Backup";
665 // remove invalid character(s)
666 targetFolder.remove(QRegExp("[:/]"));
667 if(QMessageBox::question(this, tr("Create Bootloader backup"),
668 tr("You can create a backup of the original bootloader "
669 "file. Press \"Yes\" to select an output folder on your "
670 "computer to save the file to. The file will get placed "
671 "in a new folder \"%1\" created below the selected folder.\n"
672 "Press \"No\" to skip this step.").arg(targetFolder),
673 QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
674 BrowseDirtree tree(this, tr("Browse backup folder"));
675 tree.setDir(QDir::home());
676 tree.exec();
678 backupDestination = tree.getSelected() + "/" + targetFolder;
679 qDebug() << backupDestination;
680 // backup needs to be done after the logger has been set up.
684 if(bl->capabilities() & BootloaderInstallBase::NeedsFlashing)
686 int ret;
687 ret = QMessageBox::information(this, tr("Prerequisites"),
688 tr("Bootloader installation requires you to provide "
689 "a firmware file of the original firmware (hex file). "
690 "You need to download this file yourself due to legal "
691 "reasons. Please refer to the "
692 "<a href='http://www.rockbox.org/manual.shtml'>manual</a> and the "
693 "<a href='http://www.rockbox.org/wiki/IriverBoot"
694 "#Download_and_extract_a_recent_ve'>IriverBoot</a> wiki page on "
695 "how to obtain this file.<br/>"
696 "Press Ok to continue and browse your computer for the firmware "
697 "file."),
698 QMessageBox::Ok | QMessageBox::Abort);
699 if(ret != QMessageBox::Ok) {
700 m_error = true;
701 return;
703 // open dialog to browse to hex file
704 QString hexfile;
705 hexfile = QFileDialog::getOpenFileName(this,
706 tr("Select firmware file"), QDir::homePath(), "*.hex");
707 if(!QFileInfo(hexfile).isReadable()) {
708 logger->addItem(tr("Error opening firmware file"), LOGERROR);
709 m_error = true;
710 return;
712 ((BootloaderInstallHex*)bl)->setHexfile(hexfile);
715 // the bootloader install class does NOT use any GUI stuff.
716 // All messages are passed via signals.
717 connect(bl, SIGNAL(done(bool)), logger, SLOT(abort()));
718 connect(bl, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool)));
719 connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
720 connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
722 // show logger and start install.
723 logger->show();
724 if(!backupDestination.isEmpty()) {
725 if(!bl->backup(backupDestination)) {
726 if(QMessageBox::warning(this, tr("Backup error"),
727 tr("Could not create backup file. Continue?"),
728 QMessageBox::No | QMessageBox::Yes)
729 == QMessageBox::No) {
730 logger->abort();
731 return;
735 bl->install();
738 void RbUtilQt::installBootloaderPost(bool error)
740 qDebug() << __func__ << error;
741 // if an error occured don't perform post install steps.
742 if(error) {
743 m_error = true;
744 return;
746 else
747 m_error = false;
749 m_installed = true;
750 // end here if automated install
751 if(m_auto)
752 return;
754 QString msg = BootloaderInstallBase::postinstallHints(settings->curPlatform());
755 if(!msg.isEmpty()) {
756 QMessageBox::information(this, tr("Manual steps required"), msg);
757 logger->close();
762 void RbUtilQt::installFontsBtn()
764 if(chkConfig(true)) return;
765 if(QMessageBox::question(this, tr("Confirm Installation"),
766 tr("Do you really want to install the fonts package?"),
767 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
768 // create logger
769 logger = new ProgressLoggerGui(this);
770 logger->show();
771 installFonts();
774 bool RbUtilQt::installFontsAuto()
776 installFonts();
778 return !m_error;
781 void RbUtilQt::installFonts()
783 // create zip installer
784 installer = new ZipInstaller(this);
786 installer->setUrl(settings->fontUrl());
787 installer->setLogSection("Fonts");
788 installer->setLogVersion(versmap.value("arch_date"));
789 installer->setMountPoint(settings->mountpoint());
790 if(!settings->cacheDisabled())
791 installer->setCache(true);
793 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
794 installer->install(logger);
798 void RbUtilQt::installVoice()
800 if(chkConfig(true)) return;
802 if(m_gotInfo == false)
804 QMessageBox::warning(this, tr("Warning"),
805 tr("The Application is still downloading Information about new Builds. Please try again shortly."));
806 return;
809 if(QMessageBox::question(this, tr("Confirm Installation"),
810 tr("Do you really want to install the voice file?"),
811 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
812 // create logger
813 logger = new ProgressLoggerGui(this);
814 logger->show();
816 // create zip installer
817 installer = new ZipInstaller(this);
819 QString voiceurl = settings->voiceUrl();
821 voiceurl += settings->curVoiceName() + "-" +
822 versmap.value("arch_date") + "-english.zip";
823 qDebug() << voiceurl;
825 installer->setUrl(voiceurl);
826 installer->setLogSection("Voice");
827 installer->setLogVersion(versmap.value("arch_date"));
828 installer->setMountPoint(settings->mountpoint());
829 if(!settings->cacheDisabled())
830 installer->setCache(true);
831 installer->install(logger);
835 void RbUtilQt::installDoomBtn()
837 if(chkConfig(true)) return;
838 if(!hasDoom()){
839 QMessageBox::critical(this, tr("Error"), tr("Your device doesn't have a doom plugin. Aborting."));
840 return;
843 if(QMessageBox::question(this, tr("Confirm Installation"),
844 tr("Do you really want to install the game addon files?"),
845 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
846 // create logger
847 logger = new ProgressLoggerGui(this);
848 logger->show();
850 installDoom();
852 bool RbUtilQt::installDoomAuto()
854 installDoom();
855 return !m_error;
858 bool RbUtilQt::hasDoom()
860 QFile doomrock(settings->mountpoint() +"/.rockbox/rocks/games/doom.rock");
861 return doomrock.exists();
864 void RbUtilQt::installDoom()
866 // create zip installer
867 installer = new ZipInstaller(this);
869 installer->setUrl(settings->doomUrl());
870 installer->setLogSection("Game Addons");
871 installer->setLogVersion(versmap.value("arch_date"));
872 installer->setMountPoint(settings->mountpoint());
873 if(!settings->cacheDisabled())
874 installer->setCache(true);
875 connect(installer, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
876 installer->install(logger);
880 void RbUtilQt::installThemes()
882 if(chkConfig(true)) return;
883 ThemesInstallWindow* tw = new ThemesInstallWindow(this);
884 tw->setSettings(settings);
885 tw->setModal(true);
886 tw->show();
889 void RbUtilQt::createTalkFiles(void)
891 if(chkConfig(true)) return;
892 InstallTalkWindow *installWindow = new InstallTalkWindow(this);
893 installWindow->setSettings(settings);
895 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
896 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
897 installWindow->show();
901 void RbUtilQt::createVoiceFile(void)
903 if(chkConfig(true)) return;
904 CreateVoiceWindow *installWindow = new CreateVoiceWindow(this);
905 installWindow->setSettings(settings);
907 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(downloadInfo()));
908 connect(installWindow, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
909 installWindow->show();
912 void RbUtilQt::uninstall(void)
914 if(chkConfig(true)) return;
915 UninstallWindow *uninstallWindow = new UninstallWindow(this);
916 uninstallWindow->setSettings(settings);
917 uninstallWindow->show();
921 void RbUtilQt::uninstallBootloader(void)
923 if(chkConfig(true)) return;
924 if(QMessageBox::question(this, tr("Confirm Uninstallation"),
925 tr("Do you really want to uninstall the Bootloader?"),
926 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) return;
927 // create logger
928 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
929 logger->setProgressVisible(false);
930 logger->show();
932 QString platform = settings->curPlatform();
934 // create installer
935 BootloaderInstallBase *bl;
936 QString type = settings->curBootloaderMethod();
937 if(type == "mi4") {
938 bl = new BootloaderInstallMi4();
940 else if(type == "hex") {
941 bl = new BootloaderInstallHex();
943 else if(type == "sansa") {
944 bl = new BootloaderInstallSansa();
946 else if(type == "ipod") {
947 bl = new BootloaderInstallIpod();
949 else if(type == "file") {
950 bl = new BootloaderInstallFile();
952 else {
953 logger->addItem(tr("No uninstall method known."), LOGERROR);
954 logger->abort();
955 return;
958 QString blfile = settings->mountpoint() + settings->curBootloaderFile();
959 if(settings->curPlatformName() == "h10_ums"
960 || settings->curPlatformName() == "h10_mtp") {
961 if(resolvePathCase(blfile).isEmpty())
962 blfile = settings->mountpoint()
963 + settings->curBootloaderName().replace("H10",
964 "H10EMP", Qt::CaseInsensitive);
966 bl->setBlFile(blfile);
968 connect(bl, SIGNAL(logItem(QString, int)), logger, SLOT(addItem(QString, int)));
969 connect(bl, SIGNAL(logProgress(int, int)), logger, SLOT(setProgress(int, int)));
971 int result;
972 result = bl->uninstall();
974 logger->abort();
979 void RbUtilQt::downloadManual(void)
981 if(chkConfig(true)) return;
982 if(QMessageBox::question(this, tr("Confirm download"),
983 tr("Do you really want to download the manual? The manual will be saved "
984 "to the root folder of your player."),
985 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
986 return;
988 buildInfo.open();
989 QSettings info(buildInfo.fileName(), QSettings::IniFormat, this);
990 buildInfo.close();
992 QString manual = settings->curManual();
994 QString date = (info.value("dailies/date").toString());
996 QString manualurl;
997 QString target;
998 QString section;
999 if(ui.radioPdf->isChecked()) {
1000 target = "/" + manual + ".pdf";
1001 section = "Manual (PDF)";
1003 else {
1004 target = "/" + manual + "-" + date + "-html.zip";
1005 section = "Manual (HTML)";
1007 manualurl = settings->manualUrl() + "/" + target;
1008 qDebug() << "manualurl =" << manualurl;
1010 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
1011 logger->show();
1012 installer = new ZipInstaller(this);
1013 installer->setMountPoint(settings->mountpoint());
1014 if(!settings->cacheDisabled())
1015 installer->setCache(true);
1016 installer->setLogSection(section);
1017 installer->setLogVersion(date);
1018 installer->setUrl(manualurl);
1019 installer->setUnzip(false);
1020 installer->setTarget(target);
1021 installer->install(logger);
1025 void RbUtilQt::installPortable(void)
1027 if(QMessageBox::question(this, tr("Confirm installation"),
1028 tr("Do you really want to install Rockbox Utility to your player? "
1029 "After installation you can run it from the players hard drive."),
1030 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
1031 return;
1033 ProgressLoggerGui* logger = new ProgressLoggerGui(this);
1034 logger->setProgressMax(0);
1035 logger->setProgressValue(0);
1036 logger->show();
1037 logger->addItem(tr("Installing Rockbox Utility"), LOGINFO);
1039 // check mountpoint
1040 if(!QFileInfo(settings->mountpoint()).isDir()) {
1041 logger->addItem(tr("Mount point is wrong!"),LOGERROR);
1042 logger->abort();
1043 return;
1046 // remove old files first.
1047 QFile::remove(settings->mountpoint() + "/RockboxUtility.exe");
1048 QFile::remove(settings->mountpoint() + "/RockboxUtility.ini");
1049 // copy currently running binary and currently used settings file
1050 if(!QFile::copy(qApp->applicationFilePath(), settings->mountpoint() + "/RockboxUtility.exe")) {
1051 logger->addItem(tr("Error installing Rockbox Utility"), LOGERROR);
1052 logger->abort();
1053 return;
1055 logger->addItem(tr("Installing user configuration"), LOGINFO);
1056 if(!QFile::copy(settings->userSettingFilename(), settings->mountpoint() + "/RockboxUtility.ini")) {
1057 logger->addItem(tr("Error installing user configuration"), LOGERROR);
1058 logger->abort();
1059 return;
1061 logger->addItem(tr("Successfully installed Rockbox Utility."), LOGOK);
1062 logger->abort();
1063 logger->setProgressMax(1);
1064 logger->setProgressValue(1);
1069 void RbUtilQt::updateInfo()
1071 qDebug() << "RbUtilQt::updateInfo()";
1073 QSettings log(settings->mountpoint() + "/.rockbox/rbutil.log", QSettings::IniFormat, this);
1074 QStringList groups = log.childGroups();
1075 QList<QTreeWidgetItem *> items;
1076 QTreeWidgetItem *w, *w2;
1077 QString min, max;
1078 int olditems = 0;
1080 // remove old list entries (if any)
1081 int l = ui.treeInfo->topLevelItemCount();
1082 while(l--) {
1083 QTreeWidgetItem *m;
1084 m = ui.treeInfo->takeTopLevelItem(l);
1085 // delete childs (single level deep, no recursion here)
1086 int n = m->childCount();
1087 while(n--)
1088 delete m->child(n);
1090 // get and populate new items
1091 for(int a = 0; a < groups.size(); a++) {
1092 log.beginGroup(groups.at(a));
1093 QStringList keys = log.allKeys();
1094 w = new QTreeWidgetItem;
1095 w->setFlags(Qt::ItemIsEnabled);
1096 w->setText(0, groups.at(a));
1097 items.append(w);
1098 // get minimum and maximum version information so we can hilight old files
1099 min = max = log.value(keys.at(0)).toString();
1100 for(int b = 0; b < keys.size(); b++) {
1101 if(log.value(keys.at(b)).toString() > max)
1102 max = log.value(keys.at(b)).toString();
1103 if(log.value(keys.at(b)).toString() < min)
1104 min = log.value(keys.at(b)).toString();
1107 for(int b = 0; b < keys.size(); b++) {
1108 QString file;
1109 file = settings->mountpoint() + "/" + keys.at(b);
1110 if(QFileInfo(file).isDir())
1111 continue;
1112 w2 = new QTreeWidgetItem(w, QStringList() << "/"
1113 + keys.at(b) << log.value(keys.at(b)).toString());
1114 if(log.value(keys.at(b)).toString() != max) {
1115 w2->setForeground(0, QBrush(QColor(255, 0, 0)));
1116 w2->setForeground(1, QBrush(QColor(255, 0, 0)));
1117 olditems++;
1119 items.append(w2);
1121 log.endGroup();
1122 if(min != max)
1123 w->setData(1, Qt::DisplayRole, QString("%1 / %2").arg(min, max));
1124 else
1125 w->setData(1, Qt::DisplayRole, max);
1127 ui.treeInfo->insertTopLevelItems(0, items);
1128 ui.treeInfo->resizeColumnToContents(0);
1132 QUrl RbUtilQt::proxy()
1134 if(settings->proxyType() == "manual")
1135 return QUrl(settings->proxy());
1136 else if(settings->proxy() == "system")
1138 return Detect::systemProxy();
1140 return QUrl("");
1144 bool RbUtilQt::chkConfig(bool warn)
1146 bool error = false;
1147 if(settings->curPlatform().isEmpty()
1148 || settings->mountpoint().isEmpty()
1149 || !QFileInfo(settings->mountpoint()).isWritable()) {
1150 error = true;
1152 if(warn) QMessageBox::critical(this, tr("Configuration error"),
1153 tr("Your configuration is invalid. Please go to the configuration "
1154 "dialog and make sure the selected values are correct."));
1156 return error;