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
fileFilter()49 static inline QString fileFilter()
50 {
51 return qdesigner_internal::DeviceProfileDialog::tr("Device Profiles (*.%1)").arg(QLatin1String(profileExtensionC));
52 }
53
54 // Populate a combo with a sequence of integers, also set them as data.
55 template <class IntIterator>
populateNumericCombo(IntIterator i1,IntIterator i2,QComboBox * cb)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(s, QVariant(n));
63 }
64 }
65
66 namespace qdesigner_internal {
67
DeviceProfileDialog(QDesignerDialogGuiInterface * dlgGui,QWidget * parent)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(standardFontSizes.constBegin(), standardFontSizes.constEnd(), m_ui->m_systemFontSizeCombo);
78
79 // 288pt observed on macOS.
80 const int maxPointSize = qMax(288, 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(tr("Default"), 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(*it, *it);
90
91 connect(m_ui->m_nameLineEdit, &QLineEdit::textChanged, this, &DeviceProfileDialog::nameChanged);
92 connect(m_ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
93 connect(m_ui->buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked,
94 this, &QDialog::accept);
95 // Note that Load/Save emit accepted() of the button box..
96 connect(m_ui->buttonBox->button(QDialogButtonBox::Save), &QAbstractButton::clicked,
97 this, &DeviceProfileDialog::save);
98 connect(m_ui->buttonBox->button(QDialogButtonBox::Open), &QAbstractButton::clicked,
99 this, &DeviceProfileDialog::open);
100 }
101
~DeviceProfileDialog()102 DeviceProfileDialog::~DeviceProfileDialog()
103 {
104 delete m_ui;
105 }
106
deviceProfile() const107 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(m_ui->m_systemFontSizeCombo->currentIndex()).toInt());
113
114 int dpiX, dpiY;
115 m_ui->m_dpiChooser->getDPI(&dpiX, &dpiY);
116 rc.setDpiX(dpiX);
117 rc.setDpiY(dpiY);
118
119 rc.setStyle(m_ui->m_styleCombo->itemData(m_ui->m_styleCombo->currentIndex()).toString());
120
121 return rc;
122 }
123
setDeviceProfile(const DeviceProfile & s)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(QVariant(s.fontPointSize()));
129 m_ui->m_systemFontSizeCombo->setCurrentIndex(fontSizeIndex != -1 ? fontSizeIndex : 0);
130 m_ui->m_dpiChooser->setDPI(s.dpiX(), s.dpiY());
131 const int styleIndex = m_ui->m_styleCombo->findData(s.style());
132 m_ui->m_styleCombo->setCurrentIndex(styleIndex != -1 ? styleIndex : 0);
133 }
134
setOkButtonEnabled(bool v)135 void DeviceProfileDialog::setOkButtonEnabled(bool v)
136 {
137 m_ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(v);
138 }
139
showDialog(const QStringList & existingNames)140 bool DeviceProfileDialog::showDialog(const QStringList &existingNames)
141 {
142 m_existingNames = existingNames;
143 m_ui->m_nameLineEdit->setFocus(Qt::OtherFocusReason);
144 nameChanged(m_ui->m_nameLineEdit->text());
145 return exec() == Accepted;
146 }
147
nameChanged(const QString & name)148 void DeviceProfileDialog::nameChanged(const QString &name)
149 {
150 const bool invalid = name.isEmpty() || m_existingNames.indexOf(name) != -1;
151 setOkButtonEnabled(!invalid);
152 }
153
save()154 void DeviceProfileDialog::save()
155 {
156 QString fn = m_dlgGui->getSaveFileName(this, tr("Save Profile"), QString(), 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(QIODevice::WriteOnly|QIODevice::Text)) {
166 critical(tr("Save Profile - Error"), tr("Unable to open the file '%1' for writing: %2").arg(fn, file.errorString()));
167 return;
168 }
169 file.write(deviceProfile().toXml().toUtf8());
170 }
171
open()172 void DeviceProfileDialog::open()
173 {
174 const QString fn = m_dlgGui->getOpenFileName(this, tr("Open profile"), QString(), fileFilter());
175 if (fn.isEmpty())
176 return;
177
178 QFile file(fn);
179 if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
180 critical(tr("Open Profile - Error"), tr("Unable to open the file '%1' for reading: %2").arg(fn, file.errorString()));
181 return;
182 }
183 QString errorMessage;
184 DeviceProfile newSettings;
185 if (!newSettings.fromXml(QString::fromUtf8(file.readAll()), &errorMessage)) {
186 critical(tr("Open Profile - Error"), tr("'%1' is not a valid profile: %2").arg(fn, errorMessage));
187 return;
188 }
189 setDeviceProfile(newSettings);
190 }
191
critical(const QString & title,const QString & msg)192 void DeviceProfileDialog::critical(const QString &title, const QString &msg)
193 {
194 m_dlgGui->message(this, QDesignerDialogGuiInterface::OtherMessage, QMessageBox::Critical, title, msg);
195 }
196 }
197
198 QT_END_NAMESPACE
199