1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the Qt Designer of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | #include "deviceprofiledialog.h" |
30 | #include "ui_deviceprofiledialog.h" |
31 | |
32 | #include <abstractdialoggui_p.h> |
33 | #include <deviceprofile_p.h> |
34 | |
35 | #include <QtWidgets/qdialogbuttonbox.h> |
36 | #include <QtWidgets/qboxlayout.h> |
37 | #include <QtWidgets/qpushbutton.h> |
38 | #include <QtWidgets/qstylefactory.h> |
39 | #include <QtGui/qfontdatabase.h> |
40 | #include <QtGui/qvalidator.h> |
41 | |
42 | #include <QtCore/qfileinfo.h> |
43 | #include <QtCore/qfile.h> |
44 | |
45 | QT_BEGIN_NAMESPACE |
46 | |
47 | static const char *profileExtensionC = "qdp" ; |
48 | |
49 | static inline QString fileFilter() |
50 | { |
51 | return qdesigner_internal::DeviceProfileDialog::tr(s: "Device Profiles (*.%1)" ).arg(a: QLatin1String(profileExtensionC)); |
52 | } |
53 | |
54 | // Populate a combo with a sequence of integers, also set them as data. |
55 | template <class IntIterator> |
56 | static void populateNumericCombo(IntIterator i1, IntIterator i2, QComboBox *cb) |
57 | { |
58 | QString s; |
59 | for ( ; i1 != i2 ; ++i1) { |
60 | const int n = *i1; |
61 | s.setNum(n); |
62 | cb->addItem(atext: s, auserData: QVariant(n)); |
63 | } |
64 | } |
65 | |
66 | namespace qdesigner_internal { |
67 | |
68 | DeviceProfileDialog::DeviceProfileDialog(QDesignerDialogGuiInterface *dlgGui, QWidget *parent) : |
69 | QDialog(parent), |
70 | m_ui(new Ui::DeviceProfileDialog), |
71 | m_dlgGui(dlgGui) |
72 | { |
73 | setModal(true); |
74 | m_ui->setupUi(this); |
75 | |
76 | const auto standardFontSizes = QFontDatabase::standardSizes(); |
77 | populateNumericCombo(i1: standardFontSizes.constBegin(), i2: standardFontSizes.constEnd(), cb: m_ui->m_systemFontSizeCombo); |
78 | |
79 | // 288pt observed on macOS. |
80 | const int maxPointSize = qMax(a: 288, b: standardFontSizes.constLast()); |
81 | m_ui->m_systemFontSizeCombo->setValidator(new QIntValidator(1, maxPointSize, |
82 | m_ui->m_systemFontSizeCombo)); |
83 | |
84 | // Styles |
85 | const QStringList styles = QStyleFactory::keys(); |
86 | m_ui->m_styleCombo->addItem(atext: tr(s: "Default" ), auserData: QVariant(QString())); |
87 | const QStringList::const_iterator cend = styles.constEnd(); |
88 | for (QStringList::const_iterator it = styles.constBegin(); it != cend; ++it) |
89 | m_ui->m_styleCombo->addItem(atext: *it, auserData: *it); |
90 | |
91 | connect(sender: m_ui->m_nameLineEdit, signal: &QLineEdit::textChanged, receiver: this, slot: &DeviceProfileDialog::nameChanged); |
92 | connect(sender: m_ui->buttonBox, signal: &QDialogButtonBox::rejected, receiver: this, slot: &QDialog::reject); |
93 | connect(sender: m_ui->buttonBox->button(which: QDialogButtonBox::Ok), signal: &QAbstractButton::clicked, |
94 | receiver: this, slot: &QDialog::accept); |
95 | // Note that Load/Save emit accepted() of the button box.. |
96 | connect(sender: m_ui->buttonBox->button(which: QDialogButtonBox::Save), signal: &QAbstractButton::clicked, |
97 | receiver: this, slot: &DeviceProfileDialog::save); |
98 | connect(sender: m_ui->buttonBox->button(which: QDialogButtonBox::Open), signal: &QAbstractButton::clicked, |
99 | receiver: this, slot: &DeviceProfileDialog::open); |
100 | } |
101 | |
102 | DeviceProfileDialog::~DeviceProfileDialog() |
103 | { |
104 | delete m_ui; |
105 | } |
106 | |
107 | DeviceProfile DeviceProfileDialog::deviceProfile() const |
108 | { |
109 | DeviceProfile rc; |
110 | rc.setName(m_ui->m_nameLineEdit->text()); |
111 | rc.setFontFamily(m_ui->m_systemFontComboBox->currentFont().family()); |
112 | rc.setFontPointSize(m_ui->m_systemFontSizeCombo->itemData(index: m_ui->m_systemFontSizeCombo->currentIndex()).toInt()); |
113 | |
114 | int dpiX, dpiY; |
115 | m_ui->m_dpiChooser->getDPI(dpiX: &dpiX, dpiY: &dpiY); |
116 | rc.setDpiX(dpiX); |
117 | rc.setDpiY(dpiY); |
118 | |
119 | rc.setStyle(m_ui->m_styleCombo->itemData(index: m_ui->m_styleCombo->currentIndex()).toString()); |
120 | |
121 | return rc; |
122 | } |
123 | |
124 | void DeviceProfileDialog::setDeviceProfile(const DeviceProfile &s) |
125 | { |
126 | m_ui->m_nameLineEdit->setText(s.name()); |
127 | m_ui->m_systemFontComboBox->setCurrentFont(QFont(s.fontFamily())); |
128 | const int fontSizeIndex = m_ui->m_systemFontSizeCombo->findData(data: QVariant(s.fontPointSize())); |
129 | m_ui->m_systemFontSizeCombo->setCurrentIndex(fontSizeIndex != -1 ? fontSizeIndex : 0); |
130 | m_ui->m_dpiChooser->setDPI(dpiX: s.dpiX(), dpiY: s.dpiY()); |
131 | const int styleIndex = m_ui->m_styleCombo->findData(data: s.style()); |
132 | m_ui->m_styleCombo->setCurrentIndex(styleIndex != -1 ? styleIndex : 0); |
133 | } |
134 | |
135 | void DeviceProfileDialog::setOkButtonEnabled(bool v) |
136 | { |
137 | m_ui->buttonBox->button(which: QDialogButtonBox::Ok)->setEnabled(v); |
138 | } |
139 | |
140 | bool DeviceProfileDialog::showDialog(const QStringList &existingNames) |
141 | { |
142 | m_existingNames = existingNames; |
143 | m_ui->m_nameLineEdit->setFocus(Qt::OtherFocusReason); |
144 | nameChanged(name: m_ui->m_nameLineEdit->text()); |
145 | return exec() == Accepted; |
146 | } |
147 | |
148 | void DeviceProfileDialog::nameChanged(const QString &name) |
149 | { |
150 | const bool invalid = name.isEmpty() || m_existingNames.indexOf(t: name) != -1; |
151 | setOkButtonEnabled(!invalid); |
152 | } |
153 | |
154 | void DeviceProfileDialog::save() |
155 | { |
156 | QString fn = m_dlgGui->getSaveFileName(parent: this, caption: tr(s: "Save Profile" ), dir: QString(), filter: fileFilter()); |
157 | if (fn.isEmpty()) |
158 | return; |
159 | if (QFileInfo(fn).completeSuffix().isEmpty()) { |
160 | fn += QLatin1Char('.'); |
161 | fn += QLatin1String(profileExtensionC); |
162 | } |
163 | |
164 | QFile file(fn); |
165 | if (!file.open(flags: QIODevice::WriteOnly|QIODevice::Text)) { |
166 | critical(title: tr(s: "Save Profile - Error" ), msg: tr(s: "Unable to open the file '%1' for writing: %2" ).arg(args&: fn, args: file.errorString())); |
167 | return; |
168 | } |
169 | file.write(data: deviceProfile().toXml().toUtf8()); |
170 | } |
171 | |
172 | void DeviceProfileDialog::open() |
173 | { |
174 | const QString fn = m_dlgGui->getOpenFileName(parent: this, caption: tr(s: "Open profile" ), dir: QString(), filter: fileFilter()); |
175 | if (fn.isEmpty()) |
176 | return; |
177 | |
178 | QFile file(fn); |
179 | if (!file.open(flags: QIODevice::ReadOnly|QIODevice::Text)) { |
180 | critical(title: tr(s: "Open Profile - Error" ), msg: tr(s: "Unable to open the file '%1' for reading: %2" ).arg(args: fn, args: file.errorString())); |
181 | return; |
182 | } |
183 | QString errorMessage; |
184 | DeviceProfile newSettings; |
185 | if (!newSettings.fromXml(xml: QString::fromUtf8(str: file.readAll()), errorMessage: &errorMessage)) { |
186 | critical(title: tr(s: "Open Profile - Error" ), msg: tr(s: "'%1' is not a valid profile: %2" ).arg(args: fn, args&: errorMessage)); |
187 | return; |
188 | } |
189 | setDeviceProfile(newSettings); |
190 | } |
191 | |
192 | void DeviceProfileDialog::critical(const QString &title, const QString &msg) |
193 | { |
194 | m_dlgGui->message(parent: this, context: QDesignerDialogGuiInterface::OtherMessage, icon: QMessageBox::Critical, title, text: msg); |
195 | } |
196 | } |
197 | |
198 | QT_END_NAMESPACE |
199 | |