Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Q scale factor from preferences #3960

Merged
merged 15 commits into from
Sep 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <QThread>
#include <QtDebug>

#include "config.h"
#include "coreservices.h"
#include "errordialoghandler.h"
#include "mixxxapplication.h"
Expand All @@ -22,6 +23,10 @@ namespace {
constexpr int kFatalErrorOnStartupExitCode = 1;
constexpr int kParseCmdlineArgsErrorExitCode = 2;

constexpr char kScaleFactorEnvVar[] = "QT_SCALE_FACTOR";
const QString kConfigGroup = QStringLiteral("[Config]");
const QString kScaleFactorKey = QStringLiteral("ScaleFactor");

int runMixxx(MixxxApplication* pApp, const CmdlineArgs& args) {
const auto pCoreServices = std::make_shared<mixxx::CoreServices>(args, pApp);

Expand All @@ -48,6 +53,37 @@ int runMixxx(MixxxApplication* pApp, const CmdlineArgs& args) {
}
}

void adjustScaleFactor(CmdlineArgs* pArgs) {
if (qEnvironmentVariableIsSet(kScaleFactorEnvVar)) {
bool ok;
const double f = qgetenv(kScaleFactorEnvVar).toDouble(&ok);
if (ok && f > 0) {
// The environment variable overrides the preferences option
qDebug() << "Using" << kScaleFactorEnvVar << f;
pArgs->setScaleFactor(f);
return;
}
}
// We cannot use SettingsManager, because it depends on MixxxApplication
// but the scale factor is read during it's constructor.
// QHighDpiScaling can not be used afterwards because it is private.
// This means the following code may fail after down/upgrade ... a one time issue.

// Read and parse the config file from the settings path
auto config = ConfigObject<ConfigValue>(
QDir(pArgs->getSettingsPath()).filePath(MIXXX_SETTINGS_FILE),
QString(),
QString());
QString strScaleFactor = config.getValue(
ConfigKey(kConfigGroup, kScaleFactorKey));
double scaleFactor = strScaleFactor.toDouble();
if (scaleFactor > 0) {
qDebug() << "Using preferences ScaleFactor" << scaleFactor;
qputenv(kScaleFactorEnvVar, strScaleFactor.toLocal8Bit());
pArgs->setScaleFactor(scaleFactor);
}
}

} // anonymous namespace

int main(int argc, char * argv[]) {
Expand Down Expand Up @@ -99,6 +135,8 @@ int main(int argc, char * argv[]) {
Sandbox::checkSandboxed();
#endif

adjustScaleFactor(&args);

MixxxApplication app(argc, argv);

#ifdef __APPLE__
Expand Down
16 changes: 13 additions & 3 deletions src/preferences/configobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,19 @@ ConfigValueKbd::ConfigValueKbd(const QKeySequence& keys)
QTextStream(&value) << m_keys.toString();
}

template <class ValueType> ConfigObject<ValueType>::ConfigObject(const QString& file)
: m_resourcePath(computeResourcePath()),
m_settingsPath(computeSettingsPath(file)) {
template<class ValueType>
ConfigObject<ValueType>::ConfigObject(const QString& file)
: ConfigObject(file, computeResourcePath(), computeSettingsPath(file)) {
reopen(file);
}

template<class ValueType>
ConfigObject<ValueType>::ConfigObject(
const QString& file,
const QString& resourcePath,
const QString& settingsPath)
: m_resourcePath(resourcePath),
m_settingsPath(settingsPath) {
reopen(file);
}

Expand Down
1 change: 1 addition & 0 deletions src/preferences/configobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ inline bool operator!=(const ConfigValueKbd& lhs, const ConfigValueKbd& rhs) {
template <class ValueType> class ConfigObject {
public:
ConfigObject(const QString& file);
ConfigObject(const QString& file, const QString& resourcePath, const QString& settingsPath);
ConfigObject(const QDomNode& node);
~ConfigObject();

Expand Down
109 changes: 48 additions & 61 deletions src/preferences/dialog/dlgprefinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,19 @@
using mixxx::skin::SkinManifest;
using mixxx::skin::SkinPointer;

namespace {

const QString kConfigGroup = QStringLiteral("[Config]");
const QString kControlsGroup = QStringLiteral("[Controls]");
const QString kScaleFactorKey = QStringLiteral("ScaleFactor");
const QString kStartInFullscreenKey = QStringLiteral("StartInFullscreen");
const QString kSchemeKey = QStringLiteral("Scheme");
const QString kResizableSkinKey = QStringLiteral("ResizableSkin");
const QString kLocaleKey = QStringLiteral("Locale");
const QString kTooltipsKey = QStringLiteral("Tooltips");

} // namespace

DlgPrefInterface::DlgPrefInterface(
QWidget* parent,
std::shared_ptr<mixxx::ScreensaverManager> pScreensaverManager,
Expand All @@ -34,9 +47,8 @@ DlgPrefInterface::DlgPrefInterface(
m_pScreensaverManager(pScreensaverManager),
m_pSkinLoader(pSkinLoader),
m_pSkin(pSkinLoader->getConfiguredSkin()),
m_dScaleFactorAuto(1.0),
m_bUseAutoScaleFactor(false),
m_dScaleFactor(1.0),
m_minScaleFactor(1.0),
m_dDevicePixelRatio(1.0),
m_bStartWithFullScreen(false),
m_bRebootMixxxView(false) {
Expand All @@ -45,6 +57,16 @@ DlgPrefInterface::DlgPrefInterface(
// get the pixel ratio to display a crisp skin preview when Mixxx is scaled
m_dDevicePixelRatio = getDevicePixelRatioF(this);

// Calculate the minimum scale factor that leads to a device pixel ratio of 1.0
// m_dDevicePixelRatio must not drop below 1.0 because this creates an
// unusable GUI with visual artefacts
double initialScaleFactor = CmdlineArgs::Instance().getScaleFactor();
if (initialScaleFactor <= 0) {
initialScaleFactor = 1.0;
}
double unscaledDevicePixelRatio = m_dDevicePixelRatio / initialScaleFactor;
m_minScaleFactor = 1 / unscaledDevicePixelRatio;

VERIFY_OR_DEBUG_ASSERT(m_pSkin != nullptr) {
qWarning() << "Skipping creation of DlgPrefInterface because there is no skin available.";
return;
Expand Down Expand Up @@ -149,13 +171,9 @@ DlgPrefInterface::DlgPrefInterface(
this,
&DlgPrefInterface::slotSetScheme);

checkBoxScaleFactorAuto->hide();
spinBoxScaleFactor->hide();
labelScaleFactor->hide();

// Start in fullscreen mode
checkBoxStartFullScreen->setChecked(m_pConfig->getValueString(
ConfigKey("[Config]", "StartInFullscreen")).toInt()==1);
checkBoxStartFullScreen->setChecked(
m_pConfig->getValue(ConfigKey(kConfigGroup, kStartInFullscreenKey), 0) == 1);

// Screensaver mode
comboBoxScreensaver->clear();
Expand Down Expand Up @@ -211,7 +229,7 @@ void DlgPrefInterface::slotUpdateSchemes() {
m_colorScheme = QString();
} else {
ComboBoxSchemeconf->setEnabled(true);
QString configScheme = m_pConfig->getValueString(ConfigKey("[Config]", "Scheme"));
QString configScheme = m_pConfig->getValue(ConfigKey(kConfigGroup, kSchemeKey));
bool foundConfigScheme = false;
for (int i = 0; i < schlist.size(); i++) {
ComboBoxSchemeconf->addItem(schlist[i]);
Expand All @@ -234,7 +252,7 @@ void DlgPrefInterface::slotUpdateSchemes() {

void DlgPrefInterface::slotUpdate() {
const QString skinNameOnUpdate =
m_pConfig->getValueString(ConfigKey("[Config]", "ResizableSkin"));
m_pConfig->getValue(ConfigKey(kConfigGroup, kResizableSkinKey));
const SkinPointer pSkinOnUpdate = m_skins[skinNameOnUpdate];
if (pSkinOnUpdate != nullptr && pSkinOnUpdate->isValid()) {
m_skinNameOnUpdate = pSkinOnUpdate->name();
Expand All @@ -245,19 +263,18 @@ void DlgPrefInterface::slotUpdate() {
slotUpdateSchemes();
m_bRebootMixxxView = false;

m_localeOnUpdate = m_pConfig->getValueString(ConfigKey("[Config]", "Locale"));
m_localeOnUpdate = m_pConfig->getValue(ConfigKey(kConfigGroup, kLocaleKey));
ComboBoxLocale->setCurrentIndex(ComboBoxLocale->findData(m_localeOnUpdate));

checkBoxScaleFactorAuto->setChecked(m_pConfig->getValue(
ConfigKey("[Config]", "ScaleFactorAuto"), m_bUseAutoScaleFactor));

// The spinbox shows a percentage but Mixxx stores a multiplication factor
// with 1.00 as no scaling, so multiply the stored value by 100.
spinBoxScaleFactor->setValue(m_pConfig->getValue(
ConfigKey("[Config]", "ScaleFactor"), m_dScaleFactor) * 100);
double configScaleFactor = m_pConfig->getValue(
ConfigKey(kConfigGroup, kScaleFactorKey), m_dScaleFactor);
spinBoxScaleFactor->setValue(configScaleFactor * 100);
spinBoxScaleFactor->setMinimum(m_minScaleFactor * 100);

checkBoxStartFullScreen->setChecked(m_pConfig->getValue(
ConfigKey("[Config]", "StartInFullscreen"), m_bStartWithFullScreen));
ConfigKey(kConfigGroup, kStartInFullscreenKey), m_bStartWithFullScreen));

loadTooltipPreferenceFromConfig();

Expand All @@ -276,9 +293,6 @@ void DlgPrefInterface::slotResetToDefaults() {
// Default to normal size widgets
// The spinbox shows a percentage with 100% as no scaling.
spinBoxScaleFactor->setValue(100);
if (m_dScaleFactorAuto > 0) {
checkBoxScaleFactorAuto->setChecked(true);
}

// Don't start in full screen.
checkBoxStartFullScreen->setChecked(false);
Expand All @@ -291,29 +305,6 @@ void DlgPrefInterface::slotResetToDefaults() {
radioButtonTooltipsLibraryAndSkin->setChecked(true);
}

void DlgPrefInterface::slotSetScaleFactor(double newValue) {
// The spinbox shows a percentage, but Mixxx stores a multiplication factor
// with 1.00 as no change.
newValue /= 100.0;
if (m_dScaleFactor != newValue) {
m_dScaleFactor = newValue;
m_bRebootMixxxView = true;
}
}

void DlgPrefInterface::slotSetScaleFactorAuto(bool newValue) {
if (newValue) {
if (!m_bUseAutoScaleFactor) {
m_bRebootMixxxView = true;
}
} else {
slotSetScaleFactor(newValue);
}

m_bUseAutoScaleFactor = newValue;
spinBoxScaleFactor->setEnabled(!newValue);
}

void DlgPrefInterface::slotSetTooltips() {
m_tooltipMode = mixxx::TooltipsPreference::TOOLTIPS_ON;
if (radioButtonTooltipsOff->isChecked()) {
Expand All @@ -325,9 +316,10 @@ void DlgPrefInterface::slotSetTooltips() {

void DlgPrefInterface::notifyRebootNecessary() {
// make the fact that you have to restart mixxx more obvious
QMessageBox::information(
this, tr("Information"),
tr("Mixxx must be restarted before the new locale setting will take effect."));
QMessageBox::information(this,
tr("Information"),
tr("Mixxx must be restarted before the new locale or scaling "
"settings will take effect."));
}

void DlgPrefInterface::slotSetScheme(int) {
Expand Down Expand Up @@ -389,26 +381,20 @@ void DlgPrefInterface::slotSetSkin(int) {
}

void DlgPrefInterface::slotApply() {
m_pConfig->set(ConfigKey("[Config]", "ResizableSkin"), m_pSkin->name());
m_pConfig->set(ConfigKey("[Config]", "Scheme"), m_colorScheme);
m_pConfig->set(ConfigKey(kConfigGroup, kResizableSkinKey), m_pSkin->name());
m_pConfig->set(ConfigKey(kConfigGroup, kSchemeKey), m_colorScheme);

QString locale = ComboBoxLocale->itemData(
ComboBoxLocale->currentIndex()).toString();
m_pConfig->set(ConfigKey("[Config]", "Locale"), locale);
m_pConfig->set(ConfigKey(kConfigGroup, kLocaleKey), locale);

m_pConfig->setValue(
ConfigKey("[Config]", "ScaleFactorAuto"), m_bUseAutoScaleFactor);
if (m_bUseAutoScaleFactor) {
m_pConfig->setValue(
ConfigKey("[Config]", "ScaleFactor"), m_dScaleFactorAuto);
} else {
m_pConfig->setValue(ConfigKey("[Config]", "ScaleFactor"), m_dScaleFactor);
}
double scaleFactor = spinBoxScaleFactor->value() / 100;
m_pConfig->setValue(ConfigKey(kConfigGroup, kScaleFactorKey), scaleFactor);

m_pConfig->set(ConfigKey("[Config]", "StartInFullscreen"),
m_pConfig->set(ConfigKey(kConfigGroup, kStartInFullscreenKey),
ConfigValue(checkBoxStartFullScreen->isChecked()));

m_pConfig->set(ConfigKey("[Controls]", "Tooltips"),
m_pConfig->set(ConfigKey(kControlsGroup, kTooltipsKey),
ConfigValue(static_cast<int>(m_tooltipMode)));
emit tooltipModeChanged(m_tooltipMode);

Expand All @@ -421,10 +407,11 @@ void DlgPrefInterface::slotApply() {
static_cast<mixxx::ScreenSaverPreference>(screensaverComboBoxState));
}

if (locale != m_localeOnUpdate) {
if (locale != m_localeOnUpdate || scaleFactor != m_dScaleFactor) {
notifyRebootNecessary();
// hack to prevent showing the notification when pressing "Okay" after "Apply"
m_localeOnUpdate = locale;
m_dScaleFactor = scaleFactor;
}

if (m_bRebootMixxxView) {
Expand All @@ -437,7 +424,7 @@ void DlgPrefInterface::slotApply() {

void DlgPrefInterface::loadTooltipPreferenceFromConfig() {
const auto tooltipMode = static_cast<mixxx::TooltipsPreference>(
m_pConfig->getValue(ConfigKey("[Controls]", "Tooltips"),
m_pConfig->getValue(ConfigKey(kControlsGroup, kTooltipsKey),
static_cast<int>(mixxx::TooltipsPreference::TOOLTIPS_ON)));
switch (tooltipMode) {
case mixxx::TooltipsPreference::TOOLTIPS_OFF:
Expand Down
5 changes: 1 addition & 4 deletions src/preferences/dialog/dlgprefinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ class DlgPrefInterface : public DlgPreferencePage, public Ui::DlgPrefControlsDlg
void slotSetSkinDescription();
void slotSetSkinPreview();
void slotUpdateSchemes();
void slotSetScaleFactor(double newValue);
void slotSetScaleFactorAuto(bool checked);

signals:
void reloadUserInterface();
Expand Down Expand Up @@ -75,9 +73,8 @@ class DlgPrefInterface : public DlgPreferencePage, public Ui::DlgPrefControlsDlg
QString m_colorScheme;
QString m_localeOnUpdate;
mixxx::TooltipsPreference m_tooltipMode;
double m_dScaleFactorAuto;
bool m_bUseAutoScaleFactor;
double m_dScaleFactor;
double m_minScaleFactor;
double m_dDevicePixelRatio;
bool m_bStartWithFullScreen;
mixxx::ScreenSaverPreference m_screensaverMode;
Expand Down
Loading