1 | /* $Id: UIFormEditorWidget.cpp 100346 2023-07-03 11:22:58Z vboxsync $ */
|
---|
2 | /** @file
|
---|
3 | * VBox Qt GUI - UIFormEditorWidget class implementation.
|
---|
4 | */
|
---|
5 |
|
---|
6 | /*
|
---|
7 | * Copyright (C) 2019-2023 Oracle and/or its affiliates.
|
---|
8 | *
|
---|
9 | * This file is part of VirtualBox base platform packages, as
|
---|
10 | * available from https://www.virtualbox.org.
|
---|
11 | *
|
---|
12 | * This program is free software; you can redistribute it and/or
|
---|
13 | * modify it under the terms of the GNU General Public License
|
---|
14 | * as published by the Free Software Foundation, in version 3 of the
|
---|
15 | * License.
|
---|
16 | *
|
---|
17 | * This program is distributed in the hope that it will be useful, but
|
---|
18 | * WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
20 | * General Public License for more details.
|
---|
21 | *
|
---|
22 | * You should have received a copy of the GNU General Public License
|
---|
23 | * along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
24 | *
|
---|
25 | * SPDX-License-Identifier: GPL-3.0-only
|
---|
26 | */
|
---|
27 |
|
---|
28 | /* Qt includes: */
|
---|
29 | #include <QComboBox>
|
---|
30 | #include <QEvent>
|
---|
31 | #include <QHeaderView>
|
---|
32 | #include <QItemEditorFactory>
|
---|
33 | #include <QLineEdit>
|
---|
34 | #include <QPointer>
|
---|
35 | #include <QPushButton>
|
---|
36 | #include <QSortFilterProxyModel>
|
---|
37 | #include <QSpinBox>
|
---|
38 | #include <QTextEdit>
|
---|
39 | #include <QVBoxLayout>
|
---|
40 |
|
---|
41 | /* GUI includes: */
|
---|
42 | #include "QIDialog.h"
|
---|
43 | #include "QIDialogButtonBox.h"
|
---|
44 | #include "QIStyledItemDelegate.h"
|
---|
45 | #include "QITableView.h"
|
---|
46 | #include "QIWithRetranslateUI.h"
|
---|
47 | #include "UIFormEditorWidget.h"
|
---|
48 | #include "UIIconPool.h"
|
---|
49 | #include "UINotificationCenter.h"
|
---|
50 |
|
---|
51 | /* COM includes: */
|
---|
52 | #include "CBooleanFormValue.h"
|
---|
53 | #include "CChoiceFormValue.h"
|
---|
54 | #include "CForm.h"
|
---|
55 | #include "CFormValue.h"
|
---|
56 | #include "CRangedIntegerFormValue.h"
|
---|
57 | #include "CRangedInteger64FormValue.h"
|
---|
58 | #include "CStringFormValue.h"
|
---|
59 | #include "CSystemProperties.h"
|
---|
60 | #include "CVirtualSystemDescriptionForm.h"
|
---|
61 |
|
---|
62 | /* VirtualBox interface declarations: */
|
---|
63 | #include <VBox/com/VirtualBox.h>
|
---|
64 |
|
---|
65 | /* External includes: */
|
---|
66 | #include <math.h>
|
---|
67 |
|
---|
68 |
|
---|
69 | /** Form Editor data types. */
|
---|
70 | enum UIFormEditorDataType
|
---|
71 | {
|
---|
72 | UIFormEditorDataType_Name,
|
---|
73 | UIFormEditorDataType_Value,
|
---|
74 | UIFormEditorDataType_Max
|
---|
75 | };
|
---|
76 |
|
---|
77 |
|
---|
78 | /** Class used to hold text data. */
|
---|
79 | class TextData
|
---|
80 | {
|
---|
81 | public:
|
---|
82 |
|
---|
83 | /** Constructs null text data. */
|
---|
84 | TextData() {}
|
---|
85 | /** Constructs text data on the basis of passed @a strText and @a index. */
|
---|
86 | TextData(const QString &strText, const QModelIndex index = QModelIndex())
|
---|
87 | : m_strText(strText), m_index(index) {}
|
---|
88 | /** Constructs text data on the basis of @a another text data. */
|
---|
89 | TextData(const TextData &another)
|
---|
90 | : m_strText(another.text()), m_index(another.index()) {}
|
---|
91 |
|
---|
92 | /** Assigns values of @a another text to this one. */
|
---|
93 | TextData &operator=(const TextData &another)
|
---|
94 | {
|
---|
95 | m_strText = another.text();
|
---|
96 | m_index = another.index();
|
---|
97 | return *this;
|
---|
98 | }
|
---|
99 |
|
---|
100 | /** Returns text value. */
|
---|
101 | QString text() const { return m_strText; }
|
---|
102 |
|
---|
103 | /** Defines model @a index. */
|
---|
104 | void setIndex(const QModelIndex &index) { m_index = index; }
|
---|
105 | /** Returns model index. */
|
---|
106 | QModelIndex index() const { return m_index; }
|
---|
107 |
|
---|
108 | private:
|
---|
109 |
|
---|
110 | /** Holds text value. */
|
---|
111 | QString m_strText;
|
---|
112 | /** Holds model index. */
|
---|
113 | QModelIndex m_index;
|
---|
114 | };
|
---|
115 | Q_DECLARE_METATYPE(TextData);
|
---|
116 |
|
---|
117 |
|
---|
118 | /** Class used to hold choice data. */
|
---|
119 | class ChoiceData
|
---|
120 | {
|
---|
121 | public:
|
---|
122 |
|
---|
123 | /** Constructs null choice data. */
|
---|
124 | ChoiceData()
|
---|
125 | : m_iSelectedIndex(-1) {}
|
---|
126 | /** Constructs choice data on the basis of passed @a values and @a iSelectedIndex. */
|
---|
127 | ChoiceData(const QVector<QString> &values, int iSelectedIndex)
|
---|
128 | : m_values(values), m_iSelectedIndex(iSelectedIndex) {}
|
---|
129 | /** Constructs choice data on the basis of @a another choice data. */
|
---|
130 | ChoiceData(const ChoiceData &another)
|
---|
131 | : m_values(another.values()), m_iSelectedIndex(another.selectedIndex()) {}
|
---|
132 |
|
---|
133 | /** Assigns values of @a another choice to this one. */
|
---|
134 | ChoiceData &operator=(const ChoiceData &another)
|
---|
135 | {
|
---|
136 | m_values = another.values();
|
---|
137 | m_iSelectedIndex = another.selectedIndex();
|
---|
138 | return *this;
|
---|
139 | }
|
---|
140 |
|
---|
141 | /** Returns values vector. */
|
---|
142 | QVector<QString> values() const { return m_values; }
|
---|
143 | /** Returns selected index. */
|
---|
144 | int selectedIndex() const { return m_iSelectedIndex; }
|
---|
145 | /** Returns selected value. */
|
---|
146 | QString selectedValue() const
|
---|
147 | {
|
---|
148 | return m_iSelectedIndex >= 0 && m_iSelectedIndex < m_values.size()
|
---|
149 | ? m_values.at(m_iSelectedIndex) : QString();
|
---|
150 | }
|
---|
151 |
|
---|
152 | private:
|
---|
153 |
|
---|
154 | /** Holds values vector. */
|
---|
155 | QVector<QString> m_values;
|
---|
156 | /** Holds selected index. */
|
---|
157 | int m_iSelectedIndex;
|
---|
158 | };
|
---|
159 | Q_DECLARE_METATYPE(ChoiceData);
|
---|
160 |
|
---|
161 |
|
---|
162 | /** Class used to hold ranged-integer data. */
|
---|
163 | class RangedIntegerData
|
---|
164 | {
|
---|
165 | public:
|
---|
166 |
|
---|
167 | /** Constructs null ranged-integer data. */
|
---|
168 | RangedIntegerData()
|
---|
169 | : m_iMinimum(-1), m_iMaximum(-1)
|
---|
170 | , m_iInteger(-1), m_strSuffix(QString()) {}
|
---|
171 | /** Constructs ranged-integer data on the basis of passed @a iMinimum, @a iMaximum, @a iInteger and @a strSuffix. */
|
---|
172 | RangedIntegerData(int iMinimum, int iMaximum, int iInteger, const QString strSuffix)
|
---|
173 | : m_iMinimum(iMinimum), m_iMaximum(iMaximum)
|
---|
174 | , m_iInteger(iInteger), m_strSuffix(strSuffix) {}
|
---|
175 | /** Constructs ranged-integer data on the basis of @a another ranged-integer data. */
|
---|
176 | RangedIntegerData(const RangedIntegerData &another)
|
---|
177 | : m_iMinimum(another.minimum()), m_iMaximum(another.maximum())
|
---|
178 | , m_iInteger(another.integer()), m_strSuffix(another.suffix()) {}
|
---|
179 |
|
---|
180 | /** Assigns values of @a another ranged-integer to this one. */
|
---|
181 | RangedIntegerData &operator=(const RangedIntegerData &another)
|
---|
182 | {
|
---|
183 | m_iMinimum = another.minimum();
|
---|
184 | m_iMaximum = another.maximum();
|
---|
185 | m_iInteger = another.integer();
|
---|
186 | m_strSuffix = another.suffix();
|
---|
187 | return *this;
|
---|
188 | }
|
---|
189 |
|
---|
190 | /** Returns minimum value. */
|
---|
191 | int minimum() const { return m_iMinimum; }
|
---|
192 | /** Returns maximum value. */
|
---|
193 | int maximum() const { return m_iMaximum; }
|
---|
194 | /** Returns current value. */
|
---|
195 | int integer() const { return m_iInteger; }
|
---|
196 | /** Returns suffix value. */
|
---|
197 | QString suffix() const { return m_strSuffix; }
|
---|
198 |
|
---|
199 | private:
|
---|
200 |
|
---|
201 | /** Holds minimum value. */
|
---|
202 | int m_iMinimum;
|
---|
203 | /** Holds maximum value. */
|
---|
204 | int m_iMaximum;
|
---|
205 | /** Holds current value. */
|
---|
206 | int m_iInteger;
|
---|
207 | /** Holds suffix value. */
|
---|
208 | QString m_strSuffix;
|
---|
209 | };
|
---|
210 | Q_DECLARE_METATYPE(RangedIntegerData);
|
---|
211 |
|
---|
212 |
|
---|
213 | /** Class used to hold ranged-integer64 data. */
|
---|
214 | class RangedInteger64Data
|
---|
215 | {
|
---|
216 | public:
|
---|
217 |
|
---|
218 | /** Constructs null ranged-integer64 data. */
|
---|
219 | RangedInteger64Data()
|
---|
220 | : m_iMinimum(-1), m_iMaximum(-1)
|
---|
221 | , m_iInteger(-1), m_strSuffix(QString()) {}
|
---|
222 | /** Constructs ranged-integer64 data on the basis of passed @a iMinimum, @a iMaximum, @a iInteger and @a strSuffix. */
|
---|
223 | RangedInteger64Data(qlonglong iMinimum, qlonglong iMaximum, qlonglong iInteger, const QString strSuffix)
|
---|
224 | : m_iMinimum(iMinimum), m_iMaximum(iMaximum)
|
---|
225 | , m_iInteger(iInteger), m_strSuffix(strSuffix) {}
|
---|
226 | /** Constructs ranged-integer64 data on the basis of @a another ranged-integer data. */
|
---|
227 | RangedInteger64Data(const RangedInteger64Data &another)
|
---|
228 | : m_iMinimum(another.minimum()), m_iMaximum(another.maximum())
|
---|
229 | , m_iInteger(another.integer()), m_strSuffix(another.suffix()) {}
|
---|
230 |
|
---|
231 | /** Assigns values of @a another ranged-integer to this one. */
|
---|
232 | RangedInteger64Data &operator=(const RangedInteger64Data &another)
|
---|
233 | {
|
---|
234 | m_iMinimum = another.minimum();
|
---|
235 | m_iMaximum = another.maximum();
|
---|
236 | m_iInteger = another.integer();
|
---|
237 | m_strSuffix = another.suffix();
|
---|
238 | return *this;
|
---|
239 | }
|
---|
240 |
|
---|
241 | /** Returns minimum value. */
|
---|
242 | qlonglong minimum() const { return m_iMinimum; }
|
---|
243 | /** Returns maximum value. */
|
---|
244 | qlonglong maximum() const { return m_iMaximum; }
|
---|
245 | /** Returns current value. */
|
---|
246 | qlonglong integer() const { return m_iInteger; }
|
---|
247 | /** Returns suffix value. */
|
---|
248 | QString suffix() const { return m_strSuffix; }
|
---|
249 |
|
---|
250 | private:
|
---|
251 |
|
---|
252 | /** Holds minimum value. */
|
---|
253 | qlonglong m_iMinimum;
|
---|
254 | /** Holds maximum value. */
|
---|
255 | qlonglong m_iMaximum;
|
---|
256 | /** Holds current value. */
|
---|
257 | qlonglong m_iInteger;
|
---|
258 | /** Holds suffix value. */
|
---|
259 | QString m_strSuffix;
|
---|
260 | };
|
---|
261 | Q_DECLARE_METATYPE(RangedInteger64Data);
|
---|
262 |
|
---|
263 |
|
---|
264 | /** QWidget extension used as dummy TextData editor.
|
---|
265 | * It's not actually an editor, but Edit... button instead which opens
|
---|
266 | * real editor passing stored model index received from TextData value. */
|
---|
267 | class TextEditor : public QIWithRetranslateUI<QWidget>
|
---|
268 | {
|
---|
269 | Q_OBJECT;
|
---|
270 | Q_PROPERTY(TextData text READ text WRITE setText USER true);
|
---|
271 |
|
---|
272 | public:
|
---|
273 |
|
---|
274 | /** Constructs TextData editor passing @a pParent to the base-class. */
|
---|
275 | TextEditor(QWidget *pParent = 0);
|
---|
276 |
|
---|
277 | protected:
|
---|
278 |
|
---|
279 | /** Handles translation event. */
|
---|
280 | virtual void retranslateUi() RT_OVERRIDE;
|
---|
281 |
|
---|
282 | private slots:
|
---|
283 |
|
---|
284 | /** Handles button click. */
|
---|
285 | void sltHandleButtonClick();
|
---|
286 |
|
---|
287 | private:
|
---|
288 |
|
---|
289 | /** Prepares all. */
|
---|
290 | void prepare();
|
---|
291 |
|
---|
292 | /** Defines @a text. */
|
---|
293 | void setText(const TextData &text);
|
---|
294 | /** Returns text. */
|
---|
295 | TextData text() const;
|
---|
296 |
|
---|
297 | /** Holds the button instance. */
|
---|
298 | QPushButton *m_pButton;
|
---|
299 | /** Holds the multiline text. */
|
---|
300 | QString m_strMultilineText;
|
---|
301 | /** Holds the model index. */
|
---|
302 | QModelIndex m_index;
|
---|
303 | };
|
---|
304 |
|
---|
305 |
|
---|
306 | /** QComboBox extension used as ChoiceData editor. */
|
---|
307 | class ChoiceEditor : public QComboBox
|
---|
308 | {
|
---|
309 | Q_OBJECT;
|
---|
310 | Q_PROPERTY(ChoiceData choice READ choice WRITE setChoice USER true);
|
---|
311 |
|
---|
312 | signals:
|
---|
313 |
|
---|
314 | /** Notifies listener about data should be committed. */
|
---|
315 | void sigCommitData(QWidget *pThis);
|
---|
316 |
|
---|
317 | public:
|
---|
318 |
|
---|
319 | /** Constructs ChoiceData editor passing @a pParent to the base-class. */
|
---|
320 | ChoiceEditor(QWidget *pParent = 0);
|
---|
321 |
|
---|
322 | private slots:
|
---|
323 |
|
---|
324 | /** Handles current index change. */
|
---|
325 | void sltCurrentIndexChanged();
|
---|
326 |
|
---|
327 | private:
|
---|
328 |
|
---|
329 | /** Defines the @a choice. */
|
---|
330 | void setChoice(const ChoiceData &choice);
|
---|
331 | /** Returns the choice. */
|
---|
332 | ChoiceData choice() const;
|
---|
333 | };
|
---|
334 |
|
---|
335 |
|
---|
336 | /** QSpinBox extension used as RangedIntegerData editor. */
|
---|
337 | class RangedIntegerEditor : public QSpinBox
|
---|
338 | {
|
---|
339 | Q_OBJECT;
|
---|
340 | Q_PROPERTY(RangedIntegerData rangedInteger READ rangedInteger WRITE setRangedInteger USER true);
|
---|
341 |
|
---|
342 | public:
|
---|
343 |
|
---|
344 | /** Constructs RangedIntegerData editor passing @a pParent to the base-class. */
|
---|
345 | RangedIntegerEditor(QWidget *pParent = 0);
|
---|
346 |
|
---|
347 | private:
|
---|
348 |
|
---|
349 | /** Defines @a rangedInteger. */
|
---|
350 | void setRangedInteger(const RangedIntegerData &rangedInteger);
|
---|
351 | /** Returns ranged-integer. */
|
---|
352 | RangedIntegerData rangedInteger() const;
|
---|
353 |
|
---|
354 | /** Holds the unchanged suffix. */
|
---|
355 | QString m_strSuffix;
|
---|
356 | };
|
---|
357 |
|
---|
358 |
|
---|
359 | /** QLineEdit extension used as RangedInteger64Data editor. */
|
---|
360 | class RangedInteger64Editor : public QLineEdit
|
---|
361 | {
|
---|
362 | Q_OBJECT;
|
---|
363 | Q_PROPERTY(RangedInteger64Data rangedInteger64 READ rangedInteger64 WRITE setRangedInteger64 USER true);
|
---|
364 |
|
---|
365 | public:
|
---|
366 |
|
---|
367 | /** Constructs RangedInteger64Data editor passing @a pParent to the base-class. */
|
---|
368 | RangedInteger64Editor(QWidget *pParent = 0);
|
---|
369 |
|
---|
370 | private:
|
---|
371 |
|
---|
372 | /** Defines @a rangedInteger. */
|
---|
373 | void setRangedInteger64(const RangedInteger64Data &rangedInteger64);
|
---|
374 | /** Returns ranged-integer. */
|
---|
375 | RangedInteger64Data rangedInteger64() const;
|
---|
376 |
|
---|
377 | /** Holds the minimum guest RAM in MBs. */
|
---|
378 | qlonglong m_iMinimumGuestRAM;
|
---|
379 | /** Holds the maximum value. */
|
---|
380 | qlonglong m_iMaximumGuestRAM;
|
---|
381 |
|
---|
382 | /** Holds the minimum value. */
|
---|
383 | qlonglong m_iMinimum;
|
---|
384 | /** Holds the maximum value. */
|
---|
385 | qlonglong m_iMaximum;
|
---|
386 | /** Holds the unchanged suffix. */
|
---|
387 | QString m_strSuffix;
|
---|
388 | };
|
---|
389 |
|
---|
390 |
|
---|
391 | /** QITableViewCell extension used as Form Editor table-view cell. */
|
---|
392 | class UIFormEditorCell : public QITableViewCell
|
---|
393 | {
|
---|
394 | Q_OBJECT;
|
---|
395 |
|
---|
396 | public:
|
---|
397 |
|
---|
398 | /** Constructs table cell on the basis of certain @a strText, passing @a pParent to the base-class. */
|
---|
399 | UIFormEditorCell(QITableViewRow *pParent, const QString &strText = QString());
|
---|
400 |
|
---|
401 | /** Returns the cell text. */
|
---|
402 | virtual QString text() const RT_OVERRIDE { return m_strText; }
|
---|
403 |
|
---|
404 | /** Defines the cell @a strText. */
|
---|
405 | void setText(const QString &strText) { m_strText = strText; }
|
---|
406 |
|
---|
407 | private:
|
---|
408 |
|
---|
409 | /** Holds the cell text. */
|
---|
410 | QString m_strText;
|
---|
411 | };
|
---|
412 |
|
---|
413 |
|
---|
414 | /** QITableViewRow extension used as Form Editor table-view row. */
|
---|
415 | class UIFormEditorRow : public QITableViewRow
|
---|
416 | {
|
---|
417 | Q_OBJECT;
|
---|
418 |
|
---|
419 | public:
|
---|
420 |
|
---|
421 | /** Constructs table row on the basis of certain @a comValue, passing @a pParent to the base-class.
|
---|
422 | * @param pFormEditorWidget Brings the root form-editor widget reference. */
|
---|
423 | UIFormEditorRow(QITableView *pParent, UIFormEditorWidget *pFormEditorWidget, const CFormValue &comValue);
|
---|
424 | /** Destructs table row. */
|
---|
425 | virtual ~UIFormEditorRow() RT_OVERRIDE;
|
---|
426 |
|
---|
427 | /** Returns value type. */
|
---|
428 | KFormValueType valueType() const { return m_enmValueType; }
|
---|
429 |
|
---|
430 | /** Returns the row name as string. */
|
---|
431 | QString nameToString() const;
|
---|
432 | /** Returns the row value as string. */
|
---|
433 | QString valueToString() const;
|
---|
434 |
|
---|
435 | /** Returns whether the row is enabled. */
|
---|
436 | bool isEnabled() const;
|
---|
437 | /** Returns whether the row is visible. */
|
---|
438 | bool isVisible() const;
|
---|
439 |
|
---|
440 | /** Returns value cast to bool. */
|
---|
441 | bool toBool() const;
|
---|
442 | /** Defines @a fBool value. */
|
---|
443 | void setBool(bool fBool);
|
---|
444 |
|
---|
445 | /** Returns whether cached string value is multiline. */
|
---|
446 | bool isMultilineString() const;
|
---|
447 | /** Returns value cast to text. */
|
---|
448 | TextData toText() const;
|
---|
449 | /** Defines @a text value. */
|
---|
450 | void setText(const TextData &text);
|
---|
451 | /** Returns value cast to string. */
|
---|
452 | QString toString() const;
|
---|
453 | /** Defines @a strString value. */
|
---|
454 | void setString(const QString &strString);
|
---|
455 |
|
---|
456 | /** Returns value cast to choice. */
|
---|
457 | ChoiceData toChoice() const;
|
---|
458 | /** Defines @a choice value. */
|
---|
459 | void setChoice(const ChoiceData &choice);
|
---|
460 |
|
---|
461 | /** Returns value cast to ranged-integer. */
|
---|
462 | RangedIntegerData toRangedInteger() const;
|
---|
463 | /** Defines @a rangedInteger value. */
|
---|
464 | void setRangedInteger(const RangedIntegerData &rangedInteger);
|
---|
465 |
|
---|
466 | /** Returns value cast to ranged-integer64. */
|
---|
467 | RangedInteger64Data toRangedInteger64() const;
|
---|
468 | /** Defines @a rangedInteger64 value. */
|
---|
469 | void setRangedInteger64(const RangedInteger64Data &rangedInteger64);
|
---|
470 |
|
---|
471 | /** Updates value cells. */
|
---|
472 | void updateValueCells();
|
---|
473 |
|
---|
474 | /** Check whether generation value is changed. */
|
---|
475 | bool isGenerationChanged() const;
|
---|
476 |
|
---|
477 | protected:
|
---|
478 |
|
---|
479 | /** Returns the number of children. */
|
---|
480 | virtual int childCount() const RT_OVERRIDE;
|
---|
481 | /** Returns the child item with @a iIndex. */
|
---|
482 | virtual QITableViewCell *childItem(int iIndex) const RT_OVERRIDE;
|
---|
483 |
|
---|
484 | private:
|
---|
485 |
|
---|
486 | /** Prepares all. */
|
---|
487 | void prepare();
|
---|
488 | /** Cleanups all. */
|
---|
489 | void cleanup();
|
---|
490 |
|
---|
491 | /** Holds the root form-editor widget reference. */
|
---|
492 | UIFormEditorWidget *m_pFormEditorWidget;
|
---|
493 |
|
---|
494 | /** Holds the row value. */
|
---|
495 | CFormValue m_comValue;
|
---|
496 |
|
---|
497 | /** Holds the value type. */
|
---|
498 | KFormValueType m_enmValueType;
|
---|
499 |
|
---|
500 | /** Holds current generation value. */
|
---|
501 | int m_iGeneration;
|
---|
502 |
|
---|
503 | /** Holds cached bool value. */
|
---|
504 | bool m_fBool;
|
---|
505 | /** Holds whether cached string value is multiline. */
|
---|
506 | bool m_fMultilineString;
|
---|
507 | /** Holds cached text value. */
|
---|
508 | TextData m_text;
|
---|
509 | /** Holds cached string value. */
|
---|
510 | QString m_strString;
|
---|
511 | /** Holds cached choice value. */
|
---|
512 | ChoiceData m_choice;
|
---|
513 | /** Holds cached ranged-integer value. */
|
---|
514 | RangedIntegerData m_rangedInteger;
|
---|
515 | /** Holds cached ranged-integer64 value. */
|
---|
516 | RangedInteger64Data m_rangedInteger64;
|
---|
517 |
|
---|
518 | /** Holds the cell instances. */
|
---|
519 | QVector<UIFormEditorCell*> m_cells;
|
---|
520 | };
|
---|
521 |
|
---|
522 |
|
---|
523 | /** QAbstractTableModel subclass used as Form Editor data model. */
|
---|
524 | class UIFormEditorModel : public QAbstractTableModel
|
---|
525 | {
|
---|
526 | Q_OBJECT;
|
---|
527 |
|
---|
528 | public:
|
---|
529 |
|
---|
530 | /** Constructs Form Editor model passing @a pParent to the base-class. */
|
---|
531 | UIFormEditorModel(UIFormEditorWidget *pParent);
|
---|
532 | /** Destructs Port Forwarding model. */
|
---|
533 | virtual ~UIFormEditorModel() RT_OVERRIDE;
|
---|
534 |
|
---|
535 | /** Clears form. */
|
---|
536 | void clearForm();
|
---|
537 | /** Defines form @a values. */
|
---|
538 | void setFormValues(const CFormValueVector &values);
|
---|
539 |
|
---|
540 | /** Returns the number of children. */
|
---|
541 | int childCount() const;
|
---|
542 | /** Returns the child item with @a iIndex. */
|
---|
543 | QITableViewRow *childItem(int iIndex) const;
|
---|
544 |
|
---|
545 | /** Returns the index of the item in the model specified by the given @a iRow, @a iColumn and @a parentIdx. */
|
---|
546 | virtual QModelIndex index(int iRow, int iColumn, const QModelIndex &parentIdx = QModelIndex()) const RT_OVERRIDE;
|
---|
547 |
|
---|
548 | /** Returns flags for item with certain @a index. */
|
---|
549 | virtual Qt::ItemFlags flags(const QModelIndex &index) const RT_OVERRIDE;
|
---|
550 |
|
---|
551 | /** Returns row count of certain @a parent. */
|
---|
552 | virtual int rowCount(const QModelIndex &parent = QModelIndex()) const RT_OVERRIDE;
|
---|
553 | /** Returns column count of certain @a parent. */
|
---|
554 | virtual int columnCount(const QModelIndex &parent = QModelIndex()) const RT_OVERRIDE;
|
---|
555 |
|
---|
556 | /** Returns header data for @a iSection, @a enmOrientation and @a iRole specified. */
|
---|
557 | virtual QVariant headerData(int iSection, Qt::Orientation enmOrientation, int iRole) const RT_OVERRIDE;
|
---|
558 |
|
---|
559 | /** Defines the @a iRole data for item with @a index as @a value. */
|
---|
560 | virtual bool setData(const QModelIndex &index, const QVariant &value, int iRole = Qt::EditRole) RT_OVERRIDE;
|
---|
561 | /** Returns the @a iRole data for item with @a index. */
|
---|
562 | virtual QVariant data(const QModelIndex &index, int iRole) const RT_OVERRIDE;
|
---|
563 |
|
---|
564 | /** Creates actual TextData editor for specified @a index. */
|
---|
565 | void createTextDataEditor(const QModelIndex &index);
|
---|
566 |
|
---|
567 | private:
|
---|
568 |
|
---|
569 | /** Prepares all. */
|
---|
570 | void prepare();
|
---|
571 |
|
---|
572 | /** Returns the parent table-view reference. */
|
---|
573 | QITableView *view() const;
|
---|
574 |
|
---|
575 | /** Updates row generation values. */
|
---|
576 | void updateGeneration();
|
---|
577 |
|
---|
578 | /** Returns icon hint for specified @a strItemName. */
|
---|
579 | QIcon iconHint(const QString &strItemName) const;
|
---|
580 |
|
---|
581 | /** Holds the root form-editor widget reference. */
|
---|
582 | UIFormEditorWidget *m_pFormEditorWidget;
|
---|
583 |
|
---|
584 | /** Holds the Form Editor row list. */
|
---|
585 | QList<UIFormEditorRow*> m_dataList;
|
---|
586 |
|
---|
587 | /** Holds the hardcoded icon name map. */
|
---|
588 | QMap<QString, QIcon> m_icons;
|
---|
589 | };
|
---|
590 |
|
---|
591 |
|
---|
592 | /** QSortFilterProxyModel subclass used as the Form Editor proxy-model. */
|
---|
593 | class UIFormEditorProxyModel : public QSortFilterProxyModel
|
---|
594 | {
|
---|
595 | Q_OBJECT;
|
---|
596 |
|
---|
597 | public:
|
---|
598 |
|
---|
599 | /** Constructs the Form Editor proxy-model passing @a pParent to the base-class. */
|
---|
600 | UIFormEditorProxyModel(QObject *pParent = 0);
|
---|
601 |
|
---|
602 | /** Returns the number of children. */
|
---|
603 | int childCount() const;
|
---|
604 | /** Returns the child item with @a iIndex. */
|
---|
605 | QITableViewRow *childItem(int iIndex) const;
|
---|
606 |
|
---|
607 | protected:
|
---|
608 |
|
---|
609 | /** Returns whether item in the row indicated by the given @a iSourceRow and @a srcParenIdx should be included in the model. */
|
---|
610 | virtual bool filterAcceptsRow(int iSourceRow, const QModelIndex &srcParenIdx) const RT_OVERRIDE;
|
---|
611 | };
|
---|
612 |
|
---|
613 |
|
---|
614 | /** QITableView extension used as Form Editor table-view. */
|
---|
615 | class UIFormEditorView : public QITableView
|
---|
616 | {
|
---|
617 | Q_OBJECT;
|
---|
618 |
|
---|
619 | public:
|
---|
620 |
|
---|
621 | /** Constructs Form Editor table-view. */
|
---|
622 | UIFormEditorView(QWidget *pParent = 0);
|
---|
623 |
|
---|
624 | protected:
|
---|
625 |
|
---|
626 | /** Returns the number of children. */
|
---|
627 | virtual int childCount() const RT_OVERRIDE;
|
---|
628 | /** Returns the child item with @a iIndex. */
|
---|
629 | virtual QITableViewRow *childItem(int iIndex) const RT_OVERRIDE;
|
---|
630 | };
|
---|
631 |
|
---|
632 |
|
---|
633 | /*********************************************************************************************************************************
|
---|
634 | * Class TextEditor implementation. *
|
---|
635 | *********************************************************************************************************************************/
|
---|
636 |
|
---|
637 | TextEditor::TextEditor(QWidget *pParent /* = 0 */)
|
---|
638 | : QIWithRetranslateUI<QWidget>(pParent)
|
---|
639 | , m_pButton(0)
|
---|
640 | {
|
---|
641 | prepare();
|
---|
642 | }
|
---|
643 |
|
---|
644 | void TextEditor::retranslateUi()
|
---|
645 | {
|
---|
646 | m_pButton->setText(UIFormEditorWidget::tr("Edit..."));
|
---|
647 | }
|
---|
648 |
|
---|
649 | void TextEditor::sltHandleButtonClick()
|
---|
650 | {
|
---|
651 | /* Redirect the edit call if possible: */
|
---|
652 | do
|
---|
653 | {
|
---|
654 | /* Get the view: */
|
---|
655 | if ( !parent()
|
---|
656 | || !parent()->parent())
|
---|
657 | break;
|
---|
658 | UIFormEditorView *pView = qobject_cast<UIFormEditorView*>(parent()->parent());
|
---|
659 |
|
---|
660 | /* Get the proxy model: */
|
---|
661 | if ( !pView
|
---|
662 | || !pView->model())
|
---|
663 | break;
|
---|
664 | UIFormEditorProxyModel *pProxyModel = qobject_cast<UIFormEditorProxyModel*>(pView->model());
|
---|
665 |
|
---|
666 | /* Get the source model: */
|
---|
667 | if ( !pProxyModel
|
---|
668 | || !pProxyModel->sourceModel())
|
---|
669 | break;
|
---|
670 | UIFormEditorModel *pSourceModel = qobject_cast<UIFormEditorModel*>(pProxyModel->sourceModel());
|
---|
671 |
|
---|
672 | /* Execute the call: */
|
---|
673 | if (!pSourceModel)
|
---|
674 | break;
|
---|
675 | pSourceModel->createTextDataEditor(m_index);
|
---|
676 | }
|
---|
677 | while (0);
|
---|
678 | }
|
---|
679 |
|
---|
680 | void TextEditor::prepare()
|
---|
681 | {
|
---|
682 | /* Create layout: */
|
---|
683 | QVBoxLayout *pLayout = new QVBoxLayout(this);
|
---|
684 | if (pLayout)
|
---|
685 | {
|
---|
686 | pLayout->setContentsMargins(0, 0, 0 ,0);
|
---|
687 | /* Create button: */
|
---|
688 | m_pButton = new QPushButton(this);
|
---|
689 | if (m_pButton)
|
---|
690 | {
|
---|
691 | connect(m_pButton, &QPushButton::clicked, this, &TextEditor::sltHandleButtonClick);
|
---|
692 | pLayout->addWidget(m_pButton);
|
---|
693 | }
|
---|
694 | }
|
---|
695 |
|
---|
696 | /* Apply language settings: */
|
---|
697 | retranslateUi();
|
---|
698 | }
|
---|
699 |
|
---|
700 | void TextEditor::setText(const TextData &text)
|
---|
701 | {
|
---|
702 | m_strMultilineText = text.text();
|
---|
703 | m_index = text.index();
|
---|
704 | }
|
---|
705 |
|
---|
706 | TextData TextEditor::text() const
|
---|
707 | {
|
---|
708 | return TextData(m_strMultilineText, m_index);
|
---|
709 | }
|
---|
710 |
|
---|
711 |
|
---|
712 | /*********************************************************************************************************************************
|
---|
713 | * Class ChoiceEditor implementation. *
|
---|
714 | *********************************************************************************************************************************/
|
---|
715 |
|
---|
716 | ChoiceEditor::ChoiceEditor(QWidget *pParent /* = 0 */)
|
---|
717 | : QComboBox(pParent)
|
---|
718 | {
|
---|
719 | /* Make sure QIStyledDelegate aware of us: */
|
---|
720 | setProperty("has_sigCommitData", true);
|
---|
721 | /* Configure connections: */
|
---|
722 | connect(this, static_cast<void(ChoiceEditor::*)(int)>(&ChoiceEditor::currentIndexChanged),
|
---|
723 | this, &ChoiceEditor::sltCurrentIndexChanged);
|
---|
724 | }
|
---|
725 |
|
---|
726 | void ChoiceEditor::sltCurrentIndexChanged()
|
---|
727 | {
|
---|
728 | emit sigCommitData(this);
|
---|
729 | }
|
---|
730 |
|
---|
731 | void ChoiceEditor::setChoice(const ChoiceData &choice)
|
---|
732 | {
|
---|
733 | clear();
|
---|
734 | addItems(choice.values().toList());
|
---|
735 | setCurrentIndex(choice.selectedIndex());
|
---|
736 | }
|
---|
737 |
|
---|
738 | ChoiceData ChoiceEditor::choice() const
|
---|
739 | {
|
---|
740 | QVector<QString> choices(count());
|
---|
741 | for (int i = 0; i < count(); ++i)
|
---|
742 | choices[i] = itemText(i);
|
---|
743 | return ChoiceData(choices, currentIndex());
|
---|
744 | }
|
---|
745 |
|
---|
746 |
|
---|
747 | /*********************************************************************************************************************************
|
---|
748 | * Class RangedIntegerEditor implementation. *
|
---|
749 | *********************************************************************************************************************************/
|
---|
750 |
|
---|
751 | RangedIntegerEditor::RangedIntegerEditor(QWidget *pParent /* = 0 */)
|
---|
752 | : QSpinBox(pParent)
|
---|
753 | {
|
---|
754 | }
|
---|
755 |
|
---|
756 | void RangedIntegerEditor::setRangedInteger(const RangedIntegerData &rangedInteger)
|
---|
757 | {
|
---|
758 | setMinimum(rangedInteger.minimum());
|
---|
759 | setMaximum(rangedInteger.maximum());
|
---|
760 | setValue(rangedInteger.integer());
|
---|
761 | m_strSuffix = rangedInteger.suffix();
|
---|
762 | setSuffix(m_strSuffix.isEmpty() ? QString() :
|
---|
763 | QString(" %1").arg(QApplication::translate("UICommon", m_strSuffix.toUtf8().constData())));
|
---|
764 | }
|
---|
765 |
|
---|
766 | RangedIntegerData RangedIntegerEditor::rangedInteger() const
|
---|
767 | {
|
---|
768 | return RangedIntegerData(minimum(), maximum(), value(), m_strSuffix);
|
---|
769 | }
|
---|
770 |
|
---|
771 |
|
---|
772 | /*********************************************************************************************************************************
|
---|
773 | * Class RangedInteger64Editor implementation. *
|
---|
774 | *********************************************************************************************************************************/
|
---|
775 |
|
---|
776 | RangedInteger64Editor::RangedInteger64Editor(QWidget *pParent /* = 0 */)
|
---|
777 | : QLineEdit(pParent)
|
---|
778 | , m_iMinimumGuestRAM(0)
|
---|
779 | , m_iMaximumGuestRAM(0)
|
---|
780 | , m_iMinimum(0)
|
---|
781 | , m_iMaximum(0)
|
---|
782 | {
|
---|
783 | /* Acquire min/max amount of RAM guest in theory could have: */
|
---|
784 | CSystemProperties comProps = uiCommon().virtualBox().GetSystemProperties();
|
---|
785 | if (comProps.isOk())
|
---|
786 | {
|
---|
787 | m_iMinimumGuestRAM = comProps.GetMinGuestRAM();
|
---|
788 | m_iMaximumGuestRAM = comProps.GetMaxGuestRAM();
|
---|
789 | }
|
---|
790 | }
|
---|
791 |
|
---|
792 | void RangedInteger64Editor::setRangedInteger64(const RangedInteger64Data &rangedInteger64)
|
---|
793 | {
|
---|
794 | /* Parse incoming rangedInteger64: */
|
---|
795 | m_iMinimum = rangedInteger64.minimum();
|
---|
796 | m_iMaximum = rangedInteger64.maximum();
|
---|
797 | m_strSuffix = rangedInteger64.suffix();
|
---|
798 | const qlonglong iValue = rangedInteger64.integer();
|
---|
799 |
|
---|
800 | /* Acquire effective values: */
|
---|
801 | qlonglong iMinEffective = 0;
|
---|
802 | qlonglong iMaxEffective = 0;
|
---|
803 | qlonglong iValueEffective = 0;
|
---|
804 | /* We wish to represent bytes as megabytes: */
|
---|
805 | if (m_strSuffix == "B")
|
---|
806 | {
|
---|
807 | iMinEffective = m_iMinimum / _1M;
|
---|
808 | iMaxEffective = m_iMaximum / _1M;
|
---|
809 | iValueEffective = iValue / _1M;
|
---|
810 | }
|
---|
811 | /* For now we will keep all the other suffixes untouched: */
|
---|
812 | else
|
---|
813 | {
|
---|
814 | iMinEffective = m_iMinimum;
|
---|
815 | iMaxEffective = m_iMaximum;
|
---|
816 | iValueEffective = iValue;
|
---|
817 | }
|
---|
818 |
|
---|
819 | /* Make sure minimum, maximum and actual values are within the bounds: */
|
---|
820 | iMinEffective = qMax(iMinEffective, m_iMinimumGuestRAM);
|
---|
821 | iMaxEffective = qMin(iMaxEffective, m_iMaximumGuestRAM);
|
---|
822 | iValueEffective = qMax(iValueEffective, m_iMinimumGuestRAM);
|
---|
823 | iValueEffective = qMin(iValueEffective, m_iMaximumGuestRAM);
|
---|
824 |
|
---|
825 | /* Finally assign validator bounds and actual value: */
|
---|
826 | setValidator(new QIntValidator((int)iMinEffective, (int)iMaxEffective, this));
|
---|
827 | setText(QString::number(iValueEffective));
|
---|
828 | }
|
---|
829 |
|
---|
830 | RangedInteger64Data RangedInteger64Editor::rangedInteger64() const
|
---|
831 | {
|
---|
832 | const qlonglong iValueEffective = locale().toLongLong(text());
|
---|
833 |
|
---|
834 | /* Acquire literal value: */
|
---|
835 | qlonglong iValue = 0;
|
---|
836 | /* We should bring megabytes back to bytes: */
|
---|
837 | if (m_strSuffix == "B")
|
---|
838 | iValue = iValueEffective * _1M;
|
---|
839 | /* For now we will keep all the other suffixes untouched: */
|
---|
840 | else
|
---|
841 | iValue = iValueEffective;
|
---|
842 | return RangedInteger64Data(m_iMinimum, m_iMaximum, iValue, m_strSuffix);
|
---|
843 | }
|
---|
844 |
|
---|
845 |
|
---|
846 | /*********************************************************************************************************************************
|
---|
847 | * Class UIFormEditorCell implementation. *
|
---|
848 | *********************************************************************************************************************************/
|
---|
849 |
|
---|
850 | UIFormEditorCell::UIFormEditorCell(QITableViewRow *pParent, const QString &strText /* = QString() */)
|
---|
851 | : QITableViewCell(pParent)
|
---|
852 | , m_strText(strText)
|
---|
853 | {
|
---|
854 | }
|
---|
855 |
|
---|
856 |
|
---|
857 | /*********************************************************************************************************************************
|
---|
858 | * Class UIFormEditorRow implementation. *
|
---|
859 | *********************************************************************************************************************************/
|
---|
860 |
|
---|
861 | UIFormEditorRow::UIFormEditorRow(QITableView *pParent, UIFormEditorWidget *pFormEditorWidget, const CFormValue &comValue)
|
---|
862 | : QITableViewRow(pParent)
|
---|
863 | , m_pFormEditorWidget(pFormEditorWidget)
|
---|
864 | , m_comValue(comValue)
|
---|
865 | , m_enmValueType(KFormValueType_Max)
|
---|
866 | , m_iGeneration(0)
|
---|
867 | , m_fBool(false)
|
---|
868 | , m_fMultilineString(false)
|
---|
869 | , m_text(TextData())
|
---|
870 | , m_strString(QString())
|
---|
871 | , m_choice(ChoiceData())
|
---|
872 | , m_rangedInteger(RangedIntegerData())
|
---|
873 | , m_rangedInteger64(RangedInteger64Data())
|
---|
874 | {
|
---|
875 | prepare();
|
---|
876 | }
|
---|
877 |
|
---|
878 | UIFormEditorRow::~UIFormEditorRow()
|
---|
879 | {
|
---|
880 | cleanup();
|
---|
881 | }
|
---|
882 |
|
---|
883 | QString UIFormEditorRow::nameToString() const
|
---|
884 | {
|
---|
885 | return m_cells.at(UIFormEditorDataType_Name)->text();
|
---|
886 | }
|
---|
887 |
|
---|
888 | QString UIFormEditorRow::valueToString() const
|
---|
889 | {
|
---|
890 | return m_cells.at(UIFormEditorDataType_Value)->text();
|
---|
891 | }
|
---|
892 |
|
---|
893 | bool UIFormEditorRow::isEnabled() const
|
---|
894 | {
|
---|
895 | return m_comValue.GetEnabled();
|
---|
896 | }
|
---|
897 |
|
---|
898 | bool UIFormEditorRow::isVisible() const
|
---|
899 | {
|
---|
900 | return m_comValue.GetVisible();
|
---|
901 | }
|
---|
902 |
|
---|
903 | bool UIFormEditorRow::toBool() const
|
---|
904 | {
|
---|
905 | AssertReturn(valueType() == KFormValueType_Boolean, false);
|
---|
906 | return m_fBool;
|
---|
907 | }
|
---|
908 |
|
---|
909 | void UIFormEditorRow::setBool(bool fBool)
|
---|
910 | {
|
---|
911 | AssertReturnVoid(valueType() == KFormValueType_Boolean);
|
---|
912 | CBooleanFormValue comValue(m_comValue);
|
---|
913 | UINotificationProgressVsdFormValueSet *pNotification = new UINotificationProgressVsdFormValueSet(comValue,
|
---|
914 | fBool);
|
---|
915 | UINotificationCenter *pCenter = m_pFormEditorWidget->notificationCenter()
|
---|
916 | ? m_pFormEditorWidget->notificationCenter() : gpNotificationCenter;
|
---|
917 | pCenter->handleNow(pNotification);
|
---|
918 | updateValueCells();
|
---|
919 | }
|
---|
920 |
|
---|
921 | bool UIFormEditorRow::isMultilineString() const
|
---|
922 | {
|
---|
923 | AssertReturn(valueType() == KFormValueType_String, false);
|
---|
924 | return m_fMultilineString;
|
---|
925 | }
|
---|
926 |
|
---|
927 | TextData UIFormEditorRow::toText() const
|
---|
928 | {
|
---|
929 | AssertReturn(valueType() == KFormValueType_String, TextData());
|
---|
930 | return m_text;
|
---|
931 | }
|
---|
932 |
|
---|
933 | void UIFormEditorRow::setText(const TextData &text)
|
---|
934 | {
|
---|
935 | AssertReturnVoid(valueType() == KFormValueType_String);
|
---|
936 | CStringFormValue comValue(m_comValue);
|
---|
937 | UINotificationProgressVsdFormValueSet *pNotification = new UINotificationProgressVsdFormValueSet(comValue,
|
---|
938 | text.text());
|
---|
939 | UINotificationCenter *pCenter = m_pFormEditorWidget->notificationCenter()
|
---|
940 | ? m_pFormEditorWidget->notificationCenter() : gpNotificationCenter;
|
---|
941 | pCenter->handleNow(pNotification);
|
---|
942 | updateValueCells();
|
---|
943 | }
|
---|
944 |
|
---|
945 | QString UIFormEditorRow::toString() const
|
---|
946 | {
|
---|
947 | AssertReturn(valueType() == KFormValueType_String, QString());
|
---|
948 | return m_strString;
|
---|
949 | }
|
---|
950 |
|
---|
951 | void UIFormEditorRow::setString(const QString &strString)
|
---|
952 | {
|
---|
953 | AssertReturnVoid(valueType() == KFormValueType_String);
|
---|
954 | CStringFormValue comValue(m_comValue);
|
---|
955 | UINotificationProgressVsdFormValueSet *pNotification = new UINotificationProgressVsdFormValueSet(comValue,
|
---|
956 | strString);
|
---|
957 | UINotificationCenter *pCenter = m_pFormEditorWidget->notificationCenter()
|
---|
958 | ? m_pFormEditorWidget->notificationCenter() : gpNotificationCenter;
|
---|
959 | pCenter->handleNow(pNotification);
|
---|
960 | updateValueCells();
|
---|
961 | }
|
---|
962 |
|
---|
963 | ChoiceData UIFormEditorRow::toChoice() const
|
---|
964 | {
|
---|
965 | AssertReturn(valueType() == KFormValueType_Choice, ChoiceData());
|
---|
966 | return m_choice;
|
---|
967 | }
|
---|
968 |
|
---|
969 | void UIFormEditorRow::setChoice(const ChoiceData &choice)
|
---|
970 | {
|
---|
971 | /* Do nothing for empty choices: */
|
---|
972 | if (choice.selectedIndex() == -1)
|
---|
973 | return;
|
---|
974 |
|
---|
975 | AssertReturnVoid(valueType() == KFormValueType_Choice);
|
---|
976 | CChoiceFormValue comValue(m_comValue);
|
---|
977 | UINotificationProgressVsdFormValueSet *pNotification = new UINotificationProgressVsdFormValueSet(comValue,
|
---|
978 | choice.selectedIndex());
|
---|
979 | UINotificationCenter *pCenter = m_pFormEditorWidget->notificationCenter()
|
---|
980 | ? m_pFormEditorWidget->notificationCenter() : gpNotificationCenter;
|
---|
981 | pCenter->handleNow(pNotification);
|
---|
982 | updateValueCells();
|
---|
983 | }
|
---|
984 |
|
---|
985 | RangedIntegerData UIFormEditorRow::toRangedInteger() const
|
---|
986 | {
|
---|
987 | AssertReturn(valueType() == KFormValueType_RangedInteger, RangedIntegerData());
|
---|
988 | return m_rangedInteger;
|
---|
989 | }
|
---|
990 |
|
---|
991 | void UIFormEditorRow::setRangedInteger(const RangedIntegerData &rangedInteger)
|
---|
992 | {
|
---|
993 | AssertReturnVoid(valueType() == KFormValueType_RangedInteger);
|
---|
994 | CRangedIntegerFormValue comValue(m_comValue);
|
---|
995 | UINotificationProgressVsdFormValueSet *pNotification = new UINotificationProgressVsdFormValueSet(comValue,
|
---|
996 | rangedInteger.integer());
|
---|
997 | UINotificationCenter *pCenter = m_pFormEditorWidget->notificationCenter()
|
---|
998 | ? m_pFormEditorWidget->notificationCenter() : gpNotificationCenter;
|
---|
999 | pCenter->handleNow(pNotification);
|
---|
1000 | updateValueCells();
|
---|
1001 | }
|
---|
1002 |
|
---|
1003 | RangedInteger64Data UIFormEditorRow::toRangedInteger64() const
|
---|
1004 | {
|
---|
1005 | AssertReturn(valueType() == KFormValueType_RangedInteger64, RangedInteger64Data());
|
---|
1006 | return m_rangedInteger64;
|
---|
1007 | }
|
---|
1008 |
|
---|
1009 | void UIFormEditorRow::setRangedInteger64(const RangedInteger64Data &rangedInteger64)
|
---|
1010 | {
|
---|
1011 | AssertReturnVoid(valueType() == KFormValueType_RangedInteger64);
|
---|
1012 | CRangedInteger64FormValue comValue(m_comValue);
|
---|
1013 | UINotificationProgressVsdFormValueSet *pNotification = new UINotificationProgressVsdFormValueSet(comValue,
|
---|
1014 | rangedInteger64.integer());
|
---|
1015 | UINotificationCenter *pCenter = m_pFormEditorWidget->notificationCenter()
|
---|
1016 | ? m_pFormEditorWidget->notificationCenter() : gpNotificationCenter;
|
---|
1017 | pCenter->handleNow(pNotification);
|
---|
1018 | updateValueCells();
|
---|
1019 | }
|
---|
1020 |
|
---|
1021 | void UIFormEditorRow::updateValueCells()
|
---|
1022 | {
|
---|
1023 | m_iGeneration = m_comValue.GetGeneration();
|
---|
1024 | /// @todo check for errors
|
---|
1025 |
|
---|
1026 | switch (m_enmValueType)
|
---|
1027 | {
|
---|
1028 | case KFormValueType_Boolean:
|
---|
1029 | {
|
---|
1030 | CBooleanFormValue comValue(m_comValue);
|
---|
1031 | m_fBool = comValue.GetSelected();
|
---|
1032 | m_cells[UIFormEditorDataType_Value]->setText(m_fBool ? "True" : "False");
|
---|
1033 | /// @todo check for errors
|
---|
1034 | break;
|
---|
1035 | }
|
---|
1036 | case KFormValueType_String:
|
---|
1037 | {
|
---|
1038 | CStringFormValue comValue(m_comValue);
|
---|
1039 | m_fMultilineString = comValue.GetMultiline();
|
---|
1040 | const QString strString = comValue.GetString();
|
---|
1041 | if (m_fMultilineString)
|
---|
1042 | m_text = TextData(strString);
|
---|
1043 | else
|
---|
1044 | m_strString = strString;
|
---|
1045 | m_cells[UIFormEditorDataType_Value]->setText(strString);
|
---|
1046 | /// @todo check for errors
|
---|
1047 | break;
|
---|
1048 | }
|
---|
1049 | case KFormValueType_Choice:
|
---|
1050 | {
|
---|
1051 | CChoiceFormValue comValue(m_comValue);
|
---|
1052 | const QVector<QString> values = comValue.GetValues();
|
---|
1053 | const int iSelectedIndex = comValue.GetSelectedIndex();
|
---|
1054 | m_choice = ChoiceData(values, iSelectedIndex);
|
---|
1055 | m_cells[UIFormEditorDataType_Value]->setText(m_choice.selectedValue());
|
---|
1056 | /// @todo check for errors
|
---|
1057 | break;
|
---|
1058 | }
|
---|
1059 | case KFormValueType_RangedInteger:
|
---|
1060 | {
|
---|
1061 | CRangedIntegerFormValue comValue(m_comValue);
|
---|
1062 | const int iMinimum = comValue.GetMinimum();
|
---|
1063 | const int iMaximum = comValue.GetMaximum();
|
---|
1064 | const int iInteger = comValue.GetInteger();
|
---|
1065 | const QString strSuffix = comValue.GetSuffix();
|
---|
1066 | m_rangedInteger = RangedIntegerData(iMinimum, iMaximum, iInteger, strSuffix);
|
---|
1067 | m_cells[UIFormEditorDataType_Value]->setText( strSuffix.isEmpty()
|
---|
1068 | ? QString::number(iInteger)
|
---|
1069 | : QString("%1 %2").arg(iInteger)
|
---|
1070 | .arg(strSuffix));
|
---|
1071 | /// @todo check for errors
|
---|
1072 | break;
|
---|
1073 | }
|
---|
1074 | case KFormValueType_RangedInteger64:
|
---|
1075 | {
|
---|
1076 | CRangedInteger64FormValue comValue(m_comValue);
|
---|
1077 | const qlonglong iMinimum = comValue.GetMinimum();
|
---|
1078 | const qlonglong iMaximum = comValue.GetMaximum();
|
---|
1079 | const qlonglong iInteger = comValue.GetInteger();
|
---|
1080 | const QString strSuffix = comValue.GetSuffix();
|
---|
1081 | m_rangedInteger64 = RangedInteger64Data(iMinimum, iMaximum, iInteger, strSuffix);
|
---|
1082 | /* Display suffix and effective value can be different: */
|
---|
1083 | QString strEffectiveSuffix = strSuffix;
|
---|
1084 | QString strEffectiveValue;
|
---|
1085 | if (strSuffix.isEmpty())
|
---|
1086 | strEffectiveValue = QString::number(iInteger);
|
---|
1087 | else if (strSuffix != "B")
|
---|
1088 | strEffectiveValue = QString("%1 %2").arg(iInteger).arg(strEffectiveSuffix);
|
---|
1089 | else
|
---|
1090 | {
|
---|
1091 | /* We wish to convert bytes to megabytes: */
|
---|
1092 | strEffectiveSuffix = "MB";
|
---|
1093 | strEffectiveValue = QString("%1 %2").arg(iInteger / _1M).arg(strEffectiveSuffix);
|
---|
1094 | }
|
---|
1095 | m_cells[UIFormEditorDataType_Value]->setText(strEffectiveValue);
|
---|
1096 | /// @todo check for errors
|
---|
1097 | break;
|
---|
1098 | }
|
---|
1099 | default:
|
---|
1100 | break;
|
---|
1101 | }
|
---|
1102 | }
|
---|
1103 |
|
---|
1104 | bool UIFormEditorRow::isGenerationChanged() const
|
---|
1105 | {
|
---|
1106 | const int iGeneration = m_comValue.GetGeneration();
|
---|
1107 | /// @todo check for errors
|
---|
1108 | return m_iGeneration != iGeneration;
|
---|
1109 | }
|
---|
1110 |
|
---|
1111 | int UIFormEditorRow::childCount() const
|
---|
1112 | {
|
---|
1113 | /* Return cell count: */
|
---|
1114 | return UIFormEditorDataType_Max;
|
---|
1115 | }
|
---|
1116 |
|
---|
1117 | QITableViewCell *UIFormEditorRow::childItem(int iIndex) const
|
---|
1118 | {
|
---|
1119 | /* Make sure index within the bounds: */
|
---|
1120 | AssertReturn(iIndex >= 0 && iIndex < m_cells.size(), 0);
|
---|
1121 | /* Return corresponding cell: */
|
---|
1122 | return m_cells.at(iIndex);
|
---|
1123 | }
|
---|
1124 |
|
---|
1125 | void UIFormEditorRow::prepare()
|
---|
1126 | {
|
---|
1127 | /* Cache value type: */
|
---|
1128 | m_enmValueType = m_comValue.GetType();
|
---|
1129 | /// @todo check for errors
|
---|
1130 |
|
---|
1131 | /* Create cells on the basis of variables we have: */
|
---|
1132 | m_cells.resize(UIFormEditorDataType_Max);
|
---|
1133 | const QString strName = m_comValue.GetLabel();
|
---|
1134 | /// @todo check for errors
|
---|
1135 | m_cells[UIFormEditorDataType_Name] = new UIFormEditorCell(this, strName);
|
---|
1136 | m_cells[UIFormEditorDataType_Value] = new UIFormEditorCell(this);
|
---|
1137 | updateValueCells();
|
---|
1138 | }
|
---|
1139 |
|
---|
1140 | void UIFormEditorRow::cleanup()
|
---|
1141 | {
|
---|
1142 | /* Destroy cells: */
|
---|
1143 | qDeleteAll(m_cells);
|
---|
1144 | m_cells.clear();
|
---|
1145 | }
|
---|
1146 |
|
---|
1147 |
|
---|
1148 | /*********************************************************************************************************************************
|
---|
1149 | * Class UIFormEditorModel implementation. *
|
---|
1150 | *********************************************************************************************************************************/
|
---|
1151 |
|
---|
1152 | UIFormEditorModel::UIFormEditorModel(UIFormEditorWidget *pParent)
|
---|
1153 | : QAbstractTableModel(pParent)
|
---|
1154 | , m_pFormEditorWidget(pParent)
|
---|
1155 | {
|
---|
1156 | prepare();
|
---|
1157 | }
|
---|
1158 |
|
---|
1159 | UIFormEditorModel::~UIFormEditorModel()
|
---|
1160 | {
|
---|
1161 | /* Delete the cached data: */
|
---|
1162 | qDeleteAll(m_dataList);
|
---|
1163 | m_dataList.clear();
|
---|
1164 | }
|
---|
1165 |
|
---|
1166 | void UIFormEditorModel::clearForm()
|
---|
1167 | {
|
---|
1168 | beginRemoveRows(QModelIndex(), 0, m_dataList.size());
|
---|
1169 | qDeleteAll(m_dataList);
|
---|
1170 | m_dataList.clear();
|
---|
1171 | endRemoveRows();
|
---|
1172 | }
|
---|
1173 |
|
---|
1174 | void UIFormEditorModel::setFormValues(const CFormValueVector &values)
|
---|
1175 | {
|
---|
1176 | /* Delete old lines: */
|
---|
1177 | clearForm();
|
---|
1178 |
|
---|
1179 | /* Add new lines: */
|
---|
1180 | beginInsertRows(QModelIndex(), 0, values.size() - 1);
|
---|
1181 | foreach (const CFormValue &comValue, values)
|
---|
1182 | m_dataList << new UIFormEditorRow(view(), m_pFormEditorWidget, comValue);
|
---|
1183 | endInsertRows();
|
---|
1184 | }
|
---|
1185 |
|
---|
1186 | int UIFormEditorModel::childCount() const
|
---|
1187 | {
|
---|
1188 | return rowCount();
|
---|
1189 | }
|
---|
1190 |
|
---|
1191 | QITableViewRow *UIFormEditorModel::childItem(int iIndex) const
|
---|
1192 | {
|
---|
1193 | /* Make sure index within the bounds: */
|
---|
1194 | AssertReturn(iIndex >= 0 && iIndex < m_dataList.size(), 0);
|
---|
1195 | /* Return corresponding row: */
|
---|
1196 | return m_dataList[iIndex];
|
---|
1197 | }
|
---|
1198 |
|
---|
1199 | QModelIndex UIFormEditorModel::index(int iRow, int iColumn, const QModelIndex &parentIdx /* = QModelIndex() */) const
|
---|
1200 | {
|
---|
1201 | /* No index for unknown items: */
|
---|
1202 | if (!hasIndex(iRow, iColumn, parentIdx))
|
---|
1203 | return QModelIndex();
|
---|
1204 |
|
---|
1205 | /* Provide index users with packed item pointer: */
|
---|
1206 | UIFormEditorRow *pItem = iRow >= 0 && iRow < m_dataList.size() ? m_dataList.at(iRow) : 0;
|
---|
1207 | return pItem ? createIndex(iRow, iColumn, pItem) : QModelIndex();
|
---|
1208 | }
|
---|
1209 |
|
---|
1210 | Qt::ItemFlags UIFormEditorModel::flags(const QModelIndex &index) const
|
---|
1211 | {
|
---|
1212 | /* Check index validness: */
|
---|
1213 | if (!index.isValid())
|
---|
1214 | return Qt::NoItemFlags;
|
---|
1215 | /* Switch for different columns: */
|
---|
1216 | switch (index.column())
|
---|
1217 | {
|
---|
1218 | case UIFormEditorDataType_Name:
|
---|
1219 | return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
---|
1220 | case UIFormEditorDataType_Value:
|
---|
1221 | {
|
---|
1222 | Qt::ItemFlags enmFlags = Qt::NoItemFlags;
|
---|
1223 | if (m_dataList[index.row()]->isEnabled())
|
---|
1224 | {
|
---|
1225 | enmFlags |= Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
---|
1226 | enmFlags |= m_dataList[index.row()]->valueType() == KFormValueType_Boolean
|
---|
1227 | ? Qt::ItemIsUserCheckable : Qt::ItemIsEditable;
|
---|
1228 | }
|
---|
1229 | return enmFlags;
|
---|
1230 | }
|
---|
1231 | default:
|
---|
1232 | return Qt::NoItemFlags;
|
---|
1233 | }
|
---|
1234 | }
|
---|
1235 |
|
---|
1236 | int UIFormEditorModel::rowCount(const QModelIndex &) const
|
---|
1237 | {
|
---|
1238 | return m_dataList.size();
|
---|
1239 | }
|
---|
1240 |
|
---|
1241 | int UIFormEditorModel::columnCount(const QModelIndex &) const
|
---|
1242 | {
|
---|
1243 | return UIFormEditorDataType_Max;
|
---|
1244 | }
|
---|
1245 |
|
---|
1246 | QVariant UIFormEditorModel::headerData(int iSection, Qt::Orientation enmOrientation, int iRole) const
|
---|
1247 | {
|
---|
1248 | /* Check argument validness: */
|
---|
1249 | if (iRole != Qt::DisplayRole || enmOrientation != Qt::Horizontal)
|
---|
1250 | return QVariant();
|
---|
1251 | /* Switch for different columns: */
|
---|
1252 | switch (iSection)
|
---|
1253 | {
|
---|
1254 | case UIFormEditorDataType_Name:
|
---|
1255 | return UIFormEditorWidget::tr("Name");
|
---|
1256 | case UIFormEditorDataType_Value:
|
---|
1257 | return UIFormEditorWidget::tr("Value");
|
---|
1258 | default:
|
---|
1259 | return QVariant();
|
---|
1260 | }
|
---|
1261 | }
|
---|
1262 |
|
---|
1263 | bool UIFormEditorModel::setData(const QModelIndex &index, const QVariant &value, int iRole /* = Qt::EditRole */)
|
---|
1264 | {
|
---|
1265 | /* Check index validness: */
|
---|
1266 | if (!index.isValid())
|
---|
1267 | return false;
|
---|
1268 | /* Switch for different roles: */
|
---|
1269 | switch (iRole)
|
---|
1270 | {
|
---|
1271 | /* Checkstate role: */
|
---|
1272 | case Qt::CheckStateRole:
|
---|
1273 | {
|
---|
1274 | /* Switch for different columns: */
|
---|
1275 | switch (index.column())
|
---|
1276 | {
|
---|
1277 | case UIFormEditorDataType_Value:
|
---|
1278 | {
|
---|
1279 | if (m_dataList[index.row()]->valueType() == KFormValueType_Boolean)
|
---|
1280 | {
|
---|
1281 | const Qt::CheckState enmCheckState = static_cast<Qt::CheckState>(value.toInt());
|
---|
1282 | m_dataList[index.row()]->setBool(enmCheckState == Qt::Checked);
|
---|
1283 | emit dataChanged(index, index);
|
---|
1284 | updateGeneration();
|
---|
1285 | return true;
|
---|
1286 | }
|
---|
1287 | else
|
---|
1288 | return false;
|
---|
1289 | }
|
---|
1290 | default:
|
---|
1291 | return false;
|
---|
1292 | }
|
---|
1293 | }
|
---|
1294 | /* Edit role: */
|
---|
1295 | case Qt::EditRole:
|
---|
1296 | {
|
---|
1297 | /* Switch for different columns: */
|
---|
1298 | switch (index.column())
|
---|
1299 | {
|
---|
1300 | case UIFormEditorDataType_Value:
|
---|
1301 | {
|
---|
1302 | switch (m_dataList[index.row()]->valueType())
|
---|
1303 | {
|
---|
1304 | case KFormValueType_String:
|
---|
1305 | {
|
---|
1306 | if (value.canConvert<TextData>())
|
---|
1307 | m_dataList[index.row()]->setText(value.value<TextData>());
|
---|
1308 | else
|
---|
1309 | m_dataList[index.row()]->setString(value.toString());
|
---|
1310 | emit dataChanged(index, index);
|
---|
1311 | updateGeneration();
|
---|
1312 | return true;
|
---|
1313 | }
|
---|
1314 | case KFormValueType_Choice:
|
---|
1315 | {
|
---|
1316 | m_dataList[index.row()]->setChoice(value.value<ChoiceData>());
|
---|
1317 | emit dataChanged(index, index);
|
---|
1318 | updateGeneration();
|
---|
1319 | return true;
|
---|
1320 | }
|
---|
1321 | case KFormValueType_RangedInteger:
|
---|
1322 | {
|
---|
1323 | m_dataList[index.row()]->setRangedInteger(value.value<RangedIntegerData>());
|
---|
1324 | emit dataChanged(index, index);
|
---|
1325 | updateGeneration();
|
---|
1326 | return true;
|
---|
1327 | }
|
---|
1328 | case KFormValueType_RangedInteger64:
|
---|
1329 | {
|
---|
1330 | m_dataList[index.row()]->setRangedInteger64(value.value<RangedInteger64Data>());
|
---|
1331 | emit dataChanged(index, index);
|
---|
1332 | updateGeneration();
|
---|
1333 | return true;
|
---|
1334 | }
|
---|
1335 | default:
|
---|
1336 | return false;
|
---|
1337 | }
|
---|
1338 | }
|
---|
1339 | default:
|
---|
1340 | return false;
|
---|
1341 | }
|
---|
1342 | }
|
---|
1343 | default:
|
---|
1344 | return false;
|
---|
1345 | }
|
---|
1346 | }
|
---|
1347 |
|
---|
1348 | QVariant UIFormEditorModel::data(const QModelIndex &index, int iRole) const
|
---|
1349 | {
|
---|
1350 | /* Check index validness: */
|
---|
1351 | if (!index.isValid())
|
---|
1352 | return QVariant();
|
---|
1353 | /* Switch for different roles: */
|
---|
1354 | switch (iRole)
|
---|
1355 | {
|
---|
1356 | /* Decoration role: */
|
---|
1357 | case Qt::DecorationRole:
|
---|
1358 | {
|
---|
1359 | /* Switch for different columns: */
|
---|
1360 | switch (index.column())
|
---|
1361 | {
|
---|
1362 | case UIFormEditorDataType_Name: return iconHint(m_dataList[index.row()]->nameToString());
|
---|
1363 | default: return QVariant();
|
---|
1364 | }
|
---|
1365 | }
|
---|
1366 | /* Checkstate role: */
|
---|
1367 | case Qt::CheckStateRole:
|
---|
1368 | {
|
---|
1369 | /* Switch for different columns: */
|
---|
1370 | switch (index.column())
|
---|
1371 | {
|
---|
1372 | case UIFormEditorDataType_Value:
|
---|
1373 | return m_dataList[index.row()]->valueType() == KFormValueType_Boolean
|
---|
1374 | ? m_dataList[index.row()]->toBool()
|
---|
1375 | ? Qt::Checked
|
---|
1376 | : Qt::Unchecked
|
---|
1377 | : QVariant();
|
---|
1378 | default:
|
---|
1379 | return QVariant();
|
---|
1380 | }
|
---|
1381 | }
|
---|
1382 | /* Display role: */
|
---|
1383 | case Qt::DisplayRole:
|
---|
1384 | {
|
---|
1385 | /* Switch for different columns: */
|
---|
1386 | switch (index.column())
|
---|
1387 | {
|
---|
1388 | case UIFormEditorDataType_Name:
|
---|
1389 | return m_dataList[index.row()]->nameToString();
|
---|
1390 | case UIFormEditorDataType_Value:
|
---|
1391 | return m_dataList[index.row()]->valueType() != KFormValueType_Boolean
|
---|
1392 | ? m_dataList[index.row()]->valueToString()
|
---|
1393 | : QVariant();
|
---|
1394 | default:
|
---|
1395 | return QVariant();
|
---|
1396 | }
|
---|
1397 | }
|
---|
1398 | /* Edit role: */
|
---|
1399 | case Qt::EditRole:
|
---|
1400 | {
|
---|
1401 | /* Switch for different columns: */
|
---|
1402 | switch (index.column())
|
---|
1403 | {
|
---|
1404 | case UIFormEditorDataType_Value:
|
---|
1405 | {
|
---|
1406 | switch (m_dataList[index.row()]->valueType())
|
---|
1407 | {
|
---|
1408 | case KFormValueType_String:
|
---|
1409 | {
|
---|
1410 | if (m_dataList[index.row()]->isMultilineString())
|
---|
1411 | {
|
---|
1412 | TextData td = m_dataList[index.row()]->toText();
|
---|
1413 | td.setIndex(index);
|
---|
1414 | return QVariant::fromValue(td);
|
---|
1415 | }
|
---|
1416 | else
|
---|
1417 | return QVariant::fromValue(m_dataList[index.row()]->toString());
|
---|
1418 | }
|
---|
1419 | case KFormValueType_Choice:
|
---|
1420 | return QVariant::fromValue(m_dataList[index.row()]->toChoice());
|
---|
1421 | case KFormValueType_RangedInteger:
|
---|
1422 | return QVariant::fromValue(m_dataList[index.row()]->toRangedInteger());
|
---|
1423 | case KFormValueType_RangedInteger64:
|
---|
1424 | return QVariant::fromValue(m_dataList[index.row()]->toRangedInteger64());
|
---|
1425 | default:
|
---|
1426 | return QVariant();
|
---|
1427 | }
|
---|
1428 | }
|
---|
1429 | default:
|
---|
1430 | return QVariant();
|
---|
1431 | }
|
---|
1432 | }
|
---|
1433 | /* Alignment role: */
|
---|
1434 | case Qt::TextAlignmentRole:
|
---|
1435 | {
|
---|
1436 | /* Switch for different columns: */
|
---|
1437 | switch (index.column())
|
---|
1438 | {
|
---|
1439 | case UIFormEditorDataType_Name:
|
---|
1440 | return (int)(Qt::AlignLeft | Qt::AlignVCenter);
|
---|
1441 | case UIFormEditorDataType_Value:
|
---|
1442 | return m_dataList[index.row()]->valueType() != KFormValueType_Boolean
|
---|
1443 | ? (int)(Qt::AlignLeft | Qt::AlignVCenter)
|
---|
1444 | : (int)(Qt::AlignCenter);
|
---|
1445 | default:
|
---|
1446 | return QVariant();
|
---|
1447 | }
|
---|
1448 | }
|
---|
1449 | default:
|
---|
1450 | return QVariant();
|
---|
1451 | }
|
---|
1452 | }
|
---|
1453 |
|
---|
1454 | void UIFormEditorModel::createTextDataEditor(const QModelIndex &index)
|
---|
1455 | {
|
---|
1456 | /* Create dialog on-the-fly: */
|
---|
1457 | QPointer<QIDialog> pDialog = new QIDialog(view());
|
---|
1458 | if (pDialog)
|
---|
1459 | {
|
---|
1460 | /* We will need that pointer: */
|
---|
1461 | QTextEdit *pEditor = 0;
|
---|
1462 | /* Create layout: */
|
---|
1463 | QVBoxLayout *pLayout = new QVBoxLayout(pDialog);
|
---|
1464 | if (pLayout)
|
---|
1465 | {
|
---|
1466 | /* Create text-editor: */
|
---|
1467 | pEditor = new QTextEdit;
|
---|
1468 | if (pEditor)
|
---|
1469 | {
|
---|
1470 | const TextData td = data(index, Qt::EditRole).value<TextData>();
|
---|
1471 | pEditor->setPlainText(td.text());
|
---|
1472 | pLayout->addWidget(pEditor);
|
---|
1473 | }
|
---|
1474 | /* Create button-box: */
|
---|
1475 | QIDialogButtonBox *pBox = new QIDialogButtonBox;
|
---|
1476 | if (pBox)
|
---|
1477 | {
|
---|
1478 | pBox->setStandardButtons(QDialogButtonBox::Cancel | QDialogButtonBox::Ok);
|
---|
1479 | connect(pBox, &QIDialogButtonBox::accepted, pDialog.data(), &QIDialog::accept);
|
---|
1480 | connect(pBox, &QIDialogButtonBox::rejected, pDialog.data(), &QIDialog::reject);
|
---|
1481 | pLayout->addWidget(pBox);
|
---|
1482 | }
|
---|
1483 | }
|
---|
1484 | /* Execute the dialog: */
|
---|
1485 | if (pDialog->execute() == QDialog::Accepted)
|
---|
1486 | {
|
---|
1487 | const TextData td = TextData(pEditor->toPlainText(), index);
|
---|
1488 | setData(index, QVariant::fromValue(td));
|
---|
1489 | }
|
---|
1490 | /* Cleanup: */
|
---|
1491 | delete pDialog;
|
---|
1492 | }
|
---|
1493 | }
|
---|
1494 |
|
---|
1495 | void UIFormEditorModel::prepare()
|
---|
1496 | {
|
---|
1497 | /* Prepare hardcoded icons map: */
|
---|
1498 | m_icons["Name"] = UIIconPool::iconSet(":/name_16px.png");
|
---|
1499 | m_icons["Display Name"] = UIIconPool::iconSet(":/name_16px.png");
|
---|
1500 | m_icons["Type"] = UIIconPool::iconSet(":/system_type_16px.png");
|
---|
1501 | m_icons["Version"] = UIIconPool::iconSet(":/system_version_16px.png");
|
---|
1502 | m_icons["CPU"] = UIIconPool::iconSet(":/cpu_16px.png");
|
---|
1503 | m_icons["Memory"] = UIIconPool::iconSet(":/ram_16px.png");
|
---|
1504 | m_icons["Description"] = UIIconPool::iconSet(":/description_16px.png");
|
---|
1505 | m_icons["Bucket"] = UIIconPool::iconSet(":/bucket_16px.png");
|
---|
1506 | m_icons["Keep Object"] = UIIconPool::iconSet(":/keep_object_16px.png");
|
---|
1507 | m_icons["Launch VM"] = UIIconPool::iconSet(":/launch_vm_16px.png");
|
---|
1508 | m_icons["Availability Domain"] = UIIconPool::iconSet(":/availability_domain_16px.png");
|
---|
1509 | m_icons["Shape"] = UIIconPool::iconSet(":/shape_16px.png");
|
---|
1510 | m_icons["Disk Size"] = UIIconPool::iconSet(":/disk_size_16px.png");
|
---|
1511 | m_icons["VCN"] = UIIconPool::iconSet(":/vcn_16px.png");
|
---|
1512 | m_icons["Subnet"] = UIIconPool::iconSet(":/subnet_16px.png");
|
---|
1513 | m_icons["Assign Public IP"] = UIIconPool::iconSet(":/assign_public_ip_16px.png");
|
---|
1514 | }
|
---|
1515 |
|
---|
1516 | QITableView *UIFormEditorModel::view() const
|
---|
1517 | {
|
---|
1518 | return m_pFormEditorWidget->view();
|
---|
1519 | }
|
---|
1520 |
|
---|
1521 | void UIFormEditorModel::updateGeneration()
|
---|
1522 | {
|
---|
1523 | for (int i = 0; i < m_dataList.size(); ++i)
|
---|
1524 | {
|
---|
1525 | UIFormEditorRow *pRow = m_dataList.at(i);
|
---|
1526 | if (pRow->isGenerationChanged())
|
---|
1527 | {
|
---|
1528 | pRow->updateValueCells();
|
---|
1529 | const QModelIndex changedIndex = index(i, 1);
|
---|
1530 | emit dataChanged(changedIndex, changedIndex);
|
---|
1531 | }
|
---|
1532 | }
|
---|
1533 | }
|
---|
1534 |
|
---|
1535 | QIcon UIFormEditorModel::iconHint(const QString &strItemName) const
|
---|
1536 | {
|
---|
1537 | return m_icons.value(strItemName, UIIconPool::iconSet(":/session_info_16px.png"));
|
---|
1538 | }
|
---|
1539 |
|
---|
1540 |
|
---|
1541 | /*********************************************************************************************************************************
|
---|
1542 | * Class UIFormEditorProxyModel implementation. *
|
---|
1543 | *********************************************************************************************************************************/
|
---|
1544 |
|
---|
1545 | UIFormEditorProxyModel::UIFormEditorProxyModel(QObject *pParent /* = 0 */)
|
---|
1546 | : QSortFilterProxyModel(pParent)
|
---|
1547 | {
|
---|
1548 | }
|
---|
1549 |
|
---|
1550 | int UIFormEditorProxyModel::childCount() const
|
---|
1551 | {
|
---|
1552 | return rowCount();
|
---|
1553 | }
|
---|
1554 |
|
---|
1555 | QITableViewRow *UIFormEditorProxyModel::childItem(int iIndex) const
|
---|
1556 | {
|
---|
1557 | /* Make sure iIndex within the bounds: */
|
---|
1558 | AssertReturn(iIndex >= 0 && iIndex < rowCount(), 0);
|
---|
1559 | /* Acquire actual index of source model: */
|
---|
1560 | const QModelIndex i = sourceModel()->index(iIndex, 0);
|
---|
1561 | AssertReturn(i.isValid(), 0);
|
---|
1562 | /* Get packed item pointer: */
|
---|
1563 | UIFormEditorRow *pItem = static_cast<UIFormEditorRow*>(i.internalPointer());
|
---|
1564 | AssertReturn(pItem, 0);
|
---|
1565 | return pItem;
|
---|
1566 | }
|
---|
1567 |
|
---|
1568 | bool UIFormEditorProxyModel::filterAcceptsRow(int iSourceRow, const QModelIndex &sourceParent) const
|
---|
1569 | {
|
---|
1570 | /* Acquire actual index of source model: */
|
---|
1571 | QModelIndex i = sourceModel()->index(iSourceRow, 0, sourceParent);
|
---|
1572 | if (i.isValid())
|
---|
1573 | {
|
---|
1574 | /* Get packed item pointer: */
|
---|
1575 | UIFormEditorRow *pItem = static_cast<UIFormEditorRow*>(i.internalPointer());
|
---|
1576 | /* Filter invisible items: */
|
---|
1577 | if (!pItem->isVisible())
|
---|
1578 | return false;
|
---|
1579 | }
|
---|
1580 | return true;
|
---|
1581 | }
|
---|
1582 |
|
---|
1583 |
|
---|
1584 | /*********************************************************************************************************************************
|
---|
1585 | * Class UIFormEditorView implementation. *
|
---|
1586 | *********************************************************************************************************************************/
|
---|
1587 |
|
---|
1588 | UIFormEditorView::UIFormEditorView(QWidget * /* pParent = 0 */)
|
---|
1589 | {
|
---|
1590 | /* Configure widget a bit: */
|
---|
1591 | setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked | QAbstractItemView::EditKeyPressed);
|
---|
1592 | }
|
---|
1593 |
|
---|
1594 | int UIFormEditorView::childCount() const
|
---|
1595 | {
|
---|
1596 | /* Redirect request to model: */
|
---|
1597 | AssertPtrReturn(model(), 0);
|
---|
1598 | return qobject_cast<UIFormEditorProxyModel*>(model())->childCount();
|
---|
1599 | }
|
---|
1600 |
|
---|
1601 | QITableViewRow *UIFormEditorView::childItem(int iIndex) const
|
---|
1602 | {
|
---|
1603 | /* Redirect request to model: */
|
---|
1604 | AssertPtrReturn(model(), 0);
|
---|
1605 | return qobject_cast<UIFormEditorProxyModel*>(model())->childItem(iIndex);
|
---|
1606 | }
|
---|
1607 |
|
---|
1608 |
|
---|
1609 | /*********************************************************************************************************************************
|
---|
1610 | * Class UIFormEditorWidget implementation. *
|
---|
1611 | *********************************************************************************************************************************/
|
---|
1612 |
|
---|
1613 | UIFormEditorWidget::UIFormEditorWidget(QWidget *pParent /* = 0 */,
|
---|
1614 | UINotificationCenter *pNotificationCenter /* = 0 */)
|
---|
1615 | : QWidget(pParent)
|
---|
1616 | , m_pNotificationCenter(pNotificationCenter)
|
---|
1617 | , m_pTableView(0)
|
---|
1618 | , m_pTableModel(0)
|
---|
1619 | , m_pItemEditorFactory(0)
|
---|
1620 | {
|
---|
1621 | prepare();
|
---|
1622 | }
|
---|
1623 |
|
---|
1624 | UIFormEditorWidget::~UIFormEditorWidget()
|
---|
1625 | {
|
---|
1626 | cleanup();
|
---|
1627 | }
|
---|
1628 |
|
---|
1629 | UIFormEditorView *UIFormEditorWidget::view() const
|
---|
1630 | {
|
---|
1631 | return m_pTableView;
|
---|
1632 | }
|
---|
1633 |
|
---|
1634 | QHeaderView *UIFormEditorWidget::horizontalHeader() const
|
---|
1635 | {
|
---|
1636 | AssertPtrReturn(m_pTableView, 0);
|
---|
1637 | return m_pTableView->horizontalHeader();
|
---|
1638 | }
|
---|
1639 |
|
---|
1640 | QHeaderView *UIFormEditorWidget::verticalHeader() const
|
---|
1641 | {
|
---|
1642 | AssertPtrReturn(m_pTableView, 0);
|
---|
1643 | return m_pTableView->verticalHeader();
|
---|
1644 | }
|
---|
1645 |
|
---|
1646 | void UIFormEditorWidget::setWhatsThis(const QString &strWhatsThis)
|
---|
1647 | {
|
---|
1648 | AssertPtrReturnVoid(m_pTableView);
|
---|
1649 | m_pTableView->setWhatsThis(strWhatsThis);
|
---|
1650 | }
|
---|
1651 |
|
---|
1652 | void UIFormEditorWidget::clearForm()
|
---|
1653 | {
|
---|
1654 | m_pTableModel->clearForm();
|
---|
1655 | adjustTable();
|
---|
1656 | }
|
---|
1657 |
|
---|
1658 | void UIFormEditorWidget::setValues(const QVector<CFormValue> &values)
|
---|
1659 | {
|
---|
1660 | m_pTableModel->setFormValues(values);
|
---|
1661 | adjustTable();
|
---|
1662 | }
|
---|
1663 |
|
---|
1664 | void UIFormEditorWidget::setForm(const CForm &comForm)
|
---|
1665 | {
|
---|
1666 | AssertPtrReturnVoid(m_pTableModel);
|
---|
1667 | /// @todo add some check..
|
---|
1668 | setValues(comForm.GetValues());
|
---|
1669 | }
|
---|
1670 |
|
---|
1671 | void UIFormEditorWidget::setVirtualSystemDescriptionForm(const CVirtualSystemDescriptionForm &comForm)
|
---|
1672 | {
|
---|
1673 | AssertPtrReturnVoid(m_pTableModel);
|
---|
1674 | /// @todo add some check..
|
---|
1675 | setValues(comForm.GetValues());
|
---|
1676 | }
|
---|
1677 |
|
---|
1678 | void UIFormEditorWidget::makeSureEditorDataCommitted()
|
---|
1679 | {
|
---|
1680 | m_pTableView->makeSureEditorDataCommitted();
|
---|
1681 | }
|
---|
1682 |
|
---|
1683 | bool UIFormEditorWidget::eventFilter(QObject *pObject, QEvent *pEvent)
|
---|
1684 | {
|
---|
1685 | /* Process events for table only: */
|
---|
1686 | if (pObject != m_pTableView)
|
---|
1687 | return QWidget::eventFilter(pObject, pEvent);
|
---|
1688 |
|
---|
1689 | /* Process different event-types: */
|
---|
1690 | switch (pEvent->type())
|
---|
1691 | {
|
---|
1692 | case QEvent::Show:
|
---|
1693 | case QEvent::Resize:
|
---|
1694 | {
|
---|
1695 | /* Adjust table: */
|
---|
1696 | adjustTable();
|
---|
1697 | break;
|
---|
1698 | }
|
---|
1699 | default:
|
---|
1700 | break;
|
---|
1701 | }
|
---|
1702 |
|
---|
1703 | /* Call to base-class: */
|
---|
1704 | return QWidget::eventFilter(pObject, pEvent);
|
---|
1705 | }
|
---|
1706 |
|
---|
1707 | void UIFormEditorWidget::prepare()
|
---|
1708 | {
|
---|
1709 | /* Create layout: */
|
---|
1710 | QVBoxLayout *pLayout = new QVBoxLayout(this);
|
---|
1711 | if (pLayout)
|
---|
1712 | {
|
---|
1713 | pLayout->setContentsMargins(0, 0, 0, 0);
|
---|
1714 |
|
---|
1715 | /* Create model: */
|
---|
1716 | m_pTableModel = new UIFormEditorModel(this);
|
---|
1717 |
|
---|
1718 | /* Create proxy-model: */
|
---|
1719 | UIFormEditorProxyModel *pProxyModel = new UIFormEditorProxyModel(this);
|
---|
1720 | if (pProxyModel)
|
---|
1721 | pProxyModel->setSourceModel(m_pTableModel);
|
---|
1722 |
|
---|
1723 | /* Create view: */
|
---|
1724 | m_pTableView = new UIFormEditorView(this);
|
---|
1725 | if (m_pTableView)
|
---|
1726 | {
|
---|
1727 | m_pTableView->setModel(pProxyModel);
|
---|
1728 | m_pTableView->setTabKeyNavigation(false);
|
---|
1729 | m_pTableView->verticalHeader()->hide();
|
---|
1730 | m_pTableView->verticalHeader()->setDefaultSectionSize((int)(m_pTableView->verticalHeader()->minimumSectionSize() * 1.33));
|
---|
1731 | m_pTableView->setSelectionMode(QAbstractItemView::SingleSelection);
|
---|
1732 | m_pTableView->installEventFilter(this);
|
---|
1733 |
|
---|
1734 | /* We certainly have abstract item delegate: */
|
---|
1735 | QAbstractItemDelegate *pAbstractItemDelegate = m_pTableView->itemDelegate();
|
---|
1736 | if (pAbstractItemDelegate)
|
---|
1737 | {
|
---|
1738 | /* But is this also styled item delegate? */
|
---|
1739 | QIStyledItemDelegate *pStyledItemDelegate = qobject_cast<QIStyledItemDelegate*>(pAbstractItemDelegate);
|
---|
1740 | if (pStyledItemDelegate)
|
---|
1741 | {
|
---|
1742 | /* Configure item delegate: */
|
---|
1743 | pStyledItemDelegate->setWatchForEditorDataCommits(true);
|
---|
1744 |
|
---|
1745 | /* Create new item editor factory: */
|
---|
1746 | m_pItemEditorFactory = new QItemEditorFactory;
|
---|
1747 | if (m_pItemEditorFactory)
|
---|
1748 | {
|
---|
1749 | /* Register TextEditor as the TextData editor: */
|
---|
1750 | int iTextId = qRegisterMetaType<TextData>();
|
---|
1751 | QStandardItemEditorCreator<TextEditor> *pTextEditorItemCreator = new QStandardItemEditorCreator<TextEditor>();
|
---|
1752 | m_pItemEditorFactory->registerEditor(iTextId, pTextEditorItemCreator);
|
---|
1753 |
|
---|
1754 | /* Register ChoiceEditor as the ChoiceData editor: */
|
---|
1755 | int iChoiceId = qRegisterMetaType<ChoiceData>();
|
---|
1756 | QStandardItemEditorCreator<ChoiceEditor> *pChoiceEditorItemCreator = new QStandardItemEditorCreator<ChoiceEditor>();
|
---|
1757 | m_pItemEditorFactory->registerEditor(iChoiceId, pChoiceEditorItemCreator);
|
---|
1758 |
|
---|
1759 | /* Register RangedIntegerEditor as the RangedIntegerData editor: */
|
---|
1760 | int iRangedIntegerId = qRegisterMetaType<RangedIntegerData>();
|
---|
1761 | QStandardItemEditorCreator<RangedIntegerEditor> *pRangedIntegerEditorItemCreator = new QStandardItemEditorCreator<RangedIntegerEditor>();
|
---|
1762 | m_pItemEditorFactory->registerEditor(iRangedIntegerId, pRangedIntegerEditorItemCreator);
|
---|
1763 |
|
---|
1764 | /* Register RangedInteger64Editor as the RangedInteger64Data editor: */
|
---|
1765 | int iRangedInteger64Id = qRegisterMetaType<RangedInteger64Data>();
|
---|
1766 | QStandardItemEditorCreator<RangedInteger64Editor> *pRangedInteger64EditorItemCreator = new QStandardItemEditorCreator<RangedInteger64Editor>();
|
---|
1767 | m_pItemEditorFactory->registerEditor(iRangedInteger64Id, pRangedInteger64EditorItemCreator);
|
---|
1768 |
|
---|
1769 | /* Set newly created item editor factory for table delegate: */
|
---|
1770 | pStyledItemDelegate->setItemEditorFactory(m_pItemEditorFactory);
|
---|
1771 | }
|
---|
1772 | }
|
---|
1773 | }
|
---|
1774 |
|
---|
1775 | /* Add into layout: */
|
---|
1776 | pLayout->addWidget(m_pTableView);
|
---|
1777 | }
|
---|
1778 | }
|
---|
1779 | }
|
---|
1780 |
|
---|
1781 | void UIFormEditorWidget::cleanup()
|
---|
1782 | {
|
---|
1783 | delete m_pItemEditorFactory;
|
---|
1784 | m_pItemEditorFactory = 0;
|
---|
1785 | }
|
---|
1786 |
|
---|
1787 | void UIFormEditorWidget::adjustTable()
|
---|
1788 | {
|
---|
1789 | m_pTableView->horizontalHeader()->setStretchLastSection(false);
|
---|
1790 | /* If table is NOT empty: */
|
---|
1791 | if (m_pTableModel->rowCount())
|
---|
1792 | {
|
---|
1793 | /* Resize table to contents size-hint and emit a spare place for first column: */
|
---|
1794 | m_pTableView->resizeColumnsToContents();
|
---|
1795 | const int iFullWidth = m_pTableView->viewport()->width();
|
---|
1796 | const int iNameWidth = m_pTableView->horizontalHeader()->sectionSize(UIFormEditorDataType_Name);
|
---|
1797 | const int iValueWidth = qMax(0, iFullWidth - iNameWidth);
|
---|
1798 | m_pTableView->horizontalHeader()->resizeSection(UIFormEditorDataType_Value, iValueWidth);
|
---|
1799 | }
|
---|
1800 | /* If table is empty: */
|
---|
1801 | else
|
---|
1802 | {
|
---|
1803 | /* Resize table columns to be equal in size: */
|
---|
1804 | const int iFullWidth = m_pTableView->viewport()->width();
|
---|
1805 | m_pTableView->horizontalHeader()->resizeSection(UIFormEditorDataType_Name, iFullWidth / 2);
|
---|
1806 | m_pTableView->horizontalHeader()->resizeSection(UIFormEditorDataType_Value, iFullWidth / 2);
|
---|
1807 | }
|
---|
1808 | m_pTableView->horizontalHeader()->setStretchLastSection(true);
|
---|
1809 | }
|
---|
1810 |
|
---|
1811 |
|
---|
1812 | #include "UIFormEditorWidget.moc"
|
---|