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 12 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
42 changes: 42 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#include <QApplication>
#include <QDir>
#include <QSettings>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

QSettings seems to be unused and a left-over from previous experiments?

#include <QString>
#include <QStringList>
#include <QTextCodec>
#include <QThread>
#include <QtDebug>

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

constexpr char kScaleFactorEnvVar[] = "QT_SCALE_FACTOR";
const QString kScaleFactorConfigKey = QStringLiteral("ScaleFactor");

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

Expand All @@ -48,6 +53,41 @@ 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->storeScaleFactor(f);
return;
}
}
// We cannot use ConfigObject, 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.
auto cfgFile = QFile(QDir(pArgs->getSettingsPath()).filePath(MIXXX_SETTINGS_FILE));
if (cfgFile.open(QFile::ReadOnly | QFile::Text)) {
QTextStream in(&cfgFile);
QString strScaleFactor;
QString line = in.readLine();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better use in.readLine().trimmed() (here an below) in case users edited their config file manually.

while (!line.isNull()) {
if (line.startsWith(kScaleFactorConfigKey)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered using QSettings instead of hacking a new config parser here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, unfortunately the attempt failed because QSettings expects a "=" between key and value, which is not used in our ini file.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. It looks like only the constructor depends on QApplication to construct file paths. Can you just add a ConfigObject static method like ConfigObject::fromFilePath(path)?

strScaleFactor = line.mid(kScaleFactorConfigKey.size() + 1);
break;
}
line = in.readLine();
}
double scaleFactor = strScaleFactor.toDouble();
if (scaleFactor > 0) {
qDebug() << "Using preferences ScaleFactor" << scaleFactor;
qputenv(kScaleFactorEnvVar, strScaleFactor.toLocal8Bit());
pArgs->storeScaleFactor(scaleFactor);
}
}
}

} // anonymous namespace

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

adjustScaleFactor(&args);

MixxxApplication app(argc, argv);

#ifdef __APPLE__
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