mumble-voip_mumble/src/mumble/LookConfig.cpp

321 lines
13 KiB
C++

// Copyright 2007-2023 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#include "LookConfig.h"
#include "Themes.h"
#include "AudioInput.h"
#include "AudioOutput.h"
#include "MainWindow.h"
#include "SearchDialog.h"
#include "Global.h"
#include <QtCore/QFileSystemWatcher>
#include <QtCore/QStack>
#include <QtCore/QTimer>
const QString LookConfig::name = QLatin1String("LookConfig");
static ConfigWidget *LookConfigNew(Settings &st) {
return new LookConfig(st);
}
static ConfigRegistrar registrar(1100, LookConfigNew);
LookConfig::LookConfig(Settings &st) : ConfigWidget(st) {
setupUi(this);
#ifndef Q_OS_MAC
if (!QSystemTrayIcon::isSystemTrayAvailable())
#endif
qgbTray->hide();
qcbLanguage->addItem(tr("System default"));
QDir d(QLatin1String(":"), QLatin1String("mumble_*.qm"), QDir::Name, QDir::Files);
foreach (const QString &key, d.entryList()) {
QString cc = key.mid(7, key.indexOf(QLatin1Char('.')) - 7);
QLocale tmpLocale = QLocale(cc);
// If there is no native language name, use the locale
QString displayName = cc;
if (!tmpLocale.nativeLanguageName().isEmpty()) {
displayName = QString(QLatin1String("%1 (%2)")).arg(tmpLocale.nativeLanguageName()).arg(cc);
} else if (cc == QLatin1String("eo")) {
// Can't initialize QLocale for a countryless language (QTBUG-8452, QTBUG-14592).
// We only have one so special case it.
displayName = QLatin1String("Esperanto (eo)");
}
qcbLanguage->addItem(displayName, QVariant(cc));
}
qcbExpand->addItem(tr("None"), Settings::NoChannels);
qcbExpand->addItem(tr("Only with users"), Settings::ChannelsWithUsers);
qcbExpand->addItem(tr("All"), Settings::AllChannels);
qcbChannelDrag->insertItem(Settings::Ask, tr("Ask"), Settings::Ask);
qcbChannelDrag->insertItem(Settings::DoNothing, tr("Do Nothing"), Settings::DoNothing);
qcbChannelDrag->insertItem(Settings::Move, tr("Move"), Settings::Move);
qcbUserDrag->insertItem(Settings::Ask, tr("Ask"), Settings::Ask);
qcbUserDrag->insertItem(Settings::DoNothing, tr("Do Nothing"), Settings::DoNothing);
qcbUserDrag->insertItem(Settings::Move, tr("Move"), Settings::Move);
connect(qrbLCustom, SIGNAL(toggled(bool)), qcbLockLayout, SLOT(setEnabled(bool)));
QDir userThemeDirectory = Themes::getUserThemesDirectory();
if (userThemeDirectory.exists()) {
m_themeDirectoryWatcher = new QFileSystemWatcher(this);
// Use a timer to cut down floods of directory changes. We only want
// to trigger a refresh after nothing has happened for 200ms in the
// watched directory.
m_themeDirectoryDebouncer = new QTimer(this);
m_themeDirectoryDebouncer->setSingleShot(true);
m_themeDirectoryDebouncer->setInterval(200);
m_themeDirectoryDebouncer->connect(m_themeDirectoryWatcher, SIGNAL(directoryChanged(QString)), SLOT(start()));
connect(m_themeDirectoryDebouncer, SIGNAL(timeout()), SLOT(themeDirectoryChanged()));
m_themeDirectoryWatcher->addPath(userThemeDirectory.path());
QUrl userThemeDirectoryUrl = QUrl::fromLocalFile(userThemeDirectory.path());
//: This link is located next to the theme heading in the ui config and opens the user theme directory
qlThemesDirectory->setText(tr("<a href=\"%1\">Browse</a>").arg(userThemeDirectoryUrl.toString()));
qlThemesDirectory->setOpenExternalLinks(true);
}
#define ADD_SEARCH_USERACTION(name) \
qcbSearchUserAction->addItem(Search::SearchDialog::toString(Search::SearchDialog::UserAction::name), \
static_cast< int >(Search::SearchDialog::UserAction::name))
ADD_SEARCH_USERACTION(NONE);
ADD_SEARCH_USERACTION(JOIN);
#undef ADD_SEARCH_USERACTION
#define ADD_SEARCH_CHANNELACTION(name) \
qcbSearchChannelAction->addItem(Search::SearchDialog::toString(Search::SearchDialog::ChannelAction::name), \
static_cast< int >(Search::SearchDialog::ChannelAction::name))
ADD_SEARCH_CHANNELACTION(NONE);
ADD_SEARCH_CHANNELACTION(JOIN);
#undef ADD_SEARCH_CHANNELACTION
}
QString LookConfig::title() const {
return tr("User Interface");
}
const QString &LookConfig::getName() const {
return LookConfig::name;
}
QIcon LookConfig::icon() const {
return QIcon(QLatin1String("skin:config_ui.png"));
}
void LookConfig::reloadThemes(const boost::optional< ThemeInfo::StyleInfo > configuredStyle) {
const ThemeMap themes = Themes::getThemes();
int selectedThemeEntry = 0;
qcbTheme->clear();
qcbTheme->addItem(tr("None"));
for (ThemeMap::const_iterator theme = themes.begin(); theme != themes.end(); ++theme) {
for (ThemeInfo::StylesMap::const_iterator styleit = theme->styles.begin(); styleit != theme->styles.end();
++styleit) {
if (configuredStyle && configuredStyle->themeName == styleit->themeName
&& configuredStyle->name == styleit->name) {
selectedThemeEntry = qcbTheme->count();
}
qcbTheme->addItem(theme->name + QLatin1String(" - ") + styleit->name, QVariant::fromValue(*styleit));
}
}
qcbTheme->setCurrentIndex(selectedThemeEntry);
}
void LookConfig::load(const Settings &r) {
loadComboBox(qcbLanguage, 0);
loadComboBox(qcbChannelDrag, 0);
loadComboBox(qcbUserDrag, 0);
// Load Layout checkbox state
switch (r.wlWindowLayout) {
case Settings::LayoutClassic:
qrbLClassic->setChecked(true);
break;
case Settings::LayoutStacked:
qrbLStacked->setChecked(true);
break;
case Settings::LayoutHybrid:
qrbLHybrid->setChecked(true);
break;
case Settings::LayoutCustom:
default:
s.wlWindowLayout = Settings::LayoutCustom;
qrbLCustom->setChecked(true);
break;
}
qcbLockLayout->setEnabled(r.wlWindowLayout == Settings::LayoutCustom);
for (int i = 0; i < qcbLanguage->count(); i++) {
if (qcbLanguage->itemData(i).toString() == r.qsLanguage) {
loadComboBox(qcbLanguage, i);
break;
}
}
loadComboBox(qcbAlwaysOnTop, r.aotbAlwaysOnTop);
loadComboBox(qcbExpand, r.ceExpand);
loadComboBox(qcbChannelDrag, r.ceChannelDrag);
loadComboBox(qcbUserDrag, r.ceUserDrag);
loadCheckBox(qcbUsersTop, r.bUserTop);
loadComboBox(qcbQuitBehavior, static_cast< int >(r.quitBehavior));
loadCheckBox(qcbEnableDeveloperMenu, r.bEnableDeveloperMenu);
loadCheckBox(qcbLockLayout, (r.wlWindowLayout == Settings::LayoutCustom) && r.bLockLayout);
loadCheckBox(qcbHideTray, r.bHideInTray);
loadCheckBox(qcbStateInTray, r.bStateInTray);
loadCheckBox(qcbShowUserCount, r.bShowUserCount);
loadCheckBox(qcbShowVolumeAdjustments, r.bShowVolumeAdjustments);
loadCheckBox(qcbShowNicknamesOnly, r.bShowNicknamesOnly);
loadCheckBox(qcbShowContextMenuInMenuBar, r.bShowContextMenuInMenuBar);
loadCheckBox(qcbShowTransmitModeComboBox, r.bShowTransmitModeComboBox);
loadCheckBox(qcbHighContrast, r.bHighContrast);
loadCheckBox(qcbChatBarUseSelection, r.bChatBarUseSelection);
loadCheckBox(qcbFilterHidesEmptyChannels, r.bFilterHidesEmptyChannels);
const boost::optional< ThemeInfo::StyleInfo > configuredStyle = Themes::getConfiguredStyle(r);
reloadThemes(configuredStyle);
loadCheckBox(qcbUsersAlwaysVisible, r.talkingUI_UsersAlwaysVisible);
loadCheckBox(qcbLocalUserVisible, r.bTalkingUI_LocalUserStaysVisible);
loadCheckBox(qcbAbbreviateChannelNames, r.bTalkingUI_AbbreviateChannelNames);
loadCheckBox(qcbAbbreviateCurrentChannel, r.bTalkingUI_AbbreviateCurrentChannel);
loadCheckBox(qcbShowLocalListeners, r.bTalkingUI_ShowLocalListeners);
qsbRelFontSize->setValue(r.iTalkingUI_RelativeFontSize);
qsbSilentUserLifetime->setValue(r.iTalkingUI_SilentUserLifeTime);
qsbChannelHierarchyDepth->setValue(r.iTalkingUI_ChannelHierarchyDepth);
qsbMaxNameLength->setValue(r.iTalkingUI_MaxChannelNameLength);
qsbPrefixCharCount->setValue(r.iTalkingUI_PrefixCharCount);
qsbPostfixCharCount->setValue(r.iTalkingUI_PostfixCharCount);
qleAbbreviationReplacement->setText(r.qsTalkingUI_AbbreviationReplacement);
qleChannelSeparator->setText(r.qsHierarchyChannelSeparator);
loadComboBox(qcbSearchUserAction, static_cast< int >(r.searchUserAction));
loadComboBox(qcbSearchChannelAction, static_cast< int >(r.searchChannelAction));
}
void LookConfig::save() const {
const QString oldLanguage = s.qsLanguage;
if (qcbLanguage->currentIndex() == 0)
s.qsLanguage = QString();
else
s.qsLanguage = qcbLanguage->itemData(qcbLanguage->currentIndex()).toString();
if (s.qsLanguage != oldLanguage) {
s.requireRestartToApply = true;
}
// Save Layout radioboxes state
if (qrbLClassic->isChecked()) {
s.wlWindowLayout = Settings::LayoutClassic;
} else if (qrbLStacked->isChecked()) {
s.wlWindowLayout = Settings::LayoutStacked;
} else if (qrbLHybrid->isChecked()) {
s.wlWindowLayout = Settings::LayoutHybrid;
} else {
s.wlWindowLayout = Settings::LayoutCustom;
}
s.ceExpand = static_cast< Settings::ChannelExpand >(qcbExpand->currentIndex());
s.ceChannelDrag = static_cast< Settings::ChannelDrag >(qcbChannelDrag->currentIndex());
s.ceUserDrag = static_cast< Settings::ChannelDrag >(qcbUserDrag->currentIndex());
if (qcbUsersTop->isChecked() != s.bUserTop) {
s.bUserTop = qcbUsersTop->isChecked();
s.requireRestartToApply = true;
}
s.aotbAlwaysOnTop = static_cast< Settings::AlwaysOnTopBehaviour >(qcbAlwaysOnTop->currentIndex());
s.quitBehavior = static_cast< QuitBehavior >(qcbQuitBehavior->currentIndex());
s.bEnableDeveloperMenu = qcbEnableDeveloperMenu->isChecked();
s.bLockLayout = qcbLockLayout->isChecked();
s.bHideInTray = qcbHideTray->isChecked();
s.bStateInTray = qcbStateInTray->isChecked();
s.bShowUserCount = qcbShowUserCount->isChecked();
s.bShowVolumeAdjustments = qcbShowVolumeAdjustments->isChecked();
s.bShowNicknamesOnly = qcbShowNicknamesOnly->isChecked();
s.bShowContextMenuInMenuBar = qcbShowContextMenuInMenuBar->isChecked();
s.bShowTransmitModeComboBox = qcbShowTransmitModeComboBox->isChecked();
s.bHighContrast = qcbHighContrast->isChecked();
s.bChatBarUseSelection = qcbChatBarUseSelection->isChecked();
s.bFilterHidesEmptyChannels = qcbFilterHidesEmptyChannels->isChecked();
QVariant themeData = qcbTheme->itemData(qcbTheme->currentIndex());
if (themeData.isNull()) {
Themes::setConfiguredStyle(s, boost::none, s.requireRestartToApply);
} else {
Themes::setConfiguredStyle(s, themeData.value< ThemeInfo::StyleInfo >(), s.requireRestartToApply);
}
s.talkingUI_UsersAlwaysVisible = qcbUsersAlwaysVisible->isChecked();
s.bTalkingUI_LocalUserStaysVisible = qcbLocalUserVisible->isChecked();
s.bTalkingUI_AbbreviateChannelNames = qcbAbbreviateChannelNames->isChecked();
s.bTalkingUI_AbbreviateCurrentChannel = qcbAbbreviateCurrentChannel->isChecked();
s.bTalkingUI_ShowLocalListeners = qcbShowLocalListeners->isChecked();
s.iTalkingUI_RelativeFontSize = qsbRelFontSize->value();
s.iTalkingUI_SilentUserLifeTime = qsbSilentUserLifetime->value();
s.iTalkingUI_ChannelHierarchyDepth = qsbChannelHierarchyDepth->value();
s.iTalkingUI_MaxChannelNameLength = qsbMaxNameLength->value();
s.iTalkingUI_PrefixCharCount = qsbPrefixCharCount->value();
s.iTalkingUI_PostfixCharCount = qsbPostfixCharCount->value();
s.qsTalkingUI_AbbreviationReplacement = qleAbbreviationReplacement->text();
s.qsHierarchyChannelSeparator = qleChannelSeparator->text();
s.searchUserAction = static_cast< Search::SearchDialog::UserAction >(qcbSearchUserAction->currentData().toInt());
s.searchChannelAction =
static_cast< Search::SearchDialog::ChannelAction >(qcbSearchChannelAction->currentData().toInt());
}
void LookConfig::accept() const {
Global::get().mw->setShowDockTitleBars((Global::get().s.wlWindowLayout == Settings::LayoutCustom)
&& !Global::get().s.bLockLayout);
}
void LookConfig::themeDirectoryChanged() {
qWarning() << "Theme directory changed";
QVariant themeData = qcbTheme->itemData(qcbTheme->currentIndex());
if (themeData.isNull()) {
reloadThemes(boost::none);
} else {
reloadThemes(themeData.value< ThemeInfo::StyleInfo >());
}
}
void LookConfig::on_qcbAbbreviateChannelNames_stateChanged(int state) {
bool abbreviateNames = state == Qt::Checked;
// Only enable the abbreviation related settings if abbreviation is actually enabled
qcbAbbreviateCurrentChannel->setEnabled(abbreviateNames);
qsbChannelHierarchyDepth->setEnabled(abbreviateNames);
qsbMaxNameLength->setEnabled(abbreviateNames);
qsbPrefixCharCount->setEnabled(abbreviateNames);
qsbPostfixCharCount->setEnabled(abbreviateNames);
qleAbbreviationReplacement->setEnabled(abbreviateNames);
}
void LookConfig::on_qcbUsersAlwaysVisible_stateChanged(int state) {
bool usersAlwaysVisible = state == Qt::Checked;
// Only enable the local user visibility setting when all users are not always visible
qcbLocalUserVisible->setEnabled(!usersAlwaysVisible);
// Only enable the user visibility timeout settings when all users are not always visible
qsbSilentUserLifetime->setEnabled(!usersAlwaysVisible);
}