blob: 6e46c47448238aebcbeedd2d2eae24b9375e0ef7 [file] [log] [blame]
// Copyright (C) 2015-2016 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
#include "android/skin/qt/extended-pages/settings-page.h"
#include "android/base/files/PathUtils.h"
#include "android/skin/qt/error-dialog.h"
#include "android/skin/qt/extended-pages/common.h"
#include "android/skin/qt/qt-settings.h"
#include <QApplication>
#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
// Helper function to set the contents of a QLineEdit.
static void setElidedText(QLineEdit* line_edit, const QString& text) {
QFontMetrics font_metrics(line_edit->font());
line_edit->setText(
font_metrics.elidedText(text, Qt::ElideRight, line_edit->width() * 0.9));
}
SettingsPage::SettingsPage(QWidget* parent)
: QWidget(parent), mAdb(nullptr), mUi(new Ui::SettingsPage()) {
mUi->setupUi(this);
mUi->set_saveLocBox->installEventFilter(this);
mUi->set_adbPathBox->installEventFilter(this);
QString savePath =
QDir::toNativeSeparators(getScreenshotSaveDirectory());
if (savePath.isEmpty()) {
mUi->set_saveLocBox->setText(tr("None"));
} else {
setElidedText(mUi->set_saveLocBox, savePath);
}
// ADB path
QSettings settings;
bool autoFindAdb =
settings.value(Ui::Settings::AUTO_FIND_ADB, true).toBool();
mUi->set_autoFindAdb->setChecked(autoFindAdb);
on_set_autoFindAdb_toggled(autoFindAdb);
QString adbPath = settings.value(Ui::Settings::ADB_PATH, "").toString();
adbPath = QDir::toNativeSeparators(adbPath);
setElidedText(mUi->set_adbPathBox, adbPath);
// Dark/Light theme
SettingsTheme theme =
static_cast<SettingsTheme>(settings.value(Ui::Settings::UI_THEME, 0).toInt());
if (theme < 0 || theme >= SETTINGS_THEME_NUM_ENTRIES) {
theme = static_cast<SettingsTheme>(0);
}
mUi->set_themeBox->setCurrentIndex(static_cast<int>(theme));
connect(mUi->set_forwardShortcutsToDevice, SIGNAL(currentIndexChanged(int)),
this, SIGNAL(onForwardShortcutsToDeviceChanged(int)));
// "Send keyboard shortcuts": a pull-down that acts like a checkbox
bool shortcutBool = settings.value(
Ui::Settings::FORWARD_SHORTCUTS_TO_DEVICE, false).toBool();
mUi->set_forwardShortcutsToDevice->setCurrentIndex( shortcutBool ? 1 : 0 );
#ifdef __linux__
// "Always on top" is not supported for Linux (see emulator-qt-window.cpp)
// Make the control invisible
mUi->set_onTopTitle->hide();
mUi->set_onTop->hide();
#else // Windows or OSX
bool onTopOnly = settings.value(Ui::Settings::ALWAYS_ON_TOP, false).toBool();
mUi->set_onTop->setCheckState(onTopOnly ? Qt::Checked : Qt::Unchecked);
#endif
Ui::Settings::CRASHREPORT_PREFERENCE_VALUE report_pref =
static_cast<Ui::Settings::CRASHREPORT_PREFERENCE_VALUE>(
settings.value(Ui::Settings::CRASHREPORT_PREFERENCE, 0).toInt());
switch (report_pref) {
case Ui::Settings::CRASHREPORT_PREFERENCE_ASK:
mUi->set_crashReportPrefComboBox->setCurrentIndex(
Ui::Settings::CRASHREPORT_COMBOBOX_ASK);
break;
case Ui::Settings::CRASHREPORT_PREFERENCE_ALWAYS:
mUi->set_crashReportPrefComboBox->setCurrentIndex(
Ui::Settings::CRASHREPORT_COMBOBOX_ALWAYS);
break;
case Ui::Settings::CRASHREPORT_PREFERENCE_NEVER:
mUi->set_crashReportPrefComboBox->setCurrentIndex(
Ui::Settings::CRASHREPORT_COMBOBOX_NEVER);
break;
default:
break;
}
}
void SettingsPage::setAdbInterface(android::emulation::AdbInterface* adb) {
mAdb = adb;
}
bool SettingsPage::eventFilter(QObject* object, QEvent* event)
{
if (event->type() != QEvent::FocusIn && event->type() != QEvent::FocusOut) {
return false;
}
QSettings settings;
if (object == mUi->set_saveLocBox) {
QString savePath = settings.value(Ui::Settings::SAVE_PATH, "").toString();
if (event->type() == QEvent::FocusIn) {
mUi->set_saveLocBox->setText(savePath);
} else if (event->type() == QEvent::FocusOut) {
setElidedText(mUi->set_saveLocBox, savePath);
}
} else if (object == mUi->set_adbPathBox) {
QString adbPath = settings.value(Ui::Settings::ADB_PATH, "").toString();
if (event->type() == QEvent::FocusIn) {
mUi->set_adbPathBox->setText(adbPath);
} else if (event->type() == QEvent::FocusOut) {
setElidedText(mUi->set_adbPathBox, adbPath);
}
}
return false;
}
void SettingsPage::on_set_themeBox_currentIndexChanged(int index)
{
// Select either the light or dark theme
SettingsTheme theme = (SettingsTheme)index;
if (theme < 0 || theme >= SETTINGS_THEME_NUM_ENTRIES) {
// Out of range--ignore
return;
}
QSettings settings;
settings.setValue(Ui::Settings::UI_THEME, (int)theme);
emit(themeChanged(theme));
}
void SettingsPage::on_set_saveLocFolderButton_clicked()
{
QSettings settings;
QString dirName = QFileDialog::getExistingDirectory(
this, tr("Save location"),
settings.value(Ui::Settings::SAVE_PATH, "").toString(),
QFileDialog::ShowDirsOnly);
if ( dirName.isEmpty() ) return; // Operation was canceled
dirName = QDir::toNativeSeparators(dirName);
if ( !directoryIsWritable(dirName) ) {
QString errStr = tr("The path is not writable:<br>")
+ dirName;
showErrorDialog(errStr, tr("Save location"));
return;
}
settings.setValue(Ui::Settings::SAVE_PATH, dirName);
setElidedText(mUi->set_saveLocBox, dirName);
}
void SettingsPage::on_set_adbPathButton_clicked() {
QSettings settings;
QString adbPath = settings.value(Ui::Settings::ADB_PATH, "").toString();
// Repeat this dialog until the user is successful or cancels
bool pathIsGood = false;
do {
adbPath = QFileDialog::getOpenFileName(this, tr("Backup ADB path"),
adbPath);
if (adbPath.isEmpty()) {
break; // Operation was canceled
}
// We got a path. Make sure that the file both exists and is
// executable.
QFileInfo fileInfo(adbPath);
pathIsGood = fileInfo.exists() && fileInfo.isExecutable() &&
fileInfo.fileName() ==
QString(android::base::PathUtils::toExecutableName(
"adb")
.c_str());
if (pathIsGood) {
// Save this selection
settings.setValue(Ui::Settings::ADB_PATH, adbPath);
adbPath = QDir::toNativeSeparators(adbPath);
setElidedText(mUi->set_adbPathBox, adbPath);
if (mAdb) {
mAdb->setCustomAdbPath(adbPath.toStdString());
}
} else {
// The path is not good. Force the user to cancel or try again.
QString errStr = tr("This path does not point to "
"an ADB executable.<br><br>") +
QDir::toNativeSeparators(adbPath);
QMessageBox msgBox;
msgBox.setWindowTitle(tr("Select backup ADB path"));
msgBox.setText(errStr);
msgBox.setInformativeText(tr("Do you want try again or cancel?"));
msgBox.setStandardButtons(QMessageBox::Retry | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Cancel);
int selection = msgBox.exec();
if (selection == QMessageBox::Cancel) break;
}
} while ( !pathIsGood );
}
void SettingsPage::on_set_saveLocBox_textEdited(const QString&) {
QSettings settings;
mUi->set_saveLocBox->setText(
settings.value(Ui::Settings::SAVE_PATH, "").toString());
}
void SettingsPage::on_set_adbPathBox_textEdited(const QString&) {
QSettings settings;
mUi->set_adbPathBox->setText(
settings.value(Ui::Settings::ADB_PATH, "").toString());
}
void SettingsPage::on_set_forwardShortcutsToDevice_currentIndexChanged(int index) {
QSettings settings;
settings.setValue(Ui::Settings::FORWARD_SHORTCUTS_TO_DEVICE, (index != 0));
}
void SettingsPage::on_set_onTop_toggled(bool checked) {
QSettings settings;
settings.setValue(Ui::Settings::ALWAYS_ON_TOP, checked);
emit(onTopChanged(checked));
}
void SettingsPage::on_set_autoFindAdb_toggled(bool checked) {
QSettings settings;
settings.setValue(Ui::Settings::AUTO_FIND_ADB, checked);
if (mAdb) {
if (checked) {
mAdb->setCustomAdbPath(std::string());
} else {
mAdb->setCustomAdbPath(settings.value(Ui::Settings::ADB_PATH, "")
.toString()
.toStdString());
}
}
mUi->set_adbPathBox->setHidden(checked);
mUi->set_adbPathButton->setHidden(checked);
}
static void set_reportPref_to(Ui::Settings::CRASHREPORT_PREFERENCE_VALUE v) {
QSettings settings;
settings.setValue(Ui::Settings::CRASHREPORT_PREFERENCE, v);
}
void SettingsPage::on_set_crashReportPrefComboBox_currentIndexChanged(int index) {
if (index == Ui::Settings::CRASHREPORT_COMBOBOX_ALWAYS) {
set_reportPref_to(Ui::Settings::CRASHREPORT_PREFERENCE_ALWAYS);
} else if (index == Ui::Settings::CRASHREPORT_COMBOBOX_NEVER) {
set_reportPref_to(Ui::Settings::CRASHREPORT_PREFERENCE_NEVER);
} else if (index == Ui::Settings::CRASHREPORT_COMBOBOX_ASK) {
set_reportPref_to(Ui::Settings::CRASHREPORT_PREFERENCE_ASK);
}
}