Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickfiledialogimpl.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 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
6
7#include <QtCore/qloggingcategory.h>
8#include <QtGui/private/qguiapplication_p.h>
9#include <QtGui/qpa/qplatformtheme.h>
10#include <QtQml/qqmlinfo.h>
11#include <QtQml/qqmlfile.h>
12#include <QtQuick/private/qquickitemview_p_p.h>
13#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h>
14#include <QtQuickTemplates2/private/qquickpopupitem_p_p.h>
15#include <QtQuickControls2Impl/private/qquickplatformtheme_p.h>
16#include <QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h>
17
20
22
23Q_LOGGING_CATEGORY(lcCurrentFolder, "qt.quick.dialogs.quickfiledialogimpl.currentFolder")
24Q_LOGGING_CATEGORY(lcSelectedFile, "qt.quick.dialogs.quickfiledialogimpl.selectedFile")
25Q_LOGGING_CATEGORY(lcUpdateSelectedFile, "qt.quick.dialogs.quickfiledialogimpl.updateSelectedFile")
26Q_LOGGING_CATEGORY(lcOptions, "qt.quick.dialogs.quickfiledialogimpl.options")
27Q_LOGGING_CATEGORY(lcNameFilters, "qt.quick.dialogs.quickfiledialogimpl.namefilters")
28Q_LOGGING_CATEGORY(lcAttachedNameFilters, "qt.quick.dialogs.quickfiledialogimplattached.namefilters")
29Q_LOGGING_CATEGORY(lcAttachedCurrentIndex, "qt.quick.dialogs.quickfiledialogimplattached.currentIndex")
30
34
36{
38 if (filters == nameFilters)
39 return;
40
42 emit q->nameFiltersChanged();
43}
44
46{
49 if (!attached)
50 return;
51
52 auto openButton = attached->buttonBox()->standardButton(QPlatformDialogHelper::Open);
53 if (!openButton) {
54 qmlWarning(q).nospace() << "Can't update Open button's enabled state because it wasn't found";
55 return;
56 }
57
58 openButton->setEnabled(!selectedFile.isEmpty() && attached->breadcrumbBar()
59 && !attached->breadcrumbBar()->textField()->isVisible());
60}
61
70{
73 if (!attached || !attached->fileDialogListView())
74 return;
75
76 qCDebug(lcUpdateSelectedFile) << "updateSelectedFile called with oldFolderPath" << oldFolderPath;
77
78 QString newSelectedFilePath;
79 int newSelectedFileIndex = -1;
81 if (!oldFolderPath.isEmpty() && !newFolderPath.isEmpty()) {
82 // TODO: Add another platform theme hint for this behavior too, as e.g. macOS
83 // doesn't do it this way.
84 // If the user went up a directory (or several), we should set
85 // selectedFile to be the directory that we were in (or
86 // its closest ancestor that is a child of the new directory).
87 // E.g. if oldFolderPath is /foo/bar/baz/abc/xyz, and newFolderPath is /foo/bar,
88 // then we want to set selectedFile to be /foo/bar/baz.
89 const int indexOfFolder = oldFolderPath.indexOf(newFolderPath);
90 if (indexOfFolder != -1) {
91 // [folder]
92 // [ oldFolderPath ]
93 // /foo/bar/baz/abc/xyz
94 // [rel...Paths]
95 QStringList relativePaths = oldFolderPath.mid(indexOfFolder + newFolderPath.size()).split(QLatin1Char('/'), Qt::SkipEmptyParts);
96 newSelectedFilePath = newFolderPath + QLatin1Char('/') + relativePaths.first();
97
98 // Now find the index of that directory so that we can set the ListView's currentIndex to it.
99 const QDir newFolderDir(newFolderPath);
100 // Just to be safe...
101 if (!newFolderDir.exists()) {
102 qmlWarning(q) << "Directory" << newSelectedFilePath << "doesn't exist; can't get a file entry list for it";
103 return;
104 }
105
106 const QFileInfoList filesInNewDir = fileList(newFolderDir);
107 const QFileInfo newSelectedFileInfo(newSelectedFilePath);
108 newSelectedFileIndex = filesInNewDir.indexOf(newSelectedFileInfo);
109 }
110 }
111
112 static const bool preselectFirstFile = []() {
113 const QVariant envVar = qEnvironmentVariable("QT_QUICK_DIALOGS_PRESELECT_FIRST_FILE");
114 if (envVar.isValid() && envVar.canConvert<bool>())
115 return envVar.toBool();
116 return QGuiApplicationPrivate::platformTheme()->themeHint(
118 }();
119
120 if (preselectFirstFile && newSelectedFilePath.isEmpty()) {
121 // When entering into a directory that isn't a parent of the old one, the first
122 // file delegate should be selected.
123 // TODO: is there a cheaper way to do this? QDirIterator doesn't support sorting,
124 // so we can't use that. QQuickFolderListModel uses threads to fetch its data,
125 // so should be considered asynchronous. We might be able to use it, but it would
126 // complicate the code even more...
127 const QDir newFolderDir(newFolderPath);
128 if (newFolderDir.exists()) {
129 if (!cachedFileList.isEmpty()) {
130 newSelectedFilePath = cachedFileList.first().absoluteFilePath();
131 newSelectedFileIndex = 0;
132 }
133 }
134 }
135
136 const QUrl newSelectedFileUrl = QUrl::fromLocalFile(newSelectedFilePath);
137 qCDebug(lcUpdateSelectedFile).nospace() << "updateSelectedFile is setting selectedFile to " << newSelectedFileUrl
138 << ", newSelectedFileIndex is " << newSelectedFileIndex;
139 q->setSelectedFile(newSelectedFileUrl);
141 // If the index is -1, there are no files in the directory, and so fileDialogListView's
142 // currentIndex will already be -1.
143 if (newSelectedFileIndex != -1)
144 tryUpdateFileDialogListViewCurrentIndex(newSelectedFileIndex);
145}
146
148{
150 if (Q_UNLIKELY(!attached))
151 return;
152
153 const QFileInfo fileInfo(selectedFile.toLocalFile());
154 if (fileInfo.isFile())
155 attached->fileNameTextField()->setText(fileInfo.fileName());
156}
157
159{
160 QDir::SortFlags sortFlags = QDir::IgnoreCase;
162 sortFlags.setFlag(QDir::DirsFirst);
163 return sortFlags;
164}
165
170
172{
173 qCDebug(lcSelectedFile) << "setting fileDialogListView's currentIndex to" << newCurrentIndex;
174
175 // We block signals from ListView because we don't want fileDialogListViewCurrentIndexChanged
176 // to be called, as the file it gets from the delegate will not be up-to-date (but most
177 // importantly because we already just set the selected file).
179 const QSignalBlocker blocker(attached->fileDialogListView());
180 attached->fileDialogListView()->setCurrentIndex(newCurrentIndex);
182 if (QQuickItem *currentItem = attached->fileDialogListView()->currentItem())
183 currentItem->forceActiveFocus();
184}
185
193{
194 qCDebug(lcSelectedFile) << "tryUpdateFileDialogListViewCurrentIndex called with newCurrentIndex" << newCurrentIndex;
196 Q_ASSERT(attached);
197 Q_ASSERT(attached->fileDialogListView());
198
199 // We were likely trying to set an index for a file that the ListView hadn't loaded yet.
200 // We need to wait until the ListView has loaded all expected items, but since we have no
201 // efficient way of verifying that, we just check that the count is as expected.
202 if (newCurrentIndex != -1 && newCurrentIndex >= attached->fileDialogListView()->count()) {
203 qCDebug(lcSelectedFile) << "- trying to set currentIndex to" << newCurrentIndex
204 << "but fileDialogListView only has" << attached->fileDialogListView()->count()
205 << "items; setting pendingCurrentIndexToSet to" << newCurrentIndex;
206 pendingCurrentIndexToSet = newCurrentIndex;
209 return;
210 }
211
212 setFileDialogListViewCurrentIndex(newCurrentIndex);
213}
214
216{
218 qCDebug(lcSelectedFile) << "fileDialogListView count changed to" << attached->fileDialogListView()->count();
219
220 if (pendingCurrentIndexToSet != -1 && pendingCurrentIndexToSet < attached->fileDialogListView()->count()) {
221 // The view now has all of the items we expect it to, so we can set
222 // its currentIndex back to the selected file.
223 qCDebug(lcSelectedFile) << "- ListView has expected count;"
224 << "applying pending fileDialogListView currentIndex" << pendingCurrentIndexToSet;
225
230 qCDebug(lcSelectedFile) << "- reset pendingCurrentIndexToSet to -1";
231 } else {
232 qCDebug(lcSelectedFile) << "- ListView doesn't yet have expected count of" << cachedFileList.size();
233 }
234}
235
237{
238 // Let handleClick take care of calling accept().
239}
240
242{
245 // The "Open" button was clicked, so we need to set the file to the current file, if any.
246 const QFileInfo fileInfo(selectedFile.toLocalFile());
247 if (fileInfo.isDir()) {
248 // If it's a directory, navigate to it.
249 q->setCurrentFolder(selectedFile);
250 // Don't call accept(), because selecting a folder != accepting the dialog.
251 } else {
252 // Otherwise it's a file, so select it and close the dialog.
253
255
256 // Unless it already exists...
257 const bool dontConfirmOverride = q->options()->testOption(QFileDialogOptions::DontConfirmOverwrite);
258 const bool isSaveMode = q->options()->fileMode() == QFileDialogOptions::AnyFile;
260 attached && fileInfo.exists() && isSaveMode && !dontConfirmOverride) {
261 QQuickDialog *confirmationDialog = attached->overwriteConfirmationDialog();
262 confirmationDialog->open();
263 static_cast<QQuickDialogButtonBox *>(confirmationDialog->footer())->standardButton(QPlatformDialogHelper::Yes)
265 } else {
266 selectFile();
267 }
268 }
269 }
270}
271
281
286
291
293{
294 Q_D(const QQuickFileDialogImpl);
295 return d->currentFolder;
296}
297
298void QQuickFileDialogImpl::setCurrentFolder(const QUrl &currentFolder, SetReason setReason)
299{
301 qCDebug(lcCurrentFolder).nospace() << "setCurrentFolder called with " << currentFolder
302 << " (old currentFolder is " << d->currentFolder << ")";
303
304 // As we would otherwise get the file list from scratch in a couple of places,
305 // just get it once and cache it.
306 // We need to cache it before the equality check, otherwise opening the dialog
307 // several times in the same directory wouldn't update the cache.
308 if (!currentFolder.isEmpty())
309 d->cachedFileList = d->fileList(QQmlFile::urlToLocalFileOrQrc(currentFolder));
310 else
311 d->cachedFileList.clear();
312 qCDebug(lcCurrentFolder) << "- cachedFileList size is now " << d->cachedFileList.size();
313
314 if (currentFolder == d->currentFolder)
315 return;
316
317 const QString oldFolderPath = QQmlFile::urlToLocalFileOrQrc(d->currentFolder);
318
319 d->currentFolder = currentFolder;
320 // Don't update the selectedFile if it's an Internal set, as that
321 // means that the user just set selectedFile, and we're being called as a result of that.
322 if (setReason == SetReason::External) {
323 // Since the directory changed, the old file can no longer be selected.
324 d->updateSelectedFile(oldFolderPath);
325 }
326 emit currentFolderChanged(d->currentFolder);
327}
328
330{
331 Q_D(const QQuickFileDialogImpl);
332 return d->selectedFile;
333}
334
343{
344 qCDebug(lcSelectedFile) << "setSelectedFile called with" << selectedFile;
346 if (selectedFile == d->selectedFile)
347 return;
348
349 d->selectedFile = selectedFile;
350 d->updateEnabled();
351 emit selectedFileChanged(d->selectedFile);
352}
353
361{
363 const QUrl fileDirUrl = QUrl::fromLocalFile(QFileInfo(file.toLocalFile()).dir().absolutePath());
364 const bool currentFolderChanged = d->currentFolder != fileDirUrl;
365 qCDebug(lcSelectedFile) << "setting initial currentFolder to" << fileDirUrl << "and selectedFile to" << file;
368 d->updateFileNameTextEdit();
369 d->setCurrentIndexToInitiallySelectedFile = true;
370
371 // If the currentFolder didn't change, the FolderListModel won't change and
372 // neither will the ListView. This means that setFileDialogListViewCurrentIndex
373 // will never get called and the currentIndex will not reflect selectedFile.
374 // We need to account for that here.
376 const QFileInfo newSelectedFileInfo(d->selectedFile.toLocalFile());
377 const int indexOfSelectedFileInFileDialogListView = d->cachedFileList.indexOf(newSelectedFileInfo);
378 d->tryUpdateFileDialogListViewCurrentIndex(indexOfSelectedFileInFileDialogListView);
379 }
380}
381
382QSharedPointer<QFileDialogOptions> QQuickFileDialogImpl::options() const
383{
384 Q_D(const QQuickFileDialogImpl);
385 return d->options;
386}
387
388void QQuickFileDialogImpl::setOptions(const QSharedPointer<QFileDialogOptions> &options)
389{
390 qCDebug(lcOptions).nospace() << "setOptions called with:"
391 << " acceptMode=" << options->acceptMode()
392 << " fileMode=" << options->fileMode()
393 << " initialDirectory=" << options->initialDirectory()
394 << " nameFilters=" << options->nameFilters()
395 << " initiallySelectedNameFilter=" << options->initiallySelectedNameFilter();
396
398 d->options = options;
399
400 if (d->options) {
401 d->selectedNameFilter->setOptions(options);
402 d->setNameFilters(options->nameFilters());
403
404 if (auto attached = d->attachedOrWarn()) {
405 const bool isSaveMode = d->options->fileMode() == QFileDialogOptions::AnyFile;
406 attached->fileNameLabel()->setVisible(isSaveMode);
407 attached->fileNameTextField()->setVisible(isSaveMode);
408 }
409 }
410}
411
418{
419 Q_D(const QQuickFileDialogImpl);
420 return d->options ? d->options->nameFilters() : QStringList();
421}
422
424{
426 d->setNameFilters(QStringList());
427}
428
430{
431 Q_D(const QQuickFileDialogImpl);
432 if (!d->selectedNameFilter) {
433 QQuickFileDialogImpl *that = const_cast<QQuickFileDialogImpl *>(this);
434 d->selectedNameFilter = new QQuickFileNameFilter(that);
435 if (d->options)
436 d->selectedNameFilter->setOptions(d->options);
437 }
438 return d->selectedNameFilter;
439}
440
449{
451 d->acceptLabel = label;
452 QQuickFileDialogImplAttached *attached = d->attachedOrWarn();
453 if (!attached)
454 return;
455
456 auto acceptButton = attached->buttonBox()->standardButton(QPlatformDialogHelper::Open);
457 if (!acceptButton) {
458 qmlWarning(this).nospace() << "Can't set accept label to " << label
459 << "; failed to find Open button in DialogButtonBox of " << this;
460 return;
461 }
462
463 auto buttonType = (d->options && d->options->acceptMode() == QFileDialogOptions::AcceptSave)
466 acceptButton->setText(!label.isEmpty()
468}
469
471{
473 d->rejectLabel = label;
474 QQuickFileDialogImplAttached *attached = d->attachedOrWarn();
475 if (!attached)
476 return;
477
478 auto rejectButton = attached->buttonBox()->standardButton(QPlatformDialogHelper::Cancel);
479 if (!rejectButton) {
480 qmlWarning(this).nospace() << "Can't set reject label to " << label
481 << "; failed to find Open button in DialogButtonBox of " << this;
482 return;
483 }
484
485 rejectButton->setText(!label.isEmpty()
487}
488
490{
491 qCDebug(lcNameFilters) << "selectNameFilter called with" << filter;
493 d->selectedNameFilter->update(filter);
495}
496
502{
503 const QString previous = selectedFile().fileName();
504 if (previous == fileName)
505 return;
506
507 QUrl newSelectedFile;
508 newSelectedFile.setScheme(currentFolder().scheme());
509 newSelectedFile.setPath(currentFolder().path() + u'/' + fileName);
510 setSelectedFile(newSelectedFile);
511}
512
517
519{
522
523 // Find the right-most button and set its key navigation so that
524 // tab moves focus to the breadcrumb bar's up button. I tried
525 // doing this via KeyNavigation on the DialogButtonBox in QML,
526 // but it didn't work (probably because it's not the right item).
527 QQuickFileDialogImplAttached *attached = d->attachedOrWarn();
528 if (!attached)
529 return;
530
531 const int buttonCount = attached->buttonBox()->count();
532 if (buttonCount == 0)
533 return;
534
535 QQuickAbstractButton *rightMostButton = qobject_cast<QQuickAbstractButton *>(
536 attached->buttonBox()->itemAt(buttonCount - 1));
537 if (!rightMostButton) {
538 qmlWarning(this) << "Can't find right-most button in DialogButtonBox";
539 return;
540 }
541
542 auto keyNavigationAttached = QQuickKeyNavigationAttached::qmlAttachedProperties(rightMostButton);
543 if (!keyNavigationAttached) {
544 qmlWarning(this) << "Can't create attached KeyNavigation object on" << QDebug::toString(rightMostButton);
545 return;
546 }
547
548 keyNavigationAttached->setTab(attached->breadcrumbBar()->upButton());
549}
550
552{
555
556 if (change != QQuickItem::ItemVisibleHasChanged || !isComponentComplete() || !data.boolValue)
557 return;
558
559 QQuickFileDialogImplAttached *attached = d->attachedOrWarn();
560 if (!attached)
561 return;
562
564 d->updateEnabled();
565}
566
568{
571 qmlAttachedPropertiesObject<QQuickFileDialogImpl>(q, false));
572 if (!attached)
573 qmlWarning(q) << "Expected FileDialogImpl attached object to be present on" << this;
574 return attached;
575}
576
577void QQuickFileDialogImplAttachedPrivate::nameFiltersComboBoxItemActivated(int index)
578{
579 qCDebug(lcAttachedNameFilters) << "nameFiltersComboBoxItemActivated called with" << index;
580 auto fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent);
581 if (!fileDialogImpl)
582 return;
583
584 fileDialogImpl->selectNameFilter(nameFiltersComboBox->textAt(index));
585}
586
587void QQuickFileDialogImplAttachedPrivate::fileDialogListViewCurrentIndexChanged()
588{
589 auto fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent);
590 if (!fileDialogImpl)
591 return;
592
593 auto fileDialogDelegate = qobject_cast<QQuickFileDialogDelegate*>(fileDialogListView->currentItem());
594 if (!fileDialogDelegate)
595 return;
596
598 qCDebug(lcAttachedCurrentIndex).nospace() << "fileDialogListView currentIndex changed to " << fileDialogListView->currentIndex()
599 << " with moveReason " << moveReason
600 << "; the file at that index is " << fileDialogDelegate->file();
601
602 // Only update selectedFile if the currentIndex changed as a result of user interaction;
603 // things like model changes (i.e. QQuickItemViewPrivate::applyModelChanges() calling
604 // QQuickItemViewPrivate::updateCurrent as a result of us changing the directory on the FolderListModel)
605 // shouldn't cause the selectedFile to change.
606 auto fileDialogImplPrivate = QQuickFileDialogImplPrivate::get(fileDialogImpl);
607 if (moveReason != QQuickItemViewPrivate::Other) {
608 fileDialogImpl->setSelectedFile(fileDialogDelegate->file());
609 fileDialogImplPrivate->updateFileNameTextEdit();
610 } else if (fileDialogImplPrivate->setCurrentIndexToInitiallySelectedFile) {
611 // When setting selectedFile before opening the FileDialog,
612 // we need to ensure that the currentIndex is correct, because the initial change
613 // in directory will cause the underyling FolderListModel to change its folder property,
614 // which in turn resets the fileDialogListView's currentIndex to 0.
615 const QFileInfo newSelectedFileInfo(fileDialogImplPrivate->selectedFile.toLocalFile());
616 const int indexOfSelectedFileInFileDialogListView = fileDialogImplPrivate->cachedFileList.indexOf(newSelectedFileInfo);
617 fileDialogImplPrivate->tryUpdateFileDialogListViewCurrentIndex(indexOfSelectedFileInFileDialogListView);
618 fileDialogImplPrivate->setCurrentIndexToInitiallySelectedFile = false;
619 }
620}
621
622void QQuickFileDialogImplAttachedPrivate::fileNameEditedByUser()
623{
624 if (!buttonBox)
625 return;
627 if (!openButton || !fileNameTextField)
628 return;
629 openButton->setEnabled(!fileNameTextField->text().isEmpty());
630}
631
632void QQuickFileDialogImplAttachedPrivate::fileNameEditingByUserFinished()
633{
634 auto fileDialogImpl = qobject_cast<QQuickFileDialogImpl *>(parent);
635 if (!fileDialogImpl)
636 return;
637
638 fileDialogImpl->setFileName(fileNameTextField->text());
639}
640
643{
644 if (!qobject_cast<QQuickFileDialogImpl*>(parent)) {
645 qmlWarning(this) << "FileDialogImpl attached properties should only be "
646 << "accessed through the root FileDialogImpl instance";
647 }
648}
649
651{
653 return d->buttonBox;
654}
655
657{
659 if (buttonBox == d->buttonBox)
660 return;
661
662 if (d->buttonBox) {
663 QQuickFileDialogImpl *fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent());
664 if (fileDialogImpl) {
665 auto dialogPrivate = QQuickDialogPrivate::get(fileDialogImpl);
667 dialogPrivate, &QQuickDialogPrivate::handleAccept);
669 dialogPrivate, &QQuickDialogPrivate::handleReject);
671 dialogPrivate, &QQuickDialogPrivate::handleClick);
672 }
673 }
674
675 d->buttonBox = buttonBox;
676
677 if (buttonBox) {
678 QQuickFileDialogImpl *fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent());
679 if (fileDialogImpl) {
680 auto dialogPrivate = QQuickDialogPrivate::get(fileDialogImpl);
682 dialogPrivate, &QQuickDialogPrivate::handleAccept);
684 dialogPrivate, &QQuickDialogPrivate::handleReject);
686 dialogPrivate, &QQuickDialogPrivate::handleClick);
687 }
688 }
689
691}
692
694{
696 return d->nameFiltersComboBox;
697}
698
700{
702 if (nameFiltersComboBox == d->nameFiltersComboBox)
703 return;
704
705 d->nameFiltersComboBox = nameFiltersComboBox;
706
708 d, &QQuickFileDialogImplAttachedPrivate::nameFiltersComboBoxItemActivated);
709
711}
712
714{
716 return d->nameFiltersComboBox ? d->nameFiltersComboBox->currentText() : QString();
717}
718
720{
722 qCDebug(lcAttachedNameFilters) << "selectNameFilter called with" << filter;
723 if (!d->nameFiltersComboBox)
724 return;
725
726 const int indexInComboBox = d->nameFiltersComboBox->find(filter);
727 if (indexInComboBox == -1)
728 return;
729
730 qCDebug(lcAttachedNameFilters) << "setting ComboBox's currentIndex to" << indexInComboBox;
731 d->nameFiltersComboBox->setCurrentIndex(indexInComboBox);
732}
733
735{
737 return d->fileDialogListView;
738}
739
741{
743 if (fileDialogListView == d->fileDialogListView)
744 return;
745
746 d->fileDialogListView = fileDialogListView;
747
749 d, &QQuickFileDialogImplAttachedPrivate::fileDialogListViewCurrentIndexChanged);
750
752}
753
759
761{
763 if (breadcrumbBar == d->breadcrumbBar)
764 return;
765
766 d->breadcrumbBar = breadcrumbBar;
768}
769
771{
773 return d->fileNameLabel;
774}
775
777{
779 if (fileNameLabel == d->fileNameLabel)
780 return;
781
782 d->fileNameLabel = fileNameLabel;
783
785}
786
788{
790 return d->fileNameTextField;
791}
792
794{
796 if (fileNameTextField == d->fileNameTextField)
797 return;
798
799 if (d->fileNameTextField) {
800 QObjectPrivate::disconnect(d->fileNameTextField, &QQuickTextField::editingFinished,
801 d, &QQuickFileDialogImplAttachedPrivate::fileNameEditingByUserFinished);
802 QObjectPrivate::disconnect(d->fileNameTextField, &QQuickTextField::textEdited,
803 d, &QQuickFileDialogImplAttachedPrivate::fileNameEditedByUser);
804 }
805
806 d->fileNameTextField = fileNameTextField;
807
808 if (d->fileNameTextField) {
809 QObjectPrivate::connect(d->fileNameTextField, &QQuickTextField::editingFinished,
810 d, &QQuickFileDialogImplAttachedPrivate::fileNameEditingByUserFinished);
811 QObjectPrivate::connect(d->fileNameTextField, &QQuickTextField::textEdited,
812 d, &QQuickFileDialogImplAttachedPrivate::fileNameEditedByUser);
813 }
815}
816
818{
820 return d->overwriteConfirmationDialog;
821}
822
824{
826 if (dialog == d->overwriteConfirmationDialog)
827 return;
828
829 QQuickFileDialogImpl *fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent());
830 if (d->overwriteConfirmationDialog && fileDialogImpl)
831 QObjectPrivate::disconnect(d->overwriteConfirmationDialog, &QQuickDialog::accepted,
833
834 d->overwriteConfirmationDialog = dialog;
835
836 if (d->overwriteConfirmationDialog && fileDialogImpl)
837 QObjectPrivate::connect(d->overwriteConfirmationDialog, &QQuickDialog::accepted,
839
841}
842
844
845#include "moc_qquickfiledialogimpl_p.cpp"
\inmodule QtCore
Definition qdir.h:20
QString dirName() const
Returns the name of the directory; this is not the same as the path, e.g.
Definition qdir.cpp:715
QString absolutePath() const
Returns the absolute path (a path that starts with "/" or with a drive specification),...
Definition qdir.cpp:667
@ IgnoreCase
Definition qdir.h:58
@ DirsFirst
Definition qdir.h:56
@ Files
Definition qdir.h:23
@ NoDotAndDotDot
Definition qdir.h:44
@ Dirs
Definition qdir.h:22
QString initiallySelectedNameFilter() const
AcceptMode acceptMode() const
QStringList nameFilters() const
QString fileName() const
QString absoluteFilePath() const
bool isFile() const
Returns true if this object points to a file or to a symbolic link to a file.
bool isDir() const
Returns true if this object points to a directory or to a symbolic link to a directory.
QDir dir() const
Returns a QDir object representing the path of the parent directory of the file system entry that thi...
bool exists() const
Returns true if the file system entry this QFileInfo refers to exists; otherwise returns false.
static QPlatformTheme * platformTheme()
qsizetype size() const noexcept
Definition qlist.h:397
bool isEmpty() const noexcept
Definition qlist.h:401
T & first()
Definition qlist.h:645
QObject * parent
Definition qobject.h:73
static QMetaObject::Connection connect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot, Qt::ConnectionType type=Qt::AutoConnection)
Definition qobject_p.h:299
static bool disconnect(const typename QtPrivate::FunctionPointer< Func1 >::Object *sender, Func1 signal, const typename QtPrivate::FunctionPointer< Func2 >::Object *receiverPrivate, Func2 slot)
Definition qobject_p.h:328
\inmodule QtCore
Definition qobject.h:103
QObject * parent() const
Returns a pointer to the parent object.
Definition qobject.h:346
static QString urlToLocalFileOrQrc(const QString &)
If url is a local file returns a path suitable for passing to \l{QFile}.
Definition qqmlfile.cpp:742
virtual void componentComplete()=0
Invoked after the root component that caused this instantiation has completed construction.
void activated(int index)
Q_INVOKABLE QString textAt(int index) const
\qmlmethod string QtQuick.Controls::ComboBox::textAt(int index)
Q_INVOKABLE QQuickItem * itemAt(int index) const
\qmlmethod Item QtQuick.Controls::Container::itemAt(int index)
static QString buttonText(QPlatformDialogHelper::StandardButton standardButton)
void clicked(QQuickAbstractButton *button)
Q_INVOKABLE QQuickAbstractButton * standardButton(QPlatformDialogHelper::StandardButton button) const
\qmlmethod AbstractButton QtQuick.Controls::DialogButtonBox::standardButton(StandardButton button)
virtual void handleClick(QQuickAbstractButton *button)
static QQuickDialogPrivate * get(QQuickDialog *dialog)
virtual void handleAccept()
static QPlatformDialogHelper::ButtonRole buttonRole(QQuickAbstractButton *button)
Popup dialog with standard buttons and a title, used for short-term interaction with the user.
virtual void handleReject()
void accepted()
QPointer< QQuickTextField > fileNameTextField
QPointer< QQuickDialogButtonBox > buttonBox
QPointer< QQuickListView > fileDialogListView
QPointer< QQuickComboBox > nameFiltersComboBox
void setNameFiltersComboBox(QQuickComboBox *nameFiltersComboBox)
QQuickFolderBreadcrumbBar * breadcrumbBar
void setOverwriteConfirmationDialog(QQuickDialog *dialog)
QQuickFileDialogImplAttached(QObject *parent=nullptr)
void setFileNameTextField(QQuickTextField *fileNameTextField)
void setFileNameLabel(QQuickLabel *fileNameLabel)
void setButtonBox(QQuickDialogButtonBox *buttonBox)
void setBreadcrumbBar(QQuickFolderBreadcrumbBar *breadcrumbBar)
void setFileDialogListView(QQuickListView *fileDialogListView)
void selectNameFilter(const QString &filter)
static QDir::SortFlags fileListSortFlags()
static QQuickFileDialogImplPrivate * get(QQuickFileDialogImpl *dialog)
QQuickFileDialogImplAttached * attachedOrWarn()
void setFileDialogListViewCurrentIndex(int newCurrentIndex)
void updateSelectedFile(const QString &oldFolderPath)
void handleClick(QQuickAbstractButton *button) override
static QFileInfoList fileList(const QDir &dir)
void tryUpdateFileDialogListViewCurrentIndex(int newCurrentIndex)
QQuickAbstractButton * lastButtonClicked
void setNameFilters(const QStringList &filters)
void setRejectLabel(const QString &label)
void setSelectedFile(const QUrl &file)
void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) override
void setAcceptLabel(const QString &label)
void filterSelected(const QString &filter)
void setFileName(const QString &fileName)
void setOptions(const QSharedPointer< QFileDialogOptions > &options)
void selectedFileChanged(const QUrl &selectedFileUrl)
void setCurrentFolder(const QUrl &currentFolder, SetReason setReason=SetReason::External)
void componentComplete() override
Invoked after the root component that caused this instantiation has completed construction.
QQuickFileDialogImpl(QObject *parent=nullptr)
void selectNameFilter(const QString &filter)
QQuickFileNameFilter * selectedNameFilter
static QQuickFileDialogImplAttached * qmlAttachedProperties(QObject *object)
QSharedPointer< QFileDialogOptions > options() const
void setInitialCurrentFolderAndSelectedFile(const QUrl &file)
void currentFolderChanged(const QUrl &folderUrl)
static QQuickItemViewPrivate * get(QQuickItemView *o)
Q_INVOKABLE void positionViewAtIndex(int index, int mode)
QQuickItem * currentItem
void currentIndexChanged()
void countChanged()
void setCurrentIndex(int idx)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
bool isVisible() const
void setEnabled(bool)
Q_INVOKABLE void forceActiveFocus()
\qmlmethod point QtQuick::Item::mapToItem(Item item, real x, real y) \qmlmethod point QtQuick::Item::...
ItemChange
Used in conjunction with QQuickItem::itemChange() to notify the item about certain types of changes.
Definition qquickitem.h:144
@ ItemVisibleHasChanged
Definition qquickitem.h:148
static QQuickKeyNavigationAttached * qmlAttachedProperties(QObject *)
static QVariant getThemeHint(QPlatformTheme::ThemeHint themeHint)
virtual void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data)
void open()
\qmlmethod void QtQuick.Controls::Popup::open()
bool isComponentComplete() const
void setText(const QString &)
Exception-safe wrapper around QObject::blockSignals().
Definition qobject.h:483
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3368
QString fileName(ComponentFormattingOptions options=FullyDecoded) const
Definition qurl.cpp:2497
bool isValid() const
Returns true if the URL is non-empty and valid; otherwise returns false.
Definition qurl.cpp:1882
bool isEmpty() const
Returns true if the URL has no data; otherwise returns false.
Definition qurl.cpp:1896
void setScheme(const QString &scheme)
Sets the scheme of the URL to scheme.
Definition qurl.cpp:1967
QString toLocalFile() const
Returns the path of this URL formatted as a local file path.
Definition qurl.cpp:3425
\inmodule QtCore
Definition qvariant.h:65
QPushButton * button
[2]
Combined button and popup list for selecting options.
ConnectionType
@ QueuedConnection
@ UniqueConnection
@ DirectConnection
@ SkipEmptyParts
Definition qnamespace.h:128
@ PopupFocusReason
#define Q_UNLIKELY(x)
QList< QString > QStringList
Constructs a string list that contains the given string, str.
#define Q_LOGGING_CATEGORY(name,...)
#define qCDebug(category,...)
GLuint index
[2]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLuint GLsizei const GLchar * label
[43]
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLsizei const GLchar *const * path
static QString toLocalFile(const QString &url)
Definition qqmlfile.cpp:708
Q_QML_EXPORT QQmlInfo qmlWarning(const QObject *me)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
#define emit
QFile file
[0]
QString dir
[11]
QFileDialog dialog(this)
[1]
const QStringList filters({"Image files (*.png *.xpm *.jpg)", "Text files (*.txt)", "Any files (*)" })
[6]
\inmodule QtCore \reentrant
Definition qchar.h:18
QT_BEGIN_NAMESPACE bool toBool(const QString &str)
Definition utils.h:14
\inmodule QtQuick
Definition qquickitem.h:159