1 | // Copyright (C) 2018 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qplatformdialoghelper.h" |
5 | |
6 | #include <QtCore/QCoreApplication> |
7 | #include <QtCore/QList> |
8 | #if QT_CONFIG(regularexpression) |
9 | #include <QtCore/QRegularExpression> |
10 | #endif |
11 | #if QT_CONFIG(settings) |
12 | #include <QtCore/QSettings> |
13 | #endif |
14 | #include <QtCore/QSharedData> |
15 | #include <QtCore/QUrl> |
16 | #include <QtCore/QVariant> |
17 | #include <QtGui/QColor> |
18 | #include <QtGui/QPixmap> |
19 | |
20 | #include <algorithm> |
21 | |
22 | QT_BEGIN_NAMESPACE |
23 | |
24 | using namespace Qt::StringLiterals; |
25 | |
26 | QT_IMPL_METATYPE_EXTERN_TAGGED(QPlatformDialogHelper::StandardButton, |
27 | QPlatformDialogHelper__StandardButton) |
28 | QT_IMPL_METATYPE_EXTERN_TAGGED(QPlatformDialogHelper::ButtonRole, |
29 | QPlatformDialogHelper__ButtonRole) |
30 | |
31 | /*! |
32 | \class QPlatformDialogHelper |
33 | \since 5.0 |
34 | \internal |
35 | \ingroup qpa |
36 | |
37 | \brief The QPlatformDialogHelper class allows for platform-specific customization of dialogs. |
38 | |
39 | */ |
40 | |
41 | /*! |
42 | \enum QPlatformDialogHelper::StyleHint |
43 | |
44 | This enum type specifies platform-specific style hints. |
45 | |
46 | \value DialogIsQtWindow Indicates that a platform-specific dialog is implemented |
47 | as in-process Qt window. It allows to prevent blocking the |
48 | dialog by an invisible proxy Qt dialog. |
49 | |
50 | \sa styleHint() |
51 | */ |
52 | |
53 | static const int buttonRoleLayouts[2][6][14] = |
54 | { |
55 | // Qt::Horizontal |
56 | { |
57 | // WinLayout |
58 | { QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::YesRole, QPlatformDialogHelper::AcceptRole, |
59 | QPlatformDialogHelper::AlternateRole, QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::NoRole, |
60 | QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::RejectRole, QPlatformDialogHelper::ApplyRole, |
61 | QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }, |
62 | |
63 | // MacLayout |
64 | { QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ActionRole, |
65 | QPlatformDialogHelper::Stretch, QPlatformDialogHelper::DestructiveRole | QPlatformDialogHelper::Reverse, |
66 | QPlatformDialogHelper::AlternateRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::RejectRole | QPlatformDialogHelper::Reverse, |
67 | QPlatformDialogHelper::AcceptRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::NoRole | QPlatformDialogHelper::Reverse, |
68 | QPlatformDialogHelper::YesRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }, |
69 | |
70 | // KdeLayout |
71 | { QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::YesRole, |
72 | QPlatformDialogHelper::NoRole, QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::AlternateRole, |
73 | QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::RejectRole, QPlatformDialogHelper::EOL }, |
74 | |
75 | // GnomeLayout |
76 | { QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::ActionRole, |
77 | QPlatformDialogHelper::ApplyRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::DestructiveRole | QPlatformDialogHelper::Reverse, |
78 | QPlatformDialogHelper::AlternateRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::RejectRole | QPlatformDialogHelper::Reverse, |
79 | QPlatformDialogHelper::AcceptRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::NoRole | QPlatformDialogHelper::Reverse, |
80 | QPlatformDialogHelper::YesRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::EOL }, |
81 | |
82 | // AndroidLayout (neutral, stretch, dismissive, affirmative) |
83 | // https://material.io/guidelines/components/dialogs.html#dialogs-specs |
84 | { QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ActionRole, |
85 | QPlatformDialogHelper::Stretch, QPlatformDialogHelper::RejectRole | QPlatformDialogHelper::Reverse, |
86 | QPlatformDialogHelper::NoRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::DestructiveRole | QPlatformDialogHelper::Reverse, |
87 | QPlatformDialogHelper::AlternateRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::AcceptRole | QPlatformDialogHelper::Reverse, |
88 | QPlatformDialogHelper::YesRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL } |
89 | }, |
90 | |
91 | // Qt::Vertical |
92 | { |
93 | // WinLayout |
94 | { QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::YesRole, QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::AlternateRole, |
95 | QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::NoRole, QPlatformDialogHelper::RejectRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ResetRole, |
96 | QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }, |
97 | |
98 | // MacLayout |
99 | { QPlatformDialogHelper::YesRole, QPlatformDialogHelper::NoRole, QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::RejectRole, |
100 | QPlatformDialogHelper::AlternateRole, QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::ApplyRole, |
101 | QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }, |
102 | |
103 | // KdeLayout |
104 | { QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::AlternateRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ActionRole, |
105 | QPlatformDialogHelper::YesRole, QPlatformDialogHelper::NoRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::ResetRole, |
106 | QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::RejectRole, QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL }, |
107 | |
108 | // GnomeLayout |
109 | { QPlatformDialogHelper::YesRole, QPlatformDialogHelper::NoRole, QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::RejectRole, |
110 | QPlatformDialogHelper::AlternateRole, QPlatformDialogHelper::DestructiveRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::Stretch, |
111 | QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }, |
112 | |
113 | // AndroidLayout |
114 | // (affirmative |
115 | // dismissive |
116 | // neutral) |
117 | // https://material.io/guidelines/components/dialogs.html#dialogs-specs |
118 | { QPlatformDialogHelper::YesRole, QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::AlternateRole, QPlatformDialogHelper::DestructiveRole, |
119 | QPlatformDialogHelper::NoRole, QPlatformDialogHelper::RejectRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::ApplyRole, |
120 | QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL } |
121 | } |
122 | }; |
123 | |
124 | |
125 | QPlatformDialogHelper::QPlatformDialogHelper() |
126 | { |
127 | qRegisterMetaType<StandardButton>(); |
128 | qRegisterMetaType<ButtonRole>(); |
129 | } |
130 | |
131 | QPlatformDialogHelper::~QPlatformDialogHelper() |
132 | { |
133 | } |
134 | |
135 | QVariant QPlatformDialogHelper::styleHint(StyleHint hint) const |
136 | { |
137 | return QPlatformDialogHelper::defaultStyleHint(hint); |
138 | } |
139 | |
140 | QVariant QPlatformDialogHelper::defaultStyleHint(QPlatformDialogHelper::StyleHint hint) |
141 | { |
142 | Q_UNUSED(hint); |
143 | return QVariant(); |
144 | } |
145 | |
146 | // Font dialog |
147 | |
148 | class QFontDialogOptionsPrivate : public QSharedData |
149 | { |
150 | public: |
151 | QFontDialogOptionsPrivate() = default; |
152 | |
153 | QFontDialogOptions::FontDialogOptions options; |
154 | QString windowTitle; |
155 | }; |
156 | |
157 | QFontDialogOptions::QFontDialogOptions(QFontDialogOptionsPrivate *dd) |
158 | : d(dd) |
159 | { |
160 | } |
161 | |
162 | QFontDialogOptions::~QFontDialogOptions() |
163 | { |
164 | } |
165 | |
166 | namespace { |
167 | struct FontDialogCombined : QFontDialogOptionsPrivate, QFontDialogOptions |
168 | { |
169 | FontDialogCombined() : QFontDialogOptionsPrivate(), QFontDialogOptions(this) {} |
170 | FontDialogCombined(const FontDialogCombined &other) |
171 | : QFontDialogOptionsPrivate(other), QFontDialogOptions(this) {} |
172 | }; |
173 | } |
174 | |
175 | // static |
176 | QSharedPointer<QFontDialogOptions> QFontDialogOptions::create() |
177 | { |
178 | return QSharedPointer<FontDialogCombined>::create(); |
179 | } |
180 | |
181 | QSharedPointer<QFontDialogOptions> QFontDialogOptions::clone() const |
182 | { |
183 | return QSharedPointer<FontDialogCombined>::create(arguments: *static_cast<const FontDialogCombined*>(this)); |
184 | } |
185 | |
186 | QString QFontDialogOptions::windowTitle() const |
187 | { |
188 | return d->windowTitle; |
189 | } |
190 | |
191 | void QFontDialogOptions::setWindowTitle(const QString &title) |
192 | { |
193 | d->windowTitle = title; |
194 | } |
195 | |
196 | void QFontDialogOptions::setOption(QFontDialogOptions::FontDialogOption option, bool on) |
197 | { |
198 | if (!(d->options & option) != !on) |
199 | setOptions(d->options ^ option); |
200 | } |
201 | |
202 | bool QFontDialogOptions::testOption(QFontDialogOptions::FontDialogOption option) const |
203 | { |
204 | return d->options & option; |
205 | } |
206 | |
207 | void QFontDialogOptions::setOptions(FontDialogOptions options) |
208 | { |
209 | if (options != d->options) |
210 | d->options = options; |
211 | } |
212 | |
213 | QFontDialogOptions::FontDialogOptions QFontDialogOptions::options() const |
214 | { |
215 | return d->options; |
216 | } |
217 | |
218 | /*! |
219 | \class QPlatformFontDialogHelper |
220 | \since 5.0 |
221 | \internal |
222 | \ingroup qpa |
223 | |
224 | \brief The QPlatformFontDialogHelper class allows for platform-specific customization of font dialogs. |
225 | |
226 | */ |
227 | const QSharedPointer<QFontDialogOptions> &QPlatformFontDialogHelper::options() const |
228 | { |
229 | return m_options; |
230 | } |
231 | |
232 | void QPlatformFontDialogHelper::setOptions(const QSharedPointer<QFontDialogOptions> &options) |
233 | { |
234 | m_options = options; |
235 | } |
236 | |
237 | // Color dialog |
238 | |
239 | class QColorDialogStaticData |
240 | { |
241 | public: |
242 | enum { CustomColorCount = 16, StandardColorCount = 6 * 8 }; |
243 | |
244 | QColorDialogStaticData(); |
245 | inline void readSettings(); |
246 | inline void writeSettings() const; |
247 | |
248 | QRgb customRgb[CustomColorCount]; |
249 | QRgb standardRgb[StandardColorCount]; |
250 | bool customSet; |
251 | }; |
252 | |
253 | QColorDialogStaticData::QColorDialogStaticData() : customSet(false) |
254 | { |
255 | int i = 0; |
256 | for (int g = 0; g < 4; ++g) |
257 | for (int r = 0; r < 4; ++r) |
258 | for (int b = 0; b < 3; ++b) |
259 | standardRgb[i++] = qRgb(r: r * 255 / 3, g: g * 255 / 3, b: b * 255 / 2); |
260 | std::fill(customRgb, customRgb + CustomColorCount, 0xffffffff); |
261 | readSettings(); |
262 | } |
263 | |
264 | void QColorDialogStaticData::readSettings() |
265 | { |
266 | #if QT_CONFIG(settings) |
267 | const QSettings settings(QSettings::UserScope, QStringLiteral("QtProject" )); |
268 | for (int i = 0; i < int(CustomColorCount); ++i) { |
269 | const QVariant v = settings.value(key: "Qt/customColors/"_L1 + QString::number(i)); |
270 | if (v.isValid()) |
271 | customRgb[i] = v.toUInt(); |
272 | } |
273 | #endif |
274 | } |
275 | |
276 | void QColorDialogStaticData::writeSettings() const |
277 | { |
278 | #if QT_CONFIG(settings) |
279 | if (customSet) { |
280 | const_cast<QColorDialogStaticData*>(this)->customSet = false; |
281 | QSettings settings(QSettings::UserScope, QStringLiteral("QtProject" )); |
282 | for (int i = 0; i < int(CustomColorCount); ++i) |
283 | settings.setValue(key: "Qt/customColors/"_L1 + QString::number(i), value: customRgb[i]); |
284 | } |
285 | #endif |
286 | } |
287 | |
288 | Q_GLOBAL_STATIC(QColorDialogStaticData, qColorDialogStaticData) |
289 | |
290 | class QColorDialogOptionsPrivate : public QSharedData |
291 | { |
292 | public: |
293 | QColorDialogOptionsPrivate() = default; |
294 | // Write out settings around destruction of dialogs |
295 | ~QColorDialogOptionsPrivate() { qColorDialogStaticData()->writeSettings(); } |
296 | |
297 | QColorDialogOptions::ColorDialogOptions options; |
298 | QString windowTitle; |
299 | }; |
300 | |
301 | QColorDialogOptions::QColorDialogOptions(QColorDialogOptionsPrivate *dd) |
302 | : d(dd) |
303 | { |
304 | } |
305 | |
306 | QColorDialogOptions::~QColorDialogOptions() |
307 | { |
308 | } |
309 | |
310 | namespace { |
311 | struct ColorDialogCombined : QColorDialogOptionsPrivate, QColorDialogOptions |
312 | { |
313 | ColorDialogCombined() : QColorDialogOptionsPrivate(), QColorDialogOptions(this) {} |
314 | ColorDialogCombined(const ColorDialogCombined &other) |
315 | : QColorDialogOptionsPrivate(other), QColorDialogOptions(this) {} |
316 | }; |
317 | } |
318 | |
319 | // static |
320 | QSharedPointer<QColorDialogOptions> QColorDialogOptions::create() |
321 | { |
322 | return QSharedPointer<ColorDialogCombined>::create(); |
323 | } |
324 | |
325 | QSharedPointer<QColorDialogOptions> QColorDialogOptions::clone() const |
326 | { |
327 | return QSharedPointer<ColorDialogCombined>::create(arguments: *static_cast<const ColorDialogCombined*>(this)); |
328 | } |
329 | |
330 | QString QColorDialogOptions::windowTitle() const |
331 | { |
332 | return d->windowTitle; |
333 | } |
334 | |
335 | void QColorDialogOptions::setWindowTitle(const QString &title) |
336 | { |
337 | d->windowTitle = title; |
338 | } |
339 | |
340 | void QColorDialogOptions::setOption(QColorDialogOptions::ColorDialogOption option, bool on) |
341 | { |
342 | if (!(d->options & option) != !on) |
343 | setOptions(d->options ^ option); |
344 | } |
345 | |
346 | bool QColorDialogOptions::testOption(QColorDialogOptions::ColorDialogOption option) const |
347 | { |
348 | return d->options & option; |
349 | } |
350 | |
351 | void QColorDialogOptions::setOptions(ColorDialogOptions options) |
352 | { |
353 | if (options != d->options) |
354 | d->options = options; |
355 | } |
356 | |
357 | QColorDialogOptions::ColorDialogOptions QColorDialogOptions::options() const |
358 | { |
359 | return d->options; |
360 | } |
361 | |
362 | int QColorDialogOptions::customColorCount() |
363 | { |
364 | return QColorDialogStaticData::CustomColorCount; |
365 | } |
366 | |
367 | QRgb QColorDialogOptions::customColor(int index) |
368 | { |
369 | if (uint(index) >= uint(QColorDialogStaticData::CustomColorCount)) |
370 | return qRgb(r: 255, g: 255, b: 255); |
371 | return qColorDialogStaticData()->customRgb[index]; |
372 | } |
373 | |
374 | QRgb *QColorDialogOptions::customColors() |
375 | { |
376 | return qColorDialogStaticData()->customRgb; |
377 | } |
378 | |
379 | void QColorDialogOptions::setCustomColor(int index, QRgb color) |
380 | { |
381 | if (uint(index) >= uint(QColorDialogStaticData::CustomColorCount)) |
382 | return; |
383 | qColorDialogStaticData()->customSet = true; |
384 | qColorDialogStaticData()->customRgb[index] = color; |
385 | } |
386 | |
387 | QRgb *QColorDialogOptions::standardColors() |
388 | { |
389 | return qColorDialogStaticData()->standardRgb; |
390 | } |
391 | |
392 | QRgb QColorDialogOptions::standardColor(int index) |
393 | { |
394 | if (uint(index) >= uint(QColorDialogStaticData::StandardColorCount)) |
395 | return qRgb(r: 255, g: 255, b: 255); |
396 | return qColorDialogStaticData()->standardRgb[index]; |
397 | } |
398 | |
399 | void QColorDialogOptions::setStandardColor(int index, QRgb color) |
400 | { |
401 | if (uint(index) >= uint(QColorDialogStaticData::StandardColorCount)) |
402 | return; |
403 | qColorDialogStaticData()->standardRgb[index] = color; |
404 | } |
405 | |
406 | /*! |
407 | \class QPlatformColorDialogHelper |
408 | \since 5.0 |
409 | \internal |
410 | \ingroup qpa |
411 | |
412 | \brief The QPlatformColorDialogHelper class allows for platform-specific customization of color dialogs. |
413 | |
414 | */ |
415 | const QSharedPointer<QColorDialogOptions> &QPlatformColorDialogHelper::options() const |
416 | { |
417 | return m_options; |
418 | } |
419 | |
420 | void QPlatformColorDialogHelper::setOptions(const QSharedPointer<QColorDialogOptions> &options) |
421 | { |
422 | m_options = options; |
423 | } |
424 | |
425 | // File dialog |
426 | |
427 | class QFileDialogOptionsPrivate : public QSharedData |
428 | { |
429 | public: |
430 | QFileDialogOptions::FileDialogOptions options; |
431 | QString windowTitle; |
432 | |
433 | QFileDialogOptions::ViewMode viewMode = QFileDialogOptions::Detail; |
434 | QFileDialogOptions::FileMode fileMode = QFileDialogOptions::AnyFile; |
435 | QFileDialogOptions::AcceptMode acceptMode = QFileDialogOptions::AcceptOpen; |
436 | QString labels[QFileDialogOptions::DialogLabelCount]; |
437 | QDir::Filters filters = QDir::AllEntries | QDir::NoDotAndDotDot | QDir::AllDirs; |
438 | QList<QUrl> ; |
439 | bool useDefaultNameFilters = true; |
440 | QStringList nameFilters; |
441 | QStringList mimeTypeFilters; |
442 | QString defaultSuffix; |
443 | QStringList history; |
444 | QUrl initialDirectory; |
445 | QString initiallySelectedMimeTypeFilter; |
446 | QString initiallySelectedNameFilter; |
447 | QList<QUrl> initiallySelectedFiles; |
448 | QStringList supportedSchemes; |
449 | }; |
450 | |
451 | QFileDialogOptions::QFileDialogOptions(QFileDialogOptionsPrivate *dd) |
452 | : d(dd) |
453 | { |
454 | } |
455 | |
456 | QFileDialogOptions::~QFileDialogOptions() |
457 | { |
458 | } |
459 | |
460 | namespace { |
461 | struct FileDialogCombined : QFileDialogOptionsPrivate, QFileDialogOptions |
462 | { |
463 | FileDialogCombined() : QFileDialogOptionsPrivate(), QFileDialogOptions(this) {} |
464 | FileDialogCombined(const FileDialogCombined &other) : QFileDialogOptionsPrivate(other), QFileDialogOptions(this) {} |
465 | }; |
466 | } |
467 | |
468 | // static |
469 | QSharedPointer<QFileDialogOptions> QFileDialogOptions::create() |
470 | { |
471 | return QSharedPointer<FileDialogCombined>::create(); |
472 | } |
473 | |
474 | QSharedPointer<QFileDialogOptions> QFileDialogOptions::clone() const |
475 | { |
476 | return QSharedPointer<FileDialogCombined>::create(arguments: *static_cast<const FileDialogCombined*>(this)); |
477 | } |
478 | |
479 | QString QFileDialogOptions::windowTitle() const |
480 | { |
481 | return d->windowTitle; |
482 | } |
483 | |
484 | void QFileDialogOptions::setWindowTitle(const QString &title) |
485 | { |
486 | d->windowTitle = title; |
487 | } |
488 | |
489 | void QFileDialogOptions::setOption(QFileDialogOptions::FileDialogOption option, bool on) |
490 | { |
491 | if (!(d->options & option) != !on) |
492 | setOptions(d->options ^ option); |
493 | } |
494 | |
495 | bool QFileDialogOptions::testOption(QFileDialogOptions::FileDialogOption option) const |
496 | { |
497 | return d->options & option; |
498 | } |
499 | |
500 | void QFileDialogOptions::setOptions(FileDialogOptions options) |
501 | { |
502 | if (options != d->options) |
503 | d->options = options; |
504 | } |
505 | |
506 | QFileDialogOptions::FileDialogOptions QFileDialogOptions::options() const |
507 | { |
508 | return d->options; |
509 | } |
510 | |
511 | QDir::Filters QFileDialogOptions::filter() const |
512 | { |
513 | return d->filters; |
514 | } |
515 | |
516 | void QFileDialogOptions::setFilter(QDir::Filters filters) |
517 | { |
518 | d->filters = filters; |
519 | } |
520 | |
521 | void QFileDialogOptions::setViewMode(QFileDialogOptions::ViewMode mode) |
522 | { |
523 | d->viewMode = mode; |
524 | } |
525 | |
526 | QFileDialogOptions::ViewMode QFileDialogOptions::viewMode() const |
527 | { |
528 | return d->viewMode; |
529 | } |
530 | |
531 | void QFileDialogOptions::setFileMode(QFileDialogOptions::FileMode mode) |
532 | { |
533 | d->fileMode = mode; |
534 | } |
535 | |
536 | QFileDialogOptions::FileMode QFileDialogOptions::fileMode() const |
537 | { |
538 | return d->fileMode; |
539 | } |
540 | |
541 | void QFileDialogOptions::setAcceptMode(QFileDialogOptions::AcceptMode mode) |
542 | { |
543 | d->acceptMode = mode; |
544 | } |
545 | |
546 | QFileDialogOptions::AcceptMode QFileDialogOptions::acceptMode() const |
547 | { |
548 | return d->acceptMode; |
549 | } |
550 | |
551 | void QFileDialogOptions::(const QList<QUrl> &urls) |
552 | { |
553 | d->sidebarUrls = urls; |
554 | } |
555 | |
556 | QList<QUrl> QFileDialogOptions::() const |
557 | { |
558 | return d->sidebarUrls; |
559 | } |
560 | |
561 | /*! |
562 | \since 5.7 |
563 | \internal |
564 | The bool property useDefaultNameFilters indicates that no name filters have been |
565 | set or that they are equivalent to \gui{All Files (*)}. If it is true, the |
566 | platform can choose to hide the filter combo box. |
567 | |
568 | \sa defaultNameFilterString(). |
569 | */ |
570 | bool QFileDialogOptions::useDefaultNameFilters() const |
571 | { |
572 | return d->useDefaultNameFilters; |
573 | } |
574 | |
575 | void QFileDialogOptions::setUseDefaultNameFilters(bool dnf) |
576 | { |
577 | d->useDefaultNameFilters = dnf; |
578 | } |
579 | |
580 | void QFileDialogOptions::setNameFilters(const QStringList &filters) |
581 | { |
582 | d->useDefaultNameFilters = filters.size() == 1 |
583 | && filters.first() == QFileDialogOptions::defaultNameFilterString(); |
584 | d->nameFilters = filters; |
585 | } |
586 | |
587 | QStringList QFileDialogOptions::nameFilters() const |
588 | { |
589 | return d->useDefaultNameFilters ? |
590 | QStringList(QFileDialogOptions::defaultNameFilterString()) : d->nameFilters; |
591 | } |
592 | |
593 | /*! |
594 | \since 5.6 |
595 | \internal |
596 | \return The translated default name filter string (\gui{All Files (*)}). |
597 | \sa defaultNameFilters(), nameFilters() |
598 | */ |
599 | |
600 | QString QFileDialogOptions::defaultNameFilterString() |
601 | { |
602 | return QCoreApplication::translate(context: "QFileDialog" , key: "All Files (*)" ); |
603 | } |
604 | |
605 | void QFileDialogOptions::setMimeTypeFilters(const QStringList &filters) |
606 | { |
607 | d->mimeTypeFilters = filters; |
608 | } |
609 | |
610 | QStringList QFileDialogOptions::mimeTypeFilters() const |
611 | { |
612 | return d->mimeTypeFilters; |
613 | } |
614 | |
615 | void QFileDialogOptions::setDefaultSuffix(const QString &suffix) |
616 | { |
617 | d->defaultSuffix = suffix; |
618 | if (d->defaultSuffix.size() > 1 && d->defaultSuffix.startsWith(c: u'.')) |
619 | d->defaultSuffix.remove(i: 0, len: 1); // Silently change ".txt" -> "txt". |
620 | } |
621 | |
622 | QString QFileDialogOptions::defaultSuffix() const |
623 | { |
624 | return d->defaultSuffix; |
625 | } |
626 | |
627 | void QFileDialogOptions::setHistory(const QStringList &paths) |
628 | { |
629 | d->history = paths; |
630 | } |
631 | |
632 | QStringList QFileDialogOptions::history() const |
633 | { |
634 | return d->history; |
635 | } |
636 | |
637 | void QFileDialogOptions::setLabelText(QFileDialogOptions::DialogLabel label, const QString &text) |
638 | { |
639 | if (unsigned(label) < unsigned(DialogLabelCount)) |
640 | d->labels[label] = text; |
641 | } |
642 | |
643 | QString QFileDialogOptions::labelText(QFileDialogOptions::DialogLabel label) const |
644 | { |
645 | return (unsigned(label) < unsigned(DialogLabelCount)) ? d->labels[label] : QString(); |
646 | } |
647 | |
648 | bool QFileDialogOptions::isLabelExplicitlySet(DialogLabel label) |
649 | { |
650 | return unsigned(label) < unsigned(DialogLabelCount) && !d->labels[label].isEmpty(); |
651 | } |
652 | |
653 | QUrl QFileDialogOptions::initialDirectory() const |
654 | { |
655 | return d->initialDirectory; |
656 | } |
657 | |
658 | void QFileDialogOptions::setInitialDirectory(const QUrl &directory) |
659 | { |
660 | d->initialDirectory = directory; |
661 | } |
662 | |
663 | QString QFileDialogOptions::initiallySelectedMimeTypeFilter() const |
664 | { |
665 | return d->initiallySelectedMimeTypeFilter; |
666 | } |
667 | |
668 | void QFileDialogOptions::setInitiallySelectedMimeTypeFilter(const QString &filter) |
669 | { |
670 | d->initiallySelectedMimeTypeFilter = filter; |
671 | } |
672 | |
673 | QString QFileDialogOptions::initiallySelectedNameFilter() const |
674 | { |
675 | return d->initiallySelectedNameFilter; |
676 | } |
677 | |
678 | void QFileDialogOptions::setInitiallySelectedNameFilter(const QString &filter) |
679 | { |
680 | d->initiallySelectedNameFilter = filter; |
681 | } |
682 | |
683 | QList<QUrl> QFileDialogOptions::initiallySelectedFiles() const |
684 | { |
685 | return d->initiallySelectedFiles; |
686 | } |
687 | |
688 | void QFileDialogOptions::setInitiallySelectedFiles(const QList<QUrl> &files) |
689 | { |
690 | d->initiallySelectedFiles = files; |
691 | } |
692 | |
693 | // Schemes supported by the application |
694 | void QFileDialogOptions::setSupportedSchemes(const QStringList &schemes) |
695 | { |
696 | d->supportedSchemes = schemes; |
697 | } |
698 | |
699 | QStringList QFileDialogOptions::supportedSchemes() const |
700 | { |
701 | return d->supportedSchemes; |
702 | } |
703 | |
704 | void QPlatformFileDialogHelper::selectMimeTypeFilter(const QString &filter) |
705 | { |
706 | Q_UNUSED(filter); |
707 | } |
708 | |
709 | QString QPlatformFileDialogHelper::selectedMimeTypeFilter() const |
710 | { |
711 | return QString(); |
712 | } |
713 | |
714 | // Return true if the URL is supported by the filedialog implementation *and* by the application. |
715 | bool QPlatformFileDialogHelper::isSupportedUrl(const QUrl &url) const |
716 | { |
717 | return url.isLocalFile(); |
718 | } |
719 | |
720 | /*! |
721 | \class QPlatformFileDialogHelper |
722 | \since 5.0 |
723 | \internal |
724 | \ingroup qpa |
725 | |
726 | \brief The QPlatformFileDialogHelper class allows for platform-specific customization of file dialogs. |
727 | |
728 | */ |
729 | const QSharedPointer<QFileDialogOptions> &QPlatformFileDialogHelper::options() const |
730 | { |
731 | return m_options; |
732 | } |
733 | |
734 | void QPlatformFileDialogHelper::setOptions(const QSharedPointer<QFileDialogOptions> &options) |
735 | { |
736 | m_options = options; |
737 | } |
738 | |
739 | const char QPlatformFileDialogHelper::filterRegExp[] = |
740 | "^(.*)\\(([a-zA-Z0-9_.,*? +;#\\-\\[\\]@\\{\\}/!<>\\$%&=^~:\\|]*)\\)$" ; |
741 | |
742 | // Makes a list of filters from a normal filter string "Image Files (*.png *.jpg)" |
743 | QStringList QPlatformFileDialogHelper::cleanFilterList(const QString &filter) |
744 | { |
745 | #if QT_CONFIG(regularexpression) |
746 | static const QRegularExpression regexp(QString::fromLatin1(ba: filterRegExp)); |
747 | Q_ASSERT(regexp.isValid()); |
748 | QString f = filter; |
749 | QRegularExpressionMatch match = regexp.match(subject: filter); |
750 | if (match.hasMatch()) |
751 | f = match.captured(nth: 2); |
752 | return f.split(sep: u' ', behavior: Qt::SkipEmptyParts); |
753 | #else |
754 | Q_UNUSED(filter); |
755 | return QStringList(); |
756 | #endif |
757 | } |
758 | |
759 | // Message dialog |
760 | |
761 | class QMessageDialogOptionsPrivate : public QSharedData |
762 | { |
763 | public: |
764 | QMessageDialogOptionsPrivate() : |
765 | icon(QMessageDialogOptions::NoIcon), |
766 | buttons(QPlatformDialogHelper::Ok), |
767 | nextCustomButtonId(QPlatformDialogHelper::LastButton + 1) |
768 | {} |
769 | |
770 | QString windowTitle; |
771 | QMessageDialogOptions::StandardIcon icon; |
772 | QString text; |
773 | QString informativeText; |
774 | QString detailedText; |
775 | QPlatformDialogHelper::StandardButtons buttons; |
776 | QList<QMessageDialogOptions::CustomButton> customButtons; |
777 | int nextCustomButtonId; |
778 | QPixmap iconPixmap; |
779 | QString checkBoxLabel; |
780 | Qt::CheckState checkBoxState = Qt::Unchecked; |
781 | QMessageDialogOptions::Options options; |
782 | }; |
783 | |
784 | QMessageDialogOptions::QMessageDialogOptions(QMessageDialogOptionsPrivate *dd) |
785 | : d(dd) |
786 | { |
787 | } |
788 | |
789 | QMessageDialogOptions::~QMessageDialogOptions() |
790 | { |
791 | } |
792 | |
793 | namespace { |
794 | struct MessageDialogCombined : QMessageDialogOptionsPrivate, QMessageDialogOptions |
795 | { |
796 | MessageDialogCombined() : QMessageDialogOptionsPrivate(), QMessageDialogOptions(this) {} |
797 | MessageDialogCombined(const MessageDialogCombined &other) |
798 | : QMessageDialogOptionsPrivate(other), QMessageDialogOptions(this) {} |
799 | }; |
800 | } |
801 | |
802 | // static |
803 | QSharedPointer<QMessageDialogOptions> QMessageDialogOptions::create() |
804 | { |
805 | return QSharedPointer<MessageDialogCombined>::create(); |
806 | } |
807 | |
808 | QSharedPointer<QMessageDialogOptions> QMessageDialogOptions::clone() const |
809 | { |
810 | return QSharedPointer<MessageDialogCombined>::create(arguments: *static_cast<const MessageDialogCombined*>(this)); |
811 | } |
812 | |
813 | QString QMessageDialogOptions::windowTitle() const |
814 | { |
815 | return d->windowTitle; |
816 | } |
817 | |
818 | void QMessageDialogOptions::setWindowTitle(const QString &title) |
819 | { |
820 | d->windowTitle = title; |
821 | } |
822 | |
823 | QMessageDialogOptions::StandardIcon QMessageDialogOptions::standardIcon() const |
824 | { |
825 | return d->icon; |
826 | } |
827 | |
828 | void QMessageDialogOptions::setStandardIcon(StandardIcon icon) |
829 | { |
830 | d->icon = icon; |
831 | } |
832 | |
833 | void QMessageDialogOptions::setIconPixmap(const QPixmap &pixmap) |
834 | { |
835 | d->iconPixmap = pixmap; |
836 | } |
837 | |
838 | QPixmap QMessageDialogOptions::iconPixmap() const |
839 | { |
840 | return d->iconPixmap; |
841 | } |
842 | |
843 | QString QMessageDialogOptions::text() const |
844 | { |
845 | return d->text; |
846 | } |
847 | |
848 | void QMessageDialogOptions::setText(const QString &text) |
849 | { |
850 | d->text = text; |
851 | } |
852 | |
853 | QString QMessageDialogOptions::informativeText() const |
854 | { |
855 | return d->informativeText; |
856 | } |
857 | |
858 | void QMessageDialogOptions::setInformativeText(const QString &informativeText) |
859 | { |
860 | d->informativeText = informativeText; |
861 | } |
862 | |
863 | QString QMessageDialogOptions::detailedText() const |
864 | { |
865 | return d->detailedText; |
866 | } |
867 | |
868 | void QMessageDialogOptions::setDetailedText(const QString &detailedText) |
869 | { |
870 | d->detailedText = detailedText; |
871 | } |
872 | |
873 | void QMessageDialogOptions::setStandardButtons(QPlatformDialogHelper::StandardButtons buttons) |
874 | { |
875 | d->buttons = buttons; |
876 | } |
877 | |
878 | QPlatformDialogHelper::StandardButtons QMessageDialogOptions::standardButtons() const |
879 | { |
880 | return d->buttons; |
881 | } |
882 | |
883 | int QMessageDialogOptions::addButton(const QString &label, QPlatformDialogHelper::ButtonRole role, |
884 | void *buttonImpl) |
885 | { |
886 | const CustomButton b(d->nextCustomButtonId++, label, role, buttonImpl); |
887 | d->customButtons.append(t: b); |
888 | return b.id; |
889 | } |
890 | |
891 | static inline bool operator==(const QMessageDialogOptions::CustomButton &a, |
892 | const QMessageDialogOptions::CustomButton &b) { |
893 | return a.id == b.id; |
894 | } |
895 | |
896 | void QMessageDialogOptions::removeButton(int id) |
897 | { |
898 | d->customButtons.removeOne(t: CustomButton(id)); |
899 | } |
900 | |
901 | const QList<QMessageDialogOptions::CustomButton> &QMessageDialogOptions::customButtons() |
902 | { |
903 | return d->customButtons; |
904 | } |
905 | |
906 | const QMessageDialogOptions::CustomButton *QMessageDialogOptions::customButton(int id) |
907 | { |
908 | const int i = int(d->customButtons.indexOf(t: CustomButton(id))); |
909 | return (i < 0 ? nullptr : &d->customButtons.at(i)); |
910 | } |
911 | |
912 | void QMessageDialogOptions::setCheckBox(const QString &label, Qt::CheckState state) |
913 | { |
914 | d->checkBoxLabel = label; |
915 | d->checkBoxState = state; |
916 | } |
917 | |
918 | QString QMessageDialogOptions::checkBoxLabel() const |
919 | { |
920 | return d->checkBoxLabel; |
921 | } |
922 | |
923 | Qt::CheckState QMessageDialogOptions::checkBoxState() const |
924 | { |
925 | return d->checkBoxState; |
926 | } |
927 | |
928 | void QMessageDialogOptions::setOption(QMessageDialogOptions::Option option, bool on) |
929 | { |
930 | if (!(d->options & option) != !on) |
931 | setOptions(d->options ^ option); |
932 | } |
933 | |
934 | bool QMessageDialogOptions::testOption(QMessageDialogOptions::Option option) const |
935 | { |
936 | return d->options & option; |
937 | } |
938 | |
939 | void QMessageDialogOptions::setOptions(QMessageDialogOptions::Options options) |
940 | { |
941 | if (options != d->options) |
942 | d->options = options; |
943 | } |
944 | |
945 | QMessageDialogOptions::Options QMessageDialogOptions::options() const |
946 | { |
947 | return d->options; |
948 | } |
949 | |
950 | |
951 | QPlatformDialogHelper::ButtonRole QPlatformDialogHelper::buttonRole(QPlatformDialogHelper::StandardButton button) |
952 | { |
953 | switch (button) { |
954 | case Ok: |
955 | case Save: |
956 | case Open: |
957 | case SaveAll: |
958 | case Retry: |
959 | case Ignore: |
960 | return AcceptRole; |
961 | |
962 | case Cancel: |
963 | case Close: |
964 | case Abort: |
965 | return RejectRole; |
966 | |
967 | case Discard: |
968 | return DestructiveRole; |
969 | |
970 | case Help: |
971 | return HelpRole; |
972 | |
973 | case Apply: |
974 | return ApplyRole; |
975 | |
976 | case Yes: |
977 | case YesToAll: |
978 | return YesRole; |
979 | |
980 | case No: |
981 | case NoToAll: |
982 | return NoRole; |
983 | |
984 | case RestoreDefaults: |
985 | case Reset: |
986 | return ResetRole; |
987 | |
988 | default: |
989 | break; |
990 | } |
991 | return InvalidRole; |
992 | } |
993 | |
994 | const int *QPlatformDialogHelper::buttonLayout(Qt::Orientation orientation, ButtonLayout policy) |
995 | { |
996 | if (policy == UnknownLayout) { |
997 | #if defined (Q_OS_MACOS) |
998 | policy = MacLayout; |
999 | #elif defined (Q_OS_LINUX) || defined (Q_OS_UNIX) |
1000 | policy = KdeLayout; |
1001 | #elif defined (Q_OS_ANDROID) |
1002 | policy = AndroidLayout; |
1003 | #else |
1004 | policy = WinLayout; |
1005 | #endif |
1006 | } |
1007 | return buttonRoleLayouts[orientation == Qt::Vertical][policy]; |
1008 | } |
1009 | |
1010 | /*! |
1011 | \class QPlatformMessageDialogHelper |
1012 | \since 5.0 |
1013 | \internal |
1014 | \ingroup qpa |
1015 | |
1016 | \brief The QPlatformMessageDialogHelper class allows for platform-specific customization of Message dialogs. |
1017 | |
1018 | */ |
1019 | const QSharedPointer<QMessageDialogOptions> &QPlatformMessageDialogHelper::options() const |
1020 | { |
1021 | return m_options; |
1022 | } |
1023 | |
1024 | void QPlatformMessageDialogHelper::setOptions(const QSharedPointer<QMessageDialogOptions> &options) |
1025 | { |
1026 | m_options = options; |
1027 | } |
1028 | |
1029 | QT_END_NAMESPACE |
1030 | |
1031 | #include "moc_qplatformdialoghelper.cpp" |
1032 | |