1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
9 * Copyright (C) 2007 by Dominik Riebeling
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 ****************************************************************************/
24 #include "ui_rbutilqtfrm.h"
25 #include "ui_aboutbox.h"
26 #include "configure.h"
27 #include "installwindow.h"
28 #include "installtalkwindow.h"
29 #include "createvoicewindow.h"
31 #include "themesinstallwindow.h"
32 #include "uninstallwindow.h"
34 #include "rockboxinfo.h"
39 #include "rbsettings.h"
40 #include "serverinfo.h"
41 #include "systeminfo.h"
43 #include "progressloggerinterface.h"
45 #include "bootloaderinstallbase.h"
48 #if defined(Q_OS_LINUX)
51 #if defined(Q_OS_WIN32)
60 RbUtilQt::RbUtilQt(QWidget
*parent
) : QMainWindow(parent
)
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
73 #if defined(Q_OS_LINUX)
74 QIcon
windowIcon(":/icons/rockbox-clef.svg");
75 this->setWindowIcon(windowIcon
);
78 #if defined(Q_OS_WIN32)
81 ret
= RegOpenKeyEx(HKEY_CURRENT_USER
, _TEXT("Software\\Wine"),
82 0, KEY_QUERY_VALUE
, &hk
);
83 if(ret
== ERROR_SUCCESS
) {
84 QMessageBox::warning(this, tr("Wine detected!"),
85 tr("It seems you are trying to run this program under Wine. "
86 "Please don't do this, running under Wine will fail. "
87 "Use the native Linux binary instead."),
88 QMessageBox::Ok
, QMessageBox::Ok
);
89 qDebug() << "[RbUtil] WINE DETECTED!";
99 ui
.radioPdf
->setChecked(true);
102 ui
.treeInfo
->setAlternatingRowColors(true);
103 ui
.treeInfo
->setHeaderLabels(QStringList() << tr("File") << tr("Version"));
104 ui
.treeInfo
->expandAll();
105 ui
.treeInfo
->setColumnCount(2);
106 ui
.treeInfo
->setLayoutDirection(Qt::LeftToRight
);
107 // disable quick install until version info is available
108 ui
.buttonSmall
->setEnabled(false);
109 ui
.buttonComplete
->setEnabled(false);
110 ui
.actionSmall_Installation
->setEnabled(false);
111 ui
.actionComplete_Installation
->setEnabled(false);
113 connect(ui
.tabWidget
, SIGNAL(currentChanged(int)), this, SLOT(updateTabs(int)));
114 connect(ui
.actionAbout_Qt
, SIGNAL(triggered()), qApp
, SLOT(aboutQt()));
115 connect(ui
.action_About
, SIGNAL(triggered()), this, SLOT(about()));
116 connect(ui
.action_Help
, SIGNAL(triggered()), this, SLOT(help()));
117 connect(ui
.action_Configure
, SIGNAL(triggered()), this, SLOT(configDialog()));
118 connect(ui
.actionE_xit
, SIGNAL(triggered()), this, SLOT(shutdown()));
119 connect(ui
.buttonChangeDevice
, SIGNAL(clicked()), this, SLOT(configDialog()));
120 connect(ui
.buttonRockbox
, SIGNAL(clicked()), this, SLOT(installBtn()));
121 connect(ui
.buttonBootloader
, SIGNAL(clicked()), this, SLOT(installBootloaderBtn()));
122 connect(ui
.buttonFonts
, SIGNAL(clicked()), this, SLOT(installFontsBtn()));
123 connect(ui
.buttonGames
, SIGNAL(clicked()), this, SLOT(installDoomBtn()));
124 connect(ui
.buttonTalk
, SIGNAL(clicked()), this, SLOT(createTalkFiles()));
125 connect(ui
.buttonCreateVoice
, SIGNAL(clicked()), this, SLOT(createVoiceFile()));
126 connect(ui
.buttonVoice
, SIGNAL(clicked()), this, SLOT(installVoice()));
127 connect(ui
.buttonThemes
, SIGNAL(clicked()), this, SLOT(installThemes()));
128 connect(ui
.buttonRemoveRockbox
, SIGNAL(clicked()), this, SLOT(uninstall()));
129 connect(ui
.buttonRemoveBootloader
, SIGNAL(clicked()), this, SLOT(uninstallBootloader()));
130 connect(ui
.buttonDownloadManual
, SIGNAL(clicked()), this, SLOT(downloadManual()));
131 connect(ui
.buttonSmall
, SIGNAL(clicked()), this, SLOT(smallInstall()));
132 connect(ui
.buttonComplete
, SIGNAL(clicked()), this, SLOT(completeInstall()));
134 // actions accessible from the menu
135 connect(ui
.actionComplete_Installation
, SIGNAL(triggered()), this, SLOT(completeInstall()));
136 connect(ui
.actionSmall_Installation
, SIGNAL(triggered()), this, SLOT(smallInstall()));
137 connect(ui
.actionInstall_Bootloader
, SIGNAL(triggered()), this, SLOT(installBootloaderBtn()));
138 connect(ui
.actionInstall_Rockbox
, SIGNAL(triggered()), this, SLOT(installBtn()));
139 connect(ui
.actionFonts_Package
, SIGNAL(triggered()), this, SLOT(installFontsBtn()));
140 connect(ui
.actionInstall_Themes
, SIGNAL(triggered()), this, SLOT(installThemes()));
141 connect(ui
.actionInstall_Game_Files
, SIGNAL(triggered()), this, SLOT(installDoomBtn()));
142 connect(ui
.actionInstall_Voice_File
, SIGNAL(triggered()), this, SLOT(installVoice()));
143 connect(ui
.actionCreate_Voice_File
, SIGNAL(triggered()), this, SLOT(createVoiceFile()));
144 connect(ui
.actionCreate_Talk_Files
, SIGNAL(triggered()), this, SLOT(createTalkFiles()));
145 connect(ui
.actionRemove_bootloader
, SIGNAL(triggered()), this, SLOT(uninstallBootloader()));
146 connect(ui
.actionUninstall_Rockbox
, SIGNAL(triggered()), this, SLOT(uninstall()));
147 connect(ui
.action_System_Info
, SIGNAL(triggered()), this, SLOT(sysinfo()));
148 connect(ui
.action_Trace
, SIGNAL(triggered()), this, SLOT(trace()));
151 ui
.actionInstall_Rockbox_Utility_on_player
->setEnabled(false);
153 connect(ui
.actionInstall_Rockbox_Utility_on_player
, SIGNAL(triggered()), this, SLOT(installPortable()));
159 void RbUtilQt::shutdown(void)
161 // restore default message handler to prevent trace accesses during
162 // object destruction -- the trace object could already be destroyed.
163 // Fixes segfaults on exit.
164 qInstallMsgHandler(0);
170 void RbUtilQt::trace(void)
176 void RbUtilQt::sysinfo(void)
182 void RbUtilQt::updateTabs(int count
)
194 void RbUtilQt::downloadInfo()
196 // try to get the current build information
197 daily
= new HttpGet(this);
198 connect(daily
, SIGNAL(done(bool)), this, SLOT(downloadDone(bool)));
199 connect(qApp
, SIGNAL(lastWindowClosed()), daily
, SLOT(abort()));
200 if(RbSettings::value(RbSettings::CacheOffline
).toBool())
201 daily
->setCache(true);
203 daily
->setCache(false);
204 ui
.statusbar
->showMessage(tr("Downloading build information, please wait ..."));
205 qDebug() << "[RbUtil] downloading build info";
206 daily
->setFile(&buildInfo
);
207 daily
->getFile(QUrl(SystemInfo::value(SystemInfo::ServerConfUrl
).toString()));
211 void RbUtilQt::downloadDone(bool error
)
214 qDebug() << "[RbUtil] network error:" << daily
->error();
215 ui
.statusbar
->showMessage(tr("Can't get version information!"));
216 QMessageBox::critical(this, tr("Network error"),
217 tr("Can't get version information.\n"
218 "Network error: %1. Please check your network and proxy settings.")
219 .arg(daily
->errorString()));
222 qDebug() << "[RbUtil] network status:" << daily
->error();
224 // read info into ServerInfo object
226 ServerInfo::readBuildInfo(buildInfo
.fileName());
229 // start bleeding info download
230 bleeding
= new HttpGet(this);
231 connect(bleeding
, SIGNAL(done(bool)), this, SLOT(downloadBleedingDone(bool)));
232 connect(qApp
, SIGNAL(lastWindowClosed()), bleeding
, SLOT(abort()));
233 if(RbSettings::value(RbSettings::CacheOffline
).toBool())
234 bleeding
->setCache(true);
235 bleeding
->setFile(&bleedingInfo
);
236 bleeding
->getFile(QUrl(SystemInfo::value(SystemInfo::BleedingInfo
).toString()));
237 ui
.statusbar
->showMessage(tr("Downloading build information, please wait ..."));
242 void RbUtilQt::downloadBleedingDone(bool error
)
245 qDebug() << "[RbUtil] network error:" << bleeding
->error();
246 ui
.statusbar
->showMessage(tr("Can't get version information!"));
247 QMessageBox::critical(this, tr("Network error"),
248 tr("Can't get version information.\n"
249 "Network error: %1. Please check your network and proxy settings.")
250 .arg(bleeding
->errorString()));
255 ServerInfo::readBleedingInfo(bleedingInfo
.fileName());
256 bleedingInfo
.close();
258 ui
.statusbar
->showMessage(tr("Download build information finished."), 5000);
262 //start check for updates
268 void RbUtilQt::about()
270 QDialog
*window
= new QDialog(this);
272 about
.setupUi(window
);
273 window
->setLayoutDirection(Qt::LeftToRight
);
274 window
->setModal(true);
276 QFile
licence(":/docs/gpl-2.0.html");
277 licence
.open(QIODevice::ReadOnly
);
278 QTextStream
c(&licence
);
279 QString cline
= c
.readAll();
280 about
.browserLicense
->insertHtml(cline
);
281 about
.browserLicense
->moveCursor(QTextCursor::Start
, QTextCursor::MoveAnchor
);
282 QFile
credits(":/docs/CREDITS");
283 credits
.open(QIODevice::ReadOnly
);
284 QTextStream
r(&credits
);
285 r
.setCodec(QTextCodec::codecForName("UTF-8"));
287 QString line
= r
.readLine();
288 // filter out header.
289 line
.remove(QRegExp("^[^A-Z]+.*"));
290 line
.remove(QRegExp("^People.*"));
291 about
.browserCredits
->append(line
);
293 about
.browserCredits
->moveCursor(QTextCursor::Start
, QTextCursor::MoveAnchor
);
294 QString title
= QString("<b>The Rockbox Utility</b><br/>Version %1").arg(FULLVERSION
);
295 about
.labelTitle
->setText(title
);
302 void RbUtilQt::help()
304 QUrl
helpurl("http://www.rockbox.org/wiki/RockboxUtility");
305 QDesktopServices::openUrl(helpurl
);
309 void RbUtilQt::configDialog()
311 Config
*cw
= new Config(this);
312 connect(cw
, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
317 void RbUtilQt::updateSettings()
319 qDebug() << "[RbUtil] updating current settings";
322 if(RbSettings::value(RbSettings::ProxyType
) == "system") {
323 HttpGet::setGlobalProxy(System::systemProxy());
325 else if(RbSettings::value(RbSettings::ProxyType
) == "manual") {
326 HttpGet::setGlobalProxy(RbSettings::value(RbSettings::Proxy
).toString());
329 HttpGet::setGlobalProxy(QUrl(""));
331 HttpGet::setGlobalCache(RbSettings::value(RbSettings::CachePath
).toString());
332 HttpGet::setGlobalDumbCache(RbSettings::value(RbSettings::CacheOffline
).toBool());
334 if(RbSettings::value(RbSettings::RbutilVersion
) != PUREVERSION
) {
335 QApplication::processEvents();
336 QMessageBox::information(this, tr("New installation"),
337 tr("This is a new installation of Rockbox Utility, or a new version. "
338 "The configuration dialog will now open to allow you to setup the program, "
339 " or review your settings."));
342 else if(chkConfig(false)) {
343 QApplication::processEvents();
344 QMessageBox::critical(this, tr("Configuration error"),
345 tr("Your configuration is invalid. This is most likely due "
346 "to a changed device path. The configuration dialog will "
347 "now open to allow you to correct the problem."));
353 void RbUtilQt::updateDevice()
355 /* TODO: We should check the flags of the bootloaderinstall classes, and not
356 * just check if its != none or != "fwpatcher" */
358 /* Enable bootloader installation, if possible */
359 bool bootloaderInstallable
=
360 SystemInfo::value(SystemInfo::CurBootloaderMethod
) != "none";
361 ui
.buttonBootloader
->setEnabled(bootloaderInstallable
);
362 ui
.labelBootloader
->setEnabled(bootloaderInstallable
);
363 ui
.actionInstall_Bootloader
->setEnabled(bootloaderInstallable
);
365 /* Enable bootloader uninstallation, if possible */
366 bool bootloaderUninstallable
= bootloaderInstallable
&&
367 SystemInfo::value(SystemInfo::CurBootloaderMethod
) != "fwpatcher";
368 ui
.labelRemoveBootloader
->setEnabled(bootloaderUninstallable
);
369 ui
.buttonRemoveBootloader
->setEnabled(bootloaderUninstallable
);
370 ui
.actionRemove_bootloader
->setEnabled(bootloaderUninstallable
);
372 /* Disable the whole tab widget if configuration is invalid */
373 bool configurationValid
= !chkConfig(false);
374 ui
.tabWidget
->setEnabled(configurationValid
);
375 ui
.menuA_ctions
->setEnabled(configurationValid
);
377 // displayed device info
378 QString mountpoint
= RbSettings::value(RbSettings::Mountpoint
).toString();
379 QString brand
= SystemInfo::value(SystemInfo::CurBrand
).toString();
380 QString name
= SystemInfo::value(SystemInfo::CurName
).toString() +
381 " (" + ServerInfo::value(ServerInfo::CurStatus
).toString() + ")";
382 if(name
.isEmpty()) name
= "<none>";
383 if(mountpoint
.isEmpty()) mountpoint
= "<invalid>";
384 ui
.labelDevice
->setText(tr("<b>%1 %2</b> at <b>%3</b>")
385 .arg(brand
, name
, QDir::toNativeSeparators(mountpoint
)));
387 // hide quickstart buttons if no release available
388 bool installable
= !ServerInfo::value(ServerInfo::CurReleaseVersion
).toString().isEmpty();
389 ui
.buttonSmall
->setEnabled(installable
);
390 ui
.buttonComplete
->setEnabled(installable
);
391 ui
.actionSmall_Installation
->setEnabled(installable
);
392 ui
.actionComplete_Installation
->setEnabled(installable
);
396 void RbUtilQt::updateManual()
398 if(RbSettings::value(RbSettings::Platform
) != "")
400 QString manual
= SystemInfo::value(SystemInfo::CurManual
).toString();
404 + SystemInfo::value(SystemInfo::CurBuildserverModel
).toString();
406 pdfmanual
= SystemInfo::value(SystemInfo::ManualUrl
).toString()
407 + "/" + manual
+ ".pdf";
409 htmlmanual
= SystemInfo::value(SystemInfo::ManualUrl
).toString()
410 + "/" + manual
+ "/rockbox-build.html";
411 ui
.labelPdfManual
->setText(tr("<a href='%1'>PDF Manual</a>")
413 ui
.labelHtmlManual
->setText(tr("<a href='%1'>HTML Manual (opens in browser)</a>")
417 ui
.labelPdfManual
->setText(tr("Select a device for a link to the correct manual"));
418 ui
.labelHtmlManual
->setText(tr("<a href='%1'>Manual Overview</a>")
419 .arg("http://www.rockbox.org/manual.shtml"));
424 void RbUtilQt::completeInstall()
426 if(chkConfig(true)) return;
427 if(QMessageBox::question(this, tr("Confirm Installation"),
428 tr("Do you really want to perform a complete installation?\n\n"
429 "This will install Rockbox %1. To install the most recent "
430 "development build available press \"Cancel\" and "
431 "use the \"Installation\" tab.")
432 .arg(ServerInfo::value(ServerInfo::CurReleaseVersion
).toString()),
433 QMessageBox::Ok
| QMessageBox::Cancel
) != QMessageBox::Ok
)
436 logger
= new ProgressLoggerGui(this);
439 if(smallInstallInner())
441 logger
->setRunning();
445 if(!installFontsAuto())
449 // wait for installation finished
451 QApplication::processEvents();
454 logger
->setRunning();
461 if(!installDoomAuto())
465 // wait for installation finished
467 QApplication::processEvents();
474 // it has its own logger window,so close our.
480 void RbUtilQt::smallInstall()
482 if(chkConfig(true)) return;
483 if(QMessageBox::question(this, tr("Confirm Installation"),
484 tr("Do you really want to perform a minimal installation? "
485 "A minimal installation will contain only the absolutely "
486 "necessary parts to run Rockbox.\n\n"
487 "This will install Rockbox %1. To install the most recent "
488 "development build available press \"Cancel\" and "
489 "use the \"Installation\" tab.")
490 .arg(ServerInfo::value(ServerInfo::CurReleaseVersion
).toString()),
491 QMessageBox::Ok
| QMessageBox::Cancel
) != QMessageBox::Ok
)
495 logger
= new ProgressLoggerGui(this);
501 bool RbUtilQt::smallInstallInner()
503 QString mountpoint
= RbSettings::value(RbSettings::Mountpoint
).toString();
504 // show dialog with error if mount point is wrong
505 if(!QFileInfo(mountpoint
).isDir()) {
506 logger
->addItem(tr("Mount point is wrong!"),LOGERROR
);
507 logger
->setFinished();
511 if(SystemInfo::value(SystemInfo::CurBootloaderMethod
) != "none")
516 if(!installBootloaderAuto()) {
517 logger
->setFinished();
522 // wait for boot loader installation finished
524 QApplication::processEvents();
527 if(m_error
) return true;
528 logger
->setRunning();
538 // wait for installation finished
540 QApplication::processEvents();
543 installBootloaderPost(false);
547 void RbUtilQt::installdone(bool error
)
549 qDebug() << "[RbUtil] install done";
554 void RbUtilQt::installBtn()
556 if(chkConfig(true)) return;
560 bool RbUtilQt::installAuto()
562 QString file
= SystemInfo::value(SystemInfo::ReleaseUrl
).toString();
563 file
.replace("%MODEL%", SystemInfo::value(SystemInfo::CurBuildserverModel
).toString());
564 file
.replace("%RELVERSION%", ServerInfo::value(ServerInfo::CurReleaseVersion
).toString());
566 // check installed Version and Target
567 QString warning
= Utils::checkEnvironment(false);
568 if(!warning
.isEmpty())
570 if(QMessageBox::warning(this, tr("Really continue?"), warning
,
571 QMessageBox::Ok
| QMessageBox::Abort
, QMessageBox::Abort
)
572 == QMessageBox::Abort
)
574 logger
->addItem(tr("Aborted!"), LOGERROR
);
575 logger
->setFinished();
581 RockboxInfo
rbinfo(RbSettings::value(RbSettings::Mountpoint
).toString());
582 if(rbinfo
.version() != "")
584 if(QMessageBox::question(this, tr("Installed Rockbox detected"),
585 tr("Rockbox installation detected. Do you want to backup first?"),
586 QMessageBox::Yes
| QMessageBox::No
) == QMessageBox::Yes
)
588 logger
->addItem(tr("Starting backup..."),LOGINFO
);
589 QString backupName
= RbSettings::value(RbSettings::Mountpoint
).toString()
590 + "/.backup/rockbox-backup-" + rbinfo
.version() + ".zip";
592 //! create dir, if it doesnt exist
593 QFileInfo
backupFile(backupName
);
594 if(!QDir(backupFile
.path()).exists())
597 a
.mkpath(backupFile
.path());
602 connect(&backup
,SIGNAL(zipProgress(int,int)),logger
, SLOT(setProgress(int,int)));
603 if(backup
.createZip(backupName
,
604 RbSettings::value(RbSettings::Mountpoint
).toString() + "/.rockbox") == Zip::Ok
)
606 logger
->addItem(tr("Backup successful"),LOGOK
);
610 logger
->addItem(tr("Backup failed!"),LOGERROR
);
611 logger
->setFinished();
617 //! install current build
618 ZipInstaller
* installer
= new ZipInstaller(this);
619 installer
->setUrl(file
);
620 installer
->setLogSection("Rockbox (Base)");
621 installer
->setLogVersion(ServerInfo::value(ServerInfo::CurReleaseVersion
).toString());
622 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
623 installer
->setCache(true);
624 installer
->setMountPoint(RbSettings::value(RbSettings::Mountpoint
).toString());
626 connect(installer
, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
627 connect(installer
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
628 connect(installer
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
629 connect(installer
, SIGNAL(done(bool)), logger
, SLOT(setFinished()));
630 connect(logger
, SIGNAL(aborted()), installer
, SLOT(abort()));
631 installer
->install();
636 void RbUtilQt::install()
638 InstallWindow
*installWindow
= new InstallWindow(this);
639 installWindow
->show();
642 bool RbUtilQt::installBootloaderAuto()
648 void RbUtilQt::installBootloaderBtn()
650 if(chkConfig(true)) return;
651 if(QMessageBox::question(this, tr("Confirm Installation"),
652 tr("Do you really want to install the Bootloader?"),
653 QMessageBox::Yes
| QMessageBox::No
) != QMessageBox::Yes
) return;
656 logger
= new ProgressLoggerGui(this);
661 void RbUtilQt::installBootloader()
663 QString platform
= RbSettings::value(RbSettings::Platform
).toString();
664 QString backupDestination
= "";
668 BootloaderInstallBase
*bl
= BootloaderInstallBase::createBootloaderInstaller(this,
669 SystemInfo::value(SystemInfo::CurBootloaderMethod
).toString());
671 logger
->addItem(tr("No install method known."), LOGERROR
);
672 logger
->setFinished();
676 // set bootloader filename. Do this now as installed() needs it.
677 QStringList blfile
= SystemInfo::value(SystemInfo::CurBootloaderFile
).toStringList();
678 QStringList blfilepath
;
679 for(int a
= 0; a
< blfile
.size(); a
++) {
680 blfilepath
.append(RbSettings::value(RbSettings::Mountpoint
).toString()
683 bl
->setBlFile(blfilepath
);
684 QUrl
url(SystemInfo::value(SystemInfo::BootloaderUrl
).toString()
685 + SystemInfo::value(SystemInfo::CurBootloaderName
).toString());
687 bl
->setLogfile(RbSettings::value(RbSettings::Mountpoint
).toString()
688 + "/.rockbox/rbutil.log");
690 if(bl
->installed() == BootloaderInstallBase::BootloaderRockbox
) {
691 if(QMessageBox::question(this, tr("Bootloader detected"),
692 tr("Bootloader already installed. Do you want to reinstall the bootloader?"),
693 QMessageBox::Yes
| QMessageBox::No
) == QMessageBox::No
) {
695 // keep logger open for auto installs.
696 // don't consider abort as error in auto-mode.
697 logger
->addItem(tr("Bootloader installation skipped"), LOGINFO
);
698 installBootloaderPost(false);
702 installBootloaderPost(true);
708 else if(bl
->installed() == BootloaderInstallBase::BootloaderOther
709 && bl
->capabilities() & BootloaderInstallBase::Backup
)
711 QString targetFolder
= SystemInfo::value(SystemInfo::CurPlatformName
).toString()
712 + " Firmware Backup";
713 // remove invalid character(s)
714 targetFolder
.remove(QRegExp("[:/]"));
715 if(QMessageBox::question(this, tr("Create Bootloader backup"),
716 tr("You can create a backup of the original bootloader "
717 "file. Press \"Yes\" to select an output folder on your "
718 "computer to save the file to. The file will get placed "
719 "in a new folder \"%1\" created below the selected folder.\n"
720 "Press \"No\" to skip this step.").arg(targetFolder
),
721 QMessageBox::Yes
| QMessageBox::No
) == QMessageBox::Yes
) {
722 backupDestination
= QFileDialog::getExistingDirectory(this,
723 tr("Browse backup folder"), QDir::homePath());
724 if(!backupDestination
.isEmpty())
725 backupDestination
+= "/" + targetFolder
;
727 qDebug() << "[RbUtil] backing up to" << backupDestination
;
728 // backup needs to be done after the logger has been set up.
732 if(bl
->capabilities() & BootloaderInstallBase::NeedsOf
)
735 ret
= QMessageBox::information(this, tr("Prerequisites"),
736 bl
->ofHint(),QMessageBox::Ok
| QMessageBox::Abort
);
737 if(ret
!= QMessageBox::Ok
) {
738 // consider aborting an error to close window / abort automatic
741 logger
->addItem(tr("Bootloader installation aborted"), LOGINFO
);
742 logger
->setFinished();
745 // open dialog to browse to of file
747 offile
= QFileDialog::getOpenFileName(this,
748 tr("Select firmware file"), QDir::homePath());
749 if(!QFileInfo(offile
).isReadable()) {
750 logger
->addItem(tr("Error opening firmware file"), LOGERROR
);
751 logger
->setFinished();
755 bl
->setOfFile(offile
);
758 // the bootloader install class does NOT use any GUI stuff.
759 // All messages are passed via signals.
760 connect(bl
, SIGNAL(done(bool)), logger
, SLOT(setFinished()));
761 connect(bl
, SIGNAL(done(bool)), this, SLOT(installBootloaderPost(bool)));
762 connect(bl
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
763 connect(bl
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
766 if(!backupDestination
.isEmpty()) {
767 if(!bl
->backup(backupDestination
)) {
768 if(QMessageBox::warning(this, tr("Backup error"),
769 tr("Could not create backup file. Continue?"),
770 QMessageBox::No
| QMessageBox::Yes
)
771 == QMessageBox::No
) {
772 logger
->setFinished();
780 void RbUtilQt::installBootloaderPost(bool error
)
782 qDebug() << "[RbUtil] Bootloader Post-Installation, error state:" << error
;
783 // if an error occured don't perform post install steps.
792 // end here if automated install
796 QString msg
= BootloaderInstallBase::postinstallHints(
797 RbSettings::value(RbSettings::Platform
).toString());
799 QMessageBox::information(this, tr("Manual steps required"), msg
);
805 void RbUtilQt::installFontsBtn()
807 if(chkConfig(true)) return;
808 if(QMessageBox::question(this, tr("Confirm Installation"),
809 tr("Do you really want to install the fonts package?"),
810 QMessageBox::Yes
| QMessageBox::No
) != QMessageBox::Yes
) return;
812 logger
= new ProgressLoggerGui(this);
817 bool RbUtilQt::installFontsAuto()
824 void RbUtilQt::installFonts()
826 // create zip installer
827 installer
= new ZipInstaller(this);
829 installer
->setUrl(SystemInfo::value(SystemInfo::FontUrl
).toString());
830 installer
->setLogSection("Fonts");
831 installer
->setLogVersion(ServerInfo::value(ServerInfo::DailyDate
).toString());
832 installer
->setMountPoint(RbSettings::value(RbSettings::Mountpoint
).toString());
833 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
834 installer
->setCache(true);
836 connect(installer
, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
837 connect(installer
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
838 connect(installer
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
839 connect(installer
, SIGNAL(done(bool)), logger
, SLOT(setFinished()));
840 connect(logger
, SIGNAL(aborted()), installer
, SLOT(abort()));
841 installer
->install();
845 void RbUtilQt::installVoice()
847 if(chkConfig(true)) return;
849 if(m_gotInfo
== false)
851 QMessageBox::warning(this, tr("Warning"),
852 tr("The Application is still downloading Information about new Builds."
853 " Please try again shortly."));
857 if(QMessageBox::question(this, tr("Confirm Installation"),
858 tr("Do you really want to install the voice file?"),
859 QMessageBox::Yes
| QMessageBox::No
) != QMessageBox::Yes
) return;
861 logger
= new ProgressLoggerGui(this);
864 // create zip installer
865 installer
= new ZipInstaller(this);
867 QString voiceurl
= SystemInfo::value(SystemInfo::VoiceUrl
).toString();
868 QDate date
= QDate::fromString(ServerInfo::value(ServerInfo::DailyDate
).toString(),Qt::ISODate
);
869 voiceurl
+= SystemInfo::value(SystemInfo::CurBuildserverModel
).toString() + "-" +
870 date
.toString("yyyyMMdd") + "-english.zip";
871 qDebug() << "[RbUtil] voicefile URL:" << voiceurl
;
873 installer
->setUrl(voiceurl
);
874 installer
->setLogSection("Voice");
875 installer
->setLogVersion(ServerInfo::value(ServerInfo::DailyDate
).toString());
876 installer
->setMountPoint(RbSettings::value(RbSettings::Mountpoint
).toString());
877 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
878 installer
->setCache(true);
879 connect(installer
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
880 connect(installer
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
881 connect(installer
, SIGNAL(done(bool)), logger
, SLOT(setFinished()));
882 connect(logger
, SIGNAL(aborted()), installer
, SLOT(abort()));
883 installer
->install();
887 void RbUtilQt::installDoomBtn()
889 if(chkConfig(true)) return;
891 QMessageBox::critical(this, tr("Error"),
892 tr("Your device doesn't have a doom plugin. Aborting."));
896 if(QMessageBox::question(this, tr("Confirm Installation"),
897 tr("Do you really want to install the game addon files?"),
898 QMessageBox::Yes
| QMessageBox::No
) != QMessageBox::Yes
) return;
900 logger
= new ProgressLoggerGui(this);
905 bool RbUtilQt::installDoomAuto()
911 bool RbUtilQt::hasDoom()
913 QFile
doomrock(RbSettings::value(RbSettings::Mountpoint
).toString()
914 +"/.rockbox/rocks/games/doom.rock");
915 return doomrock
.exists();
918 void RbUtilQt::installDoom()
920 // create zip installer
921 installer
= new ZipInstaller(this);
923 installer
->setUrl(SystemInfo::value(SystemInfo::DoomUrl
).toString());
924 installer
->setLogSection("Game Addons");
925 installer
->setLogVersion(ServerInfo::value(ServerInfo::DailyDate
).toString());
926 installer
->setMountPoint(RbSettings::value(RbSettings::Mountpoint
).toString());
927 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
928 installer
->setCache(true);
929 connect(installer
, SIGNAL(done(bool)), this, SLOT(installdone(bool)));
930 connect(installer
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
931 connect(installer
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
932 connect(installer
, SIGNAL(done(bool)), logger
, SLOT(setFinished()));
933 connect(logger
, SIGNAL(aborted()), installer
, SLOT(abort()));
934 installer
->install();
938 void RbUtilQt::installThemes()
940 if(chkConfig(true)) return;
941 ThemesInstallWindow
* tw
= new ThemesInstallWindow(this);
946 void RbUtilQt::createTalkFiles(void)
948 if(chkConfig(true)) return;
949 InstallTalkWindow
*installWindow
= new InstallTalkWindow(this);
950 connect(installWindow
, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
951 installWindow
->show();
955 void RbUtilQt::createVoiceFile(void)
957 if(chkConfig(true)) return;
958 CreateVoiceWindow
*installWindow
= new CreateVoiceWindow(this);
960 connect(installWindow
, SIGNAL(settingsUpdated()), this, SLOT(updateSettings()));
961 installWindow
->show();
964 void RbUtilQt::uninstall(void)
966 if(chkConfig(true)) return;
967 UninstallWindow
*uninstallWindow
= new UninstallWindow(this);
968 uninstallWindow
->show();
972 void RbUtilQt::uninstallBootloader(void)
974 if(chkConfig(true)) return;
975 if(QMessageBox::question(this, tr("Confirm Uninstallation"),
976 tr("Do you really want to uninstall the Bootloader?"),
977 QMessageBox::Yes
| QMessageBox::No
) != QMessageBox::Yes
) return;
979 ProgressLoggerGui
* logger
= new ProgressLoggerGui(this);
980 logger
->setProgressVisible(false);
983 QString platform
= RbSettings::value(RbSettings::Platform
).toString();
986 BootloaderInstallBase
*bl
= BootloaderInstallBase::createBootloaderInstaller(this,
987 SystemInfo::value(SystemInfo::CurBootloaderMethod
).toString());
990 logger
->addItem(tr("No uninstall method for this target known."), LOGERROR
);
991 logger
->setFinished();
994 if( (bl
->capabilities() & BootloaderInstallBase::Uninstall
) == 0)
996 logger
->addItem(tr("Rockbox Utility can not uninstall the bootloader on this target."
997 "Try a normal firmware update to remove the booloader."), LOGERROR
);
998 logger
->setFinished();
1003 QStringList blfile
= SystemInfo::value(SystemInfo::CurBootloaderFile
).toStringList();
1004 QStringList blfilepath
;
1005 for(int a
= 0; a
< blfile
.size(); a
++) {
1006 blfilepath
.append(RbSettings::value(RbSettings::Mountpoint
).toString()
1009 bl
->setBlFile(blfilepath
);
1011 connect(bl
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
1012 connect(bl
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
1015 result
= bl
->uninstall();
1017 logger
->setFinished();
1022 void RbUtilQt::downloadManual(void)
1024 if(chkConfig(true)) return;
1025 if(QMessageBox::question(this, tr("Confirm download"),
1026 tr("Do you really want to download the manual? The manual will be saved "
1027 "to the root folder of your player."),
1028 QMessageBox::Yes
| QMessageBox::No
) != QMessageBox::Yes
)
1031 QString manual
= SystemInfo::value(SystemInfo::CurManual
).toString();
1032 if(manual
.isEmpty())
1034 + SystemInfo::value(SystemInfo::CurBuildserverModel
).toString();
1036 QDate date
= QDate::fromString(ServerInfo::value(ServerInfo::DailyDate
).toString(),Qt::ISODate
);
1041 if(ui
.radioPdf
->isChecked()) {
1042 target
= "/" + manual
+ ".pdf";
1043 section
= "Manual (PDF)";
1046 target
= "/" + manual
+ "-" + date
.toString("yyyyMMdd") + "-html.zip";
1047 section
= "Manual (HTML)";
1049 manualurl
= SystemInfo::value(SystemInfo::ManualUrl
).toString() + "/" + target
;
1050 qDebug() << "[RbUtil] Manual URL:" << manualurl
;
1052 ProgressLoggerGui
* logger
= new ProgressLoggerGui(this);
1054 installer
= new ZipInstaller(this);
1055 installer
->setMountPoint(RbSettings::value(RbSettings::Mountpoint
).toString());
1056 if(!RbSettings::value(RbSettings::CacheDisabled
).toBool())
1057 installer
->setCache(true);
1058 installer
->setLogSection(section
);
1059 installer
->setLogVersion(ServerInfo::value(ServerInfo::DailyDate
).toString());
1060 installer
->setUrl(manualurl
);
1061 installer
->setUnzip(false);
1062 installer
->setTarget(target
);
1063 connect(installer
, SIGNAL(logItem(QString
, int)), logger
, SLOT(addItem(QString
, int)));
1064 connect(installer
, SIGNAL(logProgress(int, int)), logger
, SLOT(setProgress(int, int)));
1065 connect(installer
, SIGNAL(done(bool)), logger
, SLOT(setFinished()));
1066 connect(logger
, SIGNAL(aborted()), installer
, SLOT(abort()));
1067 installer
->install();
1071 void RbUtilQt::installPortable(void)
1073 if(QMessageBox::question(this, tr("Confirm installation"),
1074 tr("Do you really want to install Rockbox Utility to your player? "
1075 "After installation you can run it from the players hard drive."),
1076 QMessageBox::Yes
| QMessageBox::No
) != QMessageBox::Yes
)
1079 ProgressLoggerGui
* logger
= new ProgressLoggerGui(this);
1080 logger
->setProgressMax(0);
1081 logger
->setProgressValue(0);
1083 logger
->addItem(tr("Installing Rockbox Utility"), LOGINFO
);
1086 if(!QFileInfo(RbSettings::value(RbSettings::Mountpoint
).toString()).isDir()) {
1087 logger
->addItem(tr("Mount point is wrong!"),LOGERROR
);
1088 logger
->setFinished();
1092 // remove old files first.
1093 QFile::remove(RbSettings::value(RbSettings::Mountpoint
).toString()
1094 + "/RockboxUtility.exe");
1095 QFile::remove(RbSettings::value(RbSettings::Mountpoint
).toString()
1096 + "/RockboxUtility.ini");
1097 // copy currently running binary and currently used settings file
1098 if(!QFile::copy(qApp
->applicationFilePath(),
1099 RbSettings::value(RbSettings::Mountpoint
).toString()
1100 + "/RockboxUtility.exe")) {
1101 logger
->addItem(tr("Error installing Rockbox Utility"), LOGERROR
);
1102 logger
->setFinished();
1105 logger
->addItem(tr("Installing user configuration"), LOGINFO
);
1106 if(!QFile::copy(RbSettings::userSettingFilename(),
1107 RbSettings::value(RbSettings::Mountpoint
).toString()
1108 + "/RockboxUtility.ini")) {
1109 logger
->addItem(tr("Error installing user configuration"), LOGERROR
);
1110 logger
->setFinished();
1113 logger
->addItem(tr("Successfully installed Rockbox Utility."), LOGOK
);
1114 logger
->setFinished();
1115 logger
->setProgressMax(1);
1116 logger
->setProgressValue(1);
1121 void RbUtilQt::updateInfo()
1123 qDebug() << "[RbUtil] updating server info";
1125 QString mp
= RbSettings::value(RbSettings::Mountpoint
).toString();
1126 QSettings
log(mp
+ "/.rockbox/rbutil.log", QSettings::IniFormat
, this);
1127 QStringList groups
= log
.childGroups();
1128 QList
<QTreeWidgetItem
*> items
;
1129 QTreeWidgetItem
*w
, *w2
;
1133 // remove old list entries (if any)
1134 int l
= ui
.treeInfo
->topLevelItemCount();
1137 m
= ui
.treeInfo
->takeTopLevelItem(l
);
1138 // delete childs (single level deep, no recursion here)
1139 int n
= m
->childCount();
1143 // get and populate new items
1144 for(int a
= 0; a
< groups
.size(); a
++) {
1145 log
.beginGroup(groups
.at(a
));
1146 QStringList keys
= log
.allKeys();
1147 w
= new QTreeWidgetItem
;
1148 w
->setFlags(Qt::ItemIsEnabled
);
1149 w
->setText(0, groups
.at(a
));
1151 // get minimum and maximum version information so we can hilight old files
1152 min
= max
= log
.value(keys
.at(0)).toString();
1153 for(int b
= 0; b
< keys
.size(); b
++) {
1154 if(log
.value(keys
.at(b
)).toString() > max
)
1155 max
= log
.value(keys
.at(b
)).toString();
1156 if(log
.value(keys
.at(b
)).toString() < min
)
1157 min
= log
.value(keys
.at(b
)).toString();
1160 for(int b
= 0; b
< keys
.size(); b
++) {
1162 file
= mp
+ "/" + keys
.at(b
);
1163 if(QFileInfo(file
).isDir())
1165 w2
= new QTreeWidgetItem(w
, QStringList() << "/"
1166 + keys
.at(b
) << log
.value(keys
.at(b
)).toString());
1167 if(log
.value(keys
.at(b
)).toString() != max
) {
1168 w2
->setForeground(0, QBrush(QColor(255, 0, 0)));
1169 w2
->setForeground(1, QBrush(QColor(255, 0, 0)));
1176 w
->setData(1, Qt::DisplayRole
, QString("%1 / %2").arg(min
, max
));
1178 w
->setData(1, Qt::DisplayRole
, max
);
1180 ui
.treeInfo
->insertTopLevelItems(0, items
);
1181 ui
.treeInfo
->resizeColumnToContents(0);
1185 QUrl
RbUtilQt::proxy()
1187 if(RbSettings::value(RbSettings::ProxyType
) == "manual")
1188 return QUrl(RbSettings::value(RbSettings::Proxy
).toString());
1189 else if(RbSettings::value(RbSettings::ProxyType
) == "system")
1190 return System::systemProxy();
1195 bool RbUtilQt::chkConfig(bool warn
)
1198 if(RbSettings::value(RbSettings::Platform
).toString().isEmpty()
1199 || RbSettings::value(RbSettings::Mountpoint
).toString().isEmpty()
1200 || !QFileInfo(RbSettings::value(RbSettings::Mountpoint
).toString()).isWritable()) {
1203 if(warn
) QMessageBox::critical(this, tr("Configuration error"),
1204 tr("Your configuration is invalid. Please go to the configuration "
1205 "dialog and make sure the selected values are correct."));
1210 void RbUtilQt::checkUpdate(void)
1212 QString url
= SystemInfo::value(SystemInfo::RbutilUrl
).toString();
1213 #if defined(Q_OS_WIN32)
1215 #elif defined(Q_OS_LINUX)
1217 #elif defined(Q_OS_MACX)
1221 update
= new HttpGet(this);
1222 connect(update
, SIGNAL(done(bool)), this, SLOT(downloadUpdateDone(bool)));
1223 connect(qApp
, SIGNAL(lastWindowClosed()), update
, SLOT(abort()));
1224 if(RbSettings::value(RbSettings::CacheOffline
).toBool())
1225 update
->setCache(true);
1227 update
->getFile(QUrl(url
));
1230 void RbUtilQt::downloadUpdateDone(bool error
)
1233 qDebug() << "[RbUtil] network error:" << update
->error();
1236 QString
toParse(update
->readAll());
1238 QRegExp
searchString("<a[^>]*>([a-zA-Z]+[^<]*)</a>");
1239 QStringList rbutilList
;
1241 while ((pos
= searchString
.indexIn(toParse
, pos
)) != -1)
1243 rbutilList
<< searchString
.cap(1);
1244 pos
+= searchString
.matchedLength();
1246 qDebug() << "[Checkupdate] " << rbutilList
;
1248 QString newVersion
="";
1249 //check if there is a binary with higher version in this list
1250 for(int i
=0; i
< rbutilList
.size(); i
++)
1252 #if defined(Q_OS_LINUX)
1253 #if defined(__amd64__)
1254 //skip if it isnt a 64bit build
1255 if( !rbutilList
.at(i
).contains("64bit"))
1258 //skip if it is a 64bit build
1259 if(rbutilList
.at(i
).contains("64bit"))
1263 //check if it is newer, and remember newest
1264 if(newerVersion(VERSION
,rbutilList
.at(i
)))
1266 if(newVersion
== "" || newerVersion(newVersion
,rbutilList
.at(i
)))
1268 newVersion
= rbutilList
.at(i
);
1273 // if we found something newer, display info
1274 if(newVersion
!= "")
1276 QString url
= SystemInfo::value(SystemInfo::RbutilUrl
).toString();
1277 #if defined(Q_OS_WIN32)
1279 #elif defined(Q_OS_LINUX)
1281 #elif defined(Q_OS_MACX)
1286 QMessageBox::information(this,tr("RockboxUtility Update available"),
1287 tr("<b>New RockboxUtility Version available.</b> <br><br>"
1288 "Download it from here: <a href='%1'>%2</a>").arg(url
).arg(newVersion
) );
1293 bool RbUtilQt::newerVersion(QString versionOld
,QString versionNew
)
1295 QRegExp
chars("\\d*(\\D)");
1297 //strip non-number from beginning
1298 versionOld
= versionOld
.remove(0,versionOld
.indexOf(QRegExp("\\d")));
1299 versionNew
= versionNew
.remove(0,versionNew
.indexOf(QRegExp("\\d")));
1301 // split versions by "."
1302 QStringList versionListOld
= versionOld
.split(".");
1303 QStringList versionListNew
= versionNew
.split(".");
1305 QStringListIterator
iteratorOld(versionListOld
);
1306 QStringListIterator
iteratorNew(versionListNew
);
1308 //check every section
1309 while(iteratorOld
.hasNext() && iteratorNew
.hasNext())
1311 QString newPart
= iteratorNew
.next();
1312 QString oldPart
= iteratorOld
.next();
1313 QString newPartChar
= "", oldPartChar
= "";
1314 int newPartInt
= 0, oldPartInt
=0;
1316 //convert to int, if it contains chars, put into seperated variable
1317 if(newPart
.contains(chars
))
1319 newPartChar
= chars
.cap(1);
1320 newPart
= newPart
.remove(newPartChar
);
1322 newPartInt
= newPart
.toInt();
1323 //convert to int, if it contains chars, put into seperated variable
1324 if(oldPart
.contains(chars
))
1326 oldPartChar
= chars
.cap(1);
1327 oldPart
= oldPart
.remove(oldPartChar
);
1329 oldPartInt
= oldPart
.toInt();
1331 if(newPartInt
> oldPartInt
) // this section int is higher -> true
1333 else if(newPartInt
< oldPartInt
) //this section int is lower -> false
1335 else if(newPartChar
> oldPartChar
) //ints are the same, chars is higher -> true
1337 else if(newPartChar
< oldPartChar
) //ints are the same, chars is lower -> false
1339 //all the same, next section
1341 // all the same -> false