VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMediumSizeEditor.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: 9.1 KB
Line 
1/* $Id: UIMediumSizeEditor.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIMediumSizeEditor class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-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 <QGridLayout>
24# include <QLabel>
25# include <QRegExpValidator>
26# include <QSlider>
27
28/* GUI includes: */
29# include "QILineEdit.h"
30# include "VBoxGlobal.h"
31# include "UIMediumSizeEditor.h"
32
33/* COM includes: */
34# include "CSystemProperties.h"
35
36#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
37
38const qulonglong UIMediumSizeEditor::m_uSectorSize = 512;
39
40UIMediumSizeEditor::UIMediumSizeEditor(QWidget *pParent /* = 0 */)
41 : QIWithRetranslateUI<QWidget>(pParent)
42 , m_uSizeMin(_4M)
43 , m_uSizeMax(vboxGlobal().virtualBox().GetSystemProperties().GetInfoVDSize())
44 , m_iSliderScale(calculateSliderScale(m_uSizeMax))
45 , m_pSlider(0)
46 , m_pLabelMinSize(0)
47 , m_pLabelMaxSize(0)
48 , m_pEditor(0)
49{
50 /* Prepare: */
51 prepare();
52}
53
54void UIMediumSizeEditor::setMediumSize(qulonglong uSize)
55{
56 /* Remember the new size: */
57 m_uSize = uSize;
58
59 /* And assign it to the slider & editor: */
60 m_pSlider->blockSignals(true);
61 m_pSlider->setValue(sizeMBToSlider(m_uSize, m_iSliderScale));
62 m_pSlider->blockSignals(false);
63 m_pEditor->blockSignals(true);
64 m_pEditor->setText(vboxGlobal().formatSize(m_uSize));
65 m_pEditor->blockSignals(false);
66
67 /* Update the tool-tips: */
68 updateSizeToolTips(m_uSize);
69}
70
71void UIMediumSizeEditor::retranslateUi()
72{
73 /* Translate labels: */
74 m_pLabelMinSize->setText(vboxGlobal().formatSize(m_uSizeMin));
75 m_pLabelMaxSize->setText(vboxGlobal().formatSize(m_uSizeMax));
76
77 /* Translate fields: */
78 m_pSlider->setToolTip(tr("Holds the size of this medium."));
79 m_pEditor->setToolTip(tr("Holds the size of this medium."));
80
81 /* Translate tool-tips: */
82 updateSizeToolTips(m_uSize);
83}
84
85void UIMediumSizeEditor::sltSizeSliderChanged(int iValue)
86{
87 /* Update the current size: */
88 m_uSize = sliderToSizeMB(iValue, m_iSliderScale);
89 /* Update the other widget: */
90 m_pEditor->blockSignals(true);
91 m_pEditor->setText(vboxGlobal().formatSize(m_uSize));
92 m_pEditor->blockSignals(false);
93 /* Update the tool-tips: */
94 updateSizeToolTips(m_uSize);
95 /* Notify the listeners: */
96 emit sigSizeChanged(m_uSize);
97}
98
99void UIMediumSizeEditor::sltSizeEditorChanged(const QString &strValue)
100{
101 /* Update the current size: */
102 m_uSize = vboxGlobal().parseSize(strValue);
103 /* Update the other widget: */
104 m_pSlider->blockSignals(true);
105 m_pSlider->setValue(sizeMBToSlider(m_uSize, m_iSliderScale));
106 m_pSlider->blockSignals(false);
107 /* Update the tool-tips: */
108 updateSizeToolTips(m_uSize);
109 /* Notify the listeners: */
110 emit sigSizeChanged(m_uSize);
111}
112
113void UIMediumSizeEditor::sltSizeEditorEditingFinished()
114{
115 qulonglong uSize = checkSectorSizeAlignment(m_uSize);
116
117 /* The size is already aligned to sector size: */
118 if (uSize == m_uSize)
119 return;
120 setMediumSize(uSize);
121}
122
123void UIMediumSizeEditor::prepare()
124{
125 /* Create layout: */
126 QGridLayout *pLayout = new QGridLayout(this);
127 if (pLayout)
128 {
129 /* Configure layout: */
130 pLayout->setContentsMargins(0, 0, 0, 0);
131 pLayout->setColumnStretch(0, 1);
132 pLayout->setColumnStretch(1, 1);
133 pLayout->setColumnStretch(2, 0);
134
135 /* Create size slider: */
136 m_pSlider = new QSlider;
137 if (m_pSlider)
138 {
139 /* Configure slider: */
140 m_pSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
141 m_pSlider->setOrientation(Qt::Horizontal);
142 m_pSlider->setTickPosition(QSlider::TicksBelow);
143 m_pSlider->setFocusPolicy(Qt::StrongFocus);
144 m_pSlider->setPageStep(m_iSliderScale);
145 m_pSlider->setSingleStep(m_iSliderScale / 8);
146 m_pSlider->setTickInterval(0);
147 m_pSlider->setMinimum(sizeMBToSlider(m_uSizeMin, m_iSliderScale));
148 m_pSlider->setMaximum(sizeMBToSlider(m_uSizeMax, m_iSliderScale));
149 connect(m_pSlider, &QSlider::valueChanged,
150 this, &UIMediumSizeEditor::sltSizeSliderChanged);
151
152 /* Add into layout: */
153 pLayout->addWidget(m_pSlider, 0, 0, 1, 2, Qt::AlignTop);
154 }
155
156 /* Create minimum size label: */
157 m_pLabelMinSize = new QLabel;
158 if (m_pLabelMinSize)
159 {
160 /* Configure label: */
161 m_pLabelMinSize->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
162
163 /* Add into layout: */
164 pLayout->addWidget(m_pLabelMinSize, 1, 0);
165 }
166
167 /* Create maximum size label: */
168 m_pLabelMaxSize = new QLabel;
169 if (m_pLabelMaxSize)
170 {
171 /* Configure label: */
172 m_pLabelMaxSize->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
173
174 /* Add into layout: */
175 pLayout->addWidget(m_pLabelMaxSize, 1, 1);
176 }
177
178 /* Create size editor: */
179 m_pEditor = new QILineEdit;
180 if (m_pEditor)
181 {
182 /* Configure editor: */
183 m_pEditor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
184 m_pEditor->setFixedWidthByText("88888.88 MB");
185 m_pEditor->setAlignment(Qt::AlignRight);
186 m_pEditor->setValidator(new QRegExpValidator(QRegExp(vboxGlobal().sizeRegexp()), this));
187 connect(m_pEditor, &QILineEdit::textChanged,
188 this, &UIMediumSizeEditor::sltSizeEditorChanged);
189 connect(m_pEditor, &QILineEdit::editingFinished,
190 this, &UIMediumSizeEditor::sltSizeEditorEditingFinished);
191
192 /* Add into layout: */
193 pLayout->addWidget(m_pEditor, 0, 2, Qt::AlignTop);
194 }
195 }
196
197 /* Apply language settings: */
198 retranslateUi();
199}
200
201/* static */
202int UIMediumSizeEditor::calculateSliderScale(qulonglong uMaximumMediumSize)
203{
204 /* Detect how many steps to recognize between adjacent powers of 2
205 * to ensure that the last slider step is exactly that we need: */
206 int iSliderScale = 0;
207 int iPower = log2i(uMaximumMediumSize);
208 qulonglong uTickMB = (qulonglong)1 << iPower;
209 if (uTickMB < uMaximumMediumSize)
210 {
211 qulonglong uTickMBNext = (qulonglong)1 << (iPower + 1);
212 qulonglong uGap = uTickMBNext - uMaximumMediumSize;
213 iSliderScale = (int)((uTickMBNext - uTickMB) / uGap);
214#ifdef VBOX_WS_MAC
215 // WORKAROUND:
216 // There is an issue with Qt5 QSlider under OSX:
217 // Slider tick count (maximum - minimum) is limited with some
218 // "magical number" - 588351, having it more than that brings
219 // unpredictable results like slider token jumping and disappearing,
220 // so we are limiting tick count by lowering slider-scale 128 times.
221 iSliderScale /= 128;
222#endif /* VBOX_WS_MAC */
223 }
224 return qMax(iSliderScale, 8);
225}
226
227/* static */
228int UIMediumSizeEditor::log2i(qulonglong uValue)
229{
230 if (!uValue)
231 return 0;
232 int iPower = -1;
233 while (uValue)
234 {
235 ++iPower;
236 uValue >>= 1;
237 }
238 return iPower;
239}
240
241/* static */
242int UIMediumSizeEditor::sizeMBToSlider(qulonglong uValue, int iSliderScale)
243{
244 /* Make sure *any* slider value is multiple of m_uSectorSize: */
245 uValue /= m_uSectorSize;
246
247 /* Calculate result: */
248 int iPower = log2i(uValue);
249 qulonglong uTickMB = qulonglong (1) << iPower;
250 qulonglong uTickMBNext = qulonglong (1) << (iPower + 1);
251 int iStep = (uValue - uTickMB) * iSliderScale / (uTickMBNext - uTickMB);
252 int iResult = iPower * iSliderScale + iStep;
253
254 /* Return result: */
255 return iResult;
256}
257
258/* static */
259qulonglong UIMediumSizeEditor::sliderToSizeMB(int uValue, int iSliderScale)
260{
261 /* Calculate result: */
262 int iPower = uValue / iSliderScale;
263 int iStep = uValue % iSliderScale;
264 qulonglong uTickMB = qulonglong (1) << iPower;
265 qulonglong uTickMBNext = qulonglong (1) << (iPower + 1);
266 qulonglong uResult = uTickMB + (uTickMBNext - uTickMB) * iStep / iSliderScale;
267
268 /* Make sure *any* slider value is multiple of m_uSectorSize: */
269 uResult *= m_uSectorSize;
270
271 /* Return result: */
272 return uResult;
273}
274
275void UIMediumSizeEditor::updateSizeToolTips(qulonglong uSize)
276{
277 const QString strToolTip = tr("<nobr>%1 (%2 B)</nobr>").arg(vboxGlobal().formatSize(uSize)).arg(uSize);
278 m_pSlider->setToolTip(strToolTip);
279 m_pEditor->setToolTip(strToolTip);
280}
281
282qulonglong UIMediumSizeEditor::checkSectorSizeAlignment(qulonglong uSize)
283{
284 if (m_uSectorSize == 0 || uSize % m_uSectorSize == 0)
285 return uSize;
286 qulonglong uNewSize = (uSize / m_uSectorSize) * m_uSectorSize;
287 return uNewSize;
288}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use