1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qwindowdefs.h"
43
44 #ifndef QT_NO_FONTDIALOG
45
46 #include "qfontdialog.h"
47 #include "qfontdialog_p.h"
48
49 #include <qapplication.h>
50 #include <qcheckbox.h>
51 #include <qcombobox.h>
52 #include <qevent.h>
53 #include <qfontdatabase.h>
54 #include <qgroupbox.h>
55 #include <qlabel.h>
56 #include <qlayout.h>
57 #include <qlineedit.h>
58 #include <qpushbutton.h>
59 #include <qstyle.h>
60 #include <qdialogbuttonbox.h>
61 #include <qheaderview.h>
62 #include <qlistview.h>
63 #include <qstringlistmodel.h>
64 #include <qvalidator.h>
65 #include <private/qdialog_p.h>
66 #include <private/qfont_p.h>
67
68 #if defined(Q_WS_S60)
69 #include <QtGui/qdesktopwidget.h>
70 #endif
71
72 QT_BEGIN_NAMESPACE
73
74 class QFontListView : public QListView
75 {
76 Q_OBJECT
77 public:
78 QFontListView(QWidget *parent);
model() const79 inline QStringListModel *model() const {
80 return static_cast<QStringListModel *>(QListView::model());
81 }
setCurrentItem(int item)82 inline void setCurrentItem(int item) {
83 QListView::setCurrentIndex(static_cast<QAbstractListModel*>(model())->index(item));
84 }
currentItem() const85 inline int currentItem() const {
86 return QListView::currentIndex().row();
87 }
count() const88 inline int count() const {
89 return model()->rowCount();
90 }
currentText() const91 inline QString currentText() const {
92 int row = QListView::currentIndex().row();
93 return row < 0 ? QString() : model()->stringList().at(row);
94 }
currentChanged(const QModelIndex & current,const QModelIndex & previous)95 void currentChanged(const QModelIndex ¤t, const QModelIndex &previous) {
96 QListView::currentChanged(current, previous);
97 if (current.isValid())
98 emit highlighted(current.row());
99 }
text(int i) const100 QString text(int i) const {
101 return model()->stringList().at(i);
102 }
103 signals:
104 void highlighted(int);
105 };
106
QFontListView(QWidget * parent)107 QFontListView::QFontListView(QWidget *parent)
108 : QListView(parent)
109 {
110 setModel(new QStringListModel(parent));
111 setEditTriggers(NoEditTriggers);
112 }
113
114 static const Qt::WindowFlags DefaultWindowFlags =
115 Qt::Dialog | Qt::WindowSystemMenuHint;
116
117 /*!
118 \class QFontDialog
119 \ingroup standard-dialogs
120
121 \brief The QFontDialog class provides a dialog widget for selecting a font.
122
123 A font dialog is created through one of the static getFont()
124 functions.
125
126 Examples:
127
128 \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 0
129
130 The dialog can also be used to set a widget's font directly:
131 \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 1
132 If the user clicks OK the font they chose will be used for myWidget,
133 and if they click Cancel the original font is used.
134
135 \image plastique-fontdialog.png A font dialog in the Plastique widget style.
136
137 \sa QFont, QFontInfo, QFontMetrics, QColorDialog, QFileDialog, QPrintDialog,
138 {Standard Dialogs Example}
139 */
140
141 /*!
142 \since 4.5
143
144 Constructs a standard font dialog.
145
146 Use setCurrentFont() to set the initial font attributes.
147
148 The \a parent parameter is passed to the QDialog constructor.
149
150 \sa getFont()
151 */
QFontDialog(QWidget * parent)152 QFontDialog::QFontDialog(QWidget *parent)
153 : QDialog(*new QFontDialogPrivate, parent, DefaultWindowFlags)
154 {
155 Q_D(QFontDialog);
156 d->init();
157 }
158
159 /*!
160 \since 4.5
161
162 Constructs a standard font dialog with the given \a parent and specified
163 \a initial font.
164 */
QFontDialog(const QFont & initial,QWidget * parent)165 QFontDialog::QFontDialog(const QFont &initial, QWidget *parent)
166 : QDialog(*new QFontDialogPrivate, parent, DefaultWindowFlags)
167 {
168 Q_D(QFontDialog);
169 d->init();
170 setCurrentFont(initial);
171 }
172
init()173 void QFontDialogPrivate::init()
174 {
175 Q_Q(QFontDialog);
176
177 #ifdef Q_WS_MAC
178 nativeDialogInUse = false;
179 delegate = 0;
180 #endif
181
182 q->setSizeGripEnabled(true);
183 q->setWindowTitle(QFontDialog::tr("Select Font"));
184
185 // grid
186 familyEdit = new QLineEdit(q);
187 familyEdit->setReadOnly(true);
188 familyList = new QFontListView(q);
189 familyEdit->setFocusProxy(familyList);
190
191 familyAccel = new QLabel(q);
192 #ifndef QT_NO_SHORTCUT
193 familyAccel->setBuddy(familyList);
194 #endif
195 familyAccel->setIndent(2);
196
197 styleEdit = new QLineEdit(q);
198 styleEdit->setReadOnly(true);
199 styleList = new QFontListView(q);
200 styleEdit->setFocusProxy(styleList);
201
202 styleAccel = new QLabel(q);
203 #ifndef QT_NO_SHORTCUT
204 styleAccel->setBuddy(styleList);
205 #endif
206 styleAccel->setIndent(2);
207
208 sizeEdit = new QLineEdit(q);
209 sizeEdit->setFocusPolicy(Qt::ClickFocus);
210 QIntValidator *validator = new QIntValidator(1, 512, q);
211 sizeEdit->setValidator(validator);
212 sizeList = new QFontListView(q);
213
214 sizeAccel = new QLabel(q);
215 #ifndef QT_NO_SHORTCUT
216 sizeAccel->setBuddy(sizeEdit);
217 #endif
218 sizeAccel->setIndent(2);
219
220 // effects box
221 effects = new QGroupBox(q);
222 QVBoxLayout *vbox = new QVBoxLayout(effects);
223 strikeout = new QCheckBox(effects);
224 vbox->addWidget(strikeout);
225 underline = new QCheckBox(effects);
226 vbox->addWidget(underline);
227
228 sample = new QGroupBox(q);
229 QHBoxLayout *hbox = new QHBoxLayout(sample);
230 sampleEdit = new QLineEdit(sample);
231 sampleEdit->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
232 sampleEdit->setAlignment(Qt::AlignCenter);
233 // Note that the sample text is *not* translated with tr(), as the
234 // characters used depend on the charset encoding.
235 sampleEdit->setText(QLatin1String("AaBbYyZz"));
236 hbox->addWidget(sampleEdit);
237
238 writingSystemCombo = new QComboBox(q);
239
240 writingSystemAccel = new QLabel(q);
241 #ifndef QT_NO_SHORTCUT
242 writingSystemAccel->setBuddy(writingSystemCombo);
243 #endif
244 writingSystemAccel->setIndent(2);
245
246 size = 0;
247 smoothScalable = false;
248
249 QObject::connect(writingSystemCombo, SIGNAL(activated(int)), q, SLOT(_q_writingSystemHighlighted(int)));
250 QObject::connect(familyList, SIGNAL(highlighted(int)), q, SLOT(_q_familyHighlighted(int)));
251 QObject::connect(styleList, SIGNAL(highlighted(int)), q, SLOT(_q_styleHighlighted(int)));
252 QObject::connect(sizeList, SIGNAL(highlighted(int)), q, SLOT(_q_sizeHighlighted(int)));
253 QObject::connect(sizeEdit, SIGNAL(textChanged(QString)), q, SLOT(_q_sizeChanged(QString)));
254
255 QObject::connect(strikeout, SIGNAL(clicked()), q, SLOT(_q_updateSample()));
256 QObject::connect(underline, SIGNAL(clicked()), q, SLOT(_q_updateSample()));
257
258 for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) {
259 QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i);
260 QString writingSystemName = QFontDatabase::writingSystemName(ws);
261 if (writingSystemName.isEmpty())
262 break;
263 writingSystemCombo->addItem(writingSystemName);
264 }
265
266 updateFamilies();
267 if (familyList->count() != 0)
268 familyList->setCurrentItem(0);
269
270 // grid layout
271 QGridLayout *mainGrid = new QGridLayout(q);
272
273 int spacing = mainGrid->spacing();
274 if (spacing >= 0) { // uniform spacing
275 mainGrid->setSpacing(0);
276
277 mainGrid->setColumnMinimumWidth(1, spacing);
278 mainGrid->setColumnMinimumWidth(3, spacing);
279
280 int margin = 0;
281 mainGrid->getContentsMargins(0, 0, 0, &margin);
282
283 mainGrid->setRowMinimumHeight(3, margin);
284 mainGrid->setRowMinimumHeight(6, 2);
285 mainGrid->setRowMinimumHeight(8, margin);
286 }
287
288 mainGrid->addWidget(familyAccel, 0, 0);
289 mainGrid->addWidget(familyEdit, 1, 0);
290 mainGrid->addWidget(familyList, 2, 0);
291
292 mainGrid->addWidget(styleAccel, 0, 2);
293 mainGrid->addWidget(styleEdit, 1, 2);
294 mainGrid->addWidget(styleList, 2, 2);
295
296 mainGrid->addWidget(sizeAccel, 0, 4);
297 mainGrid->addWidget(sizeEdit, 1, 4);
298 mainGrid->addWidget(sizeList, 2, 4);
299
300 mainGrid->setColumnStretch(0, 38);
301 mainGrid->setColumnStretch(2, 24);
302 mainGrid->setColumnStretch(4, 10);
303
304 mainGrid->addWidget(effects, 4, 0);
305
306 mainGrid->addWidget(sample, 4, 2, 4, 3);
307
308 mainGrid->addWidget(writingSystemAccel, 5, 0);
309 mainGrid->addWidget(writingSystemCombo, 7, 0);
310
311 buttonBox = new QDialogButtonBox(q);
312 mainGrid->addWidget(buttonBox, 9, 0, 1, 5);
313
314 QPushButton *button
315 = static_cast<QPushButton *>(buttonBox->addButton(QDialogButtonBox::Ok));
316 QObject::connect(buttonBox, SIGNAL(accepted()), q, SLOT(accept()));
317 button->setDefault(true);
318
319 buttonBox->addButton(QDialogButtonBox::Cancel);
320 QObject::connect(buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
321
322 #if defined(Q_WS_WINCE)
323 q->resize(180, 120);
324 #elif defined(Q_WS_S60)
325 q->resize(QApplication::desktop()->availableGeometry(QCursor::pos()).size());
326 #else
327 q->resize(500, 360);
328 #endif // Q_WS_WINCE
329
330 sizeEdit->installEventFilter(q);
331 familyList->installEventFilter(q);
332 styleList->installEventFilter(q);
333 sizeList->installEventFilter(q);
334
335 familyList->setFocus();
336 retranslateStrings();
337 }
338
339 /*!
340 \internal
341 Destroys the font dialog and frees up its storage.
342 */
343
~QFontDialog()344 QFontDialog::~QFontDialog()
345 {
346 #ifdef Q_WS_MAC
347 Q_D(QFontDialog);
348 if (d->delegate) {
349 d->closeCocoaFontPanel();
350 return;
351 }
352 #endif
353 }
354
355 /*!
356 Executes a modal font dialog and returns a font.
357
358 If the user clicks \gui OK, the selected font is returned. If the user
359 clicks \gui Cancel, the \a initial font is returned.
360
361 The dialog is constructed with the given \a parent and the options specified
362 in \a options. \a title is shown as the window title of the dialog and \a
363 initial is the initially selected font. If the \a ok parameter is not-null,
364 the value it refers to is set to true if the user clicks \gui OK, and set to
365 false if the user clicks \gui Cancel.
366
367 Examples:
368 \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 2
369
370 The dialog can also be used to set a widget's font directly:
371 \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 3
372 In this example, if the user clicks OK the font they chose will be
373 used, and if they click Cancel the original font is used.
374
375 \warning Do not delete \a parent during the execution of the dialog.
376 If you want to do this, you should create the dialog
377 yourself using one of the QFontDialog constructors.
378 */
getFont(bool * ok,const QFont & initial,QWidget * parent,const QString & title,FontDialogOptions options)379 QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent, const QString &title,
380 FontDialogOptions options)
381 {
382 return QFontDialogPrivate::getFont(ok, initial, parent, title, options);
383 }
384
385 /*!
386 \overload
387 \since 4.5
388 */
getFont(bool * ok,const QFont & initial,QWidget * parent,const QString & title)389 QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent, const QString &title)
390 {
391 return QFontDialogPrivate::getFont(ok, initial, parent, title, 0);
392 }
393
394 /*!
395 \overload
396 */
getFont(bool * ok,const QFont & initial,QWidget * parent)397 QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget *parent)
398 {
399 return QFontDialogPrivate::getFont(ok, initial, parent, QString(), 0);
400 }
401
402 /*!
403 \overload
404
405 Executes a modal font dialog and returns a font.
406
407 If the user clicks \gui OK, the selected font is returned. If the user
408 clicks \gui Cancel, the Qt default font is returned.
409
410 The dialog is constructed with the given \a parent.
411 If the \a ok parameter is not-null, the value it refers to is set
412 to true if the user clicks \gui OK, and false if the user clicks
413 \gui Cancel.
414
415 Example:
416 \snippet doc/src/snippets/code/src_gui_dialogs_qfontdialog.cpp 4
417
418 \warning Do not delete \a parent during the execution of the dialog.
419 If you want to do this, you should create the dialog
420 yourself using one of the QFontDialog constructors.
421 */
getFont(bool * ok,QWidget * parent)422 QFont QFontDialog::getFont(bool *ok, QWidget *parent)
423 {
424 QFont initial;
425 return QFontDialogPrivate::getFont(ok, initial, parent, QString(), 0);
426 }
427
getFont(bool * ok,const QFont & initial,QWidget * parent,const QString & title,QFontDialog::FontDialogOptions options)428 QFont QFontDialogPrivate::getFont(bool *ok, const QFont &initial, QWidget *parent,
429 const QString &title, QFontDialog::FontDialogOptions options)
430 {
431 QFontDialog dlg(parent);
432 dlg.setOptions(options);
433 dlg.setCurrentFont(initial);
434 if (!title.isEmpty())
435 dlg.setWindowTitle(title);
436
437 int ret = (dlg.exec() || (options & QFontDialog::NoButtons));
438 if (ok)
439 *ok = !!ret;
440 if (ret) {
441 return dlg.selectedFont();
442 } else {
443 return initial;
444 }
445 }
446
447 /*!
448 \internal
449 An event filter to make the Up, Down, PageUp and PageDown keys work
450 correctly in the line edits. The source of the event is the object
451 \a o and the event is \a e.
452 */
453
eventFilter(QObject * o,QEvent * e)454 bool QFontDialog::eventFilter(QObject *o , QEvent *e)
455 {
456 Q_D(QFontDialog);
457 if (e->type() == QEvent::KeyPress) {
458 QKeyEvent *k = (QKeyEvent *)e;
459 if (o == d->sizeEdit &&
460 (k->key() == Qt::Key_Up ||
461 k->key() == Qt::Key_Down ||
462 k->key() == Qt::Key_PageUp ||
463 k->key() == Qt::Key_PageDown)) {
464
465 int ci = d->sizeList->currentItem();
466 (void)QApplication::sendEvent(d->sizeList, k);
467
468 if (ci != d->sizeList->currentItem()
469 && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this))
470 d->sizeEdit->selectAll();
471 return true;
472 } else if ((o == d->familyList || o == d->styleList) &&
473 (k->key() == Qt::Key_Return || k->key() == Qt::Key_Enter)) {
474 k->accept();
475 accept();
476 return true;
477 }
478 } else if (e->type() == QEvent::FocusIn
479 && style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, this)) {
480 if (o == d->familyList)
481 d->familyEdit->selectAll();
482 else if (o == d->styleList)
483 d->styleEdit->selectAll();
484 else if (o == d->sizeList)
485 d->sizeEdit->selectAll();
486 } else if (e->type() == QEvent::MouseButtonPress && o == d->sizeList) {
487 d->sizeEdit->setFocus();
488 }
489 return QDialog::eventFilter(o, e);
490 }
491
492 /*
493 Updates the contents of the "font family" list box. This
494 function can be reimplemented if you have special requirements.
495 */
496
updateFamilies()497 void QFontDialogPrivate::updateFamilies()
498 {
499 Q_Q(QFontDialog);
500
501 enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 };
502
503 QStringList familyNames = fdb.families(writingSystem);
504
505 familyList->model()->setStringList(familyNames);
506
507 QString foundryName1, familyName1, foundryName2, familyName2;
508 int bestFamilyMatch = -1;
509 match_t bestFamilyType = MATCH_NONE;
510
511 QFont f;
512
513 // ##### do the right thing for a list of family names in the font.
514 QFontDatabase::parseFontName(family, foundryName1, familyName1);
515
516 QStringList::const_iterator it = familyNames.constBegin();
517 int i = 0;
518 for(; it != familyNames.constEnd(); ++it, ++i) {
519 QFontDatabase::parseFontName(*it, foundryName2, familyName2);
520
521 //try to match...
522 if (familyName1 == familyName2) {
523 bestFamilyType = MATCH_FAMILY;
524 if (foundryName1 == foundryName2) {
525 bestFamilyMatch = i;
526 break;
527 }
528 if (bestFamilyMatch < MATCH_FAMILY)
529 bestFamilyMatch = i;
530 }
531
532 //and try some fall backs
533 match_t type = MATCH_NONE;
534 if (bestFamilyType <= MATCH_NONE && familyName2 == f.lastResortFamily())
535 type = MATCH_LAST_RESORT;
536 if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.family())
537 type = MATCH_APP;
538 // ### add fallback for writingSystem
539 if (type != MATCH_NONE) {
540 bestFamilyType = type;
541 bestFamilyMatch = i;
542 }
543 }
544
545 if (i != -1 && bestFamilyType != MATCH_NONE)
546 familyList->setCurrentItem(bestFamilyMatch);
547 else
548 familyList->setCurrentItem(0);
549 familyEdit->setText(familyList->currentText());
550 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
551 && familyList->hasFocus())
552 familyEdit->selectAll();
553
554 updateStyles();
555 }
556
557 /*
558 Updates the contents of the "font style" list box. This
559 function can be reimplemented if you have special requirements.
560 */
updateStyles()561 void QFontDialogPrivate::updateStyles()
562 {
563 Q_Q(QFontDialog);
564 QStringList styles = fdb.styles(familyList->currentText());
565 styleList->model()->setStringList(styles);
566
567 if (styles.isEmpty()) {
568 styleEdit->clear();
569 smoothScalable = false;
570 } else {
571 if (!style.isEmpty()) {
572 bool found = false;
573 bool first = true;
574 QString cstyle = style;
575
576 redo:
577 for (int i = 0; i < (int)styleList->count(); i++) {
578 if (cstyle == styleList->text(i)) {
579 styleList->setCurrentItem(i);
580 found = true;
581 break;
582 }
583 }
584 if (!found && first) {
585 if (cstyle.contains(QLatin1String("Italic"))) {
586 cstyle.replace(QLatin1String("Italic"), QLatin1String("Oblique"));
587 first = false;
588 goto redo;
589 } else if (cstyle.contains(QLatin1String("Oblique"))) {
590 cstyle.replace(QLatin1String("Oblique"), QLatin1String("Italic"));
591 first = false;
592 goto redo;
593 }
594 }
595 if (!found)
596 styleList->setCurrentItem(0);
597 } else {
598 styleList->setCurrentItem(0);
599 }
600
601 styleEdit->setText(styleList->currentText());
602 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
603 && styleList->hasFocus())
604 styleEdit->selectAll();
605
606 smoothScalable = fdb.isSmoothlyScalable(familyList->currentText(), styleList->currentText());
607 }
608
609 updateSizes();
610 }
611
612 /*!
613 \internal
614 Updates the contents of the "font size" list box. This
615 function can be reimplemented if you have special requirements.
616 */
617
updateSizes()618 void QFontDialogPrivate::updateSizes()
619 {
620 Q_Q(QFontDialog);
621
622 if (!familyList->currentText().isEmpty()) {
623 QList<int> sizes = fdb.pointSizes(familyList->currentText(), styleList->currentText());
624
625 int i = 0;
626 int current = -1;
627 QStringList str_sizes;
628 for(QList<int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); ++it) {
629 str_sizes.append(QString::number(*it));
630 if (current == -1 && *it >= size)
631 current = i;
632 ++i;
633 }
634 sizeList->model()->setStringList(str_sizes);
635 if (current == -1) {
636 // we request a size bigger than the ones in the list, select the biggest one
637 current = sizeList->count() - 1;
638 }
639 sizeList->setCurrentItem(current);
640
641 sizeEdit->blockSignals(true);
642 sizeEdit->setText((smoothScalable ? QString::number(size) : sizeList->currentText()));
643 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
644 && sizeList->hasFocus())
645 sizeEdit->selectAll();
646 sizeEdit->blockSignals(false);
647 } else {
648 sizeEdit->clear();
649 }
650
651 _q_updateSample();
652 }
653
_q_updateSample()654 void QFontDialogPrivate::_q_updateSample()
655 {
656 // compute new font
657 int pSize = sizeEdit->text().toInt();
658 QFont newFont(fdb.font(familyList->currentText(), style, pSize));
659 newFont.setStrikeOut(strikeout->isChecked());
660 newFont.setUnderline(underline->isChecked());
661
662 if (familyList->currentText().isEmpty())
663 sampleEdit->clear();
664
665 updateSampleFont(newFont);
666 }
667
updateSampleFont(const QFont & newFont)668 void QFontDialogPrivate::updateSampleFont(const QFont &newFont)
669 {
670 Q_Q(QFontDialog);
671 if (newFont != sampleEdit->font()) {
672 sampleEdit->setFont(newFont);
673 emit q->currentFontChanged(newFont);
674 }
675 }
676
677 /*!
678 \internal
679 */
_q_writingSystemHighlighted(int index)680 void QFontDialogPrivate::_q_writingSystemHighlighted(int index)
681 {
682 writingSystem = QFontDatabase::WritingSystem(index);
683 sampleEdit->setText(fdb.writingSystemSample(writingSystem));
684 updateFamilies();
685 }
686
687 /*!
688 \internal
689 */
_q_familyHighlighted(int i)690 void QFontDialogPrivate::_q_familyHighlighted(int i)
691 {
692 Q_Q(QFontDialog);
693 family = familyList->text(i);
694 familyEdit->setText(family);
695 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
696 && familyList->hasFocus())
697 familyEdit->selectAll();
698
699 updateStyles();
700 }
701
702
703 /*!
704 \internal
705 */
706
_q_styleHighlighted(int index)707 void QFontDialogPrivate::_q_styleHighlighted(int index)
708 {
709 Q_Q(QFontDialog);
710 QString s = styleList->text(index);
711 styleEdit->setText(s);
712 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
713 && styleList->hasFocus())
714 styleEdit->selectAll();
715
716 style = s;
717
718 updateSizes();
719 }
720
721
722 /*!
723 \internal
724 */
725
_q_sizeHighlighted(int index)726 void QFontDialogPrivate::_q_sizeHighlighted(int index)
727 {
728 Q_Q(QFontDialog);
729 QString s = sizeList->text(index);
730 sizeEdit->setText(s);
731 if (q->style()->styleHint(QStyle::SH_FontDialog_SelectAssociatedText, 0, q)
732 && sizeEdit->hasFocus())
733 sizeEdit->selectAll();
734
735 size = s.toInt();
736 _q_updateSample();
737 }
738
739 /*!
740 \internal
741 This slot is called if the user changes the font size.
742 The size is passed in the \a s argument as a \e string.
743 */
744
_q_sizeChanged(const QString & s)745 void QFontDialogPrivate::_q_sizeChanged(const QString &s)
746 {
747 // no need to check if the conversion is valid, since we have an QIntValidator in the size edit
748 int size = s.toInt();
749 if (this->size == size)
750 return;
751
752 this->size = size;
753 if (sizeList->count() != 0) {
754 int i;
755 for (i = 0; i < sizeList->count() - 1; i++) {
756 if (sizeList->text(i).toInt() >= this->size)
757 break;
758 }
759 sizeList->blockSignals(true);
760 sizeList->setCurrentItem(i);
761 sizeList->blockSignals(false);
762 }
763 _q_updateSample();
764 }
765
retranslateStrings()766 void QFontDialogPrivate::retranslateStrings()
767 {
768 familyAccel->setText(QFontDialog::tr("&Font"));
769 styleAccel->setText(QFontDialog::tr("Font st&yle"));
770 sizeAccel->setText(QFontDialog::tr("&Size"));
771 #ifndef Q_WS_S60
772 // Removed the title due to lack of screen estate in small S60 screen.
773 // The effects are descriptive without a title (strikeout, underline).
774 effects->setTitle(QFontDialog::tr("Effects"));
775 #endif
776 strikeout->setText(QFontDialog::tr("Stri&keout"));
777 underline->setText(QFontDialog::tr("&Underline"));
778 sample->setTitle(QFontDialog::tr("Sample"));
779 writingSystemAccel->setText(QFontDialog::tr("Wr&iting System"));
780 }
781
782 /*!
783 \reimp
784 */
changeEvent(QEvent * e)785 void QFontDialog::changeEvent(QEvent *e)
786 {
787 Q_D(QFontDialog);
788 if (e->type() == QEvent::LanguageChange) {
789 d->retranslateStrings();
790 }
791 QDialog::changeEvent(e);
792 }
793
794 /*!
795 \since 4.5
796
797 \property QFontDialog::currentFont
798 \brief the current font of the dialog.
799 */
800
801 /*!
802 \since 4.5
803
804 Sets the font highlighted in the QFontDialog to the given \a font.
805
806 \sa selectedFont()
807 */
setCurrentFont(const QFont & font)808 void QFontDialog::setCurrentFont(const QFont &font)
809 {
810 Q_D(QFontDialog);
811 d->family = font.family();
812 d->style = d->fdb.styleString(font);
813 d->size = font.pointSize();
814 if (d->size == -1) {
815 QFontInfo fi(font);
816 d->size = fi.pointSize();
817 }
818 d->strikeout->setChecked(font.strikeOut());
819 d->underline->setChecked(font.underline());
820 d->updateFamilies();
821
822 #ifdef Q_WS_MAC
823 if (d->delegate)
824 QFontDialogPrivate::setFont(d->delegate, font);
825 #endif
826 }
827
828 /*!
829 \since 4.5
830
831 Returns the current font.
832
833 \sa selectedFont()
834 */
currentFont() const835 QFont QFontDialog::currentFont() const
836 {
837 Q_D(const QFontDialog);
838 return d->sampleEdit->font();
839 }
840
841 /*!
842 Returns the font that the user selected by clicking the \gui{OK}
843 or equivalent button.
844
845 \note This font is not always the same as the font held by the
846 \l currentFont property since the user can choose different fonts
847 before finally selecting the one to use.
848 */
selectedFont() const849 QFont QFontDialog::selectedFont() const
850 {
851 Q_D(const QFontDialog);
852 return d->selectedFont;
853 }
854
855 /*!
856 \enum QFontDialog::FontDialogOption
857 \since 4.5
858
859 This enum specifies various options that affect the look and feel
860 of a font dialog.
861
862 \value NoButtons Don't display \gui{OK} and \gui{Cancel} buttons. (Useful for "live dialogs".)
863 \value DontUseNativeDialog Use Qt's standard font dialog on the Mac instead of Apple's
864 native font panel. (Currently, the native dialog is never used,
865 but this is likely to change in future Qt releases.)
866
867 \sa options, setOption(), testOption()
868 */
869
870 /*!
871 Sets the given \a option to be enabled if \a on is true;
872 otherwise, clears the given \a option.
873
874 \sa options, testOption()
875 */
setOption(FontDialogOption option,bool on)876 void QFontDialog::setOption(FontDialogOption option, bool on)
877 {
878 Q_D(QFontDialog);
879 if (!(d->opts & option) != !on)
880 setOptions(d->opts ^ option);
881 }
882
883 /*!
884 Returns true if the given \a option is enabled; otherwise, returns
885 false.
886
887 \sa options, setOption()
888 */
testOption(FontDialogOption option) const889 bool QFontDialog::testOption(FontDialogOption option) const
890 {
891 Q_D(const QFontDialog);
892 return (d->opts & option) != 0;
893 }
894
895 /*!
896 \property QFontDialog::options
897 \brief the various options that affect the look and feel of the dialog
898 \since 4.5
899
900 By default, all options are disabled.
901
902 Options should be set before showing the dialog. Setting them while the
903 dialog is visible is not guaranteed to have an immediate effect on the
904 dialog (depending on the option and on the platform).
905
906 \sa setOption(), testOption()
907 */
setOptions(FontDialogOptions options)908 void QFontDialog::setOptions(FontDialogOptions options)
909 {
910 Q_D(QFontDialog);
911
912 FontDialogOptions changed = (options ^ d->opts);
913 if (!changed)
914 return;
915
916 d->opts = options;
917 d->buttonBox->setVisible(!(options & NoButtons));
918 }
919
options() const920 QFontDialog::FontDialogOptions QFontDialog::options() const
921 {
922 Q_D(const QFontDialog);
923 return d->opts;
924 }
925
926 #ifdef Q_WS_MAC
927 // can only have one Cocoa font panel active
928 bool QFontDialogPrivate::sharedFontPanelAvailable = true;
929 #endif
930
931 /*!
932 \since 4.5
933 \overload
934
935 Opens the dialog and connects its fontSelected() signal to the slot specified
936 by \a receiver and \a member.
937
938 The signal will be disconnected from the slot when the dialog is closed.
939 */
open(QObject * receiver,const char * member)940 void QFontDialog::open(QObject *receiver, const char *member)
941 {
942 Q_D(QFontDialog);
943 connect(this, SIGNAL(fontSelected(QFont)), receiver, member);
944 d->receiverToDisconnectOnClose = receiver;
945 d->memberToDisconnectOnClose = member;
946 QDialog::open();
947 }
948
949 /*!
950 \since 4.5
951
952 \fn void QFontDialog::currentFontChanged(const QFont &font)
953
954 This signal is emitted when the current font is changed. The new font is
955 specified in \a font.
956
957 The signal is emitted while a user is selecting a font. Ultimately, the
958 chosen font may differ from the font currently selected.
959
960 \sa currentFont, fontSelected(), selectedFont()
961 */
962
963 /*!
964 \since 4.5
965
966 \fn void QFontDialog::fontSelected(const QFont &font)
967
968 This signal is emitted when a font has been selected. The selected font is
969 specified in \a font.
970
971 The signal is only emitted when a user has chosen the final font to be
972 used. It is not emitted while the user is changing the current font in the
973 font dialog.
974
975 \sa selectedFont(), currentFontChanged(), currentFont
976 */
977
978 /*!
979 \reimp
980 */
setVisible(bool visible)981 void QFontDialog::setVisible(bool visible)
982 {
983 if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) != visible)
984 return;
985 #ifdef Q_WS_MAC
986 Q_D(QFontDialog);
987 if (d->canBeNativeDialog()){
988 if (d->setVisible_sys(visible)){
989 d->nativeDialogInUse = true;
990 // Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
991 // updates the state correctly, but skips showing the non-native version:
992 setAttribute(Qt::WA_DontShowOnScreen, true);
993 } else {
994 d->nativeDialogInUse = false;
995 setAttribute(Qt::WA_DontShowOnScreen, false);
996 }
997 }
998 #endif // Q_WS_MAC
999 QDialog::setVisible(visible);
1000 }
1001
1002 /*!
1003 Closes the dialog and sets its result code to \a result. If this dialog
1004 is shown with exec(), done() causes the local event loop to finish,
1005 and exec() to return \a result.
1006
1007 \sa QDialog::done()
1008 */
done(int result)1009 void QFontDialog::done(int result)
1010 {
1011 Q_D(QFontDialog);
1012 QDialog::done(result);
1013 if (result == Accepted) {
1014 // We check if this is the same font we had before, if so we emit currentFontChanged
1015 QFont selectedFont = currentFont();
1016 if(selectedFont != d->selectedFont)
1017 emit(currentFontChanged(selectedFont));
1018 d->selectedFont = selectedFont;
1019 emit fontSelected(d->selectedFont);
1020 } else
1021 d->selectedFont = QFont();
1022 if (d->receiverToDisconnectOnClose) {
1023 disconnect(this, SIGNAL(fontSelected(QFont)),
1024 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
1025 d->receiverToDisconnectOnClose = 0;
1026 }
1027 d->memberToDisconnectOnClose.clear();
1028 }
1029
1030 #ifdef Q_WS_MAC
canBeNativeDialog()1031 bool QFontDialogPrivate::canBeNativeDialog()
1032 {
1033 Q_Q(QFontDialog);
1034 if (nativeDialogInUse)
1035 return true;
1036 if (q->testAttribute(Qt::WA_DontShowOnScreen))
1037 return false;
1038 if (opts & QFontDialog::DontUseNativeDialog)
1039 return false;
1040
1041 QLatin1String staticName(QFontDialog::staticMetaObject.className());
1042 QLatin1String dynamicName(q->metaObject()->className());
1043 return (staticName == dynamicName);
1044 }
1045 #endif // Q_WS_MAC
1046
1047 /*!
1048 \fn QFont QFontDialog::getFont(bool *ok, const QFont &initial, QWidget* parent, const char* name)
1049 \since 4.5
1050
1051 Call getFont(\a ok, \a initial, \a parent) instead.
1052
1053 \warning Do not delete \a parent during the execution of the dialog.
1054 If you want to do this, you should create the dialog
1055 yourself using one of the QFontDialog constructors.
1056
1057 The \a name parameter is ignored.
1058 */
1059
1060 /*!
1061 \fn QFont QFontDialog::getFont(bool *ok, QWidget* parent, const char* name)
1062
1063 Call getFont(\a ok, \a parent) instead.
1064
1065 \warning Do not delete \a parent during the execution of the dialog.
1066 If you want to do this, you should create the dialog
1067 yourself using one of the QFontDialog constructors.
1068
1069 The \a name parameter is ignored.
1070 */
1071
1072 QT_END_NAMESPACE
1073
1074 #include "qfontdialog.moc"
1075 #include "moc_qfontdialog.cpp"
1076
1077 #endif // QT_NO_FONTDIALOG
1078