diff options
Diffstat (limited to 'src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp')
-rw-r--r-- | src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp | 564 |
1 files changed, 0 insertions, 564 deletions
diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp deleted file mode 100644 index 8074b259..00000000 --- a/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp +++ /dev/null @@ -1,564 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the Qt Quick Dialogs module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL3$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPLv3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or later as published by the Free -** Software Foundation and appearing in the file LICENSE.GPL included in -** the packaging of this file. Please review the following information to -** ensure the GNU General Public License version 2.0 requirements will be -** met: http://www.gnu.org/licenses/gpl-2.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qquickfiledialogimpl_p.h" -#include "qquickfiledialogimpl_p_p.h" - -#include <QtCore/qloggingcategory.h> -#include <QtQml/qqmlinfo.h> -#include <QtQml/qqmlfile.h> -#include <QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h> -#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h> -#include <QtQuickTemplates2/private/qquickpopupitem_p_p.h> -#include "qquickfiledialogdelegate_p.h" -#include "qquickfolderbreadcrumbbar_p.h" - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcCurrentFolder, "qt.quick.dialogs.quickfiledialogimpl.currentFolder") -Q_LOGGING_CATEGORY(lcOptions, "qt.quick.dialogs.quickfiledialogimpl.options") -Q_LOGGING_CATEGORY(lcNameFilters, "qt.quick.dialogs.quickfiledialogimpl.namefilters") -Q_LOGGING_CATEGORY(lcAttachedNameFilters, "qt.quick.dialogs.quickfiledialogimplattached.namefilters") - -QQuickFileDialogImplPrivate::QQuickFileDialogImplPrivate() -{ -} - -void QQuickFileDialogImplPrivate::setNameFilters(const QStringList &filters) -{ - Q_Q(QQuickFileDialogImpl); - if (filters == nameFilters) - return; - - nameFilters = filters; - emit q->nameFiltersChanged(); -} - -void QQuickFileDialogImplPrivate::updateEnabled() -{ - Q_Q(QQuickFileDialogImpl); - QQuickFileDialogImplAttached *attached = attachedOrWarn(); - if (!attached) - return; - - auto openButton = attached->buttonBox()->standardButton(QPlatformDialogHelper::Open); - if (!openButton) { - qmlWarning(q).nospace() << "Can't update Open button's enabled state because it wasn't found"; - return; - } - - openButton->setEnabled(!currentFile.isEmpty() && attached->breadcrumbBar() - && !attached->breadcrumbBar()->textField()->isVisible()); -} - -/*! - \internal - - Ensures that a file is always selected after a change in \c folder. - - \a oldFolderPath is the previous value of \c folder. -*/ -void QQuickFileDialogImplPrivate::updateCurrentFile(const QString &oldFolderPath) -{ - Q_Q(QQuickFileDialogImpl); - QQuickFileDialogImplAttached *attached = attachedOrWarn(); - if (!attached || !attached->fileDialogListView()) - return; - - QString newCurrentFilePath; - int newCurrentFileIndex = 0; - const QString newFolderPath = QQmlFile::urlToLocalFileOrQrc(currentFolder); - if (!oldFolderPath.isEmpty() && !newFolderPath.isEmpty()) { - // If the user went up a directory (or several), we should set - // currentFile to be the directory that we were in (or - // its closest ancestor that is a child of the new directory). - // E.g. if oldFolderPath is /foo/bar/baz/abc/xyz, and newFolderPath is /foo/bar, - // then we want to set currentFile to be /foo/bar/baz. - const int indexOfFolder = oldFolderPath.indexOf(newFolderPath); - if (indexOfFolder != -1) { - // [folder] - // [ oldFolderPath ] - // /foo/bar/baz/abc/xyz - // [rel...Paths] - QStringList relativePaths = oldFolderPath.mid(indexOfFolder + newFolderPath.size()).split(QLatin1Char('/'), Qt::SkipEmptyParts); - newCurrentFilePath = newFolderPath + QLatin1Char('/') + relativePaths.first(); - - // Now find the index of that directory so that we can set the ListView's currentIndex to it. - const QDir newFolderDir(newFolderPath); - // Just to be safe... - if (!newFolderDir.exists()) { - qmlWarning(q) << "Directory" << newCurrentFilePath << "doesn't exist; can't get a file entry list for it"; - return; - } - - const QFileInfoList dirs = newFolderDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::DirsFirst); - const QFileInfo newCurrentFileInfo(newCurrentFilePath); - // The directory can contain files, but since we put dirs first, that should never affect the indices. - newCurrentFileIndex = dirs.indexOf(newCurrentFileInfo); - } - } - - if (newCurrentFilePath.isEmpty()) { - // When entering into a directory that isn't a parent of the old one, the first - // file delegate should be selected. - // TODO: is there a cheaper way to do this? QDirIterator doesn't support sorting, - // so we can't use that. QQuickFolderListModel uses threads to fetch its data, - // so should be considered asynchronous. We might be able to use it, but it would - // complicate the code even more... - QDir newFolderDir(newFolderPath); - if (newFolderDir.exists()) { - const QFileInfoList files = newFolderDir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, QDir::DirsFirst); - if (!files.isEmpty()) - newCurrentFilePath = files.first().absoluteFilePath(); - } - } - - if (!newCurrentFilePath.isEmpty()) { - q->setCurrentFile(QUrl::fromLocalFile(newCurrentFilePath)); - attached->fileDialogListView()->setCurrentIndex(newCurrentFileIndex); - if (QQuickItem *currentItem = attached->fileDialogListView()->currentItem()) - currentItem->forceActiveFocus(); - } -} - -void QQuickFileDialogImplPrivate::handleAccept() -{ - // Let handleClick take care of calling accept(). -} - -void QQuickFileDialogImplPrivate::handleClick(QQuickAbstractButton *button) -{ - Q_Q(QQuickFileDialogImpl); - if (buttonRole(button) == QPlatformDialogHelper::AcceptRole && currentFile.isValid()) { - // The "Open" button was clicked, so we need to set the file to the current file, if any. - const QFileInfo fileInfo(currentFile.toLocalFile()); - if (fileInfo.isDir()) { - // If it's a directory, navigate to it. - q->setCurrentFolder(currentFile); - // Don't call accept(), because selecting a folder != accepting the dialog. - } else { - // Otherwise it's a file, so select it and close the dialog. - q->setSelectedFile(currentFile); - q->accept(); - QQuickDialogPrivate::handleClick(button); - emit q->fileSelected(currentFile); - } - } -} - -QQuickFileDialogImpl::QQuickFileDialogImpl(QObject *parent) - : QQuickDialog(*(new QQuickFileDialogImplPrivate), parent) -{ -} - -QQuickFileDialogImplAttached *QQuickFileDialogImpl::qmlAttachedProperties(QObject *object) -{ - return new QQuickFileDialogImplAttached(object); -} - -QUrl QQuickFileDialogImpl::currentFolder() const -{ - Q_D(const QQuickFileDialogImpl); - return d->currentFolder; -} - -void QQuickFileDialogImpl::setCurrentFolder(const QUrl ¤tFolder) -{ - qCDebug(lcCurrentFolder) << "setCurrentFolder called with" << currentFolder; - Q_D(QQuickFileDialogImpl); - if (currentFolder == d->currentFolder) - return; - - const QString oldFolderPath = QQmlFile::urlToLocalFileOrQrc(d->currentFolder); - - d->currentFolder = currentFolder; - // Since the directory changed, the old file can no longer be selected. - setCurrentFile(QUrl()); - d->updateCurrentFile(oldFolderPath); - emit currentFolderChanged(d->currentFolder); -} - -QUrl QQuickFileDialogImpl::selectedFile() const -{ - Q_D(const QQuickFileDialogImpl); - return d->selectedFile; -} - -void QQuickFileDialogImpl::setSelectedFile(const QUrl &selectedFile) -{ - Q_D(QQuickFileDialogImpl); - if (selectedFile == d->selectedFile) - return; - - d->selectedFile = selectedFile; - emit selectedFileChanged(); -} - -QUrl QQuickFileDialogImpl::currentFile() const -{ - Q_D(const QQuickFileDialogImpl); - return d->currentFile; -} - -void QQuickFileDialogImpl::setCurrentFile(const QUrl ¤tFile) -{ - Q_D(QQuickFileDialogImpl); - if (currentFile == d->currentFile) - return; - - d->currentFile = currentFile; - d->updateEnabled(); - emit currentFileChanged(d->currentFile); -} - -QSharedPointer<QFileDialogOptions> QQuickFileDialogImpl::options() const -{ - Q_D(const QQuickFileDialogImpl); - return d->options; -} - -void QQuickFileDialogImpl::setOptions(const QSharedPointer<QFileDialogOptions> &options) -{ - qCDebug(lcOptions).nospace() << "setOptions called with:" - << " acceptMode=" << options->acceptMode() - << " fileMode=" << options->fileMode() - << " initialDirectory=" << options->initialDirectory() - << " nameFilters=" << options->nameFilters() - << " initiallySelectedNameFilter=" << options->initiallySelectedNameFilter(); - - Q_D(QQuickFileDialogImpl); - d->options = options; - - if (d->options) { - d->selectedNameFilter->setOptions(options); - d->setNameFilters(options->nameFilters()); - } -} - -/*! - \internal - - The list of user-facing strings describing the available file filters. -*/ -QStringList QQuickFileDialogImpl::nameFilters() const -{ - Q_D(const QQuickFileDialogImpl); - return d->options ? d->options->nameFilters() : QStringList(); -} - -void QQuickFileDialogImpl::resetNameFilters() -{ - Q_D(QQuickFileDialogImpl); - d->setNameFilters(QStringList()); -} - -QQuickFileNameFilter *QQuickFileDialogImpl::selectedNameFilter() const -{ - Q_D(const QQuickFileDialogImpl); - if (!d->selectedNameFilter) { - QQuickFileDialogImpl *that = const_cast<QQuickFileDialogImpl *>(this); - d->selectedNameFilter = new QQuickFileNameFilter(that); - if (d->options) - d->selectedNameFilter->setOptions(d->options); - } - return d->selectedNameFilter; -} - -/*! - \internal - - These allow QQuickPlatformFileDialog::show() to set custom labels on the - dialog buttons without having to know about/go through QQuickFileDialogImplAttached - and QQuickDialogButtonBox. -*/ -void QQuickFileDialogImpl::setAcceptLabel(const QString &label) -{ - Q_D(QQuickFileDialogImpl); - d->acceptLabel = label; - QQuickFileDialogImplAttached *attached = d->attachedOrWarn(); - if (!attached) - return; - - auto acceptButton = attached->buttonBox()->standardButton(QPlatformDialogHelper::Open); - if (!acceptButton) { - qmlWarning(this).nospace() << "Can't set accept label to " << label - << "; failed to find Open button in DialogButtonBox of " << this; - return; - } - - acceptButton->setText(!label.isEmpty() - ? label : QQuickDialogButtonBoxPrivate::buttonText(QPlatformDialogHelper::Open)); -} - -void QQuickFileDialogImpl::setRejectLabel(const QString &label) -{ - Q_D(QQuickFileDialogImpl); - d->rejectLabel = label; - QQuickFileDialogImplAttached *attached = d->attachedOrWarn(); - if (!attached) - return; - - auto rejectButton = attached->buttonBox()->standardButton(QPlatformDialogHelper::Cancel); - if (!rejectButton) { - qmlWarning(this).nospace() << "Can't set reject label to " << label - << "; failed to find Open button in DialogButtonBox of " << this; - return; - } - - rejectButton->setText(!label.isEmpty() - ? label : QQuickDialogButtonBoxPrivate::buttonText(QPlatformDialogHelper::Cancel)); -} - -void QQuickFileDialogImpl::selectNameFilter(const QString &filter) -{ - qCDebug(lcNameFilters) << "selectNameFilter called with" << filter; - Q_D(QQuickFileDialogImpl); - d->selectedNameFilter->update(filter); - emit filterSelected(filter); -} - -void QQuickFileDialogImpl::componentComplete() -{ - Q_D(QQuickFileDialogImpl); - QQuickDialog::componentComplete(); - - // Find the right-most button and set its key navigation so that - // tab moves focus to the breadcrumb bar's up button. I tried - // doing this via KeyNavigation on the DialogButtonBox in QML, - // but it didn't work (probably because it's not the right item). - QQuickFileDialogImplAttached *attached = d->attachedOrWarn(); - if (!attached) - return; - - const int buttonCount = attached->buttonBox()->count(); - if (buttonCount == 0) - return; - - QQuickAbstractButton *rightMostButton = qobject_cast<QQuickAbstractButton *>( - attached->buttonBox()->itemAt(buttonCount - 1)); - if (!rightMostButton) { - qmlWarning(this) << "Can't find right-most button in DialogButtonBox"; - return; - } - - auto keyNavigationAttached = QQuickKeyNavigationAttached::qmlAttachedProperties(rightMostButton); - if (!keyNavigationAttached) { - qmlWarning(this) << "Can't create attached KeyNavigation object on" << QDebug::toString(rightMostButton); - return; - } - - keyNavigationAttached->setTab(attached->breadcrumbBar()->upButton()); -} - -void QQuickFileDialogImpl::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) -{ - Q_D(QQuickFileDialogImpl); - QQuickDialog::itemChange(change, data); - - if (change != QQuickItem::ItemVisibleHasChanged || !isComponentComplete() || !data.boolValue) - return; - - QQuickFileDialogImplAttached *attached = d->attachedOrWarn(); - if (!attached) - return; - - attached->fileDialogListView()->forceActiveFocus(); - d->updateEnabled(); -} - -QQuickFileDialogImplAttached *QQuickFileDialogImplPrivate::attachedOrWarn() -{ - Q_Q(QQuickFileDialogImpl); - QQuickFileDialogImplAttached *attached = static_cast<QQuickFileDialogImplAttached*>( - qmlAttachedPropertiesObject<QQuickFileDialogImpl>(q)); - if (!attached) - qmlWarning(q) << "Expected FileDialogImpl attached object to be present on" << this; - return attached; -} - -void QQuickFileDialogImplAttachedPrivate::nameFiltersComboBoxItemActivated(int index) -{ - qCDebug(lcAttachedNameFilters) << "nameFiltersComboBoxItemActivated called with" << index; - auto fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent); - if (!fileDialogImpl) - return; - - fileDialogImpl->selectNameFilter(nameFiltersComboBox->textAt(index)); -} - -void QQuickFileDialogImplAttachedPrivate::fileDialogListViewCurrentIndexChanged() -{ - auto fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent); - if (!fileDialogImpl) - return; - - auto fileDialogDelegate = qobject_cast<QQuickFileDialogDelegate*>(fileDialogListView->currentItem()); - if (!fileDialogDelegate) - return; - - fileDialogImpl->setCurrentFile(fileDialogDelegate->file()); -} - -QQuickFileDialogImplAttached::QQuickFileDialogImplAttached(QObject *parent) - : QObject(*(new QQuickFileDialogImplAttachedPrivate), parent) -{ - if (!qobject_cast<QQuickFileDialogImpl*>(parent)) { - qmlWarning(this) << "FileDialogImpl attached properties should only be " - << "accessed through the root FileDialogImpl instance"; - } -} - -QQuickDialogButtonBox *QQuickFileDialogImplAttached::buttonBox() const -{ - Q_D(const QQuickFileDialogImplAttached); - return d->buttonBox; -} - -void QQuickFileDialogImplAttached::setButtonBox(QQuickDialogButtonBox *buttonBox) -{ - Q_D(QQuickFileDialogImplAttached); - if (buttonBox == d->buttonBox) - return; - - if (d->buttonBox) { - QQuickFileDialogImpl *fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent()); - if (fileDialogImpl) { - auto dialogPrivate = QQuickDialogPrivate::get(fileDialogImpl); - QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::accepted, - dialogPrivate, &QQuickDialogPrivate::handleAccept); - QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::rejected, - dialogPrivate, &QQuickDialogPrivate::handleReject); - QObjectPrivate::disconnect(d->buttonBox, &QQuickDialogButtonBox::clicked, - dialogPrivate, &QQuickDialogPrivate::handleClick); - } - } - - d->buttonBox = buttonBox; - - if (buttonBox) { - QQuickFileDialogImpl *fileDialogImpl = qobject_cast<QQuickFileDialogImpl*>(parent()); - if (fileDialogImpl) { - auto dialogPrivate = QQuickDialogPrivate::get(fileDialogImpl); - QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::accepted, - dialogPrivate, &QQuickDialogPrivate::handleAccept); - QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::rejected, - dialogPrivate, &QQuickDialogPrivate::handleReject); - QObjectPrivate::connect(d->buttonBox, &QQuickDialogButtonBox::clicked, - dialogPrivate, &QQuickDialogPrivate::handleClick); - } - } - - emit buttonBoxChanged(); -} - -QQuickComboBox *QQuickFileDialogImplAttached::nameFiltersComboBox() const -{ - Q_D(const QQuickFileDialogImplAttached); - return d->nameFiltersComboBox; -} - -void QQuickFileDialogImplAttached::setNameFiltersComboBox(QQuickComboBox *nameFiltersComboBox) -{ - Q_D(QQuickFileDialogImplAttached); - if (nameFiltersComboBox == d->nameFiltersComboBox) - return; - - d->nameFiltersComboBox = nameFiltersComboBox; - - QObjectPrivate::connect(d->nameFiltersComboBox, &QQuickComboBox::activated, - d, &QQuickFileDialogImplAttachedPrivate::nameFiltersComboBoxItemActivated); - - emit nameFiltersComboBoxChanged(); -} - -QString QQuickFileDialogImplAttached::selectedNameFilter() const -{ - Q_D(const QQuickFileDialogImplAttached); - return d->nameFiltersComboBox ? d->nameFiltersComboBox->currentText() : QString(); -} - -void QQuickFileDialogImplAttached::selectNameFilter(const QString &filter) -{ - Q_D(QQuickFileDialogImplAttached); - qCDebug(lcAttachedNameFilters) << "selectNameFilter called with" << filter; - if (!d->nameFiltersComboBox) - return; - - const int indexInComboBox = d->nameFiltersComboBox->find(filter); - if (indexInComboBox == -1) - return; - - qCDebug(lcAttachedNameFilters) << "setting ComboBox's currentIndex to" << indexInComboBox; - d->nameFiltersComboBox->setCurrentIndex(indexInComboBox); -} - -QQuickListView *QQuickFileDialogImplAttached::fileDialogListView() const -{ - Q_D(const QQuickFileDialogImplAttached); - return d->fileDialogListView; -} - -void QQuickFileDialogImplAttached::setFileDialogListView(QQuickListView *fileDialogListView) -{ - Q_D(QQuickFileDialogImplAttached); - if (fileDialogListView == d->fileDialogListView) - return; - - d->fileDialogListView = fileDialogListView; - - QObjectPrivate::connect(d->fileDialogListView, &QQuickListView::currentIndexChanged, - d, &QQuickFileDialogImplAttachedPrivate::fileDialogListViewCurrentIndexChanged); - - emit fileDialogListViewChanged(); -} - -QQuickFolderBreadcrumbBar *QQuickFileDialogImplAttached::breadcrumbBar() const -{ - Q_D(const QQuickFileDialogImplAttached); - return d->breadcrumbBar; -} - -void QQuickFileDialogImplAttached::setBreadcrumbBar(QQuickFolderBreadcrumbBar *breadcrumbBar) -{ - Q_D(QQuickFileDialogImplAttached); - if (breadcrumbBar == d->breadcrumbBar) - return; - - d->breadcrumbBar = breadcrumbBar; - emit breadcrumbBarChanged(); -} - -QT_END_NAMESPACE |