873 lines
25 KiB
C++
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);
|
|
}
|