VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIScaleFactorEditor.cpp@ 76553

Last change on this file since 76553 was 76553, checked in by vboxsync, 5 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: UIScaleFactorEditor.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIScaleFactorEditor class implementation.
4 */
5
6/*
7 * Copyright (C) 2009-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifdef VBOX_WITH_PRECOMPILED_HEADERS
19# include <precomp.h>
20#else /* !VBOX_WITH_PRECOMPILED_HEADERS */
21
22/* Qt includes: */
23# include <QComboBox>
24# include <QGridLayout>
25# include <QLabel>
26# include <QSpacerItem>
27# include <QSpinBox>
28# include <QWidget>
29
30/* GUI includes: */
31# include "QIAdvancedSlider.h"
32# include "UIDesktopWidgetWatchdog.h"
33# include "UIScaleFactorEditor.h"
34
35/* External includes: */
36# include <math.h>
37
38#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
39
40
41UIScaleFactorEditor::UIScaleFactorEditor(QWidget *pParent)
42 : QIWithRetranslateUI<QWidget>(pParent)
43 , m_pScaleSpinBox(0)
44 , m_pMainLayout(0)
45 , m_pMonitorComboBox(0)
46 , m_pScaleSlider(0)
47 , m_pMaxScaleLabel(0)
48 , m_pMinScaleLabel(0)
49 , m_dDefaultScaleFactor(1.0)
50{
51 /* Prepare: */
52 prepare();
53 /* Append a default scale factor to the list as an global scale factor: */
54 m_scaleFactors.append(1.0);
55}
56
57void UIScaleFactorEditor::setMonitorCount(int iMonitorCount)
58{
59 if (!m_pMonitorComboBox)
60 return;
61 /* We always have 0th for global scale factor (in combo box and scale factor list): */
62 int iEndMonitorCount = iMonitorCount + 1;
63 int iCurrentMonitorCount = m_pMonitorComboBox->count();
64 if (iEndMonitorCount == iCurrentMonitorCount)
65 return;
66 m_pMonitorComboBox->setEnabled(iMonitorCount > 1);
67 m_pMonitorComboBox->blockSignals(true);
68 int iCurrentMonitorIndex = m_pMonitorComboBox->currentIndex();
69 if (iCurrentMonitorCount < iEndMonitorCount)
70 {
71 for (int i = iCurrentMonitorCount; i < iEndMonitorCount; ++i)
72 m_pMonitorComboBox->insertItem(i, tr("Monitor %1").arg(i));
73 }
74 else
75 {
76 for (int i = iCurrentMonitorCount - 1; i >= iEndMonitorCount; --i)
77 m_pMonitorComboBox->removeItem(i);
78 }
79 m_pMonitorComboBox->setEnabled(iMonitorCount > 1);
80 /* If we have a single monitor select the "All Monitors" item in the combo
81 but make sure we retain the scale factor of the 0th monitor: */
82 if (iMonitorCount <= 1)
83 {
84 if (m_scaleFactors.size() >= 2)
85 m_scaleFactors[0] = m_scaleFactors[1];
86 m_pMonitorComboBox->setCurrentIndex(0);
87 }
88 m_pMonitorComboBox->blockSignals(false);
89 /* Update the slider and spinbox values if the combobox index has changed: */
90 if (iCurrentMonitorIndex != m_pMonitorComboBox->currentIndex())
91 updateValuesAfterMonitorChange();
92}
93
94void UIScaleFactorEditor::setScaleFactors(const QList<double> &scaleFactors)
95{
96 m_scaleFactors.clear();
97 /* If we have a single value from the extra data and we treat if as a default scale factor: */
98 if (scaleFactors.size() == 1)
99 {
100 m_dDefaultScaleFactor = scaleFactors.at(0);
101 m_scaleFactors.append(m_dDefaultScaleFactor);
102 setIsGlobalScaleFactor(true);
103 return;
104 }
105
106 /* Insert 0th element as the global scalar value: */
107 m_scaleFactors.append(m_dDefaultScaleFactor);
108 m_scaleFactors.append(scaleFactors);
109 setIsGlobalScaleFactor(false);
110}
111
112QList<double> UIScaleFactorEditor::scaleFactors() const
113{
114 QList<double> scaleFactorList;
115 if (m_scaleFactors.size() == 0)
116 return scaleFactorList;
117
118 /* Decide if the users wants a global (not per monitor) scaling. */
119 bool globalScaleFactor = false;
120
121 /* if "All Monitors" item is selected in the combobox: */
122 if (m_pMonitorComboBox && m_pMonitorComboBox->currentIndex() == 0)
123 globalScaleFactor = true;
124 /* Also check if all of the monitor scale factors equal to the global scale factor: */
125 if (!globalScaleFactor)
126 {
127 globalScaleFactor = true;
128 for (int i = 1; i < m_scaleFactors.size() && globalScaleFactor; ++i)
129 if (m_scaleFactors[0] != m_scaleFactors[i])
130 globalScaleFactor = false;
131 }
132
133 if (globalScaleFactor)
134 {
135 scaleFactorList << m_scaleFactors.at(0);
136 }
137 else
138 {
139 /* Skip the 0th scale factor: */
140 for (int i = 1; i < m_scaleFactors.size(); ++i)
141 scaleFactorList.append(m_scaleFactors.at(i));
142 }
143
144 return scaleFactorList;
145}
146
147void UIScaleFactorEditor::setIsGlobalScaleFactor(bool bFlag)
148{
149 if (!m_pMonitorComboBox)
150 return;
151 if (bFlag && m_pMonitorComboBox->count() >= 1)
152 m_pMonitorComboBox->setCurrentIndex(0);
153 else
154 if(m_pMonitorComboBox->count() >= 2)
155 m_pMonitorComboBox->setCurrentIndex(1);
156 updateValuesAfterMonitorChange();
157}
158
159void UIScaleFactorEditor::setDefaultScaleFactor(double dDefaultScaleFactor)
160{
161 m_dDefaultScaleFactor = dDefaultScaleFactor;
162}
163
164void UIScaleFactorEditor::setSpinBoxWidthHint(int iHint)
165{
166 m_pScaleSpinBox->setMinimumWidth(iHint);
167}
168
169void UIScaleFactorEditor::retranslateUi()
170{
171 if (m_pMaxScaleLabel)
172 m_pMaxScaleLabel->setText(tr("Max"));
173
174 if (m_pMinScaleLabel)
175 m_pMinScaleLabel->setText(tr("Min"));
176
177 if (m_pMonitorComboBox && m_pMonitorComboBox->count() > 0)
178 {
179 m_pMonitorComboBox->setItemText(0, tr("All Monitors"));
180 for (int i = 1; i < m_pMonitorComboBox->count(); ++i)
181 m_pMonitorComboBox->setItemText(i, tr("Monitor %1").arg(i));
182 }
183 setToolTip(tr("Controls the guest screen scale factor."));
184}
185
186void UIScaleFactorEditor::sltScaleSpinBoxValueChanged(int value)
187{
188 setSliderValue(value);
189 if (m_pMonitorComboBox)
190 setScaleFactor(m_pMonitorComboBox->currentIndex(), value);
191}
192
193void UIScaleFactorEditor::sltScaleSliderValueChanged(int value)
194{
195 setSpinBoxValue(value);
196 if (m_pMonitorComboBox)
197 setScaleFactor(m_pMonitorComboBox->currentIndex(), value);
198}
199
200void UIScaleFactorEditor::sltMonitorComboIndexChanged(int)
201{
202 updateValuesAfterMonitorChange();
203}
204
205void UIScaleFactorEditor::prepare()
206{
207 m_pMainLayout = new QGridLayout;
208 if (!m_pMainLayout)
209 return;
210 QMargins margins = m_pMainLayout->contentsMargins();
211 m_pMainLayout->setContentsMargins(0, margins.top(), 0, margins.bottom());
212 m_pMonitorComboBox = new QComboBox;
213 if (m_pMonitorComboBox)
214 {
215 m_pMainLayout->addWidget(m_pMonitorComboBox, 0, 0);
216 m_pMonitorComboBox->insertItem(0, "All Monitors");
217 connect(m_pMonitorComboBox ,static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
218 this, &UIScaleFactorEditor::sltMonitorComboIndexChanged);
219 }
220
221 QGridLayout *pSliderLayout = new QGridLayout;
222 pSliderLayout->setSpacing(0);
223 m_pScaleSlider = new QIAdvancedSlider;
224 {
225 pSliderLayout->addWidget(m_pScaleSlider, 0, 0, 1, 3);
226 m_pScaleSlider->setMinimum(100);
227 m_pScaleSlider->setMaximum(200);
228 m_pScaleSlider->setPageStep(10);
229 m_pScaleSlider->setSingleStep(1);
230 m_pScaleSlider->setTickInterval(10);
231 m_pScaleSlider->setSnappingEnabled(true);
232 connect(m_pScaleSlider, static_cast<void(QIAdvancedSlider::*)(int)>(&QIAdvancedSlider::valueChanged),
233 this, &UIScaleFactorEditor::sltScaleSliderValueChanged);
234 }
235
236 m_pMinScaleLabel = new QLabel;
237 if (m_pMinScaleLabel)
238 pSliderLayout->addWidget(m_pMinScaleLabel, 1, 0);
239
240 QSpacerItem *pSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
241 if (pSpacer)
242 pSliderLayout->addItem(pSpacer, 1, 1);
243
244 m_pMaxScaleLabel = new QLabel;
245 if (m_pMaxScaleLabel)
246 pSliderLayout->addWidget(m_pMaxScaleLabel, 1, 2);
247
248 m_pMainLayout->addLayout(pSliderLayout, 0, 1, 2, 1);
249
250 m_pScaleSpinBox = new QSpinBox;
251 if (m_pScaleSpinBox)
252 {
253 m_pMainLayout->addWidget(m_pScaleSpinBox, 0, 3);
254 m_pScaleSpinBox->setSuffix("%");
255 m_pScaleSpinBox->setMinimum(100);
256 m_pScaleSpinBox->setMaximum(200);
257 connect(m_pScaleSpinBox ,static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged),
258 this, &UIScaleFactorEditor::sltScaleSpinBoxValueChanged);
259 }
260
261 configureScaleFactorMinMaxValues();
262 setLayout(m_pMainLayout);
263 retranslateUi();
264}
265
266void UIScaleFactorEditor::setScaleFactor(int iMonitorIndex, int iScaleFactor)
267{
268 /* Make sure we have the corresponding scale values for all monitors: */
269 if (m_pMonitorComboBox->count() > m_scaleFactors.size())
270 {
271 for (int i = m_scaleFactors.size(); i < m_pMonitorComboBox->count(); ++i)
272 m_scaleFactors.append(m_dDefaultScaleFactor);
273 }
274 m_scaleFactors[iMonitorIndex] = iScaleFactor / 100.0;
275}
276
277void UIScaleFactorEditor::setSliderValue(int iValue)
278{
279 if (m_pScaleSlider && iValue != m_pScaleSlider->value())
280 {
281 m_pScaleSlider->blockSignals(true);
282 m_pScaleSlider->setValue(iValue);
283 m_pScaleSlider->blockSignals(false);
284 }
285}
286
287void UIScaleFactorEditor::setSpinBoxValue(int iValue)
288{
289 if (m_pScaleSpinBox && iValue != m_pScaleSpinBox->value())
290 {
291 m_pScaleSpinBox->blockSignals(true);
292 m_pScaleSpinBox->setValue(iValue);
293 m_pScaleSpinBox->blockSignals(false);
294 }
295}
296
297void UIScaleFactorEditor::updateValuesAfterMonitorChange()
298{
299 /* Set the spinbox value for the currently selected monitor: */
300 if (m_pMonitorComboBox)
301 {
302 int currentMonitorIndex = m_pMonitorComboBox->currentIndex();
303 while (m_scaleFactors.size() <= currentMonitorIndex)
304 m_scaleFactors.append(m_dDefaultScaleFactor);
305
306 setSpinBoxValue(100 * m_scaleFactors.at(currentMonitorIndex));
307 setSliderValue(100 * m_scaleFactors.at(currentMonitorIndex));
308
309 }
310}
311
312void UIScaleFactorEditor::configureScaleFactorMinMaxValues()
313{
314 int iHostScreenCount = gpDesktop->screenCount();
315 if (iHostScreenCount == 0)
316 return;
317 double dMaxDevicePixelRatio = gpDesktop->devicePixelRatio(0);
318 for (int i = 1; i < iHostScreenCount; ++i)
319 if (dMaxDevicePixelRatio < gpDesktop->devicePixelRatio(i))
320 dMaxDevicePixelRatio = gpDesktop->devicePixelRatio(i);
321
322 const int iMinimum = 100;
323 const int iMaximum = ceil(iMinimum + 100 * dMaxDevicePixelRatio);
324
325 const int iStep = 25;
326
327 m_pScaleSlider->setMinimum(iMinimum);
328 m_pScaleSlider->setMaximum(iMaximum);
329 m_pScaleSlider->setPageStep(iStep);
330 m_pScaleSlider->setSingleStep(1);
331 m_pScaleSlider->setTickInterval(iStep);
332 m_pScaleSpinBox->setMinimum(iMinimum);
333 m_pScaleSpinBox->setMaximum(iMaximum);
334}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use