mumble-voip_mumble/src/mumble/OverlayConfig.cpp

873 lines
25 KiB
C++

// Copyright 2010-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 "OverlayConfig.h"
#include "Channel.h"
#include "Database.h"
#include "MainWindow.h"
#include "NetworkConfig.h"
#include "Overlay.h"
#include "OverlayPositionableItem.h"
#include "OverlayText.h"
#include "OverlayUserGroup.h"
#include "PathListWidget.h"
#include "Screen.h"
#include "ServerHandler.h"
#include "User.h"
#include "Global.h"
#include "GlobalShortcut.h"
#ifdef Q_OS_WIN
# include "../../overlay/overlay_blacklist.h"
# include "../../overlay/overlay_launchers.h"
# include "../../overlay/overlay_whitelist.h"
#endif
#include <QSettings>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#include <QtWidgets/QColorDialog>
#include <QtWidgets/QDesktopWidget>
#include <QtWidgets/QFileDialog>
#include <QtWidgets/QFontDialog>
const QString OverlayConfig::name = QLatin1String("OverlayConfig");
static const int OVERLAYCONFIG_PATH_ROLE = Qt::UserRole;
static const int OVERLAYCONFIG_BUILTIN_ROLE = Qt::UserRole + 1;
// Hide overlay config for Mac OS X universal builds
#if !defined(USE_MAC_UNIVERSAL)
static ConfigWidget *OverlayConfigDialogNew(Settings &st) {
return new OverlayConfig(st);
}
static ConfigRegistrar registrarOverlayConfig(6000, OverlayConfigDialogNew);
#endif
void OverlayConfig::initDisplayFps() {
// set up FPS preview
qgsFpsPreview.clear();
qgsFpsPreview.setBackgroundBrush(qgvFpsPreview->backgroundBrush());
qgpiFpsDemo = new QGraphicsPixmapItem();
refreshFpsDemo();
qgsFpsPreview.addItem(qgpiFpsDemo);
qgpiFpsDemo->show();
qgvFpsPreview->setScene(&qgsFpsPreview);
qgvFpsPreview->centerOn(qgpiFpsDemo);
qgpiFpsLive = new OverlayPositionableItem(&s.os.qrfFps, true);
qgpiFpsLive->setZValue(-2.0f);
refreshFpsLive();
}
void OverlayConfig::initDisplayClock() {
qgpiTimeLive = new OverlayPositionableItem(&s.os.qrfTime, true);
qgpiTimeLive->setZValue(-2.0f);
refreshTimeLive();
}
void OverlayConfig::initDisplay() {
// set up overlay preview
qgpiScreen = new QGraphicsPixmapItem();
qgpiScreen->setPixmap(qpScreen);
qgpiScreen->setOpacity(0.5f);
qgpiScreen->setZValue(-10.0f);
initDisplayFps();
initDisplayClock();
qgtiInstructions = new QGraphicsTextItem();
qgtiInstructions->setHtml(QString::fromLatin1("<ul><li>%1</li><li>%2</li><li>%3</li></ul>")
.arg(tr("To move the users, drag the little red dot."),
tr("To resize the users, mouse wheel over a user."),
tr("For more options, right click a user.")));
qgtiInstructions->setOpacity(1.0f);
qgtiInstructions->setZValue(-5.0f);
qgtiInstructions->setDefaultTextColor(Qt::white);
qgs.clear();
qgs.setSceneRect(QRectF(0, 0, qgpiScreen->pixmap().width(), qgpiScreen->pixmap().height()));
qgs.setBackgroundBrush(qgvView->backgroundBrush());
qgs.addItem(qgpiScreen);
qgpiScreen->show();
qgs.addItem(qgpiFpsLive);
qgpiFpsLive->show();
qgs.addItem(qgpiTimeLive);
qgpiTimeLive->show();
oug = new OverlayUserGroup(&s.os);
oug->bShowExamples = true;
qgs.addItem(oug);
oug->show();
qgs.addItem(qgtiInstructions);
qgtiInstructions->show();
qgvView->setScene(&qgs);
qgvView->installEventFilter(this);
}
void OverlayConfig::refreshFpsDemo() {
bpFpsDemo = OverlayTextLine(QString::fromLatin1("%1").arg(42), s.os.qfFps).createPixmap(s.os.qcFps);
qgpiFpsDemo->setPixmap(bpFpsDemo);
qgvFpsPreview->centerOn(qgpiFpsDemo);
}
void OverlayConfig::refreshFpsLive() {
if (s.os.bFps) {
qgpiFpsLive->setPixmap(bpFpsDemo.scaled(bpFpsDemo.size() * fViewScale));
qgpiFpsLive->setOffset((-bpFpsDemo.qpBasePoint + QPoint(0, bpFpsDemo.iAscent)) * fViewScale);
} else {
qgpiFpsLive->setPixmap(QPixmap());
}
qgpiFpsLive->setItemVisible(s.os.bFps);
}
void OverlayConfig::refreshTimeLive() {
if (s.os.bTime) {
bpTimeDemo = OverlayTextLine(QString::fromLatin1("%1").arg(QTime::currentTime().toString()), s.os.qfFps)
.createPixmap(s.os.qcFps);
qgpiTimeLive->setPixmap(bpTimeDemo.scaled(bpTimeDemo.size() * fViewScale));
qgpiTimeLive->setOffset((-bpTimeDemo.qpBasePoint + QPoint(0, bpTimeDemo.iAscent)) * fViewScale);
} else {
qgpiTimeLive->setPixmap(QPixmap());
}
qgpiTimeLive->setItemVisible(s.os.bTime);
}
OverlayConfig::OverlayConfig(Settings &st)
: ConfigWidget(st), qgpiScreen(nullptr), qgs(), qgsFpsPreview(), qgpiFpsDemo(nullptr), oug(nullptr),
qgtiInstructions(nullptr), fViewScale(1.0f) {
setupUi(this);
qlwPaths->setPathType(PathListWidget::FOLDER);
qcbOverlayExclusionMode->insertItem(static_cast< int >(OverlaySettings::LauncherFilterExclusionMode),
tr("Launcher Filter"));
qcbOverlayExclusionMode->insertItem(static_cast< int >(OverlaySettings::WhitelistExclusionMode), tr("Whitelist"));
qcbOverlayExclusionMode->insertItem(static_cast< int >(OverlaySettings::BlacklistExclusionMode), tr("Blacklist"));
qcbOverlayExclusionMode->setCurrentIndex(static_cast< int >(OverlaySettings::LauncherFilterExclusionMode));
if (!isInstalled()) {
qswOverlayPage->setCurrentWidget(qwOverlayInstall);
} else if (needsUpgrade()) {
qswOverlayPage->setCurrentWidget(qwOverlayUpgrade);
} else {
qswOverlayPage->setCurrentWidget(qwOverlayConfig);
qpbUninstall->setVisible(supportsInstallableOverlay());
}
// Grab a desktop screenshot as background
QScreen *screen = qApp->primaryScreen();
if (const QWindow *window = windowHandle()) {
screen = window->screen();
}
// From Qt's documentation (Qt Widgets screenshot example):
// "Although this is unlikely to happen, applications should check for null
// pointers since there might be situations in which no screen is connected."
if (screen) {
qpScreen = screen->grabWindow(0);
}
if (qpScreen.size().isEmpty()) {
qWarning() << __FUNCTION__ << "failed to grab screenshot, falling back.";
if (screen) {
const QRect desktopSize = screen->geometry();
qpScreen = QPixmap(desktopSize.width(), desktopSize.height());
} else {
qpScreen = QPixmap(1280, 720);
}
qpScreen.fill(Qt::darkGreen);
}
initDisplay();
// Attach the upgrade button to the install click handler. Currently, the
// actions they perform are the same. The distinction is only there to inform
// users as to what's actually going on.
connect(qpbUpgrade, SIGNAL(clicked()), this, SLOT(on_qpbInstall_clicked()));
}
void OverlayConfig::updateOverlayExclusionModeState() {
OverlaySettings::OverlayExclusionMode exclusionMode =
static_cast< OverlaySettings::OverlayExclusionMode >(qcbOverlayExclusionMode->currentIndex());
switch (exclusionMode) {
case OverlaySettings::LauncherFilterExclusionMode:
qwLaunchers->setHidden(false);
qwWhitelist->setHidden(false);
qwPaths->setHidden(false);
qwBlacklist->setHidden(false);
// Show all whitelist items (including built-in items)
// in launcher filter mode.
for (int i = 0; i < qlwWhitelist->count(); i++) {
QListWidgetItem *item = qlwWhitelist->item(i);
item->setHidden(false);
}
break;
case OverlaySettings::WhitelistExclusionMode:
qwLaunchers->setHidden(true);
qwWhitelist->setHidden(false);
qwPaths->setHidden(true);
qwBlacklist->setHidden(true);
// Hide the built-in items when in WhitelistExclusionMode.
// They are only considered in launcher filter mode.
for (int i = 0; i < qlwWhitelist->count(); i++) {
QListWidgetItem *item = qlwWhitelist->item(i);
bool isBuiltin = item->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool();
if (isBuiltin) {
item->setHidden(true);
} else {
item->setHidden(false);
}
}
break;
case OverlaySettings::BlacklistExclusionMode:
qwLaunchers->setHidden(true);
qwWhitelist->setHidden(true);
qwPaths->setHidden(true);
qwBlacklist->setHidden(false);
break;
}
}
void OverlayConfig::load(const Settings &r) {
s.os = r.os;
loadCheckBox(qcbEnable, s.os.bEnable);
qcbShowFps->setChecked(s.os.bFps);
qcbShowTime->setChecked(s.os.bTime);
qgpFps->setEnabled(s.os.bEnable);
qcbOverlayExclusionMode->setCurrentIndex(static_cast< int >(s.os.oemOverlayExcludeMode));
// Launchers
{
qlwLaunchers->clear();
QStringList builtinLaunchers;
#ifdef Q_OS_WIN
int i = 0;
while (overlayLaunchers[i]) {
QString str = QLatin1String(overlayLaunchers[i]);
builtinLaunchers << str;
++i;
}
#endif
foreach (QString str, builtinLaunchers) {
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(str);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, qlwLaunchers);
qlwiApplication->setData(OVERLAYCONFIG_PATH_ROLE, QVariant(str));
qlwiApplication->setData(OVERLAYCONFIG_BUILTIN_ROLE, QVariant(true));
// Use italic for 'default' items.
QFont font = qlwiApplication->font();
font.setItalic(true);
qlwiApplication->setFont(font);
qlwiApplication->setFlags(qlwiApplication->flags() | Qt::ItemIsUserCheckable);
if (s.os.qslLaunchersExclude.contains(str)) {
qlwiApplication->setCheckState(Qt::Unchecked);
} else {
qlwiApplication->setCheckState(Qt::Checked);
}
}
foreach (QString str, s.os.qslLaunchers) {
if (builtinLaunchers.contains(str)) {
continue;
}
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(str);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, qlwLaunchers);
qlwiApplication->setData(OVERLAYCONFIG_PATH_ROLE, QVariant(str));
qlwiApplication->setData(OVERLAYCONFIG_BUILTIN_ROLE, QVariant(false));
}
}
// Whitelist
{
qlwWhitelist->clear();
QStringList builtinWhitelist;
#ifdef Q_OS_WIN
int i = 0;
while (overlayWhitelist[i]) {
QString str = QLatin1String(overlayWhitelist[i]);
builtinWhitelist << str;
++i;
}
#endif
foreach (QString str, builtinWhitelist) {
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(str);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, qlwWhitelist);
qlwiApplication->setData(OVERLAYCONFIG_PATH_ROLE, QVariant(str));
qlwiApplication->setData(OVERLAYCONFIG_BUILTIN_ROLE, QVariant(true));
// Use italic for 'default' items.
QFont font = qlwiApplication->font();
font.setItalic(true);
qlwiApplication->setFont(font);
qlwiApplication->setFlags(qlwiApplication->flags() | Qt::ItemIsUserCheckable);
if (s.os.qslWhitelistExclude.contains(str)) {
qlwiApplication->setCheckState(Qt::Unchecked);
} else {
qlwiApplication->setCheckState(Qt::Checked);
}
}
foreach (QString str, s.os.qslWhitelist) {
if (builtinWhitelist.contains(str)) {
continue;
}
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(str);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, qlwWhitelist);
qlwiApplication->setData(OVERLAYCONFIG_PATH_ROLE, QVariant(str));
qlwiApplication->setData(OVERLAYCONFIG_BUILTIN_ROLE, QVariant(false));
}
}
// Paths
{
qlwPaths->clear();
foreach (QString str, s.os.qslPaths) {
QListWidgetItem *qlwiApplication = new QListWidgetItem(QIcon(), str, qlwPaths);
qlwiApplication->setData(OVERLAYCONFIG_PATH_ROLE, QVariant(str));
qlwiApplication->setData(OVERLAYCONFIG_BUILTIN_ROLE, QVariant(false));
}
}
// Blacklist
{
qlwBlacklist->clear();
QStringList builtinBlacklist;
#ifdef Q_OS_WIN
int i = 0;
while (overlayBlacklist[i]) {
QString str = QLatin1String(overlayBlacklist[i]);
builtinBlacklist << str;
++i;
}
#endif
foreach (QString str, builtinBlacklist) {
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(str);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, qlwBlacklist);
qlwiApplication->setData(OVERLAYCONFIG_PATH_ROLE, QVariant(str));
qlwiApplication->setData(OVERLAYCONFIG_BUILTIN_ROLE, QVariant(true));
// Use italic for 'default' items.
QFont font = qlwiApplication->font();
font.setItalic(true);
qlwiApplication->setFont(font);
qlwiApplication->setFlags(qlwiApplication->flags() | Qt::ItemIsUserCheckable);
if (s.os.qslBlacklistExclude.contains(str)) {
qlwiApplication->setCheckState(Qt::Unchecked);
} else {
qlwiApplication->setCheckState(Qt::Checked);
}
}
foreach (QString str, s.os.qslBlacklist) {
if (builtinBlacklist.contains(str)) {
continue;
}
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(str);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, qlwBlacklist);
qlwiApplication->setData(OVERLAYCONFIG_PATH_ROLE, QVariant(str));
qlwiApplication->setData(OVERLAYCONFIG_BUILTIN_ROLE, QVariant(false));
}
}
initDisplay();
resizeScene(true);
update();
}
QString OverlayConfig::title() const {
return tr("Overlay");
}
const QString &OverlayConfig::getName() const {
return OverlayConfig::name;
}
QIcon OverlayConfig::icon() const {
return QIcon(QLatin1String("skin:config_osd.png"));
}
void OverlayConfig::save() const {
s.os.bEnable = qcbEnable->isChecked();
s.os.bFps = qcbShowFps->isChecked();
s.os.bTime = qcbShowTime->isChecked();
s.os.oemOverlayExcludeMode =
static_cast< OverlaySettings::OverlayExclusionMode >(qcbOverlayExclusionMode->currentIndex());
// Launchers
{
s.os.qslLaunchers.clear();
s.os.qslLaunchersExclude.clear();
for (int i = 0; i < qlwLaunchers->count(); i++) {
bool isBuiltin = (qlwLaunchers->item(i)->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool());
bool isChecked = false;
if (isBuiltin) {
isChecked = qlwLaunchers->item(i)->checkState() == Qt::Checked;
}
QString str = qlwLaunchers->item(i)->data(OVERLAYCONFIG_PATH_ROLE).toString();
if (isBuiltin) {
if (!isChecked) {
s.os.qslLaunchersExclude << str;
}
} else {
s.os.qslLaunchers << str;
}
}
}
// Whitelist
{
s.os.qslWhitelist.clear();
s.os.qslWhitelistExclude.clear();
for (int i = 0; i < qlwWhitelist->count(); i++) {
bool isBuiltin = (qlwWhitelist->item(i)->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool());
bool isChecked = false;
if (isBuiltin) {
isChecked = qlwWhitelist->item(i)->checkState() == Qt::Checked;
}
QString str = qlwWhitelist->item(i)->data(OVERLAYCONFIG_PATH_ROLE).toString();
if (isBuiltin) {
if (!isChecked) {
s.os.qslWhitelistExclude << str;
}
} else {
s.os.qslWhitelist << str;
}
}
}
// Paths
{
s.os.qslPaths.clear();
s.os.qslPathsExclude.clear();
for (int i = 0; i < qlwPaths->count(); i++) {
bool isBuiltin = (qlwPaths->item(i)->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool());
bool isChecked = false;
if (isBuiltin) {
isChecked = qlwPaths->item(i)->checkState() == Qt::Checked;
}
QString str = qlwPaths->item(i)->data(OVERLAYCONFIG_PATH_ROLE).toString();
if (isBuiltin) {
if (!isChecked) {
s.os.qslPathsExclude << str;
}
} else {
s.os.qslPaths << str;
}
}
}
// Blacklist
{
s.os.qslBlacklist.clear();
s.os.qslBlacklistExclude.clear();
for (int i = 0; i < qlwBlacklist->count(); i++) {
bool isBuiltin = (qlwBlacklist->item(i)->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool());
bool isChecked = false;
if (isBuiltin) {
isChecked = qlwBlacklist->item(i)->checkState() == Qt::Checked;
}
QString str = qlwBlacklist->item(i)->data(OVERLAYCONFIG_PATH_ROLE).toString();
if (isBuiltin) {
if (!isChecked) {
s.os.qslBlacklistExclude << str;
}
} else {
s.os.qslBlacklist << str;
}
}
}
}
void OverlayConfig::accept() const {
Global::get().o->forceSettings();
Global::get().o->setActive(s.os.bEnable);
}
bool OverlayConfig::eventFilter(QObject *obj, QEvent *evt) {
if (evt->type() == QEvent::Resize)
QMetaObject::invokeMethod(this, "resizeScene", Qt::QueuedConnection);
return ConfigWidget::eventFilter(obj, evt);
}
void OverlayConfig::resizeScene(bool force) {
QSize sz = qgvView->viewport()->size();
int ph = qgpiScreen->pixmap().height();
int pw = qgpiScreen->pixmap().width();
if (!force && ((ph == sz.height() && pw <= sz.width()) || (ph <= sz.height() && pw == sz.width()))) {
return;
}
qgpiScreen->setPixmap(qpScreen.scaled(sz, Qt::KeepAspectRatio, Qt::SmoothTransformation));
qgs.setSceneRect(QRectF(0, 0, qgpiScreen->pixmap().width(), qgpiScreen->pixmap().height()));
fViewScale = static_cast< float >(qgpiScreen->pixmap().height()) / static_cast< float >(qpScreen.height());
refreshFpsLive();
refreshTimeLive();
QFont f = qgtiInstructions->font();
f.setPointSizeF(qgs.sceneRect().height() / 20.0f);
qgtiInstructions->setFont(f);
qgtiInstructions->setPos(qgs.sceneRect().width() / 20.0f, qgs.sceneRect().height() / 10.0f);
qgtiInstructions->setTextWidth(qgs.sceneRect().width() * 18.0f / 20.0f);
qgvView->fitInView(qgs.sceneRect(), Qt::KeepAspectRatio);
oug->updateLayout();
oug->updateUsers();
qgpiFpsLive->updateRender();
qgpiTimeLive->updateRender();
}
void OverlayConfig::on_qlwLaunchers_itemSelectionChanged() {
QList< QListWidgetItem * > items = qlwLaunchers->selectedItems();
if (items.isEmpty()) {
qpbLaunchersRemove->setEnabled(false);
return;
}
QListWidgetItem *item = items.at(0);
bool isBuiltin = item->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool();
if (isBuiltin) {
qpbLaunchersRemove->setEnabled(false);
} else {
qpbLaunchersRemove->setEnabled(true);
}
}
void OverlayConfig::on_qcbOverlayExclusionMode_currentIndexChanged(int) {
updateOverlayExclusionModeState();
}
void OverlayConfig::on_qpbLaunchersAdd_clicked() {
#if defined(Q_OS_WIN)
QString file = QFileDialog::getOpenFileName(this, tr("Choose executable"), QString(), QLatin1String("*.exe"));
#elif defined(Q_OS_MAC)
QString file = QFileDialog::getOpenFileName(this, tr("Choose application"), QString(), QLatin1String("*.app"));
#else
QString file = QString();
#endif
if (!file.isEmpty()) {
QString qsAppIdentifier = OverlayAppInfo::applicationIdentifierForPath(file);
QStringList qslIdentifiers;
for (int i = 0; i < qlwLaunchers->count(); i++)
qslIdentifiers << qlwLaunchers->item(i)->data(Qt::UserRole).toString();
if (!qslIdentifiers.contains(qsAppIdentifier)) {
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(qsAppIdentifier);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, qlwLaunchers);
qlwiApplication->setData(Qt::UserRole, QVariant(qsAppIdentifier));
qlwLaunchers->setCurrentItem(qlwiApplication);
}
}
}
void OverlayConfig::on_qpbLaunchersRemove_clicked() {
int row = qlwLaunchers->currentRow();
if (row != -1)
delete qlwLaunchers->takeItem(row);
}
void OverlayConfig::on_qlwWhitelist_itemSelectionChanged() {
QList< QListWidgetItem * > items = qlwWhitelist->selectedItems();
if (items.isEmpty()) {
qpbWhitelistRemove->setEnabled(false);
return;
}
QListWidgetItem *item = items.at(0);
bool isBuiltin = item->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool();
if (isBuiltin) {
qpbWhitelistRemove->setEnabled(false);
} else {
qpbWhitelistRemove->setEnabled(true);
}
}
void OverlayConfig::addWhitelistPath(const QString &path) {
QString qsAppIdentifier = OverlayAppInfo::applicationIdentifierForPath(path);
QListWidget *sel = qlwWhitelist;
QStringList qslIdentifiers;
for (int i = 0; i < sel->count(); i++)
qslIdentifiers << sel->item(i)->data(Qt::UserRole).toString();
if (!qslIdentifiers.contains(qsAppIdentifier)) {
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(qsAppIdentifier);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, sel);
qlwiApplication->setData(Qt::UserRole, QVariant(qsAppIdentifier));
sel->setCurrentItem(qlwiApplication);
}
}
void OverlayConfig::on_qpbWhitelistAdd_clicked() {
#if defined(Q_OS_WIN)
QString file = QFileDialog::getOpenFileName(this, tr("Choose executable"), QString(), QLatin1String("*.exe"));
#elif defined(Q_OS_MAC)
QString file = QFileDialog::getOpenFileName(this, tr("Choose application"), QString(), QLatin1String("*.app"));
#else
QString file = QString();
#endif
if (!file.isEmpty()) {
addWhitelistPath(file);
}
}
void OverlayConfig::on_qpbWhitelistRemove_clicked() {
QListWidget *sel = qlwWhitelist;
int row = sel->currentRow();
if (row != -1)
delete sel->takeItem(row);
}
void OverlayConfig::on_qlwPaths_itemSelectionChanged() {
QList< QListWidgetItem * > items = qlwPaths->selectedItems();
if (items.isEmpty()) {
qpbPathsRemove->setEnabled(false);
return;
}
QListWidgetItem *item = items.at(0);
bool isBuiltin = item->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool();
if (isBuiltin) {
qpbPathsRemove->setEnabled(false);
} else {
qpbPathsRemove->setEnabled(true);
}
}
void OverlayConfig::on_qpbPathsAdd_clicked() {
QString existingPath = QFileDialog::getExistingDirectory(this, tr("Choose path"));
QString dir = QDir::toNativeSeparators(existingPath);
QListWidget *sel = qlwPaths;
QStringList qslIdentifiers;
for (int i = 0; i < sel->count(); i++)
qslIdentifiers << sel->item(i)->data(Qt::UserRole).toString();
if (!dir.isEmpty() && !qslIdentifiers.contains(dir)) {
QListWidgetItem *qlwiPath = new QListWidgetItem(QIcon(), dir, sel);
qlwiPath->setData(Qt::UserRole, QVariant(dir));
sel->setCurrentItem(qlwiPath);
}
}
void OverlayConfig::on_qpbPathsRemove_clicked() {
int row = qlwPaths->currentRow();
if (row != -1)
delete qlwPaths->takeItem(row);
}
void OverlayConfig::on_qlwBlacklist_itemSelectionChanged() {
QList< QListWidgetItem * > items = qlwBlacklist->selectedItems();
if (items.isEmpty()) {
qpbBlacklistRemove->setEnabled(false);
return;
}
QListWidgetItem *item = items.at(0);
bool isBuiltin = item->data(OVERLAYCONFIG_BUILTIN_ROLE).toBool();
if (isBuiltin) {
qpbBlacklistRemove->setEnabled(false);
} else {
qpbBlacklistRemove->setEnabled(true);
}
}
void OverlayConfig::on_qpbBlacklistAdd_clicked() {
#if defined(Q_OS_WIN)
QString file = QFileDialog::getOpenFileName(this, tr("Choose executable"), QString(), QLatin1String("*.exe"));
#elif defined(Q_OS_MAC)
QString file = QFileDialog::getOpenFileName(this, tr("Choose application"), QString(), QLatin1String("*.app"));
#else
QString file = QString();
#endif
if (!file.isEmpty()) {
QString qsAppIdentifier = OverlayAppInfo::applicationIdentifierForPath(file);
QListWidget *sel = qlwBlacklist;
QStringList qslIdentifiers;
for (int i = 0; i < sel->count(); i++)
qslIdentifiers << sel->item(i)->data(Qt::UserRole).toString();
if (!qslIdentifiers.contains(qsAppIdentifier)) {
OverlayAppInfo oai = OverlayAppInfo::applicationInfoForId(qsAppIdentifier);
QListWidgetItem *qlwiApplication = new QListWidgetItem(oai.qiIcon, oai.qsDisplayName, sel);
qlwiApplication->setData(Qt::UserRole, QVariant(qsAppIdentifier));
sel->setCurrentItem(qlwiApplication);
}
}
}
void OverlayConfig::on_qpbBlacklistRemove_clicked() {
QListWidget *sel = qlwBlacklist;
int row = sel->currentRow();
if (row != -1)
delete sel->takeItem(row);
}
void OverlayConfig::on_qcbEnable_stateChanged(int state) {
qgpFps->setEnabled(state == Qt::Checked);
}
void OverlayConfig::on_qpbInstall_clicked() {
qpbInstall->setEnabled(false);
if (installFiles()) {
qswOverlayPage->setCurrentWidget(qwOverlayConfig);
}
qpbInstall->setEnabled(true);
}
void OverlayConfig::on_qpbUninstall_clicked() {
qpbUninstall->setEnabled(false);
if (uninstallFiles()) {
qswOverlayPage->setCurrentWidget(qwOverlayInstall);
}
qpbUninstall->setEnabled(true);
}
void OverlayConfig::on_qcbShowFps_stateChanged(int state) {
Q_UNUSED(state);
s.os.bFps = qcbShowFps->isChecked();
refreshFpsLive();
}
void OverlayConfig::on_qcbShowTime_stateChanged(int state) {
Q_UNUSED(state);
s.os.bTime = qcbShowTime->isChecked();
refreshTimeLive();
}
void OverlayConfig::on_qpbFpsFont_clicked() {
bool ok;
QFont new_font = QFontDialog::getFont(&ok, s.os.qfFps);
if (ok) {
s.os.qfFps = new_font;
refreshFpsDemo();
refreshFpsLive();
refreshTimeLive();
}
}
void OverlayConfig::on_qpbFpsColor_clicked() {
QColor color = QColorDialog::getColor(s.os.qcFps);
if (color.isValid()) {
s.os.qcFps = color;
refreshFpsDemo();
refreshFpsLive();
refreshTimeLive();
}
}
void OverlayConfig::on_qpbLoadPreset_clicked() {
QString fn = QFileDialog::getOpenFileName(this, tr("Load Overlay Presets"), QDir::homePath(),
tr("Mumble overlay presets (*.mumblelay)"));
if (fn.isEmpty()) {
return;
}
OverlaySettings load_preset;
try {
// First try regular format
load_preset.load(fn);
} catch (const std::exception &) {
// If that fails, fall back to the legacy format
QSettings qs(fn, QSettings::IniFormat);
qs.beginGroup(QLatin1String("overlay"));
load_preset.legacyLoad(&qs);
qs.endGroup();
}
#ifdef Q_OS_WIN
load_preset.qslLaunchers = s.os.qslLaunchers;
load_preset.qslLaunchersExclude = s.os.qslLaunchersExclude;
load_preset.qslWhitelist = s.os.qslWhitelist;
load_preset.qslWhitelistExclude = s.os.qslWhitelistExclude;
load_preset.qslPaths = s.os.qslPaths;
load_preset.qslPathsExclude = s.os.qslPathsExclude;
load_preset.qslBlacklist = s.os.qslBlacklist;
load_preset.qslBlacklistExclude = s.os.qslBlacklistExclude;
#endif
load_preset.bEnable = s.os.bEnable;
s.os = load_preset;
load(s);
}
void OverlayConfig::on_qpbSavePreset_clicked() {
QString fn = QFileDialog::getSaveFileName(this, tr("Save Overlay Presets"), QDir::homePath(),
tr("Mumble overlay presets (*.mumblelay)"));
if (fn.isEmpty()) {
return;
}
s.os.savePresets(fn);
}