handle new installations (or upgrades) differently from invalid configurations
[kugel-rb.git] / rbutil / rbutilqt / configure.cpp
blob364068f61a2bed4e08a49f134b380f937738b90f
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 "configure.h"
24 #include "autodetection.h"
25 #include "ui_configurefrm.h"
26 #include "browsedirtree.h"
27 #include "encoders.h"
28 #include "tts.h"
29 #include "detect.h"
31 #include <stdio.h>
32 #if defined(Q_OS_WIN32)
33 #if defined(UNICODE)
34 #define _UNICODE
35 #endif
36 #include <tchar.h>
37 #include <windows.h>
38 #endif
40 #define DEFAULT_LANG "English (C)"
42 Config::Config(QWidget *parent,int index) : QDialog(parent)
44 programPath = qApp->applicationDirPath() + "/";
45 ui.setupUi(this);
46 ui.tabConfiguration->setCurrentIndex(index);
47 ui.radioManualProxy->setChecked(true);
48 QRegExpValidator *proxyValidator = new QRegExpValidator(this);
49 QRegExp validate("[0-9]*");
50 proxyValidator->setRegExp(validate);
51 ui.proxyPort->setValidator(proxyValidator);
52 #if !defined(Q_OS_LINUX) && !defined(Q_OS_WIN32)
53 ui.radioSystemProxy->setEnabled(false); // not on macox for now
54 #endif
55 // build language list and sort alphabetically
56 QStringList langs = findLanguageFiles();
57 for(int i = 0; i < langs.size(); ++i)
58 lang.insert(languageName(langs.at(i)) + tr(" (%1)").arg(langs.at(i)), langs.at(i));
59 lang.insert(DEFAULT_LANG, "");
60 QMap<QString, QString>::const_iterator i = lang.constBegin();
61 while (i != lang.constEnd()) {
62 ui.listLanguages->addItem(i.key());
63 i++;
65 ui.listLanguages->setSelectionMode(QAbstractItemView::SingleSelection);
66 connect(ui.listLanguages, SIGNAL(itemSelectionChanged()), this, SLOT(updateLanguage()));
67 ui.proxyPass->setEchoMode(QLineEdit::Password);
68 ui.treeDevices->setAlternatingRowColors(true);
69 ui.listLanguages->setAlternatingRowColors(true);
71 this->setModal(true);
73 connect(ui.buttonOk, SIGNAL(clicked()), this, SLOT(accept()));
74 connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(abort()));
75 connect(ui.radioNoProxy, SIGNAL(toggled(bool)), this, SLOT(setNoProxy(bool)));
76 connect(ui.radioSystemProxy, SIGNAL(toggled(bool)), this, SLOT(setSystemProxy(bool)));
77 connect(ui.browseMountPoint, SIGNAL(clicked()), this, SLOT(browseFolder()));
78 connect(ui.buttonAutodetect,SIGNAL(clicked()),this,SLOT(autodetect()));
79 connect(ui.buttonCacheBrowse, SIGNAL(clicked()), this, SLOT(browseCache()));
80 connect(ui.buttonCacheClear, SIGNAL(clicked()), this, SLOT(cacheClear()));
81 connect(ui.configTts, SIGNAL(clicked()), this, SLOT(configTts()));
82 connect(ui.configEncoder, SIGNAL(clicked()), this, SLOT(configEnc()));
83 connect(ui.comboTts, SIGNAL(currentIndexChanged(int)), this, SLOT(updateTtsState(int)));
84 connect(ui.treeDevices, SIGNAL(itemSelectionChanged()), this, SLOT(updateEncState()));
90 void Config::accept()
92 qDebug() << "Config::accept()";
93 // proxy: save entered proxy values, not displayed.
94 if(ui.radioManualProxy->isChecked()) {
95 proxy.setScheme("http");
96 proxy.setUserName(ui.proxyUser->text());
97 proxy.setPassword(ui.proxyPass->text());
98 proxy.setHost(ui.proxyHost->text());
99 proxy.setPort(ui.proxyPort->text().toInt());
102 settings->setProxy(proxy.toString());
103 qDebug() << "new proxy:" << proxy;
104 // proxy type
105 QString proxyType;
106 if(ui.radioNoProxy->isChecked()) proxyType = "none";
107 else if(ui.radioSystemProxy->isChecked()) proxyType = "system";
108 else proxyType = "manual";
109 settings->setProxyType(proxyType);
111 // language
112 if(settings->curLang() != language)
113 QMessageBox::information(this, tr("Language changed"),
114 tr("You need to restart the application for the changed language to take effect."));
115 settings->setLang(language);
117 // mountpoint
118 QString mp = ui.mountPoint->text();
119 if(QFileInfo(mp).isDir())
120 settings->setMountpoint(QDir::fromNativeSeparators(mp));
122 // platform
123 QString nplat;
124 if(ui.treeDevices->selectedItems().size() != 0) {
125 nplat = ui.treeDevices->selectedItems().at(0)->data(0, Qt::UserRole).toString();
126 settings->setCurPlatform(nplat);
129 // cache settings
130 if(QFileInfo(ui.cachePath->text()).isDir())
131 settings->setCachePath(ui.cachePath->text());
132 else // default to system temp path
133 settings->setCachePath( QDir::tempPath());
134 settings->setCacheDisable(ui.cacheDisable->isChecked());
135 settings->setCacheOffline(ui.cacheOfflineMode->isChecked());
137 // tts settings
138 int i = ui.comboTts->currentIndex();
139 settings->setCurTTS(ui.comboTts->itemData(i).toString());
141 settings->setCurVersion(PUREVERSION);
143 // sync settings
144 settings->sync();
145 this->close();
146 emit settingsUpdated();
150 void Config::abort()
152 qDebug() << "Config::abort()";
153 this->close();
156 void Config::setSettings(RbSettings* sett)
158 settings = sett;
160 setUserSettings();
161 setDevices();
164 void Config::setUserSettings()
166 // set proxy
167 proxy = settings->proxy();
169 if(proxy.port() > 0)
170 ui.proxyPort->setText(QString("%1").arg(proxy.port()));
171 else ui.proxyPort->setText("");
172 ui.proxyHost->setText(proxy.host());
173 ui.proxyUser->setText(proxy.userName());
174 ui.proxyPass->setText(proxy.password());
176 QString proxyType = settings->proxyType();
177 if(proxyType == "manual") ui.radioManualProxy->setChecked(true);
178 else if(proxyType == "system") ui.radioSystemProxy->setChecked(true);
179 else ui.radioNoProxy->setChecked(true);
181 // set language selection
182 QList<QListWidgetItem*> a;
183 QString b;
184 // find key for lang value
185 QMap<QString, QString>::const_iterator i = lang.constBegin();
186 while (i != lang.constEnd()) {
187 if(i.value() == settings->curLang()) {
188 b = i.key();
189 break;
191 i++;
193 a = ui.listLanguages->findItems(b, Qt::MatchExactly);
194 if(a.size() <= 0)
195 a = ui.listLanguages->findItems(DEFAULT_LANG, Qt::MatchExactly);
196 if(a.size() > 0)
197 ui.listLanguages->setCurrentItem(a.at(0));
199 // devices tab
200 ui.mountPoint->setText(QDir::toNativeSeparators(settings->mountpoint()));
202 // cache tab
203 if(!QFileInfo(settings->cachePath()).isDir())
204 settings->setCachePath(QDir::tempPath());
205 ui.cachePath->setText(settings->cachePath());
206 ui.cacheDisable->setChecked(settings->cacheDisabled());
207 ui.cacheOfflineMode->setChecked(settings->cacheOffline());
208 updateCacheInfo(settings->cachePath());
212 void Config::updateCacheInfo(QString path)
214 QList<QFileInfo> fs;
215 fs = QDir(path + "/rbutil-cache/").entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
216 qint64 sz = 0;
217 for(int i = 0; i < fs.size(); i++) {
218 sz += fs.at(i).size();
219 qDebug() << fs.at(i).fileName() << fs.at(i).size();
221 ui.cacheSize->setText(tr("Current cache size is %L1 kiB.")
222 .arg(sz/1024));
226 void Config::setDevices()
229 // setup devices table
230 qDebug() << "Config::setDevices()";
232 QStringList platformList = settings->allPlatforms();
234 QMap <QString, QString> manuf;
235 QMap <QString, QString> devcs;
236 for(int it = 0; it < platformList.size(); it++)
238 QString curname = settings->name(platformList.at(it));
239 QString curbrand = settings->brand(platformList.at(it));
240 manuf.insertMulti(curbrand, platformList.at(it));
241 devcs.insert(platformList.at(it), curname);
244 QString platform;
245 platform = devcs.value(settings->curPlatform());
247 // set up devices table
248 ui.treeDevices->header()->hide();
249 ui.treeDevices->expandAll();
250 ui.treeDevices->setColumnCount(1);
251 QList<QTreeWidgetItem *> items;
253 // get manufacturers
254 QStringList brands = manuf.uniqueKeys();
255 QTreeWidgetItem *w;
256 QTreeWidgetItem *w2;
257 QTreeWidgetItem *w3 = 0;
258 for(int c = 0; c < brands.size(); c++) {
259 qDebug() << brands.at(c);
260 w = new QTreeWidgetItem();
261 w->setFlags(Qt::ItemIsEnabled);
262 w->setText(0, brands.at(c));
263 items.append(w);
265 // go through platforms again for sake of order
266 for(int it = 0; it < platformList.size(); it++) {
268 QString curname = settings->name(platformList.at(it));
269 QString curbrand = settings->brand(platformList.at(it));
271 if(curbrand != brands.at(c)) continue;
272 qDebug() << "adding:" << brands.at(c) << curname;
273 w2 = new QTreeWidgetItem(w, QStringList(curname));
274 w2->setData(0, Qt::UserRole, platformList.at(it));
276 if(platform.contains(curname)) {
277 w2->setSelected(true);
278 w->setExpanded(true);
279 w3 = w2; // save pointer to hilight old selection
281 items.append(w2);
284 ui.treeDevices->insertTopLevelItems(0, items);
285 if(w3 != 0)
286 ui.treeDevices->setCurrentItem(w3); // hilight old selection
288 // tts / encoder tab
290 //encoders
291 updateEncState();
293 //tts
294 QStringList ttslist = TTSBase::getTTSList();
295 for(int a = 0; a < ttslist.size(); a++)
296 ui.comboTts->addItem(TTSBase::getTTSName(ttslist.at(a)), ttslist.at(a));
297 //update index of combobox
298 int index = ui.comboTts->findData(settings->curTTS());
299 if(index < 0) index = 0;
300 ui.comboTts->setCurrentIndex(index);
301 updateTtsState(index);
306 void Config::updateTtsState(int index)
308 QString ttsName = ui.comboTts->itemData(index).toString();
309 TTSBase* tts = TTSBase::getTTS(ttsName);
310 tts->setCfg(settings);
312 if(tts->configOk())
314 ui.configTTSstatus->setText(tr("Configuration OK"));
315 ui.configTTSstatusimg->setPixmap(QPixmap(QString::fromUtf8(":/icons/go-next.png")));
317 else
319 ui.configTTSstatus->setText(tr("Configuration INVALID"));
320 ui.configTTSstatusimg->setPixmap(QPixmap(QString::fromUtf8(":/icons/dialog-error.png")));
324 void Config::updateEncState()
326 // FIXME: this is a workaround to make the encoder follow the device selection
327 // even with the settings (and thus the device) being saved. Needs to be redone
328 // properly later by extending the settings object
329 if(ui.treeDevices->selectedItems().size() == 0)
330 return;
332 QString devname = ui.treeDevices->selectedItems().at(0)->data(0, Qt::UserRole).toString();
333 QString olddevice = settings->curPlatform();
334 settings->setCurPlatform(devname);
335 QString encoder = settings->curEncoder();
336 ui.encoderName->setText(EncBase::getEncoderName(settings->curEncoder()));
337 settings->setCurPlatform(olddevice);
339 EncBase* enc = EncBase::getEncoder(encoder);
340 enc->setCfg(settings);
342 if(enc->configOk())
344 ui.configEncstatus->setText(tr("Configuration OK"));
345 ui.configEncstatusimg->setPixmap(QPixmap(QString::fromUtf8(":/icons/go-next.png")));
347 else
349 ui.configEncstatus->setText(tr("Configuration INVALID"));
350 ui.configEncstatusimg->setPixmap(QPixmap(QString::fromUtf8(":/icons/dialog-error.png")));
354 void Config::setNoProxy(bool checked)
356 bool i = !checked;
357 ui.proxyPort->setEnabled(i);
358 ui.proxyHost->setEnabled(i);
359 ui.proxyUser->setEnabled(i);
360 ui.proxyPass->setEnabled(i);
364 void Config::setSystemProxy(bool checked)
366 bool i = !checked;
367 ui.proxyPort->setEnabled(i);
368 ui.proxyHost->setEnabled(i);
369 ui.proxyUser->setEnabled(i);
370 ui.proxyPass->setEnabled(i);
371 if(checked) {
372 // save values in input box
373 proxy.setScheme("http");
374 proxy.setUserName(ui.proxyUser->text());
375 proxy.setPassword(ui.proxyPass->text());
376 proxy.setHost(ui.proxyHost->text());
377 proxy.setPort(ui.proxyPort->text().toInt());
378 // show system values in input box
379 QUrl envproxy = Detect::systemProxy();
381 ui.proxyHost->setText(envproxy.host());
383 ui.proxyPort->setText(QString("%1").arg(envproxy.port()));
384 ui.proxyUser->setText(envproxy.userName());
385 ui.proxyPass->setText(envproxy.password());
388 else {
389 ui.proxyHost->setText(proxy.host());
390 if(proxy.port() > 0)
391 ui.proxyPort->setText(QString("%1").arg(proxy.port()));
392 else ui.proxyPort->setText("");
393 ui.proxyUser->setText(proxy.userName());
394 ui.proxyPass->setText(proxy.password());
400 QStringList Config::findLanguageFiles()
402 QDir dir(programPath);
403 QStringList fileNames;
404 QStringList langs;
405 fileNames = dir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name);
407 QDir resDir(":/lang");
408 fileNames += resDir.entryList(QStringList("*.qm"), QDir::Files, QDir::Name);
410 QRegExp exp("^rbutil_(.*)\\.qm");
411 for(int i = 0; i < fileNames.size(); i++) {
412 QString a = fileNames.at(i);
413 a.replace(exp, "\\1");
414 langs.append(a);
416 langs.sort();
417 qDebug() << "Config::findLanguageFiles()" << langs;
419 return langs;
423 QString Config::languageName(const QString &qmFile)
425 QTranslator translator;
427 QString file = "rbutil_" + qmFile;
428 if(!translator.load(file, programPath))
429 translator.load(file, ":/lang");
431 return translator.translate("Configure", "English",
432 "This is the localized language name, i.e. your language.");
436 void Config::updateLanguage()
438 qDebug() << "updateLanguage()";
439 QList<QListWidgetItem*> a = ui.listLanguages->selectedItems();
440 if(a.size() > 0)
441 language = lang.value(a.at(0)->text());
442 qDebug() << language;
446 void Config::browseFolder()
448 browser = new BrowseDirtree(this,tr("Select your device"));
449 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
450 browser->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
451 #elif defined(Q_OS_WIN32)
452 browser->setFilter(QDir::Drives);
453 #endif
454 #if defined(Q_OS_MACX)
455 browser->setRoot("/Volumes");
456 #elif defined(Q_OS_LINUX)
457 browser->setDir("/media");
458 #endif
459 if( ui.mountPoint->text() != "" )
461 browser->setDir(ui.mountPoint->text());
463 browser->show();
464 connect(browser, SIGNAL(itemChanged(QString)), this, SLOT(setMountpoint(QString)));
468 void Config::browseCache()
470 cbrowser = new BrowseDirtree(this);
471 #if defined(Q_OS_LINUX) || defined(Q_OS_MACX)
472 cbrowser->setFilter(QDir::AllDirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
473 #elif defined(Q_OS_WIN32)
474 cbrowser->setFilter(QDir::Drives);
475 #endif
476 cbrowser->setDir(ui.cachePath->text());
477 connect(cbrowser, SIGNAL(itemChanged(QString)), this, SLOT(setCache(QString)));
478 cbrowser->show();
482 void Config::setMountpoint(QString m)
484 ui.mountPoint->setText(m);
488 void Config::setCache(QString c)
490 ui.cachePath->setText(c);
491 updateCacheInfo(c);
495 void Config::autodetect()
497 Autodetection detector(this);
498 detector.setSettings(settings);
499 // disable tree during detection as "working" feedback.
500 // TODO: replace the tree view with a splash screen during this time.
501 ui.treeDevices->setEnabled(false);
502 QCoreApplication::processEvents();
504 if(detector.detect()) //let it detect
506 QString devicename = detector.getDevice();
507 // deexpand all items
508 for(int a = 0; a < ui.treeDevices->topLevelItemCount(); a++)
509 ui.treeDevices->topLevelItem(a)->setExpanded(false);
510 //deselect the selected item(s)
511 for(int a = 0; a < ui.treeDevices->selectedItems().size(); a++)
512 ui.treeDevices->selectedItems().at(a)->setSelected(false);
514 // find the new item
515 // enumerate all platform items
516 QList<QTreeWidgetItem*> itmList= ui.treeDevices->findItems("*",Qt::MatchWildcard);
517 for(int i=0; i< itmList.size();i++)
519 //enumerate device items
520 for(int j=0;j < itmList.at(i)->childCount();j++)
522 QString data = itmList.at(i)->child(j)->data(0, Qt::UserRole).toString();
524 if(devicename == data) // item found
526 itmList.at(i)->child(j)->setSelected(true); //select the item
527 itmList.at(i)->setExpanded(true); //expand the platform item
528 //ui.treeDevices->indexOfTopLevelItem(itmList.at(i)->child(j));
529 break;
534 if(!detector.errdev().isEmpty()) {
535 QString text;
536 if(detector.errdev() == "sansae200")
537 text = tr("Sansa e200 in MTP mode found!\n"
538 "You need to change your player to MSC mode for installation. ");
539 if(detector.errdev() == "h10")
540 text = tr("H10 20GB in MTP mode found!\n"
541 "You need to change your player to UMS mode for installation. ");
542 text += tr("Unless you changed this installation will fail!");
544 QMessageBox::critical(this, tr("Fatal error"), text, QMessageBox::Ok);
545 return;
547 if(!detector.incompatdev().isEmpty()) {
548 QString text;
549 // we need to set the platform here to get the brand from the
550 // settings object
551 settings->setCurPlatform(detector.incompatdev());
552 text = tr("Detected an unsupported %1 player variant. Sorry, "
553 "Rockbox doesn't run on your player.").arg(settings->curBrand());
555 QMessageBox::critical(this, tr("Fatal error: incompatible player found"),
556 text, QMessageBox::Ok);
557 return;
560 if(detector.getMountPoint() != "" )
562 ui.mountPoint->setText(QDir::toNativeSeparators(detector.getMountPoint()));
564 else
566 QMessageBox::warning(this, tr("Autodetection"),
567 tr("Could not detect a Mountpoint.\n"
568 "Select your Mountpoint manually."),
569 QMessageBox::Ok ,QMessageBox::Ok);
572 else
574 QMessageBox::warning(this, tr("Autodetection"),
575 tr("Could not detect a device.\n"
576 "Select your device and Mountpoint manually."),
577 QMessageBox::Ok ,QMessageBox::Ok);
580 ui.treeDevices->setEnabled(true);
583 void Config::cacheClear()
585 if(QMessageBox::critical(this, tr("Really delete cache?"),
586 tr("Do you really want to delete the cache? "
587 "Make absolutely sure this setting is correct as it will "
588 "remove <b>all</b> files in this folder!").arg(ui.cachePath->text()),
589 QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
590 return;
592 QString cache = ui.cachePath->text() + "/rbutil-cache/";
593 if(!QFileInfo(cache).isDir()) {
594 QMessageBox::critical(this, tr("Path wrong!"),
595 tr("The cache path is invalid. Aborting."), QMessageBox::Ok);
596 return;
598 QDir dir(cache);
599 QStringList fn;
600 fn = dir.entryList(QStringList("*"), QDir::Files, QDir::Name);
601 qDebug() << fn;
603 for(int i = 0; i < fn.size(); i++) {
604 QString f = cache + fn.at(i);
605 QFile::remove(f);
606 qDebug() << "removed:" << f;
608 updateCacheInfo(settings->cachePath());
612 void Config::configTts()
614 int index = ui.comboTts->currentIndex();
615 TTSBase* tts = TTSBase::getTTS(ui.comboTts->itemData(index).toString());
617 tts->setCfg(settings);
618 tts->showCfg();
619 updateTtsState(ui.comboTts->currentIndex());
623 void Config::configEnc()
625 EncBase* enc = EncBase::getEncoder(settings->curEncoder());
627 enc->setCfg(settings);
628 enc->showCfg();
629 updateEncState();