diff options
Diffstat (limited to 'src/quickdialogs2')
126 files changed, 10830 insertions, 0 deletions
diff --git a/src/quickdialogs2/CMakeLists.txt b/src/quickdialogs2/CMakeLists.txt new file mode 100644 index 0000000000..88ae96331c --- /dev/null +++ b/src/quickdialogs2/CMakeLists.txt @@ -0,0 +1,3 @@ +add_subdirectory(quickdialogs2utils) +add_subdirectory(quickdialogs2quickimpl) +add_subdirectory(quickdialogs2) diff --git a/src/quickdialogs2/quickdialogs2/CMakeLists.txt b/src/quickdialogs2/quickdialogs2/CMakeLists.txt new file mode 100644 index 0000000000..b73561b488 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/CMakeLists.txt @@ -0,0 +1,36 @@ +##################################################################### +## QuickDialogs2 Module: +##################################################################### + +qt_internal_add_qml_module(QuickDialogs2 + URI "QtQuick.Dialogs" + VERSION "${PROJECT_VERSION}" + CLASS_NAME QtQuickDialogsPlugin + PLUGIN_TARGET qtquickdialogsplugin + SOURCES + qquickabstractdialog.cpp + qquickabstractdialog_p.h + qquickfiledialog.cpp + qquickfiledialog_p.h + qquickfontdialog.cpp + qquickfontdialog_p.h + qtquickdialogs2foreign_p.h + qtquickdialogs2global_p.h + DEFINES + QT_BUILD_QUICKDIALOGS2_LIB + QT_NO_CAST_FROM_ASCII + QT_NO_CAST_TO_ASCII + INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_SOURCE_DIR} + LIBRARIES + Qt::CorePrivate + Qt::GuiPrivate + Qt::QmlPrivate + Qt::QuickPrivate + Qt::QuickDialogs2UtilsPrivate + Qt::QuickDialogs2QuickImplPrivate +) + +qt_internal_add_docs(QuickDialogs2 + doc/qtquickdialogs.qdocconf +) diff --git a/src/quickdialogs2/quickdialogs2/doc/images/qtquickdialogs-filedialog-gtk.png b/src/quickdialogs2/quickdialogs2/doc/images/qtquickdialogs-filedialog-gtk.png Binary files differnew file mode 100644 index 0000000000..9360d747a2 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/doc/images/qtquickdialogs-filedialog-gtk.png diff --git a/src/quickdialogs2/quickdialogs2/doc/images/qtquickdialogs-fontdialog-gtk.png b/src/quickdialogs2/quickdialogs2/doc/images/qtquickdialogs-fontdialog-gtk.png Binary files differnew file mode 100644 index 0000000000..0c6217bdb4 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/doc/images/qtquickdialogs-fontdialog-gtk.png diff --git a/src/quickdialogs2/quickdialogs2/doc/qtquickdialogs.qdocconf b/src/quickdialogs2/quickdialogs2/doc/qtquickdialogs.qdocconf new file mode 100644 index 0000000000..e53a5c22a8 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/doc/qtquickdialogs.qdocconf @@ -0,0 +1,40 @@ +include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) +include($QT_INSTALL_DOCS/config/exampleurl-qtquickcontrols2.qdocconf) + +project = QtQuickDialogs +description = Qt Quick Dialogs Reference Documentation +version = $QT_VERSION + +qhp.projects = QtQuickDialogs + +qhp.QtQuickDialogs.file = qtquickdialogs.qhp +qhp.QtQuickDialogs.namespace = org.qt-project.qtquickdialogs.$QT_VERSION_TAG +qhp.QtQuickDialogs.virtualFolder = qtquickdialogs +qhp.QtQuickDialogs.indexTitle = Qt Quick Dialogs +qhp.QtQuickDialogs.indexRoot = + +qhp.QtQuickDialogs.filterAttributes = qtquickdialogs $QT_VERSION qtrefdoc +qhp.QtQuickDialogs.customFilters.Qt.name = QtQuickDialogs $QT_VERSION +qhp.QtQuickDialogs.customFilters.Qt.filterAttributes = qtquickdialogs $QT_VERSION + +qhp.QtQuickDialogs.subprojects = qmltypes +qhp.QtQuickDialogs.subprojects.qmltypes.title = QML Types +qhp.QtQuickDialogs.subprojects.qmltypes.indexTitle = Qt Quick Dialogs QML Types +qhp.QtQuickDialogs.subprojects.qmltypes.selectors = qmlclass +qhp.QtQuickDialogs.subprojects.qmltypes.sortPages = true + +depends = qtcore qtgui qtdoc qtqml qtquick qtquickcontrols + +# This module has no documented C++ types, clear the module header +moduleheader = + +headerdirs += .. +sourcedirs += .. \ + src + +imagedirs += images + +navigation.landingpage = "Qt Quick Dialogs" +navigation.qmltypespage = "Qt Quick Dialogs QML Types" + +tagfile = qtquickdialogs.tags diff --git a/src/quickdialogs2/quickdialogs2/doc/src/includes/fallback.qdocinc b/src/quickdialogs2/quickdialogs2/doc/src/includes/fallback.qdocinc new file mode 100644 index 0000000000..f3a4a1805b --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/doc/src/includes/fallback.qdocinc @@ -0,0 +1 @@ +Qt Quick Dialogs uses a Qt Quick implementation as a fallback on platforms that do not have a native implementation available. diff --git a/src/quickdialogs2/quickdialogs2/qquickabstractdialog.cpp b/src/quickdialogs2/quickdialogs2/qquickabstractdialog.cpp new file mode 100644 index 0000000000..262e2ee36d --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qquickabstractdialog.cpp @@ -0,0 +1,454 @@ +/**************************************************************************** +** +** 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 "qquickabstractdialog_p.h" + +#include <QtCore/qloggingcategory.h> +#include <QtGui/private/qguiapplication_p.h> +#include <QtQuick/qquickitem.h> +#include <QtQuick/qquickwindow.h> +#include <QtQuickDialogs2QuickImpl/private/qquickdialogimplfactory_p.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcDialogs, "qt.quick.dialogs") + +/*! + \internal + + A dialog that can be backed by different implementations. + + Each dialog has a handle to QPlatformDialogHelper, which is created in create(). + The helper acts as an intermediary between the QML-facing dialog object + and the native/widget/quick implementation: + + +------------+ +------------------------------------+ +-------------------------------------+ + | | | | | | + | FileDialog |----->| Native/Widget/Quick QPlatformFile- |----->| Native OS dialog/QQuickFileDialog/ | + | | | DialogHelper subclass | | QQuickFileDialogImpl | + | | | | | | + +------------+ +------------------------------------+ +-------------------------------------+ +*/ + +/*! + \qmltype Dialog + \inherits QtObject +//! \instantiates QQuickAbstractDialog + \inqmlmodule QtQuick.Dialogs + \since 6.2 + \brief The base class of native dialogs. + + The Dialog type provides common QML API for native platform dialogs. + + To show a native dialog, construct an instance of one of the concrete + Dialog implementations, set the desired properties, and call \l open(). + Dialog emits \l accepted() or \l rejected() when the user is done with + the dialog. +*/ + +/*! + \qmlsignal void QtQuick.Dialogs::Dialog::accepted() + + This signal is emitted when the dialog has been accepted either + interactively or by calling \l accept(). + + \note This signal is \e not emitted when closing the dialog with \l close(). + + \sa rejected() +*/ + +/*! + \qmlsignal void QtQuick.Dialogs::Dialog::rejected() + + This signal is emitted when the dialog has been rejected either + interactively or by calling \l reject(). + + \note This signal is \e not emitted when closing the dialog with \l close(). + + \sa accepted() +*/ + +Q_DECLARE_LOGGING_CATEGORY(lcDialogs) + +QQuickAbstractDialog::QQuickAbstractDialog(QPlatformTheme::DialogType type, QObject *parent) + : QObject(parent), + m_type(type) +{ +} + +QQuickAbstractDialog::~QQuickAbstractDialog() +{ + destroy(); +} + +QPlatformDialogHelper *QQuickAbstractDialog::handle() const +{ + return m_handle.get(); +} + +/*! + \qmldefault + \qmlproperty list<Object> QtQuick.Dialogs::Dialog::data + + This default property holds the list of all objects declared as children of + the dialog. +*/ +QQmlListProperty<QObject> QQuickAbstractDialog::data() +{ + return QQmlListProperty<QObject>(this, &m_data); +} + +/*! + \qmlproperty Window QtQuick.Dialogs::Dialog::parentWindow + + This property holds the parent window of the dialog. + + Unless explicitly set, the window is automatically resolved by iterating + the QML parent objects until a \l Window or an \l Item that has a window + is found. +*/ +QWindow *QQuickAbstractDialog::parentWindow() const +{ + return m_parentWindow; +} + +void QQuickAbstractDialog::setParentWindow(QWindow *window) +{ + qCDebug(lcDialogs) << "set parent window to" << window; + if (m_parentWindow == window) + return; + + m_parentWindow = window; + emit parentWindowChanged(); +} + +/*! + \qmlproperty string QtQuick.Dialogs::Dialog::title + + This property holds the title of the dialog. +*/ +QString QQuickAbstractDialog::title() const +{ + return m_title; +} + +void QQuickAbstractDialog::setTitle(const QString &title) +{ + if (m_title == title) + return; + + m_title = title; + emit titleChanged(); +} + +/*! + \qmlproperty Qt::WindowFlags QtQuick.Dialogs::Dialog::flags + + This property holds the window flags of the dialog. The default value is \c Qt.Dialog. +*/ +Qt::WindowFlags QQuickAbstractDialog::flags() const +{ + return m_flags; +} + +void QQuickAbstractDialog::setFlags(Qt::WindowFlags flags) +{ + if (m_flags == flags) + return; + + m_flags = flags; + emit flagsChanged(); +} + +/*! + \qmlproperty Qt::WindowModality QtQuick.Dialogs::Dialog::modality + + This property holds the modality of the dialog. The default value is \c Qt.WindowModal. + + Available values: + \value Qt.NonModal The dialog is not modal and does not block input to other windows. + \value Qt.WindowModal The dialog is modal to a single window hierarchy and blocks input to its parent window, all grandparent windows, and all siblings of its parent and grandparent windows. + \value Qt.ApplicationModal The dialog is modal to the application and blocks input to all windows. +*/ +Qt::WindowModality QQuickAbstractDialog::modality() const +{ + return m_modality; +} + +void QQuickAbstractDialog::setModality(Qt::WindowModality modality) +{ + if (m_modality == modality) + return; + + m_modality = modality; + emit modalityChanged(); +} + +/*! + \qmlproperty bool QtQuick.Dialogs::Dialog::visible + + This property holds the visibility of the dialog. The default value is \c false. + + \sa open(), close() +*/ +bool QQuickAbstractDialog::isVisible() const +{ + return m_handle && m_visible; +} + +void QQuickAbstractDialog::setVisible(bool visible) +{ + qCDebug(lcDialogs) << "setVisible called with" << visible; + + if (visible) { + // Don't try to open before component completion, as we won't have a window yet, + // and open() sets m_visible to false if it fails. + if (!m_complete) + m_visibleRequested = true; + else + open(); + } else { + close(); + } +} + +/*! + \qmlproperty StandardCode QtQuick.Dialogs::Dialog::result + + This property holds the result code. + + Standard result codes: + \value Dialog.Accepted + \value Dialog.Rejected + + \note MessageDialog sets the result to the value of the clicked standard + button instead of using the standard result codes. +*/ +QQuickAbstractDialog::StandardCode QQuickAbstractDialog::result() const +{ + return m_result; +} + +void QQuickAbstractDialog::setResult(StandardCode result) +{ + if (m_result == result) + return; + + m_result = result; + emit resultChanged(); +} + +/*! + \qmlmethod void QtQuick.Dialogs::Dialog::open() + + Opens the dialog. + + \sa visible, close() +*/ +void QQuickAbstractDialog::open() +{ + qCDebug(lcDialogs) << "open called"; + if (m_visible || !create()) + return; + + onShow(m_handle.get()); + m_visible = m_handle->show(m_flags, m_modality, m_parentWindow); + if (m_visible) + emit visibleChanged(); +} + +/*! + \qmlmethod void QtQuick.Dialogs::Dialog::close() + + Closes the dialog. + + \sa visible, open() +*/ +void QQuickAbstractDialog::close() +{ + if (!m_handle || !m_visible) + return; + + onHide(m_handle.get()); + m_handle->hide(); + m_visible = false; + emit visibleChanged(); +} + +/*! + \qmlmethod void QtQuick.Dialogs::Dialog::accept() + + Closes the dialog and emits the \l accepted() signal. + + \sa reject() +*/ +void QQuickAbstractDialog::accept() +{ + done(Accepted); +} + +/*! + \qmlmethod void QtQuick.Dialogs::Dialog::reject() + + Closes the dialog and emits the \l rejected() signal. + + \sa accept() +*/ +void QQuickAbstractDialog::reject() +{ + done(Rejected); +} + +/*! + \qmlmethod void QtQuick.Dialogs::Dialog::done(StandardCode result) + + Closes the dialog and sets the \a result. + + \sa accept(), reject(), result +*/ +void QQuickAbstractDialog::done(StandardCode result) +{ + close(); + setResult(result); + + if (result == Accepted) + emit accepted(); + else if (result == Rejected) + emit rejected(); +} + +void QQuickAbstractDialog::classBegin() +{ +} + +void QQuickAbstractDialog::componentComplete() +{ + qCDebug(lcDialogs) << "componentComplete"; + m_complete = true; + + if (!m_parentWindow) { + qCDebug(lcDialogs) << "- no parent window; searching for one"; + setParentWindow(findParentWindow()); + } + + if (m_visibleRequested) { + qCDebug(lcDialogs) << "visible was bound to true before component completion; opening dialog"; + open(); + m_visibleRequested = false; + } +} + +static const char *qmlTypeName(const QObject *object) +{ + return object->metaObject()->className() + qstrlen("QQuickPlatform"); +} + +bool QQuickAbstractDialog::create() +{ + qCDebug(lcDialogs) << qmlTypeName(this) << "attempting to create dialog backend of type" + << m_type << "with parent window" << m_parentWindow; + if (m_handle) + return m_handle.get(); + + qCDebug(lcDialogs) << "- attempting to create a native dialog"; + if (useNativeDialog()) + m_handle.reset(QGuiApplicationPrivate::platformTheme()->createPlatformDialogHelper(m_type)); + + if (!m_handle) { + qCDebug(lcDialogs) << "- attempting to create a quick dialog"; + m_handle.reset(QQuickDialogImplFactory::createPlatformDialogHelper(m_type, this)); + } + + qCDebug(lcDialogs) << qmlTypeName(this) << "created ->" << m_handle.get(); + if (m_handle) { + onCreate(m_handle.get()); + connect(m_handle.get(), &QPlatformDialogHelper::accept, this, &QQuickAbstractDialog::accept); + connect(m_handle.get(), &QPlatformDialogHelper::reject, this, &QQuickAbstractDialog::reject); + } + return m_handle.get(); +} + +void QQuickAbstractDialog::destroy() +{ + m_handle.reset(); +} + +bool QQuickAbstractDialog::useNativeDialog() const +{ + if (QCoreApplication::testAttribute(Qt::AA_DontUseNativeDialogs)) { + qCDebug(lcDialogs) << " - Qt::AA_DontUseNativeDialogs was set; not using native dialog"; + return false; + } + + if (!QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(m_type)) { + qCDebug(lcDialogs) << " - the platform theme told us a native dialog isn't available; not using native dialog"; + return false; + } + + return true; +} + +void QQuickAbstractDialog::onCreate(QPlatformDialogHelper *dialog) +{ + Q_UNUSED(dialog); +} + +void QQuickAbstractDialog::onShow(QPlatformDialogHelper *dialog) +{ + Q_UNUSED(dialog); +} + +void QQuickAbstractDialog::onHide(QPlatformDialogHelper *dialog) +{ + Q_UNUSED(dialog); +} + +QWindow *QQuickAbstractDialog::findParentWindow() const +{ + QObject *obj = parent(); + while (obj) { + QWindow *window = qobject_cast<QWindow *>(obj); + if (window) + return window; + QQuickItem *item = qobject_cast<QQuickItem *>(obj); + if (item && item->window()) + return item->window(); + obj = obj->parent(); + } + return nullptr; +} + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2/qquickabstractdialog_p.h b/src/quickdialogs2/quickdialogs2/qquickabstractdialog_p.h new file mode 100644 index 0000000000..07e9ffbf5a --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qquickabstractdialog_p.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKABSTRACTDIALOG_P_H +#define QQUICKABSTRACTDIALOG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <memory> + +#include <QtCore/qobject.h> +#include <QtGui/qpa/qplatformtheme.h> +#include <QtGui/qpa/qplatformdialoghelper.h> +#include <QtQml/qqmlparserstatus.h> +#include <QtQml/qqmllist.h> +#include <QtQml/qqml.h> + +#include "qtquickdialogs2global_p.h" + +QT_BEGIN_NAMESPACE + +class QWindow; +class QPlatformDialogHelper; + +class Q_QUICKDIALOGS2_PRIVATE_EXPORT QQuickAbstractDialog : public QObject, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + Q_PROPERTY(QQmlListProperty<QObject> data READ data FINAL) + Q_PROPERTY(QWindow *parentWindow READ parentWindow WRITE setParentWindow NOTIFY parentWindowChanged FINAL) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged FINAL) + Q_PROPERTY(Qt::WindowFlags flags READ flags WRITE setFlags NOTIFY flagsChanged FINAL) + Q_PROPERTY(Qt::WindowModality modality READ modality WRITE setModality NOTIFY modalityChanged FINAL) + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged FINAL) + Q_PROPERTY(StandardCode result READ result WRITE setResult NOTIFY resultChanged FINAL) + Q_CLASSINFO("DefaultProperty", "data") + Q_MOC_INCLUDE(<QtGui/qwindow.h>) + QML_ANONYMOUS + QML_ADDED_IN_VERSION(6, 2) + +public: + explicit QQuickAbstractDialog(QPlatformTheme::DialogType type, QObject *parent = nullptr); + ~QQuickAbstractDialog(); + + QPlatformDialogHelper *handle() const; + + QQmlListProperty<QObject> data(); + + QWindow *parentWindow() const; + void setParentWindow(QWindow *window); + + QString title() const; + void setTitle(const QString &title); + + Qt::WindowFlags flags() const; + void setFlags(Qt::WindowFlags flags); + + Qt::WindowModality modality() const; + void setModality(Qt::WindowModality modality); + + bool isVisible() const; + void setVisible(bool visible); + + enum StandardCode { Rejected, Accepted }; + Q_ENUM(StandardCode) + + StandardCode result() const; + void setResult(StandardCode result); + +public Q_SLOTS: + void open(); + void close(); + virtual void accept(); + virtual void reject(); + virtual void done(StandardCode result); + +Q_SIGNALS: + void accepted(); + void rejected(); + void parentWindowChanged(); + void titleChanged(); + void flagsChanged(); + void modalityChanged(); + void visibleChanged(); + void resultChanged(); + +protected: + void classBegin() override; + void componentComplete() override; + + bool create(); + void destroy(); + + virtual bool useNativeDialog() const; + virtual void onCreate(QPlatformDialogHelper *dialog); + virtual void onShow(QPlatformDialogHelper *dialog); + virtual void onHide(QPlatformDialogHelper *dialog); + + QWindow *findParentWindow() const; + +private: + bool m_visibleRequested = false; + bool m_visible = false; + bool m_complete = false; + StandardCode m_result = Rejected; + QWindow *m_parentWindow = nullptr; + QString m_title; + Qt::WindowFlags m_flags = Qt::Dialog; + Qt::WindowModality m_modality = Qt::WindowModal; + QPlatformTheme::DialogType m_type; + QList<QObject *> m_data; + std::unique_ptr<QPlatformDialogHelper> m_handle; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickAbstractDialog) + +#endif // QQUICKABSTRACTDIALOG_P_H diff --git a/src/quickdialogs2/quickdialogs2/qquickfiledialog.cpp b/src/quickdialogs2/quickdialogs2/qquickfiledialog.cpp new file mode 100644 index 0000000000..f63cbbf006 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qquickfiledialog.cpp @@ -0,0 +1,612 @@ +/**************************************************************************** +** +** 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 "qquickfiledialog_p.h" + +#include <QtCore/qlist.h> +#include <QtCore/qloggingcategory.h> +#include <QtQml/qqmlfile.h> + +#include <QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcFileDialog, "qt.quick.dialogs.filedialog") + +/*! + \qmltype FileDialog + \inherits Dialog +//! \instantiates QQuickFileDialog + \inqmlmodule QtQuick.Dialogs + \since 6.2 + \brief A file dialog. + + The FileDialog type provides a QML API for file dialogs. + + \image qtquickdialogs-filedialog-gtk.png + + To show a file dialog, construct an instance of FileDialog, set the + desired properties, and call \l {Dialog::}{open()}. The \l currentFile + or \l currentFiles properties can be used to determine the currently + selected file(s) in the dialog. The \l selectedFile and \l selectedFiles + properties are updated only after the final selection has been made by + accepting the dialog. + + \code + MenuItem { + text: "Open..." + onTriggered: fileDialog.open() + } + + FileDialog { + id: fileDialog + currentFile: document.source + folder: StandardPaths.writableLocation(StandardPaths.DocumentsLocation) + } + + MyDocument { + id: document + source: fileDialog.file + } + \endcode + + \section2 Availability + + A native platform file dialog is currently available on the following platforms: + + \list + \li iOS + \li Linux (when running with the GTK+ platform theme) + \li macOS + \li Windows + \endlist + + \include includes/fallback.qdocinc + + \sa FolderDialog, StandardPaths +*/ + +Q_DECLARE_LOGGING_CATEGORY(lcDialogs) + +QQuickFileDialog::QQuickFileDialog(QObject *parent) + : QQuickAbstractDialog(QPlatformTheme::FileDialog, parent), + m_fileMode(OpenFile), + m_options(QFileDialogOptions::create()), + m_selectedNameFilter(nullptr) +{ + m_options->setFileMode(QFileDialogOptions::ExistingFile); + m_options->setAcceptMode(QFileDialogOptions::AcceptOpen); +} + +/*! + \qmlproperty enumeration QtQuick.Dialogs::FileDialog::fileMode + + This property holds the mode of the dialog. + + Available values: + \value FileDialog.OpenFile The dialog is used to select an existing file (default). + \value FileDialog.OpenFiles The dialog is used to select multiple existing files. + \value FileDialog.SaveFile The dialog is used to select any file. The file does not have to exist. +*/ +QQuickFileDialog::FileMode QQuickFileDialog::fileMode() const +{ + return m_fileMode; +} + +void QQuickFileDialog::setFileMode(FileMode mode) +{ + qCDebug(lcFileDialog) << "setFileMode called with" << mode; + if (mode == m_fileMode) + return; + + switch (mode) { + case OpenFile: + m_options->setFileMode(QFileDialogOptions::ExistingFile); + m_options->setAcceptMode(QFileDialogOptions::AcceptOpen); + break; + case OpenFiles: + m_options->setFileMode(QFileDialogOptions::ExistingFiles); + m_options->setAcceptMode(QFileDialogOptions::AcceptOpen); + break; + case SaveFile: + m_options->setFileMode(QFileDialogOptions::AnyFile); + m_options->setAcceptMode(QFileDialogOptions::AcceptSave); + break; + default: + break; + } + + m_fileMode = mode; + emit fileModeChanged(); +} + +/*! + \qmlproperty url QtQuick.Dialogs::FileDialog::selectedFile + \readonly + + This property holds the final accepted file. + + If there are multiple selected files, this property refers to the first + file. + + Unlike the \l currentFile property, the \c selectedFile property is not + updated while the user is selecting files in the dialog, but only after the + final selection has been made. That is, when the user has clicked + \uicontrol OK to accept a file. Alternatively, the + \l {Dialog::}{accepted()} signal can be handled to get the final selection. + + \sa selectedFiles, currentFile, {Dialog::}{accepted()}, currentFolder +*/ +QUrl QQuickFileDialog::selectedFile() const +{ + return addDefaultSuffix(m_selectedFiles.value(0)); +} + +/*! + \qmlproperty list<url> QtQuick.Dialogs::FileDialog::selectedFiles + + This property holds the final accepted files. + + Unlike the \l currentFiles property, the \c selectedFiles property is not + updated while the user is selecting files in the dialog, but only after the + final selection has been made. That is, when the user has clicked + \uicontrol OK to accept files. Alternatively, the \l {Dialog::}{accepted()} + signal can be handled to get the final selection. + + \sa currentFiles, {Dialog::}{accepted()}, currentFolder +*/ +QList<QUrl> QQuickFileDialog::selectedFiles() const +{ + return addDefaultSuffixes(m_selectedFiles); +} + +void QQuickFileDialog::setSelectedFiles(const QList<QUrl> &selectedFiles) +{ + if (m_selectedFiles == selectedFiles) + return; + + bool firstChanged = m_selectedFiles.value(0) != selectedFiles.value(0); + m_selectedFiles = selectedFiles; + if (firstChanged) + emit selectedFileChanged(); + emit selectedFilesChanged(); +} + +/*! + \qmlproperty url QtQuick.Dialogs::FileDialog::currentFile + + This property holds the currently selected file in the dialog. + + Unlike the \l selectedFile property, the \c currentFile property is updated + while the user is selecting files in the dialog, even before the final + selection has been made. + + \sa selectedFile, currentFiles, currentFolder +*/ +QUrl QQuickFileDialog::currentFile() const +{ + return currentFiles().value(0); +} + +void QQuickFileDialog::setCurrentFile(const QUrl &file) +{ + setCurrentFiles(QList<QUrl>() << file); +} + +/*! + \qmlproperty list<url> QtQuick.Dialogs::FileDialog::currentFiles + + This property holds the currently selected files in the dialog. + + Unlike the \l selectedFiles property, the \c currentFiles property is + updated while the user is selecting files in the dialog, even before the + final selection has been made. + + \sa selectedFiles, currentFile, currentFolder +*/ +QList<QUrl> QQuickFileDialog::currentFiles() const +{ + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(handle())) + return fileDialog->selectedFiles(); + return m_options->initiallySelectedFiles(); +} + +void QQuickFileDialog::setCurrentFiles(const QList<QUrl> ¤tFiles) +{ + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(handle())) { + for (const QUrl &file : currentFiles) + fileDialog->selectFile(file); + } + m_options->setInitiallySelectedFiles(currentFiles); +} + +/*! + \qmlproperty url QtQuick.Dialogs::FileDialog::currentFolder + + This property holds the folder where files are selected. It can be set to + control the initial directory that is shown when the dialog is opened. + + For selecting a folder, use FolderDialog instead. + + \sa FolderDialog +*/ +QUrl QQuickFileDialog::currentFolder() const +{ + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(handle())) + return fileDialog->directory(); + + // If we're not using a native file dialog and the folder is invalid, + // return the current directory. + if (!m_options->initialDirectory().isValid()) + return QUrl::fromLocalFile(QDir::currentPath()); + + return m_options->initialDirectory(); +} + +void QQuickFileDialog::setCurrentFolder(const QUrl ¤tFolder) +{ + qCDebug(lcFileDialog) << "setCurrentFolder called with" << currentFolder; + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(handle())) + fileDialog->setDirectory(currentFolder); + m_options->setInitialDirectory(currentFolder); +} + +/*! + \qmlproperty flags QtQuick.Dialogs::FileDialog::options + + This property holds the various options that affect the look and feel of the dialog. + + By default, all options are disabled. + + Options should be set before showing the dialog. Setting them while the dialog is + visible is not guaranteed to have an immediate effect on the dialog (depending on + the option and on the platform). + + Available options: + \value FileDialog.DontResolveSymlinks Don't resolve symlinks in the file dialog. By default symlinks are resolved. + \value FileDialog.DontConfirmOverwrite Don't ask for confirmation if an existing file is selected. By default confirmation is requested. + \value FileDialog.ReadOnly Indicates that the dialog doesn't allow creating directories. + \value FileDialog.HideNameFilterDetails Indicates if the file name filter details are hidden or not. +*/ +QFileDialogOptions::FileDialogOptions QQuickFileDialog::options() const +{ + return m_options->options(); +} + +void QQuickFileDialog::setOptions(QFileDialogOptions::FileDialogOptions options) +{ + if (options == m_options->options()) + return; + + m_options->setOptions(options); + emit optionsChanged(); +} + +void QQuickFileDialog::resetOptions() +{ + setOptions({}); +} + +/*! + \qmlproperty list<string> QtQuick.Dialogs::FileDialog::nameFilters + + This property holds the filters that restrict the types of files that + can be selected. + + \code + FileDialog { + nameFilters: ["Text files (*.txt)", "HTML files (*.html *.htm)"] + } + \endcode + + Different platforms may restrict the files that can be selected in + different ways. For example, macOS will disable file entries that do not + match the filters, whereas Windows will hide them. + + \note \b{*.*} is not a portable filter, because the historical assumption + that the file extension determines the file type is not consistent on every + operating system. It is possible to have a file with no dot in its name (for + example, \c Makefile). In a native Windows file dialog, \b{*.*} will match + such files, while in other types of file dialogs it may not. So it is better + to use \b{*} if you mean to select any file. + + \sa selectedNameFilter +*/ +QStringList QQuickFileDialog::nameFilters() const +{ + return m_options->nameFilters(); +} + +void QQuickFileDialog::setNameFilters(const QStringList &filters) +{ + qCDebug(lcFileDialog).nospace() << "setNameFilters called with " << filters + << " (old filters were: " << m_options->nameFilters() << ")"; + if (filters == m_options->nameFilters()) + return; + + m_options->setNameFilters(filters); + if (m_selectedNameFilter) { + int index = m_selectedNameFilter->index(); + if (index < 0 || index >= filters.count()) + index = 0; + m_selectedNameFilter->update(filters.value(index)); + } + emit nameFiltersChanged(); +} + +void QQuickFileDialog::resetNameFilters() +{ + setNameFilters(QStringList()); +} + +/*! + \qmlproperty int QtQuick.Dialogs::FileDialog::selectedNameFilter.index + \qmlproperty string QtQuick.Dialogs::FileDialog::selectedNameFilter.name + \qmlproperty list<string> QtQuick.Dialogs::FileDialog::selectedNameFilter.extensions + \qmlproperty list<string> QtQuick.Dialogs::FileDialog::selectedNameFilter.globs + + These properties hold the currently selected name filter. + + \table + \header + \li Name + \li Description + \row + \li \b index : int + \li This property determines which \l {nameFilters}{name filter} is selected. + The specified filter is selected when the dialog is opened. The value is + updated when the user selects another filter. + \row + \li [read-only] \b name : string + \li This property holds the name of the selected filter. In the + example below, the name of the first filter is \c {"Text files"} + and the second is \c {"HTML files"}. + \row + \li [read-only] \b extensions : list<string> + \li This property holds the list of extensions of the selected filter. + In the example below, the list of extensions of the first filter is + \c {["txt"]} and the second is \c {["html", "htm"]}. + \row + \li [read-only] \b globs : list<string> + \li This property holds the list of globs of the selected filter. + In the example below, the list of globs of the first filter is + \c {["*.txt"]} and the second is \c {["*.html", "*.htm"]}. + + This property is useful in conjunction with \l {FolderListModel}'s + \l {FolderListModel::}{nameFilters} property, for example. + \endtable + + \code + FileDialog { + id: fileDialog + selectedNameFilter.index: 1 + nameFilters: ["Text files (*.txt)", "HTML files (*.html *.htm)"] + } + + MyDocument { + id: document + fileType: fileDialog.selectedNameFilter.extensions[0] + } + \endcode + + \sa nameFilters +*/ +QQuickFileNameFilter *QQuickFileDialog::selectedNameFilter() const +{ + if (!m_selectedNameFilter) { + QQuickFileDialog *that = const_cast<QQuickFileDialog *>(this); + m_selectedNameFilter = new QQuickFileNameFilter(that); + m_selectedNameFilter->setOptions(m_options); + } + return m_selectedNameFilter; +} + +/*! + \qmlproperty string QtQuick.Dialogs::FileDialog::defaultSuffix + + This property holds a suffix that is added to selected files that have + no suffix specified. The suffix is typically used to indicate the file + type (e.g. "txt" indicates a text file). + + If the first character is a dot ('.'), it is removed. +*/ +QString QQuickFileDialog::defaultSuffix() const +{ + return m_options->defaultSuffix(); +} + +void QQuickFileDialog::setDefaultSuffix(const QString &suffix) +{ + if (suffix == m_options->defaultSuffix()) + return; + + m_options->setDefaultSuffix(suffix); + emit defaultSuffixChanged(); +} + +void QQuickFileDialog::resetDefaultSuffix() +{ + setDefaultSuffix(QString()); +} + +/*! + \qmlproperty string QtQuick.Dialogs::FileDialog::acceptLabel + + This property holds the label text shown on the button that accepts the dialog. + + When set to an empty string, the default label of the underlying platform is used. + The default label is typically \uicontrol Open or \uicontrol Save depending on which + \l fileMode the dialog is used in. + + The default value is an empty string. + + \sa rejectLabel +*/ +QString QQuickFileDialog::acceptLabel() const +{ + return m_options->labelText(QFileDialogOptions::Accept); +} + +void QQuickFileDialog::setAcceptLabel(const QString &label) +{ + if (label == m_options->labelText(QFileDialogOptions::Accept)) + return; + + m_options->setLabelText(QFileDialogOptions::Accept, label); + emit acceptLabelChanged(); +} + +void QQuickFileDialog::resetAcceptLabel() +{ + setAcceptLabel(QString()); +} + +/*! + \qmlproperty string QtQuick.Dialogs::FileDialog::rejectLabel + + This property holds the label text shown on the button that rejects the dialog. + + When set to an empty string, the default label of the underlying platform is used. + The default label is typically \uicontrol Cancel. + + The default value is an empty string. + + \sa acceptLabel +*/ +QString QQuickFileDialog::rejectLabel() const +{ + return m_options->labelText(QFileDialogOptions::Reject); +} + +void QQuickFileDialog::setRejectLabel(const QString &label) +{ + if (label == m_options->labelText(QFileDialogOptions::Reject)) + return; + + m_options->setLabelText(QFileDialogOptions::Reject, label); + emit rejectLabelChanged(); +} + +void QQuickFileDialog::resetRejectLabel() +{ + setRejectLabel(QString()); +} + +bool QQuickFileDialog::useNativeDialog() const +{ + if (!QQuickAbstractDialog::useNativeDialog()) + return false; + + if (m_options->testOption(QFileDialogOptions::DontUseNativeDialog)) { + qCDebug(lcDialogs) << " - the FileDialog was told not to use a native dialog; not using native dialog"; + return false; + } + + return true; +} + +void QQuickFileDialog::onCreate(QPlatformDialogHelper *dialog) +{ + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(dialog)) { + connect(fileDialog, &QPlatformFileDialogHelper::currentChanged, this, &QQuickFileDialog::currentFileChanged); + connect(fileDialog, &QPlatformFileDialogHelper::currentChanged, this, &QQuickFileDialog::currentFilesChanged); + connect(fileDialog, &QPlatformFileDialogHelper::directoryEntered, this, &QQuickFileDialog::currentFolderChanged); + fileDialog->setOptions(m_options); + } +} + +void QQuickFileDialog::onShow(QPlatformDialogHelper *dialog) +{ + m_options->setWindowTitle(title()); + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(dialog)) { + // Ensure that a name filter is always selected. + int index = selectedNameFilter()->index(); + if (index == -1) + index = 0; + const QString filter = m_options->nameFilters().value(index); + m_options->setInitiallySelectedNameFilter(filter); + + fileDialog->setOptions(m_options); // setOptions only assigns a member and isn't virtual + + connect(fileDialog, &QPlatformFileDialogHelper::filterSelected, m_selectedNameFilter, &QQuickFileNameFilter::update); + fileDialog->selectNameFilter(filter); + + const QUrl initialDir = m_options->initialDirectory(); + // If it's not valid, or it's a file and not a directory, we shouldn't set it. + if (m_firstShow && initialDir.isValid() && QDir(QQmlFile::urlToLocalFileOrQrc(initialDir)).exists()) + fileDialog->setDirectory(m_options->initialDirectory()); + } + if (m_firstShow) + m_firstShow = false; +} + +void QQuickFileDialog::onHide(QPlatformDialogHelper *dialog) +{ + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(dialog)) { + if (m_selectedNameFilter) + disconnect(fileDialog, &QPlatformFileDialogHelper::filterSelected, m_selectedNameFilter, &QQuickFileNameFilter::update); + } +} + +void QQuickFileDialog::accept() +{ + if (QPlatformFileDialogHelper *fileDialog = qobject_cast<QPlatformFileDialogHelper *>(handle())) { + // Take the currently selected files and make them the final set of files. + setSelectedFiles(fileDialog->selectedFiles()); + } + QQuickAbstractDialog::accept(); +} + +QUrl QQuickFileDialog::addDefaultSuffix(const QUrl &file) const +{ + QUrl url = file; + const QString path = url.path(); + const QString suffix = m_options->defaultSuffix(); + if (!suffix.isEmpty() && !path.endsWith(QLatin1Char('/')) && path.lastIndexOf(QLatin1Char('.')) == -1) + url.setPath(path + QLatin1Char('.') + suffix); + return url; +} + +QList<QUrl> QQuickFileDialog::addDefaultSuffixes(const QList<QUrl> &files) const +{ + QList<QUrl> urls; + urls.reserve(files.size()); + for (const QUrl &file : files) + urls += addDefaultSuffix(file); + return urls; +} + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2/qquickfiledialog_p.h b/src/quickdialogs2/quickdialogs2/qquickfiledialog_p.h new file mode 100644 index 0000000000..0dccbe727c --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qquickfiledialog_p.h @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFILEDIALOG_P_H +#define QQUICKFILEDIALOG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qurl.h> +#include <QtQml/qqml.h> + +#include "qquickabstractdialog_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFileNameFilter; + +class Q_QUICKDIALOGS2_PRIVATE_EXPORT QQuickFileDialog : public QQuickAbstractDialog +{ + Q_OBJECT + Q_PROPERTY(FileMode fileMode READ fileMode WRITE setFileMode NOTIFY fileModeChanged FINAL) + Q_PROPERTY(QUrl selectedFile READ selectedFile NOTIFY selectedFileChanged FINAL) + Q_PROPERTY(QList<QUrl> selectedFiles READ selectedFiles NOTIFY selectedFilesChanged FINAL) + Q_PROPERTY(QUrl currentFile READ currentFile WRITE setCurrentFile NOTIFY currentFileChanged FINAL) + Q_PROPERTY(QList<QUrl> currentFiles READ currentFiles WRITE setCurrentFiles NOTIFY currentFilesChanged FINAL) + Q_PROPERTY(QUrl currentFolder READ currentFolder WRITE setCurrentFolder NOTIFY currentFolderChanged FINAL) + Q_PROPERTY(QFileDialogOptions::FileDialogOptions options READ options WRITE setOptions RESET resetOptions NOTIFY optionsChanged FINAL) + Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters RESET resetNameFilters NOTIFY nameFiltersChanged FINAL) + Q_PROPERTY(QQuickFileNameFilter *selectedNameFilter READ selectedNameFilter CONSTANT) + Q_PROPERTY(QString defaultSuffix READ defaultSuffix WRITE setDefaultSuffix RESET resetDefaultSuffix NOTIFY defaultSuffixChanged FINAL) + Q_PROPERTY(QString acceptLabel READ acceptLabel WRITE setAcceptLabel RESET resetAcceptLabel NOTIFY acceptLabelChanged FINAL) + Q_PROPERTY(QString rejectLabel READ rejectLabel WRITE setRejectLabel RESET resetRejectLabel NOTIFY rejectLabelChanged FINAL) + Q_FLAGS(QFileDialogOptions::FileDialogOptions) + QML_NAMED_ELEMENT(FileDialog) + QML_ADDED_IN_VERSION(6, 2) + Q_MOC_INCLUDE(<QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h>) + +public: + explicit QQuickFileDialog(QObject *parent = nullptr); + + enum FileMode { + OpenFile, + OpenFiles, + SaveFile + }; + Q_ENUM(FileMode) + + FileMode fileMode() const; + void setFileMode(FileMode fileMode); + + QUrl selectedFile() const; + + QList<QUrl> selectedFiles() const; + + QUrl currentFile() const; + void setCurrentFile(const QUrl &file); + + QList<QUrl> currentFiles() const; + void setCurrentFiles(const QList<QUrl> ¤tFiles); + + QUrl currentFolder() const; + void setCurrentFolder(const QUrl ¤tFolder); + + QFileDialogOptions::FileDialogOptions options() const; + void setOptions(QFileDialogOptions::FileDialogOptions options); + void resetOptions(); + + QStringList nameFilters() const; + void setNameFilters(const QStringList &filters); + void resetNameFilters(); + + QQuickFileNameFilter *selectedNameFilter() const; + + QString defaultSuffix() const; + void setDefaultSuffix(const QString &suffix); + void resetDefaultSuffix(); + + QString acceptLabel() const; + void setAcceptLabel(const QString &label); + void resetAcceptLabel(); + + QString rejectLabel() const; + void setRejectLabel(const QString &label); + void resetRejectLabel(); + +Q_SIGNALS: + void fileModeChanged(); + void selectedFileChanged(); + void selectedFilesChanged(); + void currentFileChanged(); + void currentFilesChanged(); + void currentFolderChanged(); + void optionsChanged(); + void nameFiltersChanged(); + void defaultSuffixChanged(); + void acceptLabelChanged(); + void rejectLabelChanged(); + +protected: + bool useNativeDialog() const override; + void onCreate(QPlatformDialogHelper *dialog) override; + void onShow(QPlatformDialogHelper *dialog) override; + void onHide(QPlatformDialogHelper *dialog) override; + void accept() override; + +private: + QUrl addDefaultSuffix(const QUrl &file) const; + QList<QUrl> addDefaultSuffixes(const QList<QUrl> &files) const; + + void setSelectedFiles(const QList<QUrl> &selectedFiles); + + FileMode m_fileMode; + QList<QUrl> m_selectedFiles; + bool m_firstShow = true; + QSharedPointer<QFileDialogOptions> m_options; + mutable QQuickFileNameFilter *m_selectedNameFilter; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickFileDialog) + +#endif // QQUICKFILEDIALOG_P_H diff --git a/src/quickdialogs2/quickdialogs2/qquickfontdialog.cpp b/src/quickdialogs2/quickdialogs2/qquickfontdialog.cpp new file mode 100644 index 0000000000..5bf5904977 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qquickfontdialog.cpp @@ -0,0 +1,227 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFONTDIALOG_CPP +#define QQUICKFONTDIALOG_CPP + +#include "qquickfontdialog_p.h" + +#include <QtCore/qloggingcategory.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype FontDialog + \inherits Dialog +//! \instantiates QQuickFontDialog + \inqmlmodule QtQuick.Dialogs + \since 6.2 + \brief A font dialog. + + The FontDialog type provides a QML API for font dialogs. + + \image qtquickdialogs-fontdialog-gtk.png + + To show a font dialog, construct an instance of FontDialog, set the + desired properties, and call \l {Dialog::}{open()}. The \l currentFont + property can be used to determine the currently selected font in the + dialog. The \l selectedFont property is updated only after the final selection + has been made by accepting the dialog. + + \code + MenuItem { + text: "Font" + onTriggered: fontDialog.open() + } + + FontDialog { + id: fontDialog + currentFont.family: document.font + } + + MyDocument { + id: document + font: fontDialog.selectedFont + } + \endcode + + \section2 Availability + + A native platform font dialog is currently available on the following platforms: + + \list + \li macOS + \li Linux (when running with the GTK+ platform theme) + \endlist + + \include includes/fallback.qdocinc +*/ + +Q_LOGGING_CATEGORY(lcFontDialog, "qt.quick.dialogs.fontdialog") + +QQuickFontDialog::QQuickFontDialog(QObject *parent) + : QQuickAbstractDialog(QPlatformTheme::FontDialog, parent), + m_options(QFontDialogOptions::create()) +{ +} + +/*! + \qmlproperty font QtQuick.Dialogs::FontDialog::currentFont + + This property holds the currently selected font in the dialog. + + Unlike the \l selectedFont property, the \c currentFont property is updated + while the user is selecting fonts in the dialog, even before the final + selection has been made. + + \sa selectedFont +*/ + +QFont QQuickFontDialog::currentFont() const +{ + if (QPlatformFontDialogHelper *fontDialog = qobject_cast<QPlatformFontDialogHelper *>(handle())) + return fontDialog->currentFont(); + return QFont(); +} + +void QQuickFontDialog::setCurrentFont(const QFont &font) +{ + if (QPlatformFontDialogHelper *fontDialog = + qobject_cast<QPlatformFontDialogHelper *>(handle())) + fontDialog->setCurrentFont(font); +} + +/*! + \qmlproperty font QtQuick.Dialogs::FontDialog::selectedFont + + This property holds the final accepted font. + + Unlike the \l currentFont property, the \c selectedFont property is not updated + while the user is selecting fonts in the dialog, but only after the final + selection has been made. That is, when the user has clicked \uicontrol Open + to accept a font. Alternatively, the \l {Dialog::}{accepted()} signal + can be handled to get the final selection. + + \sa currentFont, {Dialog::}{accepted()} +*/ + +QFont QQuickFontDialog::selectedFont() const +{ + return m_selectedFont; +} + +void QQuickFontDialog::setSelectedFont(const QFont &font) +{ + if (m_selectedFont == font) + return; + + m_selectedFont = font; + emit selectedFontChanged(); +} + +/*! + \qmlproperty flags QtQuick.Dialogs::FontDialog::options + + This property holds the various options that affect the look and feel of the dialog. + + By default, all options are disabled. + + Options should be set before showing the dialog. Setting them while the dialog is + visible is not guaranteed to have an immediate effect on the dialog (depending on + the option and on the platform). + + Available options: + \value FontDialog.ScalableFonts Show scalable fonts. + \value FontDialog.NonScalableFonts Show non-scalable fonts. + \value FontDialog.MonospacedFonts Show monospaced fonts. + \value FontDialog.ProportionalFonts Show proportional fonts. + \value FontDialog.NoButtons Don't display \uicontrol Open and \uicontrol Cancel buttons (useful + for "live dialogs"). +*/ + +QFontDialogOptions::FontDialogOptions QQuickFontDialog::options() const +{ + return m_options->options(); +} + +void QQuickFontDialog::setOptions(QFontDialogOptions::FontDialogOptions options) +{ + if (options == m_options->options()) + return; + + m_options->setOptions(options); + emit optionsChanged(); +} + +void QQuickFontDialog::resetOptions() +{ + setOptions({}); +} + +bool QQuickFontDialog::useNativeDialog() const +{ + return QQuickAbstractDialog::useNativeDialog() + && !(m_options->testOption(QFontDialogOptions::DontUseNativeDialog)); +} + +void QQuickFontDialog::onCreate(QPlatformDialogHelper *dialog) +{ + if (QPlatformFontDialogHelper *fontDialog = qobject_cast<QPlatformFontDialogHelper *>(dialog)) { + connect(fontDialog, &QPlatformFontDialogHelper::currentFontChanged, this, + &QQuickFontDialog::currentFontChanged); + connect(fontDialog, &QPlatformFontDialogHelper::fontSelected, this, + &QQuickFontDialog::setSelectedFont); + fontDialog->setOptions(m_options); + } +} + +void QQuickFontDialog::onShow(QPlatformDialogHelper *dialog) +{ + m_options->setWindowTitle(title()); + if (QPlatformFontDialogHelper *fontDialog = qobject_cast<QPlatformFontDialogHelper *>(dialog)) + fontDialog->setOptions(m_options); // setOptions only assigns a member and isn't virtual +} + +void QQuickFontDialog::accept() +{ + if (auto fontDialog = qobject_cast<QPlatformFontDialogHelper *>(handle())) + setSelectedFont(fontDialog->currentFont()); + QQuickAbstractDialog::accept(); +} + +QT_END_NAMESPACE + +#endif // QQUICKFONTDIALOG_CPP diff --git a/src/quickdialogs2/quickdialogs2/qquickfontdialog_p.h b/src/quickdialogs2/quickdialogs2/qquickfontdialog_p.h new file mode 100644 index 0000000000..c12cbd6298 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qquickfontdialog_p.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFONTDIALOG_P_H +#define QQUICKFONTDIALOG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qquickabstractdialog_p.h" + +#include <QtGui/qfont.h> + +QT_BEGIN_NAMESPACE + +class Q_QUICKDIALOGS2_PRIVATE_EXPORT QQuickFontDialog : public QQuickAbstractDialog +{ + Q_OBJECT + Q_PROPERTY(QFont selectedFont READ selectedFont WRITE setSelectedFont NOTIFY selectedFontChanged) + Q_PROPERTY(QFont currentFont READ currentFont WRITE setCurrentFont NOTIFY currentFontChanged FINAL) + Q_PROPERTY(QFontDialogOptions::FontDialogOptions options READ options WRITE setOptions + RESET resetOptions NOTIFY optionsChanged) + Q_FLAGS(QFontDialogOptions::FontDialogOptions) + QML_NAMED_ELEMENT(FontDialog) + QML_ADDED_IN_VERSION(6, 2) + +public: + explicit QQuickFontDialog(QObject *parent = nullptr); + + void setCurrentFont(const QFont &font); + QFont currentFont() const; + + void setSelectedFont(const QFont &font); + QFont selectedFont() const; + + QFontDialogOptions::FontDialogOptions options() const; + void setOptions(QFontDialogOptions::FontDialogOptions options); + void resetOptions(); + +Q_SIGNALS: + void selectedFontChanged(); + void currentFontChanged(); + void optionsChanged(); + +protected: + bool useNativeDialog() const override; + void onCreate(QPlatformDialogHelper *dialog) override; + void onShow(QPlatformDialogHelper *dialog) override; + void accept() override; + +private: + QFont m_selectedFont; + QSharedPointer<QFontDialogOptions> m_options; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickFontDialog) + +#endif // QQUICKFONTDIALOG_P_H diff --git a/src/quickdialogs2/quickdialogs2/qtquickdialogs2foreign_p.h b/src/quickdialogs2/quickdialogs2/qtquickdialogs2foreign_p.h new file mode 100644 index 0000000000..6337434f2a --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qtquickdialogs2foreign_p.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QTQUICKDIALOGS2FOREIGN_P_H +#define QTQUICKDIALOGS2FOREIGN_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qpa/qplatformdialoghelper.h> +#include <QtQml/qqml.h> +#include <QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h> + +QT_BEGIN_NAMESPACE + +struct QPlatformDialogHelperForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QPlatformDialogHelper) + QML_ADDED_IN_VERSION(6, 2) +}; + +struct QQuickFileNameFilterForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QQuickFileNameFilter) + QML_ADDED_IN_VERSION(6, 2) +}; + +QT_END_NAMESPACE + +#endif // QTQUICKDIALOGS2FOREIGN_P_H diff --git a/src/quickdialogs2/quickdialogs2/qtquickdialogs2global_p.h b/src/quickdialogs2/quickdialogs2/qtquickdialogs2global_p.h new file mode 100644 index 0000000000..cae55a95a3 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2/qtquickdialogs2global_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QTQUICKDIALOGS2GLOBAL_P_H +#define QTQUICKDIALOGS2GLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtQml/private/qqmlglobal_p.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_QUICKDIALOGS2_LIB) +# define Q_QUICKDIALOGS2_PRIVATE_EXPORT Q_DECL_EXPORT +# else +# define Q_QUICKDIALOGS2_PRIVATE_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_QUICKDIALOGS2_PRIVATE_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // QTQUICKDIALOGS2GLOBAL_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/CMakeLists.txt b/src/quickdialogs2/quickdialogs2quickimpl/CMakeLists.txt new file mode 100644 index 0000000000..f0d94d31fb --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/CMakeLists.txt @@ -0,0 +1,137 @@ +##################################################################### +## QuickDialogs2QuickImpl Module: +##################################################################### + +set(qml_files + "qml/FileDialog.qml" + "qml/FileDialogDelegate.qml" + "qml/FileDialogDelegateLabel.qml" + "qml/FolderBreadcrumbBar.qml" + "qml/FontDialog.qml" + "qml/FontDialogContent.qml" + "qml/+Fusion/FileDialog.qml" + "qml/+Fusion/FileDialogDelegate.qml" + "qml/+Fusion/FolderBreadcrumbBar.qml" + "qml/+Fusion/FontDialog.qml" + "qml/+Imagine/FileDialog.qml" + "qml/+Imagine/FileDialogDelegate.qml" + "qml/+Imagine/FolderBreadcrumbBar.qml" + "qml/+Imagine/FontDialog.qml" + "qml/+Material/FileDialog.qml" + "qml/+Material/FileDialogDelegate.qml" + "qml/+Material/FolderBreadcrumbBar.qml" + "qml/+Material/FontDialog.qml" + "qml/+Universal/FileDialog.qml" + "qml/+Universal/FileDialogDelegate.qml" + "qml/+Universal/FolderBreadcrumbBar.qml" + "qml/+Universal/FontDialog.qml" +) + +qt_internal_add_qml_module(QuickDialogs2QuickImpl + URI "QtQuick.Dialogs.quickimpl" + VERSION "${PROJECT_VERSION}" + CLASS_NAME QtQuickDialogs2QuickImplPlugin + PLUGIN_TARGET qtquickdialogs2quickimplplugin + SOURCES + qquickdialogimplfactory.cpp + qquickdialogimplfactory_p.h + qquickfiledialogdelegate.cpp + qquickfiledialogdelegate_p.h + qquickfiledialogimpl.cpp + qquickfiledialogimpl_p.h + qquickfiledialogimpl_p_p.h + qquickfolderbreadcrumbbar.cpp + qquickfolderbreadcrumbbar_p.h + qquickfolderbreadcrumbbar_p_p.h + qquickplatformfiledialog.cpp + qquickplatformfiledialog_p.h + qquickplatformfontdialog_p.h + qquickplatformfontdialog.cpp + qtquickdialogs2quickimplforeign_p.h + qtquickdialogs2quickimplglobal_p.h + qquickfontdialogimpl_p.h + qquickfontdialogimpl_p_p.h + qquickfontdialogimpl.cpp + QML_FILES + ${qml_files} + DEFINES + QT_BUILD_QUICKDIALOGS2QUICKIMPL_LIB + QT_NO_CAST_FROM_ASCII + QT_NO_CAST_TO_ASCII + INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_SOURCE_DIR} + LIBRARIES + Qt::CorePrivate + Qt::GuiPrivate + Qt::QmlPrivate + Qt::QuickPrivate + Qt::QuickTemplates2Private + Qt::QuickDialogs2UtilsPrivate +) + +# Resources: +set(qtquickdialogs2quickimpl_resource_files + "images/crumb-separator-icon-round.png" + "images/crumb-separator-icon-round@2x.png" + "images/crumb-separator-icon-round@3x.png" + "images/crumb-separator-icon-round@4x.png" + "images/crumb-separator-icon-square.png" + "images/crumb-separator-icon-square@2x.png" + "images/crumb-separator-icon-square@3x.png" + "images/crumb-separator-icon-square@4x.png" + "images/file-icon-round.png" + "images/file-icon-round@2x.png" + "images/file-icon-round@3x.png" + "images/file-icon-round@4x.png" + "images/file-icon-square.png" + "images/file-icon-square@2x.png" + "images/file-icon-square@3x.png" + "images/file-icon-square@4x.png" + "images/folder-icon-round.png" + "images/folder-icon-round@2x.png" + "images/folder-icon-round@3x.png" + "images/folder-icon-round@4x.png" + "images/folder-icon-square.png" + "images/folder-icon-square@2x.png" + "images/folder-icon-square@3x.png" + "images/folder-icon-square@4x.png" + "images/imagine/filedialogdelegate-background@2x.9.png" + "images/imagine/filedialogdelegate-background@3x.9.png" + "images/imagine/filedialogdelegate-background@4x.9.png" + "images/imagine/filedialogdelegate-background.9.png" + "images/imagine/filedialogdelegate-background-disabled@2x.9.png" + "images/imagine/filedialogdelegate-background-disabled@3x.9.png" + "images/imagine/filedialogdelegate-background-disabled@4x.9.png" + "images/imagine/filedialogdelegate-background-disabled.9.png" + "images/imagine/filedialogdelegate-background-pressed@2x.9.png" + "images/imagine/filedialogdelegate-background-pressed@3x.9.png" + "images/imagine/filedialogdelegate-background-pressed@4x.9.png" + "images/imagine/filedialogdelegate-background-pressed.9.png" + "images/imagine/filedialogdelegate-background-focused@2x.9.png" + "images/imagine/filedialogdelegate-background-focused@3x.9.png" + "images/imagine/filedialogdelegate-background-focused@4x.9.png" + "images/imagine/filedialogdelegate-background-focused.9.png" + "images/imagine/filedialogdelegate-background-highlighted@2x.9.png" + "images/imagine/filedialogdelegate-background-highlighted@3x.9.png" + "images/imagine/filedialogdelegate-background-highlighted@4x.9.png" + "images/imagine/filedialogdelegate-background-highlighted.9.png" + "images/up-icon-round.png" + "images/up-icon-round@2x.png" + "images/up-icon-round@3x.png" + "images/up-icon-round@4x.png" + "images/up-icon-square.png" + "images/up-icon-square@2x.png" + "images/up-icon-square@3x.png" + "images/up-icon-square@4x.png" + "images/up-icon-thick-square.png" + "images/up-icon-thick-square@2x.png" + "images/up-icon-thick-square@3x.png" + "images/up-icon-thick-square@4x.png" +) + +qt_internal_add_resource(QuickDialogs2QuickImpl "QuickDialogs2QuickImpl" + PREFIX + "/qt-project.org/imports/QtQuick/Dialogs/quickimpl" + FILES + ${qtquickdialogs2quickimpl_resource_files} +) diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round.png Binary files differnew file mode 100644 index 0000000000..aaa5a3e431 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round.svg new file mode 100644 index 0000000000..013cedefa3 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round.svg @@ -0,0 +1,136 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="8" + height="8" + viewBox="0 0 8 8" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="crumb-separator-icon-round.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8"> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect3421" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect1367" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect1365" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + </defs> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="16.000001" + inkscape:cx="6.7812496" + inkscape:cy="15.031249" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0" + height="14px"> + <inkscape:grid + type="xygrid" + id="grid856" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="crumb-separator-icon-round" + transform="translate(2.046,3.0914383)"> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect2017" + width="8" + height="8" + x="-2.046" + y="-3.0914383" /> + </g> + <path + id="rect858" + style="fill:#757575;stroke-width:2.43737;stroke-linejoin:round" + d="M 3.0219754,1.01117 6.416287,3.5317721 a 0.74259596,0.74259596 90 0 1 0,1.1923778 L 3.0219754,7.2447519 A 0.5029757,0.5029757 26.701285 0 1 2.2191312,6.8409408 l 0,-5.4259596 A 0.5029757,0.5029757 153.29872 0 1 3.0219754,1.01117 Z" + sodipodi:nodetypes="cccc" + inkscape:path-effect="#path-effect3421" + inkscape:original-d="m 2.2191312,0.41498117 5,3.71297983 -5,3.7129798 z" /> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect1449" + width="8" + height="8" + x="0" + y="0" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@2x.png Binary files differnew file mode 100644 index 0000000000..3f66fe172b --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@3x.png Binary files differnew file mode 100644 index 0000000000..24d9f6a64e --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@4x.png Binary files differnew file mode 100644 index 0000000000..1dc83ef09f --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-round@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square.png Binary files differnew file mode 100644 index 0000000000..1f7ac63e7f --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square.svg new file mode 100644 index 0000000000..9663673470 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square.svg @@ -0,0 +1,134 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="8" + height="8" + viewBox="0 0 8 8" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="crumb-separator-icon-square.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8"> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect3421" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect1367" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect1365" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + </defs> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="90.509672" + inkscape:cx="4.43599" + inkscape:cy="3.3311357" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0" + height="14px"> + <inkscape:grid + type="xygrid" + id="grid856" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="crumb-separator-icon-square" + transform="translate(2.046,3.0914383)"> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect2017" + width="8" + height="8" + x="-2.046" + y="-3.0914383" /> + <path + style="fill:#757575;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -0.046,-2.0914383 4,3 -4,3 z" + id="path1065" + sodipodi:nodetypes="cccc" /> + </g> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect1449" + width="8" + height="8" + x="0" + y="0" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@2x.png Binary files differnew file mode 100644 index 0000000000..524872c1e9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@3x.png Binary files differnew file mode 100644 index 0000000000..33bce847c8 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@4x.png Binary files differnew file mode 100644 index 0000000000..185c3eb7ae --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/crumb-separator-icon-square@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round.png Binary files differnew file mode 100644 index 0000000000..c2a4928daf --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round.svg new file mode 100644 index 0000000000..7ac6a23b5c --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round.svg @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="14" + height="18" + viewBox="0 0 14 18" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="file-icon-round.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <path + style="fill:none;stroke:#757575;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 1.5003822,2.5063148 1.5000273,15.5 A 0.99997269,0.99997269 45.000782 0 0 2.5,16.5 h 9 a 1,1 135 0 0 1,-1 V 6.3440001 A 2.3479106,2.3479106 66.930332 0 0 11.778973,4.6510931 L 9.221027,2.192907 A 2.4805476,2.4805476 21.904486 0 0 7.5000004,1.5009022 l -4.9995913,0.00451 A 1.0009299,1.0009299 134.97494 0 0 1.5003822,2.5063148 Z" + id="path917" + sodipodi:nodetypes="cccccc" + inkscape:path-effect="#path-effect1367" + inkscape:original-d="M 1.5004095,1.5063148 1.5,16.5 h 11 V 5.3440001 L 8.5,1.5 Z" /> + <path + id="path921" + style="fill:none;stroke:#757575;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 12.35,6.5 H 8.5 a 1,1 45 0 1 -1,-1 V 1.55" + inkscape:path-effect="#path-effect1365" + inkscape:original-d="M 12.35,6.5 H 7.5 V 1.55" + sodipodi:nodetypes="ccc" /> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8"> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect1367" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect1365" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + </defs> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="32.000001" + inkscape:cx="7.8906248" + inkscape:cy="9.7343747" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid856" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="file-icon-round" + transform="translate(2.046,3.0914383)" /> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect2270" + width="14" + height="18" + x="0" + y="0" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@2x.png Binary files differnew file mode 100644 index 0000000000..86af70d1cf --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@3x.png Binary files differnew file mode 100644 index 0000000000..06fea29ed0 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@4x.png Binary files differnew file mode 100644 index 0000000000..09f8787314 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-round@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square.png Binary files differnew file mode 100644 index 0000000000..9e8f3ddd8f --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square.svg new file mode 100644 index 0000000000..107afa385e --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square.svg @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="14" + height="18" + viewBox="0 0 14 18" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="file-icon-square.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <path + style="fill:none;stroke:#757575;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 1.5004095,1.5063148 1.5,16.5 h 11 V 5.3440001 L 8.5,1.5 Z" + id="path917" + sodipodi:nodetypes="cccccc" /> + <path + style="fill:none;stroke:#757575;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 8.5,1.55 V 5.5" + id="path919" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;stroke:#757575;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 12.45,5.5 H 8.5" + id="path921" + sodipodi:nodetypes="cc" /> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="22.627417" + inkscape:cx="0.022097087" + inkscape:cy="8.1538251" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid856" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="file-icon-square" + transform="translate(2.046,3.0914383)" /> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect1895" + width="14" + height="18" + x="0" + y="0" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@2x.png Binary files differnew file mode 100644 index 0000000000..8d33067744 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@3x.png Binary files differnew file mode 100644 index 0000000000..2987d2caed --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@4x.png Binary files differnew file mode 100644 index 0000000000..69d76176e9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/file-icon-square@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round.png Binary files differnew file mode 100644 index 0000000000..60bc6c72c1 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round.svg new file mode 100644 index 0000000000..ba6b627644 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round.svg @@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="18" + height="14" + viewBox="0 0 18 14" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="folder-icon-round.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <path + style="fill:none;stroke:#757575;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 1.5003723,2.5063148 1.5000372,11.5 A 0.99996275,0.99996275 45.001067 0 0 2.5,12.5 h 13 a 1,1 135 0 0 1,-1 v -7 a 1,1 45 0 0 -1,-1 h -5 A 2.4142136,2.4142136 22.5 0 1 8.7928932,2.7928932 L 8.2071068,2.2071068 A 2.4106245,2.4106245 22.469847 0 0 6.5000006,1.5010525 l -3.9995917,0.00421 A 1.0010904,1.0010904 134.97091 0 0 1.5003723,2.5063148 Z" + id="path917" + sodipodi:nodetypes="ccccccc" + inkscape:path-effect="#path-effect1132" + inkscape:original-d="M 1.5004095,1.5063148 1.5,12.5 h 15 v -9 h -7 l -2,-2 z" /> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8"> + <inkscape:path-effect + effect="fillet_chamfer" + id="path-effect1132" + is_visible="true" + lpeversion="1" + satellites_param="F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1 @ F,0,0,1,0,1,0,1" + unit="px" + method="auto" + mode="F" + radius="1" + chamfer_steps="1" + flexible="false" + use_knot_distance="true" + apply_no_radius="true" + apply_with_radius="true" + only_selected="false" + hide_knots="false" /> + </defs> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="16" + inkscape:cx="-11.28125" + inkscape:cy="7.40625" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid856" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="folder-icon-round" + transform="translate(2.046,3.0914383)" /> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect2548" + width="18" + height="14" + x="0" + y="0" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@2x.png Binary files differnew file mode 100644 index 0000000000..e28734374f --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@3x.png Binary files differnew file mode 100644 index 0000000000..5ee70a955e --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@4x.png Binary files differnew file mode 100644 index 0000000000..47d28a4b75 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-round@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square.png Binary files differnew file mode 100644 index 0000000000..b84a90aecb --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square.svg new file mode 100644 index 0000000000..0002b5ac8e --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square.svg @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="18" + height="14" + viewBox="0 0 18 14" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="folder-icon-square.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <path + style="fill:none;stroke:#757575;stroke-width:1;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 1.5004095,1.5063148 1.5,12.5 h 15 v -9 h -7 l -2,-2 z" + id="path917" + sodipodi:nodetypes="ccccccc" /> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="16" + inkscape:cx="-1.59375" + inkscape:cy="12.65625" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid856" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="folder-icon-square" + transform="translate(2.046,3.0914383)"> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect1423" + width="18" + height="14" + x="-2.046" + y="-3.0914383" /> + </g> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@2x.png Binary files differnew file mode 100644 index 0000000000..9bf320bbf0 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@3x.png Binary files differnew file mode 100644 index 0000000000..9f12edb6ee --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@4x.png Binary files differnew file mode 100644 index 0000000000..9ec5b389bd --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/folder-icon-square@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled.9.png Binary files differnew file mode 100644 index 0000000000..ce48ee7422 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@2x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@2x.9.png Binary files differnew file mode 100644 index 0000000000..c7abb65c3f --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@2x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@3x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@3x.9.png Binary files differnew file mode 100644 index 0000000000..46b84d7da4 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@3x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@4x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@4x.9.png Binary files differnew file mode 100644 index 0000000000..f4dfd338f9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-disabled@4x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused.9.png Binary files differnew file mode 100644 index 0000000000..39fa866442 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@2x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@2x.9.png Binary files differnew file mode 100644 index 0000000000..6b61562c14 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@2x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@3x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@3x.9.png Binary files differnew file mode 100644 index 0000000000..e46c0bf1d9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@3x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@4x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@4x.9.png Binary files differnew file mode 100644 index 0000000000..010444e8e1 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-focused@4x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted.9.png Binary files differnew file mode 100644 index 0000000000..6f565e8be2 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@2x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@2x.9.png Binary files differnew file mode 100644 index 0000000000..9fd0a434bb --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@2x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@3x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@3x.9.png Binary files differnew file mode 100644 index 0000000000..62b7435b84 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@3x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@4x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@4x.9.png Binary files differnew file mode 100644 index 0000000000..96444b8905 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-highlighted@4x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed.9.png Binary files differnew file mode 100644 index 0000000000..39fa866442 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@2x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@2x.9.png Binary files differnew file mode 100644 index 0000000000..6b61562c14 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@2x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@3x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@3x.9.png Binary files differnew file mode 100644 index 0000000000..e46c0bf1d9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@3x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@4x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@4x.9.png Binary files differnew file mode 100644 index 0000000000..010444e8e1 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background-pressed@4x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background.9.png Binary files differnew file mode 100644 index 0000000000..cef1bafab3 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background.svg new file mode 100644 index 0000000000..acecfcc9ac --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background.svg @@ -0,0 +1,358 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="210mm" + height="297mm" + viewBox="0 0 210 297" + version="1.1" + id="svg5" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="filedialogdelegate-background.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata122"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <sodipodi:namedview + id="namedview7" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + objecttolerance="10.0" + gridtolerance="10.0" + guidetolerance="10.0" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + inkscape:pagecheckerboard="0" + inkscape:document-units="px" + showgrid="false" + inkscape:zoom="3.2715084" + inkscape:cx="24.912056" + inkscape:cy="54.867657" + inkscape:window-width="1848" + inkscape:window-height="1016" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="g1413" + showguides="true" + inkscape:guide-bbox="true" + inkscape:document-rotation="0"> + <sodipodi:guide + position="6.0854167,296.96676" + orientation="-1,0" + id="guide2310" + inkscape:label="" + inkscape:locked="true" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="3.363578,293.03125" + orientation="0,1" + id="guide2322" + inkscape:label="" + inkscape:locked="true" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="12.170833,297.68429" + orientation="-1,0" + id="guide2760" + inkscape:label="" + inkscape:locked="true" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="18.25625,297.91758" + orientation="-1,0" + id="guide949" + inkscape:label="" + inkscape:locked="true" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="24.341667,299.40187" + orientation="-1,0" + id="guide941" + inkscape:label="" + inkscape:locked="true" + inkscape:color="rgb(0,0,255)" /> + <sodipodi:guide + position="30.427083,299.08734" + orientation="-1,0" + id="guide1165" + inkscape:label="" + inkscape:locked="false" + inkscape:color="rgb(0,0,255)" /> + </sodipodi:namedview> + <defs + id="defs2" /> + <g + inkscape:label="[9] filedialogdelegate-background-highlighted" + inkscape:groupmode="layer" + id="g1413" + style="display:inline" + sodipodi:insensitive="true"> + <rect + style="fill:none;stroke-width:0.946642;stroke-linejoin:round" + id="rect1401" + width="6.0854168" + height="3.96875" + x="30.427084" + y="-6.9388939e-18" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:7.98967;stroke-linejoin:round" + id="rect1403" + width="0.26458332" + height="3.4395833" + x="30.427084" + y="0.26458332" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.1547;stroke-linejoin:round" + id="rect1405" + width="0.26458332" + height="5.5562401" + x="-0.26415125" + y="30.691679" + transform="matrix(3.6708238e-5,-1,1,1.4067378e-5,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect1407" + width="0.26458332" + height="0.26458287" + x="-3.9588995" + y="33.337505" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect1409" + width="0.26458332" + height="0.26458287" + x="-2.1059568" + y="36.247913" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#4fc1e9;fill-opacity:1;fill-rule:evenodd;stroke-width:0.263352" + id="rect1411" + width="5.5562501" + height="3.4395833" + x="30.691668" + y="0.26458332" /> + </g> + <g + inkscape:label="[9] filedialogdelegate-background-focused" + inkscape:groupmode="layer" + id="g939" + style="display:inline" + sodipodi:insensitive="true"> + <rect + style="fill:none;stroke-width:0.946642;stroke-linejoin:round" + id="rect927" + width="6.0854168" + height="3.96875" + x="18.25625" + y="-6.9388939e-18" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:7.98967;stroke-linejoin:round" + id="rect929" + width="0.26458332" + height="3.4395833" + x="18.25625" + y="0.26458332" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.1547;stroke-linejoin:round" + id="rect931" + width="0.26458332" + height="5.5562401" + x="-0.26432261" + y="18.520845" + transform="matrix(3.6708238e-5,-1,1,1.4067378e-5,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect933" + width="0.26458332" + height="0.26458287" + x="-3.9624968" + y="21.166674" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect935" + width="0.26458332" + height="0.26458287" + x="-2.1095541" + y="24.077082" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#e6e9ed;fill-opacity:1;fill-rule:evenodd;stroke-width:0.263352" + id="rect937" + width="5.5562501" + height="3.4395833" + x="18.520834" + y="0.26458332" /> + </g> + <g + inkscape:label="[9] filedialogdelegate-background-pressed" + inkscape:groupmode="layer" + id="g867" + style="display:inline" + sodipodi:insensitive="true"> + <rect + style="fill:none;stroke-width:0.946642;stroke-linejoin:round" + id="rect855" + width="6.0854168" + height="3.96875" + x="12.170834" + y="-6.9388939e-18" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:7.98967;stroke-linejoin:round" + id="rect857" + width="0.26458332" + height="3.4395833" + x="12.170834" + y="0.26458332" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.1547;stroke-linejoin:round" + id="rect859" + width="0.26458332" + height="5.5562401" + x="-0.26440823" + y="12.435429" + transform="matrix(3.6708238e-5,-1,1,1.4067378e-5,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect861" + width="0.26458332" + height="0.26458287" + x="-3.9642947" + y="15.081257" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect863" + width="0.26458332" + height="0.26458287" + x="-2.111352" + y="17.991665" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#e6e9ed;fill-opacity:1;fill-rule:evenodd;stroke-width:0.263352" + id="rect865" + width="5.5562501" + height="3.4395833" + x="12.435416" + y="0.26458332" /> + </g> + <g + inkscape:label="[9] filedialogdelegate-background-disabled" + inkscape:groupmode="layer" + id="g2435" + style="display:inline" + sodipodi:insensitive="true"> + <rect + style="fill:none;stroke-width:0.946642;stroke-linejoin:round" + id="rect2425" + width="6.0854168" + height="3.96875" + x="6.0854168" + y="-6.9388939e-18" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:7.98967;stroke-linejoin:round" + id="rect2427" + width="0.26458332" + height="3.4395833" + x="6.0854168" + y="0.26458332" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.1547;stroke-linejoin:round" + id="rect2429" + width="0.26458332" + height="5.5562401" + x="-0.264494" + y="6.3500099" + transform="matrix(3.6708238e-5,-1,1,1.4067378e-5,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect2431" + width="0.26458332" + height="0.26458287" + x="-3.9660921" + y="8.995841" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect2433" + width="0.26458332" + height="0.26458287" + x="-2.1131494" + y="11.906255" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#f5f7fa;fill-opacity:1;fill-rule:evenodd;stroke-width:0.263352" + id="rect124" + width="5.5562501" + height="3.4395833" + x="6.3499999" + y="0.26458332" /> + </g> + <g + inkscape:label="[9] filedialogdelegate-background" + inkscape:groupmode="layer" + id="layer1" + style="display:inline" + sodipodi:insensitive="true"> + <rect + style="fill:none;stroke-width:0.946642;stroke-linejoin:round" + id="rect846" + width="6.0854168" + height="3.96875" + x="0" + y="-6.9388939e-18" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:7.98967;stroke-linejoin:round" + id="rect1054" + width="0.26458332" + height="3.4395833" + x="0" + y="0.26458332" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10.1547;stroke-linejoin:round" + id="rect1212" + width="0.26458332" + height="5.5562401" + x="-0.26457959" + y="0.26459303" + transform="matrix(3.6708238e-5,-1,1,1.4067378e-5,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect1505" + width="0.26458332" + height="0.26458287" + x="-3.9678898" + y="2.9104238" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:2.21594;stroke-linejoin:round" + id="rect1587" + width="0.26458332" + height="0.26458287" + x="-2.1149471" + y="5.8208375" + transform="matrix(1.7480114e-6,-1,0.99999996,2.9541491e-4,0,0)" /> + <rect + style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.0578;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="rect3108" + width="5.5562501" + height="3.4395833" + x="0.26458332" + y="0.26458332" /> + </g> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@2x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@2x.9.png Binary files differnew file mode 100644 index 0000000000..5a136a0ca9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@2x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@3x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@3x.9.png Binary files differnew file mode 100644 index 0000000000..f47a366b7b --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@3x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@4x.9.png b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@4x.9.png Binary files differnew file mode 100644 index 0000000000..9ecb680f20 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/imagine/filedialogdelegate-background@4x.9.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round.png Binary files differnew file mode 100644 index 0000000000..a4b7bc0383 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round.svg new file mode 100644 index 0000000000..fd05395798 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round.svg @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="up-icon-round.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="16" + inkscape:cx="-1.96875" + inkscape:cy="10.65625" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid1497" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="up-icon-round" /> + <g + id="g1413" + transform="translate(0.3592822,-0.0034197)"> + <path + style="fill:none;fill-opacity:1;stroke:#757575;stroke-width:2.23721;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="m 7.6407178,2.1165354 3e-7,11.7737686" + id="path20" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:1;stroke:#757575;stroke-width:2.23721;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 7.6407178,2.1165354 2.6616436,7.0956099" + id="path950" + sodipodi:nodetypes="cc" /> + <path + style="fill:none;fill-opacity:1;stroke:#757575;stroke-width:2.23721;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + d="M 7.6407178,2.1165354 12.619792,7.0956096" + id="path952" + sodipodi:nodetypes="cc" /> + </g> + <rect + style="fill:none;stroke-width:5.33333;stroke-linejoin:round" + id="rect2897" + width="16" + height="16" + x="0" + y="0" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@2x.png Binary files differnew file mode 100644 index 0000000000..25ee970a17 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@3x.png Binary files differnew file mode 100644 index 0000000000..486f2f46a9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@4x.png Binary files differnew file mode 100644 index 0000000000..585402531c --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-round@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square.png Binary files differnew file mode 100644 index 0000000000..f7d4151a5a --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square.svg new file mode 100644 index 0000000000..93fc45bae4 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square.svg @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="up-icon-square.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="11.313709" + inkscape:cx="-6.3197669" + inkscape:cy="28.416854" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid1497" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="up-icon-square" /> + <path + style="fill:#757575;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 8.000315,1 -6,6 L 3,8 8,3 13,8 14,7 Z" + id="path928" + sodipodi:nodetypes="ccccccc" /> + <rect + style="fill:none;stroke-width:5.33333;stroke-linejoin:round" + id="rect2897" + width="16" + height="16" + x="0" + y="0" /> + <rect + style="fill:#757575;fill-opacity:1;stroke:none;stroke-width:5.23075;stroke-linejoin:round" + id="rect4947" + width="1.5" + height="11" + x="7.2501574" + y="3" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@2x.png Binary files differnew file mode 100644 index 0000000000..2e2a3d94eb --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@3x.png Binary files differnew file mode 100644 index 0000000000..8965148c90 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@4x.png Binary files differnew file mode 100644 index 0000000000..0a56bbcc0a --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-square@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square.png Binary files differnew file mode 100644 index 0000000000..3f9f87624a --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square.svg b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square.svg new file mode 100644 index 0000000000..dd20777be7 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square.svg @@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + width="16" + height="16" + viewBox="0 0 16 16" + version="1.1" + id="svg2" + inkscape:version="1.1-alpha (b0f32e08fc, 2021-03-07)" + sodipodi:docname="up-icon-thick-square.svg" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns="http://www.w3.org/2000/svg" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:dc="http://purl.org/dc/elements/1.1/"> + <metadata + id="metadata10"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + </cc:Work> + </rdf:RDF> + </metadata> + <defs + id="defs8" /> + <sodipodi:namedview + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1" + objecttolerance="10" + gridtolerance="10" + guidetolerance="10" + inkscape:pageopacity="0" + inkscape:pageshadow="2" + inkscape:window-width="1848" + inkscape:window-height="1016" + id="namedview6" + showgrid="true" + inkscape:zoom="22.627417" + inkscape:cx="2.3201941" + inkscape:cy="10.00998" + inkscape:window-x="72" + inkscape:window-y="27" + inkscape:window-maximized="1" + inkscape:current-layer="layer1" + inkscape:document-rotation="0" + inkscape:pagecheckerboard="0"> + <inkscape:grid + type="xygrid" + id="grid1497" /> + </sodipodi:namedview> + <g + inkscape:groupmode="layer" + id="layer1" + inkscape:label="up-icon-thick-square" /> + <path + style="fill:#757575;fill-opacity:1;stroke:none;stroke-width:1.34164px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 2,8 6,-6 6,6 h -3 v 7 H 5 V 8 Z" + id="path1103" + sodipodi:nodetypes="cccccccc" /> + <rect + style="fill:none;stroke-width:4;stroke-linejoin:round" + id="rect1748" + width="16" + height="16" + x="0" + y="0" /> +</svg> diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@2x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@2x.png Binary files differnew file mode 100644 index 0000000000..b4efe13228 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@2x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@3x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@3x.png Binary files differnew file mode 100644 index 0000000000..2e8302b1f0 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@3x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@4x.png b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@4x.png Binary files differnew file mode 100644 index 0000000000..5cf05ab305 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/images/up-icon-thick-square@4x.png diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FileDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FileDialog.qml new file mode 100644 index 0000000000..744f32f4e2 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FileDialog.qml @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import Qt.labs.folderlistmodel +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Fusion +import QtQuick.Controls.Fusion.impl +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +import "." as DialogsImpl + +FileDialogImpl { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitHeaderWidth, + implicitFooterWidth) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + padding: 6 + horizontalPadding: 12 + + standardButtons: T.Dialog.Open | T.Dialog.Cancel + + /* + We use attached properties because we want to handle logic in C++, and: + - We can't assume the footer only contains a DialogButtonBox (which would allow us + to connect up to it in QQuickFileDialogImpl); it also needs to hold a ComboBox + and therefore the root footer item will be e.g. a layout item instead. + - We don't want to create our own "FileDialogButtonBox" (in order to be able to handle the logic + in C++) because we'd need to copy (and hence duplicate code in) DialogButtonBox.qml. + */ + FileDialogImpl.buttonBox: buttonBox + FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox + FileDialogImpl.fileDialogListView: fileDialogListView + FileDialogImpl.breadcrumbBar: breadcrumbBar + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + color: control.palette.window + border.color: control.palette.mid + radius: 2 + + Rectangle { + z: -1 + x: 1 + y: 1 + width: parent.width + height: parent.height + color: control.palette.shadow + opacity: 0.2 + radius: 2 + } + } + + header: ColumnLayout { + spacing: 0 + + Label { + objectName: "dialogTitleBarLabel" + text: control.title + horizontalAlignment: Label.AlignHCenter + elide: Label.ElideRight + font.bold: true + padding: 6 + + Layout.fillWidth: true + Layout.leftMargin: 12 + Layout.rightMargin: 12 + Layout.topMargin: control.title.length > 0 ? 0 : 12 + Layout.preferredHeight: control.title.length > 0 ? implicitHeight : 0 + } + + DialogsImpl.FolderBreadcrumbBar { + id: breadcrumbBar + fileDialog: control + + Layout.fillWidth: true + Layout.leftMargin: 12 + Layout.rightMargin: 12 + + KeyNavigation.tab: fileDialogListView + } + } + + contentItem: Frame { + padding: 0 + verticalPadding: 1 + + ListView { + id: fileDialogListView + objectName: "fileDialogListView" + anchors.fill: parent + clip: true + focus: true + boundsBehavior: Flickable.StopAtBounds + + ScrollBar.vertical: ScrollBar {} + + model: FolderListModel { + folder: control.currentFolder + nameFilters: control.selectedNameFilter.globs + showDirsFirst: true + } + delegate: DialogsImpl.FileDialogDelegate { + objectName: "fileDialogDelegate" + index + x: 1 + width: ListView.view.width - 2 + highlighted: ListView.isCurrentItem + fileDialog: control + fileDetailRowWidth: nameFiltersComboBox.width + + KeyNavigation.backtab: breadcrumbBar + KeyNavigation.tab: nameFiltersComboBox + } + } + } + + footer: RowLayout { + id: rowLayout + spacing: 12 + + ComboBox { + // OK to use IDs here, since users shouldn't be overriding this stuff. + id: nameFiltersComboBox + model: control.nameFilters + + Layout.leftMargin: 12 + Layout.fillWidth: true + Layout.bottomMargin: 12 + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 6 + horizontalPadding: 0 + verticalPadding: 0 + background: null + + Layout.rightMargin: 12 + Layout.bottomMargin: 12 + } + } + + T.Overlay.modal: Rectangle { + color: Fusion.topShadow + } + + T.Overlay.modeless: Rectangle { + color: Fusion.topShadow + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FileDialogDelegate.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FileDialogDelegate.qml new file mode 100644 index 0000000000..3c2b7b9c3c --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FileDialogDelegate.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl as ControlsImpl +import QtQuick.Controls.Fusion +import QtQuick.Controls.Fusion.impl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FileDialogDelegate { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 6 + spacing: 6 + + file: fileUrl + + icon.width: 16 + icon.height: 16 + icon.color: highlighted ? palette.highlightedText : palette.text + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/" + + (fileIsDir ? "folder" : "file") + "-icon-round.png" + + // We don't use index here, but in C++. Since we're using required + // properties, the index context property will not be injected, so we can't + // use its QQmlContext to access it. + required property int index + required property string fileName + required property url fileUrl + required property int fileSize + required property date fileModified + required property bool fileIsDir + + required property int fileDetailRowWidth + + contentItem: FileDialogDelegateLabel { + delegate: control + fileDetailRowTextColor: control.highlighted ? Fusion.highlightedText(control.palette) : control.palette.text + fileDetailRowWidth: control.fileDetailRowWidth + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 20 + color: control.down ? Fusion.buttonColor(control.palette, false, true, true) + : control.highlighted ? Fusion.highlight(control.palette) : control.palette.base + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FolderBreadcrumbBar.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FolderBreadcrumbBar.qml new file mode 100644 index 0000000000..066a60d754 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FolderBreadcrumbBar.qml @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FolderBreadcrumbBar { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + (upButton ? upButton.implicitWidth + upButtonSpacing : 0) + + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + upButtonSpacing: 6 + + contentItem: ListView { + id: listView + currentIndex: control.currentIndex + model: control.contentModel + orientation: ListView.Horizontal + snapMode: ListView.SnapToItem + highlightMoveDuration: 0 + interactive: false + clip: true + + Rectangle { + anchors.fill: parent + color: control.palette.light + border.color: control.palette.mid + radius: 2 + z: -1 + } + } + buttonDelegate: Button { + id: buttonDelegateRoot + text: folderName + flat: true + + // The default of 100 is a bit too wide for short directory names. + Binding { + target: buttonDelegateRoot.background + property: "implicitWidth" + value: 24 + } + + required property int index + required property string folderName + } + separatorDelegate: IconImage { + id: iconImage + source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/crumb-separator-icon-round.png" + sourceSize: Qt.size(8, 8) + width: 8 + 6 + height: control.contentItem.height + color: control.palette.dark + y: (control.height - height) / 2 + } + upButton: Button { + x: control.leftPadding + y: control.topPadding + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/up-icon-round.png" + icon.width: 16 + icon.height: 16 + width: height + height: Math.max(implicitHeight, control.contentItem.height) + focusPolicy: Qt.TabFocus + } + textField: TextField { + text: control.fileDialog.selectedFile + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FontDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FontDialog.qml new file mode 100644 index 0000000000..dd75338f21 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Fusion/FontDialog.qml @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Fusion +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +FontDialogImpl { + id: control + + implicitWidth: Math.max(control.implicitBackgroundWidth + control.leftInset + control.rightInset, + control.contentWidth + control.leftPadding + control.rightPadding, + control.implicitHeaderWidth, + control.implicitFooterWidth) + implicitHeight: Math.max(control.implicitBackgroundHeight + control.topInset + control.bottomInset, + control.contentHeight + control.topPadding + control.bottomPadding + + (control.implicitHeaderHeight > 0 ? control.implicitHeaderHeight + control.spacing : 0) + + (control.implicitFooterHeight > 0 ? control.implicitFooterHeight + control.spacing : 0)) + + leftPadding: 20 + rightPadding: 20 + // Ensure that the background's border is visible. + leftInset: -1 + rightInset: -1 + topInset: -1 + bottomInset: -1 + + standardButtons: T.Dialog.Ok | T.Dialog.Cancel + + FontDialogImpl.buttonBox: buttonBox + FontDialogImpl.familyListView: content.familyListView + FontDialogImpl.styleListView: content.styleListView + FontDialogImpl.sizeListView: content.sizeListView + FontDialogImpl.sampleEdit: content.sampleEdit + FontDialogImpl.writingSystemComboBox: writingSystemComboBox + FontDialogImpl.underlineCheckBox: content.underline + FontDialogImpl.strikeoutCheckBox: content.strikeout + FontDialogImpl.familyEdit: content.familyEdit + FontDialogImpl.styleEdit: content.styleEdit + FontDialogImpl.sizeEdit: content.sizeEdit + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + color: control.palette.window + border.color: control.palette.mid + radius: 2 + + Rectangle { + z: -1 + x: 1 + y: 1 + width: parent.width + height: parent.height + color: control.palette.shadow + opacity: 0.2 + radius: 2 + } + } + + Overlay.modal: Rectangle { + color: Fusion.topShadow + } + + Overlay.modeless: Rectangle { + color: Fusion.topShadow + } + + header: Label { + text: control.title + horizontalAlignment: Label.AlignHCenter + elide: Label.ElideRight + font.bold: true + padding: 6 + } + + contentItem: FontDialogContent { + id: content + } + + footer: RowLayout { + id: rowLayout + spacing: 12 + + Label { + text: qsTr("Writing System") + + Layout.leftMargin: 12 + Layout.topMargin: 6 + Layout.bottomMargin: 6 + } + ComboBox{ + id: writingSystemComboBox + + Layout.fillWidth: true + Layout.topMargin: 6 + Layout.bottomMargin: 6 + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 6 + horizontalPadding: 0 + verticalPadding: 0 + background: null + + Layout.rightMargin: 12 + Layout.topMargin: 6 + Layout.bottomMargin: 6 + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FileDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FileDialog.qml new file mode 100644 index 0000000000..fdf8f36e94 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FileDialog.qml @@ -0,0 +1,190 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import Qt.labs.folderlistmodel +import QtQuick +import QtQuick.Templates as T +import QtQuick.Controls.Imagine +import QtQuick.Controls.Imagine.impl +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts + +import "." as DialogsImpl + +FileDialogImpl { + id: control + + // Can't set implicitWidth of the NinePatchImage background, so we do it here. + implicitWidth: Math.max(600, + implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitHeaderWidth, + implicitFooterWidth) + implicitHeight: Math.max(400, + implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + topPadding: background ? background.topPadding : 0 + leftPadding: background ? background.leftPadding : 0 + rightPadding: background ? background.rightPadding : 0 + bottomPadding: background ? background.bottomPadding : 0 + + topInset: background ? -background.topInset || 0 : 0 + leftInset: background ? -background.leftInset || 0 : 0 + rightInset: background ? -background.rightInset || 0 : 0 + bottomInset: background ? -background.bottomInset || 0 : 0 + + standardButtons: T.Dialog.Open | T.Dialog.Cancel + + FileDialogImpl.buttonBox: buttonBox + FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox + FileDialogImpl.fileDialogListView: fileDialogListView + FileDialogImpl.breadcrumbBar: breadcrumbBar + + background: NinePatchImage { + source: Imagine.url + "dialog-background" + NinePatchImageSelector on source { + states: [ + {"modal": control.modal}, + {"dim": control.dim} + ] + } + } + + header: ColumnLayout { + spacing: 12 + + Label { + text: control.title + elide: Label.ElideRight + font.bold: true + + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.topMargin: 12 + Layout.fillWidth: true + Layout.preferredHeight: control.title.length > 0 ? implicitHeight : 0 + + background: NinePatchImage { + width: parent.width + height: parent.height + + source: Imagine.url + "dialog-title" + NinePatchImageSelector on source { + states: [ + {"modal": control.modal}, + {"dim": control.dim} + ] + } + } + } + + DialogsImpl.FolderBreadcrumbBar { + id: breadcrumbBar + fileDialog: control + + Layout.leftMargin: 16 + Layout.rightMargin: 16 + Layout.fillWidth: true + Layout.maximumWidth: parent.width - 28 + } + } + + contentItem: ListView { + id: fileDialogListView + objectName: "fileDialogListView" + clip: true + boundsBehavior: Flickable.StopAtBounds + + ScrollBar.vertical: ScrollBar {} + + model: FolderListModel { + folder: control.currentFolder + nameFilters: control.selectedNameFilter.globs + showDirsFirst: true + } + delegate: DialogsImpl.FileDialogDelegate { + objectName: "fileDialogDelegate" + index + width: ListView.view.width + highlighted: ListView.isCurrentItem + fileDialog: control + fileDetailRowWidth: nameFiltersComboBox.width + } + } + + footer: RowLayout { + id: rowLayout + spacing: 20 + + ComboBox { + id: nameFiltersComboBox + model: control.nameFilters + + Layout.leftMargin: 16 + Layout.bottomMargin: 16 + Layout.fillWidth: true + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 12 + + Layout.bottomMargin: 16 + Layout.rightMargin: 16 + } + } + + T.Overlay.modal: NinePatchImage { + source: Imagine.url + "dialog-overlay" + NinePatchImageSelector on source { + states: [ + {"modal": true} + ] + } + } + + T.Overlay.modeless: NinePatchImage { + source: Imagine.url + "dialog-overlay" + NinePatchImageSelector on source { + states: [ + {"modal": false} + ] + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FileDialogDelegate.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FileDialogDelegate.qml new file mode 100644 index 0000000000..9785afd1ca --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FileDialogDelegate.qml @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick.Controls +import QtQuick.Controls.Imagine +import QtQuick.Controls.Imagine.impl +import QtQuick.Controls.impl as ControlsImpl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FileDialogDelegate { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + spacing: 12 + + topPadding: background ? background.topPadding : 0 + leftPadding: background ? background.leftPadding : 0 + rightPadding: background ? background.rightPadding : 0 + bottomPadding: background ? background.bottomPadding : 0 + + topInset: background ? -background.topInset || 0 : 0 + leftInset: background ? -background.leftInset || 0 : 0 + rightInset: background ? -background.rightInset || 0 : 0 + bottomInset: background ? -background.bottomInset || 0 : 0 + + file: fileUrl + + icon.width: 16 + icon.height: 16 + icon.color: highlighted ? palette.highlightedText : palette.text + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/" + + (fileIsDir ? "folder" : "file") + "-icon-round.png" + + required property int index + required property string fileName + required property url fileUrl + required property int fileSize + required property date fileModified + required property bool fileIsDir + + required property int fileDetailRowWidth + + contentItem: FileDialogDelegateLabel { + delegate: control + fileDetailRowTextColor: control.icon.color + fileDetailRowWidth: control.fileDetailRowWidth + } + + background: NinePatchImage { + source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/imagine/filedialogdelegate-background" + NinePatchImageSelector on source { + states: [ + { "disabled": !control.enabled }, + { "pressed": control.down }, + { "focused": control.visualFocus }, + { "highlighted": control.highlighted }, + { "mirrored": control.mirrored }, + { "hovered": control.hovered } + ] + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FolderBreadcrumbBar.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FolderBreadcrumbBar.qml new file mode 100644 index 0000000000..2a56a3c392 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FolderBreadcrumbBar.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FolderBreadcrumbBar { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + (upButton ? upButton.implicitWidth + upButtonSpacing : 0) + + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + upButtonSpacing: 20 + padding: 1 + + background: Rectangle {} + contentItem: ListView { + id: listView + currentIndex: control.currentIndex + model: control.contentModel + orientation: ListView.Horizontal + snapMode: ListView.SnapToItem + highlightMoveDuration: 0 + interactive: false + clip: true + } + buttonDelegate: Button { + id: buttonDelegateRoot + text: folderName + flat: true + + required property int index + required property string folderName + } + separatorDelegate: IconImage { + id: iconImage + source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/crumb-separator-icon-round.png" + sourceSize: Qt.size(8, 8) + width: 8 + height: control.contentItem.height + y: (control.height - height) / 2 + } + upButton: ToolButton { + x: control.leftPadding + y: control.topPadding + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/up-icon-thick-square.png" + icon.width: 16 + icon.height: 16 + focusPolicy: Qt.TabFocus + } + textField: TextField { + text: control.fileDialog.selectedFile + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FontDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FontDialog.qml new file mode 100644 index 0000000000..47bd53dafc --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Imagine/FontDialog.qml @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Imagine +import QtQuick.Controls.Imagine.impl +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +FontDialogImpl { + id: control + + // Can't set implicitWidth of the NinePatchImage background, so we do it here. + implicitWidth: Math.max(600, + implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitHeaderWidth, + implicitFooterWidth) + implicitHeight: Math.max(400, + implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + topPadding: background ? background.topPadding : 0 + leftPadding: background ? background.leftPadding : 0 + rightPadding: background ? background.rightPadding : 0 + bottomPadding: background ? background.bottomPadding : 0 + + topInset: background ? -background.topInset || 0 : 0 + leftInset: background ? -background.leftInset || 0 : 0 + rightInset: background ? -background.rightInset || 0 : 0 + bottomInset: background ? -background.bottomInset || 0 : 0 + + standardButtons: T.Dialog.Ok | T.Dialog.Cancel + + FontDialogImpl.buttonBox: buttonBox + FontDialogImpl.familyListView: content.familyListView + FontDialogImpl.styleListView: content.styleListView + FontDialogImpl.sizeListView: content.sizeListView + FontDialogImpl.sampleEdit: content.sampleEdit + FontDialogImpl.writingSystemComboBox: writingSystemComboBox + FontDialogImpl.underlineCheckBox: content.underline + FontDialogImpl.strikeoutCheckBox: content.strikeout + FontDialogImpl.familyEdit: content.familyEdit + FontDialogImpl.styleEdit: content.styleEdit + FontDialogImpl.sizeEdit: content.sizeEdit + + background: NinePatchImage { + source: Imagine.url + "dialog-background" + NinePatchImageSelector on source { + states: [ + {"modal": control.modal}, + {"dim": control.dim} + ] + } + } + + Overlay.modal: NinePatchImage { + source: Imagine.url + "dialog-overlay" + NinePatchImageSelector on source { + states: [ + {"modal": true} + ] + } + } + + Overlay.modeless: NinePatchImage { + source: Imagine.url + "dialog-overlay" + NinePatchImageSelector on source { + states: [ + {"modal": false} + ] + } + } + + header: Label { + text: control.title + elide: Label.ElideRight + font.bold: true + + leftPadding: 16 + rightPadding: 16 + topPadding: 12 + height: control.title.length > 0 ? implicitHeight : 0 + + background: NinePatchImage { + width: parent.width + height: parent.height + + source: Imagine.url + "dialog-title" + NinePatchImageSelector on source { + states: [ + {"modal": control.modal}, + {"dim": control.dim} + ] + } + } + } + + contentItem: FontDialogContent { + id: content + rowSpacing: 16 + } + + footer: RowLayout { + id: rowLayout + spacing: 20 + + Label { + text: qsTr("Writing System") + Layout.leftMargin: 20 + Layout.bottomMargin: 16 + } + ComboBox{ + id: writingSystemComboBox + + Layout.fillWidth: true + Layout.bottomMargin: 16 + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 12 + Layout.rightMargin: 20 + Layout.bottomMargin: 16 + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FileDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FileDialog.qml new file mode 100644 index 0000000000..7e7c430785 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FileDialog.qml @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import Qt.labs.folderlistmodel +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Material +import QtQuick.Controls.Material.impl +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +import "." as DialogsImpl + +FileDialogImpl { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitFooterWidth) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + leftPadding: 24 + rightPadding: 24 + + standardButtons: T.Dialog.Open | T.Dialog.Cancel + + Material.elevation: 24 + + FileDialogImpl.buttonBox: buttonBox + FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox + FileDialogImpl.fileDialogListView: fileDialogListView + FileDialogImpl.breadcrumbBar: breadcrumbBar + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + radius: 2 + color: control.Material.dialogColor + + layer.enabled: control.Material.elevation > 0 + layer.effect: ElevationEffect { + elevation: control.Material.elevation + } + } + + header: ColumnLayout { + spacing: 12 + + Label { + text: control.title + visible: control.title.length > 0 + elide: Label.ElideRight + font.bold: true + font.pixelSize: 16 + + Layout.leftMargin: 24 + Layout.rightMargin: 24 + Layout.topMargin: 24 + Layout.fillWidth: true + } + + DialogsImpl.FolderBreadcrumbBar { + id: breadcrumbBar + fileDialog: control + + Layout.leftMargin: 24 + Layout.rightMargin: 24 + Layout.fillWidth: true + Layout.maximumWidth: parent.width - 48 + } + } + + contentItem: ListView { + id: fileDialogListView + objectName: "fileDialogListView" + clip: true + + ScrollBar.vertical: ScrollBar {} + + model: FolderListModel { + folder: control.currentFolder + nameFilters: control.selectedNameFilter.globs + showDirsFirst: true + } + delegate: DialogsImpl.FileDialogDelegate { + objectName: "fileDialogDelegate" + index + width: ListView.view.width + highlighted: ListView.isCurrentItem + fileDialog: control + fileDetailRowWidth: nameFiltersComboBox.width + } + } + + footer: RowLayout { + id: rowLayout + spacing: 20 + + ComboBox { + id: nameFiltersComboBox + model: control.nameFilters + + Layout.leftMargin: 20 + Layout.fillWidth: true + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 12 + horizontalPadding: 0 + verticalPadding: 20 + + Layout.rightMargin: 20 + } + } + + Overlay.modal: Rectangle { + color: Color.transparent(control.palette.shadow, 0.5) + } + + Overlay.modeless: Rectangle { + color: Color.transparent(control.palette.shadow, 0.12) + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FileDialogDelegate.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FileDialogDelegate.qml new file mode 100644 index 0000000000..eb4bae9bfc --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FileDialogDelegate.qml @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls.impl +import QtQuick.Controls.Material +import QtQuick.Controls.Material.impl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FileDialogDelegate { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 16 + verticalPadding: 8 + spacing: 16 + + icon.width: 16 + icon.height: 16 + icon.color: enabled ? Material.foreground : Material.hintTextColor + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/" + + (fileIsDir ? "folder" : "file") + "-icon-square.png" + + file: fileUrl + + required property int index + required property string fileName + required property url fileUrl + required property int fileSize + required property date fileModified + required property bool fileIsDir + + required property int fileDetailRowWidth + + contentItem: FileDialogDelegateLabel { + delegate: control + fileDetailRowTextColor: control.Material.hintTextColor + fileDetailRowWidth: control.fileDetailRowWidth + } + + background: Rectangle { + implicitHeight: control.Material.delegateHeight + + color: control.highlighted ? Color.transparent(control.Material.accentColor, 0.08) : "transparent" + + Ripple { + width: parent.width + height: parent.height + + clip: visible + pressed: control.pressed + anchor: control + active: control.down || control.visualFocus || control.hovered + color: control.highlighted ? control.Material.highlightedRippleColor : control.Material.rippleColor + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FolderBreadcrumbBar.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FolderBreadcrumbBar.qml new file mode 100644 index 0000000000..7b839034da --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FolderBreadcrumbBar.qml @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Material +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FolderBreadcrumbBar { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + (upButton ? upButton.implicitWidth + upButtonSpacing : 0) + + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + upButtonSpacing: 20 + padding: 1 + + background: Rectangle {} + contentItem: ListView { + id: listView + currentIndex: control.currentIndex + model: control.contentModel + orientation: ListView.Horizontal + snapMode: ListView.SnapToItem + highlightMoveDuration: 0 + interactive: false + clip: true + } + buttonDelegate: Button { + id: buttonDelegateRoot + text: folderName + flat: true + font.capitalization: Font.MixedCase + + // The default of 100 is a bit too wide for short directory names. + Binding { + target: buttonDelegateRoot.background + property: "implicitWidth" + value: control.Material.buttonHeight + } + + required property int index + required property string folderName + } + separatorDelegate: IconImage { + id: iconImage + source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/crumb-separator-icon-square.png" + sourceSize: Qt.size(8, 8) + // The image is 8x8, and add 2 px padding on each side. + width: 8 + 4 + height: control.contentItem.height + color: control.Material.hintTextColor + y: (control.height - height) / 2 + } + upButton: ToolButton { + x: control.leftPadding + y: control.topPadding + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/up-icon-thick-square.png" + icon.width: 16 + icon.height: 16 + width: height + focusPolicy: Qt.TabFocus + } + textField: TextField { + text: control.fileDialog.selectedFile + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FontDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FontDialog.qml new file mode 100644 index 0000000000..5113468012 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Material/FontDialog.qml @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Material +import QtQuick.Controls.Material.impl +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +FontDialogImpl { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitFooterWidth) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + leftPadding: 24 + rightPadding: 24 + + standardButtons: T.Dialog.Ok | T.Dialog.Cancel + + Material.elevation: 24 + + FontDialogImpl.buttonBox: buttonBox + FontDialogImpl.familyListView: content.familyListView + FontDialogImpl.styleListView: content.styleListView + FontDialogImpl.sizeListView: content.sizeListView + FontDialogImpl.sampleEdit: content.sampleEdit + FontDialogImpl.writingSystemComboBox: writingSystemComboBox + FontDialogImpl.underlineCheckBox: content.underline + FontDialogImpl.strikeoutCheckBox: content.strikeout + FontDialogImpl.familyEdit: content.familyEdit + FontDialogImpl.styleEdit: content.styleEdit + FontDialogImpl.sizeEdit: content.sizeEdit + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + radius: 2 + color: control.Material.dialogColor + + layer.enabled: control.Material.elevation > 0 + layer.effect: ElevationEffect { + elevation: control.Material.elevation + } + } + + Overlay.modal: Rectangle { + color: Color.transparent(control.palette.shadow, 0.5) + } + + Overlay.modeless: Rectangle { + color: Color.transparent(control.palette.shadow, 0.12) + } + + header: Label { + text: control.title + visible: control.title.length > 0 + elide: Label.ElideRight + font.bold: true + font.pixelSize: 16 + + leftPadding: 24 + rightPadding: 24 + topPadding: 24 + bottomPadding: 24 + } + + contentItem: FontDialogContent { + id: content + familyEdit.bottomPadding: 8 + styleEdit.bottomPadding: 8 + sizeEdit.bottomPadding: 8 + } + + footer: RowLayout { + id: rowLayout + spacing: 20 + + Label { + text: qsTr("Writing System") + + Layout.leftMargin: 20 + } + ComboBox{ + id: writingSystemComboBox + + Layout.fillWidth: true + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 12 + horizontalPadding: 0 + verticalPadding: 20 + + Layout.rightMargin: 20 + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FileDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FileDialog.qml new file mode 100644 index 0000000000..02b7368c74 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FileDialog.qml @@ -0,0 +1,165 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import Qt.labs.folderlistmodel +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.Universal +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +import "." as DialogsImpl + +FileDialogImpl { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitHeaderWidth, + implicitFooterWidth) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + padding: 24 + verticalPadding: 18 + + standardButtons: T.Dialog.Open | T.Dialog.Cancel + + FileDialogImpl.buttonBox: buttonBox + FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox + FileDialogImpl.fileDialogListView: fileDialogListView + FileDialogImpl.breadcrumbBar: breadcrumbBar + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + color: control.Universal.chromeMediumLowColor + border.color: control.Universal.chromeHighColor + border.width: 1 // FlyoutBorderThemeThickness + } + + header: ColumnLayout { + spacing: 12 + + Label { + text: control.title + elide: Label.ElideRight + // TODO: QPlatformTheme::TitleBarFont + font.pixelSize: 20 + + Layout.leftMargin: 24 + Layout.rightMargin: 24 + Layout.topMargin: 18 + Layout.fillWidth: true + Layout.preferredHeight: control.title.length > 0 ? implicitHeight : 0 + + background: Rectangle { + x: 1; y: 1 // // FlyoutBorderThemeThickness + color: control.Universal.chromeMediumLowColor + width: parent.width - 2 + height: parent.height - 1 + } + } + + DialogsImpl.FolderBreadcrumbBar { + id: breadcrumbBar + fileDialog: control + + Layout.leftMargin: 24 + Layout.rightMargin: 24 + Layout.fillWidth: true + Layout.maximumWidth: parent.width - 48 + } + } + + contentItem: ListView { + id: fileDialogListView + objectName: "fileDialogListView" + clip: true + boundsBehavior: Flickable.StopAtBounds + + ScrollBar.vertical: ScrollBar {} + + model: FolderListModel { + folder: control.currentFolder + nameFilters: control.selectedNameFilter.globs + showDirsFirst: true + } + delegate: DialogsImpl.FileDialogDelegate { + objectName: "fileDialogDelegate" + index + width: ListView.view.width + highlighted: ListView.isCurrentItem + fileDialog: control + fileDetailRowWidth: nameFiltersComboBox.width + } + } + + footer: RowLayout { + id: rowLayout + spacing: 24 + + ComboBox { + id: nameFiltersComboBox + model: control.nameFilters + + Layout.leftMargin: 24 + Layout.fillWidth: true + Layout.topMargin: 6 + Layout.bottomMargin: 24 + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 12 + horizontalPadding: 0 + + Layout.rightMargin: 24 + } + } + + T.Overlay.modal: Rectangle { + color: control.Universal.baseLowColor + } + + T.Overlay.modeless: Rectangle { + color: control.Universal.baseLowColor + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FileDialogDelegate.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FileDialogDelegate.qml new file mode 100644 index 0000000000..d4322dc5fa --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FileDialogDelegate.qml @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls.impl +import QtQuick.Controls.Universal +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FileDialogDelegate { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + spacing: 12 + + padding: 12 + topPadding: padding - 1 + bottomPadding: padding + 1 + + icon.width: 20 + icon.height: 20 + icon.color: Color.transparent(Universal.foreground, enabled ? 1.0 : 0.2) + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/" + + (fileIsDir ? "folder" : "file") + "-icon-square.png" + + file: fileUrl + + required property int index + required property string fileName + required property url fileUrl + required property int fileSize + required property date fileModified + required property bool fileIsDir + + required property int fileDetailRowWidth + + contentItem: FileDialogDelegateLabel { + delegate: control + fileDetailRowTextColor: control.icon.color + fileDetailRowWidth: control.fileDetailRowWidth + } + + background: Rectangle { + visible: control.down || control.highlighted || control.visualFocus || control.hovered + color: control.down ? control.Universal.listMediumColor : + control.hovered ? control.Universal.listLowColor : control.Universal.altMediumLowColor + + Rectangle { + width: parent.width + height: parent.height + visible: control.visualFocus || control.highlighted + color: control.Universal.accent + opacity: control.Universal.theme === Universal.Light ? 0.4 : 0.6 + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FolderBreadcrumbBar.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FolderBreadcrumbBar.qml new file mode 100644 index 0000000000..f270b41168 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FolderBreadcrumbBar.qml @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Universal +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FolderBreadcrumbBar { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + (upButton ? upButton.implicitWidth + upButtonSpacing : 0) + + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + upButtonSpacing: 20 + padding: 1 + + background: Rectangle {} + contentItem: ListView { + id: listView + currentIndex: control.currentIndex + model: control.contentModel + orientation: ListView.Horizontal + snapMode: ListView.SnapToItem + highlightMoveDuration: 0 + interactive: false + clip: true + } + buttonDelegate: ToolButton { + id: buttonDelegateRoot + text: folderName + + // The default is a bit too wide for short directory names. + Binding { + target: buttonDelegateRoot.background + property: "implicitWidth" + value: 48 + } + + required property int index + required property string folderName + } + separatorDelegate: IconImage { + id: iconImage + source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/crumb-separator-icon-square.png" + sourceSize: Qt.size(8, 8) + // The image is 8x8, and add 2 px padding on each side. + width: 8 + 4 + height: control.contentItem.height + color: Color.transparent(control.Universal.foreground, enabled ? 1.0 : 0.2) + y: (control.height - height) / 2 + } + upButton: ToolButton { + x: control.leftPadding + y: control.topPadding + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/up-icon-square.png" + icon.width: 16 + icon.height: 16 + width: height + focusPolicy: Qt.TabFocus + } + textField: TextField { + text: control.fileDialog.selectedFile + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FontDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FontDialog.qml new file mode 100644 index 0000000000..1bd3092e6b --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/+Universal/FontDialog.qml @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Controls.Universal +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +FontDialogImpl { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitHeaderWidth, + implicitFooterWidth) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + padding: 24 + verticalPadding: 18 + + standardButtons: T.Dialog.Ok | T.Dialog.Cancel + + FontDialogImpl.buttonBox: buttonBox + FontDialogImpl.familyListView: content.familyListView + FontDialogImpl.styleListView: content.styleListView + FontDialogImpl.sizeListView: content.sizeListView + FontDialogImpl.sampleEdit: content.sampleEdit + FontDialogImpl.writingSystemComboBox: writingSystemComboBox + FontDialogImpl.underlineCheckBox: content.underline + FontDialogImpl.strikeoutCheckBox: content.strikeout + FontDialogImpl.familyEdit: content.familyEdit + FontDialogImpl.styleEdit: content.styleEdit + FontDialogImpl.sizeEdit: content.sizeEdit + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + color: control.Universal.chromeMediumLowColor + border.color: control.Universal.chromeHighColor + border.width: 1 // FlyoutBorderThemeThickness + } + + Overlay.modal: Rectangle { + color: control.Universal.baseLowColor + } + + Overlay.modeless: Rectangle { + color: control.Universal.baseLowColor + } + + header: Label { + text: control.title + elide: Label.ElideRight + // TODO: QPlatformTheme::TitleBarFont + font.pixelSize: 20 + + leftPadding: 24 + rightPadding: 24 + topPadding: 18 + height: control.title.length > 0 ? implicitHeight : 0 + + background: Rectangle { + x: 1; y: 1 // // FlyoutBorderThemeThickness + color: control.Universal.chromeMediumLowColor + width: parent.width - 2 + height: parent.height - 1 + } + } + + contentItem: FontDialogContent { + id: content + rowSpacing: 12 + } + + footer: RowLayout { + id: rowLayout + spacing: 24 + + Label { + text: qsTr("Writing System") + + Layout.leftMargin: 24 + Layout.topMargin: 6 + Layout.bottomMargin: 24 + } + ComboBox{ + id: writingSystemComboBox + + Layout.fillWidth: true + Layout.topMargin: 6 + Layout.bottomMargin: 24 + + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + spacing: 12 + horizontalPadding: 0 + + Layout.rightMargin: 24 + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialog.qml new file mode 100644 index 0000000000..99a90cbc09 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialog.qml @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import Qt.labs.folderlistmodel +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +import "." as DialogsImpl + +FileDialogImpl { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + contentWidth + leftPadding + rightPadding, + implicitHeaderWidth, + implicitFooterWidth) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + contentHeight + topPadding + bottomPadding + + (implicitHeaderHeight > 0 ? implicitHeaderHeight + spacing : 0) + + (implicitFooterHeight > 0 ? implicitFooterHeight + spacing : 0)) + + leftPadding: 20 + rightPadding: 20 + // Ensure that the background's border is visible. + leftInset: -1 + rightInset: -1 + topInset: -1 + bottomInset: -1 + + standardButtons: T.Dialog.Open | T.Dialog.Cancel + + /* + We use attached properties because we want to handle logic in C++, and: + - We can't assume the footer only contains a DialogButtonBox (which would allow us + to connect up to it in QQuickFileDialogImpl); it also needs to hold a ComboBox + and therefore the root footer item will be e.g. a layout item instead. + - We don't want to create our own "FileDialogButtonBox" (in order to be able to handle the logic + in C++) because we'd need to copy (and hence duplicate code in) DialogButtonBox.qml. + */ + FileDialogImpl.buttonBox: buttonBox + FileDialogImpl.nameFiltersComboBox: nameFiltersComboBox + FileDialogImpl.fileDialogListView: fileDialogListView + FileDialogImpl.breadcrumbBar: breadcrumbBar + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + color: control.palette.window + border.color: control.palette.dark + } + + header: Pane { + palette.window: control.palette.light + padding: 20 + + contentItem: Column { + spacing: 12 + + Label { + objectName: "dialogTitleBarLabel" + width: parent.width + text: control.title + visible: control.title.length > 0 + horizontalAlignment: Label.AlignHCenter + elide: Label.ElideRight + font.bold: true + } + + DialogsImpl.FolderBreadcrumbBar { + id: breadcrumbBar + width: parent.width + fileDialog: control + + KeyNavigation.tab: fileDialogListView + } + } + } + + contentItem: ListView { + id: fileDialogListView + objectName: "fileDialogListView" + clip: true + focus: true + boundsBehavior: Flickable.StopAtBounds + + ScrollBar.vertical: ScrollBar {} + + model: FolderListModel { + folder: control.currentFolder + nameFilters: control.selectedNameFilter.globs + showDirsFirst: true + } + delegate: DialogsImpl.FileDialogDelegate { + objectName: "fileDialogDelegate" + index + width: ListView.view.width + highlighted: ListView.isCurrentItem + fileDialog: control + fileDetailRowWidth: nameFiltersComboBox.width + + KeyNavigation.backtab: breadcrumbBar + KeyNavigation.tab: nameFiltersComboBox + } + } + + footer: Rectangle { + color: control.palette.light + implicitWidth: rowLayout.implicitWidth + implicitHeight: rowLayout.implicitHeight + + RowLayout { + id: rowLayout + width: parent.width + height: parent.height + spacing: 20 + + ComboBox { + // OK to use IDs here, since users shouldn't be overriding this stuff. + id: nameFiltersComboBox + model: control.nameFilters + + Layout.leftMargin: 20 + Layout.fillWidth: true + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + palette.window: control.palette.light + spacing: 12 + horizontalPadding: 0 + verticalPadding: 20 + + Layout.rightMargin: 20 + } + } + } + + Overlay.modal: Rectangle { + color: Color.transparent(control.palette.shadow, 0.5) + } + + Overlay.modeless: Rectangle { + color: Color.transparent(control.palette.shadow, 0.12) + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialogDelegate.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialogDelegate.qml new file mode 100644 index 0000000000..03250faa7e --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialogDelegate.qml @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl as ControlsImpl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FileDialogDelegate { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding, + implicitIndicatorHeight + topPadding + bottomPadding) + + padding: 12 + spacing: 8 + topPadding: 0 + bottomPadding: 0 + + file: fileUrl + + icon.width: 16 + icon.height: 16 + icon.color: highlighted ? palette.highlightedText : palette.text + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/" + + (fileIsDir ? "folder" : "file") + "-icon-round.png" + + // We don't use index here, but in C++. Since we're using required + // properties, the index context property will not be injected, so we can't + // use its QQmlContext to access it. + required property int index + required property string fileName + required property url fileUrl + required property int fileSize + required property date fileModified + required property bool fileIsDir + + required property int fileDetailRowWidth + + contentItem: FileDialogDelegateLabel { + delegate: control + fileDetailRowTextColor: control.icon.color + fileDetailRowWidth: control.fileDetailRowWidth + } + + background: Rectangle { + implicitWidth: 100 + implicitHeight: 40 + visible: control.down || control.highlighted || control.visualFocus + color: Color.blend(control.down ? control.palette.midlight : control.palette.light, + control.palette.highlight, control.highlighted ? 0.15 : 0.0) + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialogDelegateLabel.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialogDelegateLabel.qml new file mode 100644 index 0000000000..9768cd51f0 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/FileDialogDelegateLabel.qml @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +/* + Most of the elements in here are the same between styles, so we + have a reusable component for it and provide some properties to enable style-specific tweaks. +*/ +Item { + id: root + implicitWidth: column.implicitWidth + implicitHeight: column.implicitHeight + + required property DialogsQuickImpl.FileDialogDelegate delegate + required property int fileDetailRowWidth + + property color fileDetailRowTextColor + + Column { + id: column + y: (parent.height - height) / 2 + + Row { + spacing: root.delegate.spacing + + IconImage { + id: iconImage + source: root.delegate.icon.source + sourceSize: Qt.size(root.delegate.icon.width, root.delegate.icon.height) + width: root.delegate.icon.width + height: root.delegate.icon.height + color: root.delegate.icon.color + y: (parent.height - height) / 2 + } + Label { + text: root.delegate.fileName + color: root.delegate.icon.color + y: (parent.height - height) / 2 + } + } + + Item { + id: fileDetailRow + x: iconImage.width + root.delegate.spacing + width: fileDetailRowWidth - x - root.delegate.leftPadding + implicitHeight: childrenRect.height + + Label { + text: locale.formattedDataSize(root.delegate.fileSize) + font.pixelSize: root.delegate.font.pixelSize * 0.75 + color: root.fileDetailRowTextColor + } + Label { + text: Qt.formatDateTime(root.delegate.fileModified) + font.pixelSize: root.delegate.font.pixelSize * 0.75 + color: root.fileDetailRowTextColor + x: parent.width - width + } + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/FolderBreadcrumbBar.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/FolderBreadcrumbBar.qml new file mode 100644 index 0000000000..f04d58043b --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/FolderBreadcrumbBar.qml @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Dialogs.quickimpl as DialogsQuickImpl + +DialogsQuickImpl.FolderBreadcrumbBar { + id: control + + implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, + implicitContentWidth + (upButton ? upButton.implicitWidth + upButtonSpacing : 0) + + leftPadding + rightPadding) + implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, + implicitContentHeight + topPadding + bottomPadding) + upButtonSpacing: 20 + padding: 1 + + background: Rectangle { + border.color: control.palette.button + } + contentItem: ListView { + id: listView + currentIndex: control.currentIndex + model: control.contentModel + orientation: ListView.Horizontal + snapMode: ListView.SnapToItem + highlightMoveDuration: 0 + interactive: false + clip: true + } + buttonDelegate: Button { + id: buttonDelegateRoot + text: folderName + flat: true + + // The default of 100 is a bit too wide for short directory names. + Binding { + target: buttonDelegateRoot.background + property: "implicitWidth" + value: 40 + } + + required property int index + required property string folderName + } + separatorDelegate: IconImage { + id: iconImage + source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/crumb-separator-icon-round.png" + sourceSize: Qt.size(8, 8) + width: 8 + height: control.contentItem.height + color: control.palette.button + y: (control.height - height) / 2 + } + upButton: ToolButton { + x: control.leftPadding + y: control.topPadding + icon.source: "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/images/up-icon-round.png" + icon.width: 16 + icon.height: 16 + width: height + focusPolicy: Qt.TabFocus + } + textField: TextField { + text: control.fileDialog.selectedFile + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/FontDialog.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/FontDialog.qml new file mode 100644 index 0000000000..e2caea4043 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/FontDialog.qml @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts +import QtQuick.Templates as T + +FontDialogImpl { + id: control + + implicitWidth: Math.max(control.implicitBackgroundWidth + control.leftInset + control.rightInset, + control.contentWidth + control.leftPadding + control.rightPadding, + control.implicitHeaderWidth, + control.implicitFooterWidth) + implicitHeight: Math.max(control.implicitBackgroundHeight + control.topInset + control.bottomInset, + control.contentHeight + control.topPadding + control.bottomPadding + + (control.implicitHeaderHeight > 0 ? control.implicitHeaderHeight + control.spacing : 0) + + (control.implicitFooterHeight > 0 ? control.implicitFooterHeight + control.spacing : 0)) + + leftPadding: 20 + rightPadding: 20 + // Ensure that the background's border is visible. + leftInset: -1 + rightInset: -1 + topInset: -1 + bottomInset: -1 + + spacing: 12 + + standardButtons: T.Dialog.Ok | T.Dialog.Cancel + + FontDialogImpl.buttonBox: buttonBox + FontDialogImpl.familyListView: content.familyListView + FontDialogImpl.styleListView: content.styleListView + FontDialogImpl.sizeListView: content.sizeListView + FontDialogImpl.sampleEdit: content.sampleEdit + FontDialogImpl.writingSystemComboBox: writingSystemComboBox + FontDialogImpl.underlineCheckBox: content.underline + FontDialogImpl.strikeoutCheckBox: content.strikeout + FontDialogImpl.familyEdit: content.familyEdit + FontDialogImpl.styleEdit: content.styleEdit + FontDialogImpl.sizeEdit: content.sizeEdit + + background: Rectangle { + implicitWidth: 600 + implicitHeight: 400 + color: control.palette.window + border.color: control.palette.dark + } + + Overlay.modal: Rectangle { + color: Color.transparent(control.palette.shadow, 0.5) + } + + Overlay.modeless: Rectangle { + color: Color.transparent(control.palette.shadow, 0.12) + } + + header: Pane { + palette.window: control.palette.light + padding: 20 + + contentItem: Label { + width: parent.width + text: control.title + visible: control.title.length > 0 + horizontalAlignment: Label.AlignHCenter + elide: Label.ElideRight + font.bold: true + } + } + + contentItem: FontDialogContent { + id: content + } + + footer: Rectangle { + color: control.palette.light + implicitWidth: rowLayout.implicitWidth + implicitHeight: rowLayout.implicitHeight + + RowLayout { + id: rowLayout + width: parent.width + height: parent.height + spacing: 20 + + Label { + text: qsTr("Writing System") + + Layout.leftMargin: 20 + } + ComboBox{ + id: writingSystemComboBox + + Layout.fillWidth: true + } + + DialogButtonBox { + id: buttonBox + standardButtons: control.standardButtons + palette.window: control.palette.light + spacing: 12 + horizontalPadding: 0 + verticalPadding: 20 + + Layout.rightMargin: 20 + } + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qml/FontDialogContent.qml b/src/quickdialogs2/quickdialogs2quickimpl/qml/FontDialogContent.qml new file mode 100644 index 0000000000..a0b7dd3861 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qml/FontDialogContent.qml @@ -0,0 +1,267 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +import QtQuick +import QtQuick.Controls +import QtQuick.Controls.impl +import QtQuick.Dialogs +import QtQuick.Dialogs.quickimpl +import QtQuick.Layouts + +GridLayout { + property alias familyListView: fontFamilyListView + property alias styleListView: fontStyleListView + property alias sizeListView: fontSizeListView + property alias sampleEdit: fontSample + property alias underline: fontUnderline + property alias strikeout: fontStrikeout + property alias familyEdit: fontFamilyEdit + property alias styleEdit: fontStyleEdit + property alias sizeEdit: fontSizeEdit + + columns: 3 + + ColumnLayout { + spacing: 0 + + Layout.preferredWidth: 50 + + Label { + text: qsTr("Family") + Layout.alignment: Qt.AlignLeft + } + TextField { + id: fontFamilyEdit + objectName: "familyEdit" + readOnly: true + Layout.fillWidth: true + focus: true + } + Frame { + Layout.fillWidth: true + Layout.fillHeight: true + background: Rectangle { + color: "white" + } + ListView { + id: fontFamilyListView + objectName: "familyListView" + implicitHeight: 200 + anchors.fill: parent + clip: true + + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AlwaysOn + } + + boundsBehavior: Flickable.StopAtBounds + + highlightMoveVelocity: -1 + highlightMoveDuration: 1 + highlightFollowsCurrentItem: true + keyNavigationEnabled: true + + delegate: ItemDelegate { + width: ListView.view.width + highlighted: ListView.isCurrentItem + onClicked: () => fontFamilyListView.currentIndex = index + text: modelData + } + } + } + } + + ColumnLayout { + spacing: 0 + + Layout.preferredWidth: 30 + + Label { + text: qsTr("Style") + Layout.alignment: Qt.AlignLeft + } + TextField { + id: fontStyleEdit + objectName: "styleEdit" + readOnly: true + Layout.fillWidth: true + } + Frame { + Layout.fillWidth: true + Layout.fillHeight: true + background: Rectangle { + color: "white" + } + ListView { + id: fontStyleListView + objectName: "styleListView" + implicitHeight: 200 + anchors.fill: parent + clip: true + + ScrollBar.vertical: ScrollBar {} + boundsBehavior: Flickable.StopAtBounds + + highlightMoveVelocity: -1 + highlightMoveDuration: 1 + highlightFollowsCurrentItem: true + keyNavigationEnabled: true + + delegate: ItemDelegate { + width: ListView.view.width + highlighted: ListView.isCurrentItem + onClicked: () => fontStyleListView.currentIndex = index + text: modelData + } + } + } + } + + ColumnLayout { + spacing: 0 + + Layout.preferredWidth: 20 + + Label { + text: qsTr("Size") + Layout.alignment: Qt.AlignLeft + } + TextField { + id: fontSizeEdit + objectName: "sizeEdit" + Layout.fillWidth: true + validator: IntValidator { + bottom: 1 + top: 512 + } + } + Frame { + Layout.fillWidth: true + Layout.fillHeight: true + + background: Rectangle { + color: "white" + } + ListView { + id: fontSizeListView + objectName: "sizeListView" + implicitHeight: 200 + anchors.fill: parent + clip: true + + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AlwaysOn + } + + boundsBehavior: Flickable.StopAtBounds + + highlightMoveVelocity: -1 + highlightMoveDuration: 1 + highlightFollowsCurrentItem: true + keyNavigationEnabled: true + + delegate: ItemDelegate { + width: ListView.view.width + highlighted: ListView.isCurrentItem + onClicked: () => fontSizeListView.currentIndex = index + text: modelData + } + } + } + } + + ColumnLayout { + Layout.preferredWidth: 80 + + GroupBox { + id: effectsGroupBox + title: qsTr("Effects") + + Layout.fillWidth: true + Layout.fillHeight: true + + label: Label { + anchors.left: effectsGroupBox.left + text: parent.title + } + + RowLayout { + anchors.fill: parent + CheckBox { + id: fontUnderline + objectName: "underlineEffect" + text: qsTr("Underline") + } + CheckBox{ + id: fontStrikeout + objectName: "strikeoutEffect" + text: qsTr("Strikeout") + } + } + } + } + + GroupBox { + id: sample + padding: label.implicitHeight + title: qsTr("Sample") + + Layout.fillWidth: true + Layout.preferredWidth: 80 + Layout.fillHeight: true + Layout.columnSpan: 2 + clip: true + + background: Rectangle { + y: sample.topPadding - sample.bottomPadding + width: parent.width - sample.leftPadding + sample.rightPadding + height: parent.height - sample.topPadding + sample.bottomPadding + radius: 3 + } + + label: Label { + anchors.left: sample.left + text: sample.title + } + + TextEdit { + id: fontSample + objectName: "sampleEdit" + anchors.centerIn: parent + readOnly: true + } + } +} diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickdialogimplfactory.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickdialogimplfactory.cpp new file mode 100644 index 0000000000..da298432b4 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickdialogimplfactory.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 "qquickdialogimplfactory_p.h" + +#include <QtCore/qloggingcategory.h> + +#include "qquickplatformfiledialog_p.h" +#include "qquickplatformfontdialog_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \internal + + Creates concrete QML-based dialogs. +*/ + +Q_LOGGING_CATEGORY(lcQuickDialogImplFactory, "qt.quick.dialogs.quickdialogimplfactory") + +QPlatformDialogHelper *QQuickDialogImplFactory::createPlatformDialogHelper( + QPlatformTheme::DialogType type, QObject *parent) +{ + switch (type) { + case QPlatformTheme::FileDialog: { + auto dialog = new QQuickPlatformFileDialog(parent); + // If the QML file failed to load, we need to handle it gracefully. + if (!dialog->isValid()) { + delete dialog; + return nullptr; + } + + return dialog; + } + case QPlatformTheme::FontDialog: { + auto dialog = new QQuickPlatformFontDialog(parent); + + if (!dialog->isValid()) { + delete dialog; + return nullptr; + } + return dialog; + } + default: + break; + } + + return nullptr; +} + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickdialogimplfactory_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickdialogimplfactory_p.h new file mode 100644 index 0000000000..54aa921f30 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickdialogimplfactory_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKQMLDIALOGFACTORY_P_H +#define QQUICKQMLDIALOGFACTORY_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobject.h> +#include <QtGui/qpa/qplatformtheme.h> + +#include "qtquickdialogs2quickimplglobal_p.h" + +QT_BEGIN_NAMESPACE + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickDialogImplFactory +{ +public: + static QPlatformDialogHelper *createPlatformDialogHelper(QPlatformTheme::DialogType type, + QObject *parent); +}; + +QT_END_NAMESPACE + +#endif // QQUICKQMLDIALOGFACTORY_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogdelegate.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogdelegate.cpp new file mode 100644 index 0000000000..b1d4477305 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogdelegate.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** 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 "qquickfiledialogdelegate_p.h" + +#include <QtCore/qfileinfo.h> +#include <QtGui/qpa/qplatformtheme.h> +#include <QtQml/QQmlFile> +#include <QtQml/qqmlexpression.h> +#include <QtQuick/private/qquicklistview_p.h> +#include <QtQuickTemplates2/private/qquickitemdelegate_p_p.h> + +#include "qquickfiledialogimpl_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFileDialogDelegatePrivate : public QQuickItemDelegatePrivate +{ + Q_DECLARE_PUBLIC(QQuickFileDialogDelegate) + +public: + void highlightFile(); + void chooseFile(); + + bool acceptKeyClick(Qt::Key key) const override; + + QQuickFileDialogImpl *fileDialog = nullptr; + QUrl file; +}; + +void QQuickFileDialogDelegatePrivate::highlightFile() +{ + Q_Q(QQuickFileDialogDelegate); + QQuickListViewAttached *attached = static_cast<QQuickListViewAttached*>( + qmlAttachedPropertiesObject<QQuickListView>(q)); + if (!attached) + return; + + QQmlContext *delegateContext = qmlContext(q); + if (!delegateContext) + return; + + bool converted = false; + const int index = q->property("index").toInt(&converted); + if (converted) { + attached->view()->setCurrentIndex(index); + fileDialog->setCurrentFile(file); + } +} + +void QQuickFileDialogDelegatePrivate::chooseFile() +{ + const QFileInfo fileInfo(QQmlFile::urlToLocalFileOrQrc(file)); + if (fileInfo.isDir()) { + // If it's a directory, navigate to it. + fileDialog->setCurrentFolder(file); + } else { + // Otherwise it's a file, so select it and close the dialog. + fileDialog->setSelectedFile(file); + fileDialog->accept(); + } +} + +bool QQuickFileDialogDelegatePrivate::acceptKeyClick(Qt::Key key) const +{ + return key == Qt::Key_Return || key == Qt::Key_Enter; +} + +QQuickFileDialogDelegate::QQuickFileDialogDelegate(QQuickItem *parent) + : QQuickItemDelegate(*(new QQuickFileDialogDelegatePrivate), parent) +{ + Q_D(QQuickFileDialogDelegate); + // Clicking and tabbing should result in it getting focus, + // as e.g. Ubuntu and Windows both allow tabbing through file dialogs. + setFocusPolicy(Qt::StrongFocus); + setCheckable(true); + QObjectPrivate::connect(this, &QQuickFileDialogDelegate::clicked, + d, &QQuickFileDialogDelegatePrivate::highlightFile); + QObjectPrivate::connect(this, &QQuickFileDialogDelegate::doubleClicked, + d, &QQuickFileDialogDelegatePrivate::chooseFile); +} + +QQuickFileDialogImpl *QQuickFileDialogDelegate::fileDialog() const +{ + Q_D(const QQuickFileDialogDelegate); + return d->fileDialog; +} + +void QQuickFileDialogDelegate::setFileDialog(QQuickFileDialogImpl *fileDialog) +{ + Q_D(QQuickFileDialogDelegate); + if (fileDialog == d->fileDialog) + return; + + d->fileDialog = fileDialog; + emit fileDialogChanged(); +} + +QUrl QQuickFileDialogDelegate::file() const +{ + Q_D(const QQuickFileDialogDelegate); + return d->file; +} + +void QQuickFileDialogDelegate::setFile(const QUrl &file) +{ + Q_D(QQuickFileDialogDelegate); + if (file == d->file) + return; + + d->file = file; + emit fileChanged(); +} + +void QQuickFileDialogDelegate::keyReleaseEvent(QKeyEvent *event) +{ + Q_D(QQuickFileDialogDelegate); + // We need to respond to being triggered by enter being pressed, + // but we can't use event->isAccepted() to check, because events are pre-accepted. + auto connection = QObjectPrivate::connect(this, &QQuickFileDialogDelegate::clicked, + d, &QQuickFileDialogDelegatePrivate::chooseFile); + + QQuickItemDelegate::keyReleaseEvent(event); + + disconnect(connection); +} + +QT_END_NAMESPACE + +#include "moc_qquickfiledialogdelegate_p.cpp" diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogdelegate_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogdelegate_p.h new file mode 100644 index 0000000000..093e27bdbd --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogdelegate_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFILEDIALOGDELEGATE_P_H +#define QQUICKFILEDIALOGDELEGATE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuickTemplates2/private/qquickitemdelegate_p.h> + +#include "qtquickdialogs2quickimplglobal_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFileDialogImpl; +class QQuickFileDialogDelegatePrivate; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogDelegate : public QQuickItemDelegate +{ + Q_OBJECT + Q_PROPERTY(QQuickFileDialogImpl *fileDialog READ fileDialog WRITE setFileDialog NOTIFY fileDialogChanged) + Q_PROPERTY(QUrl file READ file WRITE setFile NOTIFY fileChanged) + QML_NAMED_ELEMENT(FileDialogDelegate) + QML_ADDED_IN_VERSION(6, 2) + +public: + explicit QQuickFileDialogDelegate(QQuickItem *parent = nullptr); + + QQuickFileDialogImpl *fileDialog() const; + void setFileDialog(QQuickFileDialogImpl *fileDialog); + + QUrl file() const; + void setFile(const QUrl &file); + +Q_SIGNALS: + void fileDialogChanged(); + void fileChanged(); + +protected: + void keyReleaseEvent(QKeyEvent *event) override; + +private: + Q_DISABLE_COPY(QQuickFileDialogDelegate) + Q_DECLARE_PRIVATE(QQuickFileDialogDelegate) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickFileDialogDelegate) + +#endif // QQUICKFILEDIALOGDELEGATE_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp new file mode 100644 index 0000000000..8074b2594e --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl.cpp @@ -0,0 +1,564 @@ +/**************************************************************************** +** +** 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 diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl_p.h new file mode 100644 index 0000000000..23f8cf14a4 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl_p.h @@ -0,0 +1,168 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFILEDIALOGIMPL_P_H +#define QQUICKFILEDIALOGIMPL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuick/private/qquicklistview_p.h> +#include <QtQuickTemplates2/private/qquickdialog_p.h> + +#include "qtquickdialogs2quickimplglobal_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickComboBox; +class QQuickDialogButtonBox; + +class QQuickFileDialogImplAttached; +class QQuickFileDialogImplAttachedPrivate; +class QQuickFileDialogImplPrivate; +class QQuickFileNameFilter; +class QQuickFolderBreadcrumbBar; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImpl : public QQuickDialog +{ + Q_OBJECT + Q_PROPERTY(QUrl currentFolder READ currentFolder WRITE setCurrentFolder NOTIFY currentFolderChanged FINAL) + Q_PROPERTY(QUrl selectedFile READ selectedFile WRITE setSelectedFile NOTIFY selectedFileChanged FINAL) + Q_PROPERTY(QUrl currentFile READ currentFile WRITE setCurrentFile NOTIFY currentFileChanged FINAL) + Q_PROPERTY(QStringList nameFilters READ nameFilters NOTIFY nameFiltersChanged FINAL) + Q_PROPERTY(QQuickFileNameFilter *selectedNameFilter READ selectedNameFilter CONSTANT) + QML_NAMED_ELEMENT(FileDialogImpl) + QML_ATTACHED(QQuickFileDialogImplAttached) + QML_ADDED_IN_VERSION(6, 2) + Q_MOC_INCLUDE(<QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h>) + Q_MOC_INCLUDE(<QtQuickDialogs2QuickImpl/private/qquickfolderbreadcrumbbar_p.h>) + +public: + explicit QQuickFileDialogImpl(QObject *parent = nullptr); + + static QQuickFileDialogImplAttached *qmlAttachedProperties(QObject *object); + + QUrl currentFolder() const; + void setCurrentFolder(const QUrl ¤tFolder); + + QUrl selectedFile() const; + void setSelectedFile(const QUrl &file); + + QUrl currentFile() const; + void setCurrentFile(const QUrl ¤tFile); + + QSharedPointer<QFileDialogOptions> options() const; + void setOptions(const QSharedPointer<QFileDialogOptions> &options); + + QStringList nameFilters() const; + void resetNameFilters(); + + QQuickFileNameFilter *selectedNameFilter() const; + + void setAcceptLabel(const QString &label); + void setRejectLabel(const QString &label); + +public Q_SLOTS: + void selectNameFilter(const QString &filter); + +Q_SIGNALS: + void currentFolderChanged(const QUrl &folderUrl); + void selectedFileChanged(); + void currentFileChanged(const QUrl ¤tFileUrl); + void nameFiltersChanged(); + void fileSelected(const QUrl &fileUrl); + void filterSelected(const QString &filter); + +private: + void componentComplete() override; + void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) override; + + Q_DISABLE_COPY(QQuickFileDialogImpl) + Q_DECLARE_PRIVATE(QQuickFileDialogImpl) +}; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFileDialogImplAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickDialogButtonBox *buttonBox READ buttonBox WRITE setButtonBox NOTIFY buttonBoxChanged FINAL) + Q_PROPERTY(QQuickComboBox *nameFiltersComboBox READ nameFiltersComboBox WRITE setNameFiltersComboBox NOTIFY nameFiltersComboBoxChanged) + Q_PROPERTY(QQuickListView *fileDialogListView READ fileDialogListView WRITE setFileDialogListView NOTIFY fileDialogListViewChanged) + Q_PROPERTY(QQuickFolderBreadcrumbBar *breadcrumbBar READ breadcrumbBar WRITE setBreadcrumbBar NOTIFY breadcrumbBarChanged) + Q_MOC_INCLUDE(<QtQuickTemplates2/private/qquickdialogbuttonbox_p.h>) + Q_MOC_INCLUDE(<QtQuickTemplates2/private/qquickcombobox_p.h>) + +public: + explicit QQuickFileDialogImplAttached(QObject *parent = nullptr); + + QQuickDialogButtonBox *buttonBox() const; + void setButtonBox(QQuickDialogButtonBox *buttonBox); + + QQuickComboBox *nameFiltersComboBox() const; + void setNameFiltersComboBox(QQuickComboBox *nameFiltersComboBox); + + QString selectedNameFilter() const; + void selectNameFilter(const QString &filter); + + QQuickListView *fileDialogListView() const; + void setFileDialogListView(QQuickListView *fileDialogListView); + + QQuickFolderBreadcrumbBar *breadcrumbBar() const; + void setBreadcrumbBar(QQuickFolderBreadcrumbBar *breadcrumbBar); + +Q_SIGNALS: + void buttonBoxChanged(); + void nameFiltersComboBoxChanged(); + void fileDialogListViewChanged(); + void breadcrumbBarChanged(); + +private: + Q_DISABLE_COPY(QQuickFileDialogImplAttached) + Q_DECLARE_PRIVATE(QQuickFileDialogImplAttached) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickFileDialogImpl) + +#endif // QQUICKFILEDIALOGIMPL_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl_p_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl_p_p.h new file mode 100644 index 0000000000..1831a7dc58 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfiledialogimpl_p_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFILEDIALOG_P_P_H +#define QQUICKFILEDIALOG_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuickTemplates2/private/qquickcombobox_p.h> +#include <QtQuickTemplates2/private/qquickdialog_p_p.h> +#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p.h> + +#include "qquickfiledialogimpl_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFileNameFilter; + +class QQuickFileDialogImplPrivate : public QQuickDialogPrivate +{ + Q_DECLARE_PUBLIC(QQuickFileDialogImpl) + +public: + QQuickFileDialogImplPrivate(); + + static QQuickFileDialogImplPrivate *get(QQuickFileDialogImpl *dialog) + { + return dialog->d_func(); + } + + QQuickFileDialogImplAttached *attachedOrWarn(); + + void setNameFilters(const QStringList &filters); + + void updateEnabled(); + void updateCurrentFile(const QString &oldFolderPath); + + void handleAccept() override; + void handleClick(QQuickAbstractButton *button) override; + + QSharedPointer<QFileDialogOptions> options; + QUrl currentFolder; + QUrl selectedFile; + QUrl currentFile; + QStringList nameFilters; + mutable QQuickFileNameFilter *selectedNameFilter = nullptr; + QString acceptLabel; + QString rejectLabel; +}; + +class QQuickFileDialogImplAttachedPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickFileDialogImplAttached) + + void nameFiltersComboBoxItemActivated(int index); + void fileDialogListViewCurrentIndexChanged(); + +public: + QPointer<QQuickDialogButtonBox> buttonBox; + QPointer<QQuickComboBox> nameFiltersComboBox; + QPointer<QQuickListView> fileDialogListView; + QPointer<QQuickFolderBreadcrumbBar> breadcrumbBar; +}; + +QT_END_NAMESPACE + +#endif // QQUICKFILEDIALOG_P_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar.cpp new file mode 100644 index 0000000000..c204d8fa29 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar.cpp @@ -0,0 +1,784 @@ +/**************************************************************************** +** +** 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 "qquickfolderbreadcrumbbar_p.h" +#include "qquickfolderbreadcrumbbar_p_p.h" + +#include <QtCore/qdir.h> +#include <QtCore/qloggingcategory.h> +#if QT_CONFIG(shortcut) +#include <QtGui/private/qshortcutmap_p.h> +#endif +#include <QtGui/private/qguiapplication_p.h> +#include <QtQml/QQmlFile> +#include <QtQuick/private/qquicktextinput_p.h> +#include <QtQuickTemplates2/private/qquickabstractbutton_p.h> +#include <QtQuickTemplates2/private/qquickpopupitem_p_p.h> +#include <QtQuickTemplates2/private/qquickshortcutcontext_p_p.h> + +#include "qquickfiledialogimpl_p.h" +#include "qquickfiledialogimpl_p_p.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcFolderBreadcrumbBar, "qt.quick.dialogs.folderbreadcrumbbar") +Q_LOGGING_CATEGORY(lcContentSize, "qt.quick.dialogs.folderbreadcrumbbar.contentsize") +Q_LOGGING_CATEGORY(lcDelegates, "qt.quick.dialogs.folderbreadcrumbbar.delegates") +Q_LOGGING_CATEGORY(lcShortcuts, "qt.quick.dialogs.folderbreadcrumbbar.shortcuts") +Q_LOGGING_CATEGORY(lcTextInput, "qt.quick.dialogs.folderbreadcrumbbar.textinput") +Q_LOGGING_CATEGORY(lcCurrentItem, "qt.quick.dialogs.folderbreadcrumbbar.currentitem") + +QQuickItem *QQuickFolderBreadcrumbBarPrivate::createDelegateItem(QQmlComponent *component, const QVariantMap &initialProperties) +{ + Q_Q(QQuickFolderBreadcrumbBar); + // If we don't use the correct context, it won't be possible to refer to + // the control's id from within the delegates. + QQmlContext *creationContext = component->creationContext(); + // The component might not have been created in QML, in which case + // the creation context will be null and we have to create it ourselves. + if (!creationContext) + creationContext = qmlContext(q); + QQmlContext *context = new QQmlContext(creationContext, q); + context->setContextObject(q); + QQuickItem *item = qobject_cast<QQuickItem*>(component->createWithInitialProperties(initialProperties, context)); + if (item) + QQml_setParent_noEvent(item, q); + qCDebug(lcDelegates) << "- created delegate item" << item << "with initialProperties" << initialProperties; + return item; +} + +QString QQuickFolderBreadcrumbBarPrivate::folderBaseName(const QString &folderPath) +{ + if (folderPath == QLatin1String("/")) { + // Unix root. + return folderPath; + } else if (folderPath.endsWith(QLatin1String(":/"))) { + // Windows drive. + return folderPath.mid(0, folderPath.size() - 1); + } + const QString baseName = folderPath.mid(folderPath.lastIndexOf(QLatin1Char('/')) + 1); + return baseName; +} + +/*! + \internal + + Returns \c { "/foo", "/foo/bar", "/foo/bar/baz" } if \a folder is \c "/foo/bar/baz". +*/ +QStringList QQuickFolderBreadcrumbBarPrivate::crumbPathsForFolder(const QUrl &folder) +{ + const QString folderPath = QDir::fromNativeSeparators(QQmlFile::urlToLocalFileOrQrc(folder)); + QDir dir(folderPath); + // In order to collect the paths for each breadcrumb, we need to work backwards, so we prepend. + QStringList paths; + do { + paths.prepend(dir.absolutePath()); + } while (dir.cdUp()); + return paths; +} + +void QQuickFolderBreadcrumbBarPrivate::repopulate() +{ + Q_Q(QQuickFolderBreadcrumbBar); + qCDebug(lcDelegates) << "attemping to repopulate breadcrumb bar using folder..."; + + if (repopulating) + return; + + if (!buttonDelegate || !separatorDelegate || !q->contentItem()) { + qCWarning(lcDelegates) << "Both delegates and contentItem must be set before repopulating"; + return; + } + + QBoolBlocker repopulateGuard(repopulating); + + auto failureCleanup = [=](){ + folderPaths.clear(); + while (q->count() > 0) + q->removeItem(q->itemAt(0)); + }; + + qCDebug(lcDelegates) << "- getting paths for directory" << fileDialog->currentFolder(); + folderPaths = crumbPathsForFolder(fileDialog->currentFolder()); + + while (q->count() > 0) + q->removeItem(q->itemAt(0)); + + for (int i = 0; i < folderPaths.size(); ++i) { + const QString &folderPath = folderPaths.at(i); + + QVariantMap initialProperties = { + { QStringLiteral("index"), QVariant::fromValue(i) }, + { QStringLiteral("folderName"), QVariant::fromValue(folderBaseName(folderPath)) } + }; + QQuickItem *buttonItem = createDelegateItem(buttonDelegate, initialProperties); + if (!buttonItem) { + qCWarning(lcDelegates) << "Failed creating breadcrumb buttonDelegate item:\n" << buttonDelegate->errorString(); + failureCleanup(); + break; + } + if (QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(buttonItem)) { + QObjectPrivate::connect(button, &QQuickAbstractButton::clicked, + this, &QQuickFolderBreadcrumbBarPrivate::crumbClicked); + } + insertItem(q->count(), buttonItem); + + // Don't add a separator for the last button. + if (i < folderPaths.size() - 1) { + initialProperties = {}; + QQuickItem *separatorItem = createDelegateItem(separatorDelegate, initialProperties); + if (!separatorItem) { + qCWarning(lcDelegates) << "Failed creating breadcrumb separatorDelegate item:\n" << buttonDelegate->errorString(); + failureCleanup(); + break; + } + insertItem(q->count(), separatorItem); + } + } + + const int finalCount = q->count(); + // We would do - 2, since separators are included in the count, + // but as we don't add a separator for the last button, we only need to subtract 1. + const int newCurrentIndex = finalCount > 2 ? finalCount - 1 : -1; + qCDebug(lcDelegates) << "- setting currentIndex to" << newCurrentIndex; + q->setCurrentIndex(newCurrentIndex); + + updateImplicitContentSize(); + + qCDebug(lcDelegates) << "... bar now contains" << q->count() + << "buttons and separators in total, for the following paths:" << folderPaths; +} + +void QQuickFolderBreadcrumbBarPrivate::crumbClicked() +{ + Q_Q(QQuickFolderBreadcrumbBar); + qCDebug(lcCurrentItem) << "updateCurrentIndex called by sender" << q->sender(); + QQuickAbstractButton *button = qobject_cast<QQuickAbstractButton*>(q->sender()); + if (button) { + const int buttonIndex = contentModel->indexOf(button, nullptr); + q->setCurrentIndex(buttonIndex); + const QUrl folderUrl = QUrl::fromLocalFile(folderPaths.at(buttonIndex / 2)); + // TODO: don't repopulate the whole model when clicking on crumbs + qCDebug(lcCurrentItem) << "setting file dialog's folder to" << folderUrl; + fileDialog->setCurrentFolder(folderUrl); + } +} + +void QQuickFolderBreadcrumbBarPrivate::folderChanged() +{ + if (componentComplete) + repopulate(); +} + +static inline QString upButtonName() +{ + return QStringLiteral("upButton"); +} + +void QQuickFolderBreadcrumbBarPrivate::cancelUpButton() +{ + Q_Q(QQuickFolderBreadcrumbBar); + quickCancelDeferred(q, upButtonName()); +} + +void QQuickFolderBreadcrumbBarPrivate::executeUpButton(bool complete) +{ + Q_Q(QQuickFolderBreadcrumbBar); + if (upButton.wasExecuted()) + return; + + if (!upButton || complete) + quickBeginDeferred(q, upButtonName(), upButton); + if (complete) + quickCompleteDeferred(q, upButtonName(), upButton); +} + +void QQuickFolderBreadcrumbBarPrivate::goUp() +{ + QDir dir(QQmlFile::urlToLocalFileOrQrc(fileDialog->currentFolder())); + dir.cdUp(); + fileDialog->setCurrentFolder(QUrl::fromLocalFile(dir.absolutePath())); +} + +static inline QString textFieldName() +{ + return QStringLiteral("textField"); +} + +void QQuickFolderBreadcrumbBarPrivate::cancelTextField() +{ + Q_Q(QQuickFolderBreadcrumbBar); + quickCancelDeferred(q, textFieldName()); +} + +void QQuickFolderBreadcrumbBarPrivate::executeTextField(bool complete) +{ + Q_Q(QQuickFolderBreadcrumbBar); + if (textField.wasExecuted()) + return; + + if (!textField || complete) + quickBeginDeferred(q, textFieldName(), textField); + if (complete) + quickCompleteDeferred(q, textFieldName(), textField); +} + +void QQuickFolderBreadcrumbBarPrivate::toggleTextFieldVisibility() +{ + const QUrl url = !fileDialog->selectedFile().isEmpty() ? fileDialog->selectedFile() : fileDialog->currentFolder(); + textField->setText(QQmlFile::urlToLocalFileOrQrc(url)); + textField->setVisible(!textField->isVisible()); + + qCDebug(lcTextInput) << "text field visibility changed to" << textField->isVisible(); + + if (textField->isVisible()) { + // The text field is now visible, so give it focus, + // select the text, and let it handle escape/back. + textField->forceActiveFocus(Qt::ShortcutFocusReason); + textField->selectAll(); + } + + // We connect to the TextField's visibleChanged signal, so textFieldVisibleChanged() + // will get called automatically and we don't need to call it here. + + contentItem->setVisible(!textField->isVisible()); + + // When the TextField is visible, certain items in the dialog need to be disabled. + auto fileDialogPrivate = QQuickFileDialogImplPrivate::get(fileDialog); + fileDialogPrivate->updateEnabled(); +} + +void QQuickFolderBreadcrumbBarPrivate::textFieldAccepted() +{ + const QUrl fileUrl = QUrl::fromLocalFile(textField->text()); + const bool mustExist = fileDialog->options()->acceptMode() != QFileDialogOptions::AcceptSave; + const bool enteredPathIsValidUrl = fileUrl.isValid(); + bool enteredPathExists = false; + bool enteredPathIsDir = false; + if (enteredPathIsValidUrl) { + const QFileInfo fileInfo(textField->text()); + enteredPathExists = fileInfo.exists(); + if (enteredPathExists) + enteredPathIsDir = fileInfo.isDir(); + } + + qCDebug(lcTextInput).nospace() << "text field accepted -" + << " text=" << textField->text() + << " fileUrl=" << fileUrl + << " mustExist=" << mustExist + << " enteredPathIsValidUrl=" << enteredPathIsValidUrl + << " enteredPathExists=" << enteredPathExists + << " enteredPathIsDir=" << enteredPathIsDir; + + if (enteredPathIsDir && (enteredPathExists || !mustExist)) { + qCDebug(lcTextInput) << "path entered is a folder; setting folder"; + fileDialog->setCurrentFolder(fileUrl); + } else if (!enteredPathIsDir && (enteredPathExists || !mustExist)) { + qCDebug(lcTextInput) << "path entered is a file; setting file and calling accept()"; + // It's important that we set the currentFile here, as that's what + // QQuickPlatformFileDialog::selectedFiles() needs to return, and + // QQuickFileDialog::accept() sets its file property based on + // selectedFiles(). + fileDialog->setCurrentFile(fileUrl); + fileDialog->setSelectedFile(fileUrl); + fileDialog->accept(); + } else { + qCDebug(lcTextInput) << "path entered is not valid; not setting file/folder"; + } + + toggleTextFieldVisibility(); +} + +void QQuickFolderBreadcrumbBarPrivate::textFieldVisibleChanged() +{ + qCDebug(lcShortcuts) << "text field was either hidden or shown"; + + if (textField && textField->isVisible()) + handleTextFieldShown(); + else + handleTextFieldHidden(); +} + +void QQuickFolderBreadcrumbBarPrivate::textFieldActiveFocusChanged() +{ + // When the text field loses focus, it should be hidden. + if (!textField->hasActiveFocus() && textField->isVisible()) + toggleTextFieldVisibility(); +} + +/* + When the text field is visible: + + - Ctrl+L should do nothing (matches e.g. Ubuntu and Windows) + - Escape/back should hide it +*/ +void QQuickFolderBreadcrumbBarPrivate::handleTextFieldShown() +{ +#if QT_CONFIG(shortcut) + Q_Q(QQuickFolderBreadcrumbBar); + if (editPathToggleShortcutId == 0) + return; + + QGuiApplicationPrivate *appPrivate = QGuiApplicationPrivate::instance(); + qCDebug(lcShortcuts) << "text field was shown; grabbing/ungrabbing relevant shortcuts..."; + + // Disable the back/escape shortcuts for QQuickPopup so that the TextField can get them. + auto popupItem = qobject_cast<QQuickPopupItem*>(fileDialog->popupItem()); + popupItem->ungrabShortcut(); + + appPrivate->shortcutMap.removeShortcut(editPathToggleShortcutId, q); + editPathToggleShortcutId = 0; + + editPathBackShortcutId = appPrivate->shortcutMap.addShortcut( + q, Qt::Key_Back, Qt::WindowShortcut, QQuickShortcutContext::matcher); + editPathEscapeShortcutId = appPrivate->shortcutMap.addShortcut( + q, Qt::Key_Escape, Qt::WindowShortcut, QQuickShortcutContext::matcher); + + qCDebug(lcShortcuts).nospace() << "... shortcut IDs:" + << " editPathToggleShortcutId=" << editPathToggleShortcutId + << " editPathBackShortcutId=" << editPathBackShortcutId + << " editPathEscapeShortcutId=" << editPathEscapeShortcutId; +#endif +} + +/* + When the text field is not visible: + + - Ctrl+L should make it visible + - Escape/back should close the dialog +*/ +void QQuickFolderBreadcrumbBarPrivate::handleTextFieldHidden() +{ +#if QT_CONFIG(shortcut) + Q_Q(QQuickFolderBreadcrumbBar); + + QGuiApplicationPrivate *appPrivate = QGuiApplicationPrivate::instance(); + qCDebug(lcShortcuts) << "text field was hidden; grabbing/ungrabbing relevant shortcuts..."; + + if (editPathToggleShortcutId == 0) { + editPathToggleShortcutId = appPrivate->shortcutMap.addShortcut( + q, Qt::CTRL | Qt::Key_L, Qt::WindowShortcut, QQuickShortcutContext::matcher); + } + + // When the bar is first completed, this function is called, since the text field starts off hidden. + // If removeShortcut is called with a zero id, all shortcuts for the given object will be removed, + // and we don't want that. + if (editPathBackShortcutId != 0) { + appPrivate->shortcutMap.removeShortcut(editPathBackShortcutId, q); + editPathBackShortcutId = 0; + } + if (editPathEscapeShortcutId != 0) { + appPrivate->shortcutMap.removeShortcut(editPathEscapeShortcutId, q); + editPathEscapeShortcutId = 0; + } + + // Re-enable the back/escape shortcuts for QQuickPopup now that TextField no longer needs them. + auto popupItem = qobject_cast<QQuickPopupItem*>(fileDialog->popupItem()); + if (popupItem) + popupItem->grabShortcut(); + + qCDebug(lcShortcuts).nospace() << "... shortcut IDs: " + << " editPathToggleShortcutId=" << editPathToggleShortcutId + << " editPathBackShortcutId=" << editPathBackShortcutId + << " editPathEscapeShortcutId=" << editPathEscapeShortcutId; +#endif +} + +void QQuickFolderBreadcrumbBarPrivate::ungrabEditPathShortcuts() +{ +#if QT_CONFIG(shortcut) + Q_Q(QQuickFolderBreadcrumbBar); + QGuiApplicationPrivate *appPrivate = QGuiApplicationPrivate::instance(); + qCDebug(lcShortcuts) << "ungrabbing all edit path shortcuts"; + + if (editPathToggleShortcutId != 0) { + appPrivate->shortcutMap.removeShortcut(editPathToggleShortcutId, q); + editPathToggleShortcutId = 0; + } + if (editPathBackShortcutId != 0) { + appPrivate->shortcutMap.removeShortcut(editPathBackShortcutId, q); + editPathBackShortcutId = 0; + } + if (editPathEscapeShortcutId != 0) { + appPrivate->shortcutMap.removeShortcut(editPathEscapeShortcutId, q); + editPathEscapeShortcutId = 0; + } +#endif +} + +qreal QQuickFolderBreadcrumbBarPrivate::getContentWidth() const +{ + Q_Q(const QQuickFolderBreadcrumbBar); + const int count = contentModel->count(); + qreal totalWidth = qMax(0, count - 1) * spacing; + for (int i = 0; i < count; ++i) { + QQuickItem *item = q->itemAt(i); + if (item) { + QQuickItemPrivate *p = QQuickItemPrivate::get(item); + if (!p->widthValid()) + totalWidth += item->implicitWidth(); + else + totalWidth += item->width(); + } + } + qCDebug(lcContentSize) << "content width:" << totalWidth; + return totalWidth; +} + +qreal QQuickFolderBreadcrumbBarPrivate::getContentHeight() const +{ + Q_Q(const QQuickFolderBreadcrumbBar); + const int count = contentModel->count(); + qreal maxHeight = 0; + for (int i = 0; i < count; ++i) { + QQuickItem *item = q->itemAt(i); + if (item) + maxHeight = qMax(maxHeight, item->implicitHeight()); + } + qCDebug(lcContentSize) << "content height:" << maxHeight; + return maxHeight; +} + +void QQuickFolderBreadcrumbBarPrivate::resizeContent() +{ + Q_Q(QQuickFolderBreadcrumbBar); + if (contentItem) { + const int upButtonSpace = q->upButton() ? q->upButton()->width() + upButtonSpacing : 0; + contentItem->setPosition(QPointF(q->leftPadding() + upButtonSpace, q->topPadding())); + contentItem->setSize(QSizeF(q->availableWidth() - upButtonSpace, q->availableHeight())); + + if (textField) { + textField->setPosition(contentItem->position()); + textField->setSize(contentItem->size()); + } + } +} + +void QQuickFolderBreadcrumbBarPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) +{ + QQuickContainerPrivate::itemGeometryChanged(item, change, diff); + if (change.sizeChange()) + updateImplicitContentSize(); +} + +void QQuickFolderBreadcrumbBarPrivate::itemImplicitWidthChanged(QQuickItem *item) +{ + QQuickContainerPrivate::itemImplicitWidthChanged(item); + if (item != contentItem) + updateImplicitContentWidth(); +} + +void QQuickFolderBreadcrumbBarPrivate::itemImplicitHeightChanged(QQuickItem *item) +{ + QQuickContainerPrivate::itemImplicitHeightChanged(item); + if (item != contentItem) + updateImplicitContentHeight(); +} + +/*! + \internal + + Private class for breadcrumb navigation of a directory. + + Given a FileDialog, FolderBreadCrumbbar creates breadcrumb buttons and + separators from the specified delegate components. +*/ + +QQuickFolderBreadcrumbBar::QQuickFolderBreadcrumbBar(QQuickItem *parent) + : QQuickContainer(*(new QQuickFolderBreadcrumbBarPrivate), parent) +{ + Q_D(QQuickFolderBreadcrumbBar); + d->changeTypes |= QQuickItemPrivate::Geometry | QQuickItemPrivate::ImplicitWidth | QQuickItemPrivate::ImplicitHeight; +} + +QQuickFileDialogImpl *QQuickFolderBreadcrumbBar::fileDialog() const +{ + Q_D(const QQuickFolderBreadcrumbBar); + return d->fileDialog; +} + +void QQuickFolderBreadcrumbBar::setFileDialog(QQuickFileDialogImpl *fileDialog) +{ + Q_D(QQuickFolderBreadcrumbBar); + if (fileDialog == d->fileDialog) + return; + + if (d->fileDialog) + QObjectPrivate::disconnect(d->fileDialog, &QQuickFileDialogImpl::currentFolderChanged, + d, &QQuickFolderBreadcrumbBarPrivate::folderChanged); + + d->fileDialog = fileDialog; + + if (d->fileDialog) + QObjectPrivate::connect(d->fileDialog, &QQuickFileDialogImpl::currentFolderChanged, + d, &QQuickFolderBreadcrumbBarPrivate::folderChanged); + + emit fileDialogChanged(); +} + +QQmlComponent *QQuickFolderBreadcrumbBar::buttonDelegate() +{ + Q_D(QQuickFolderBreadcrumbBar); + return d->buttonDelegate; +} + +void QQuickFolderBreadcrumbBar::setButtonDelegate(QQmlComponent *delegate) +{ + Q_D(QQuickFolderBreadcrumbBar); + qCDebug(lcFolderBreadcrumbBar) << "setButtonDelegate called with" << delegate; + if (d->componentComplete) { + // Simplify the code by disallowing this. + qCWarning(lcFolderBreadcrumbBar) << "BreadcrumbBar does not support setting delegates after component completion"; + return; + } + + if (delegate == d->buttonDelegate) + return; + + d->buttonDelegate = delegate; + emit buttonDelegateChanged(); +} + +QQmlComponent *QQuickFolderBreadcrumbBar::separatorDelegate() +{ + Q_D(QQuickFolderBreadcrumbBar); + return d->separatorDelegate; +} + +void QQuickFolderBreadcrumbBar::setSeparatorDelegate(QQmlComponent *delegate) +{ + Q_D(QQuickFolderBreadcrumbBar); + qCDebug(lcFolderBreadcrumbBar) << "setSeparatorDelegate called with" << delegate; + if (d->componentComplete) { + qCWarning(lcFolderBreadcrumbBar) << "BreadcrumbBar does not support setting delegates after component completion"; + return; + } + + if (delegate == d->separatorDelegate) + return; + + d->separatorDelegate = delegate; + emit separatorDelegateChanged(); +} + +QQuickAbstractButton *QQuickFolderBreadcrumbBar::upButton() +{ + Q_D(QQuickFolderBreadcrumbBar); + if (!d->upButton) + d->executeUpButton(); + return d->upButton; +} + +void QQuickFolderBreadcrumbBar::setUpButton(QQuickAbstractButton *upButton) +{ + Q_D(QQuickFolderBreadcrumbBar); + if (upButton == d->upButton) + return; + + if (!d->upButton.isExecuting()) + d->cancelUpButton(); + + if (d->upButton) { + QObjectPrivate::disconnect(d->upButton.data(), &QQuickAbstractButton::clicked, + d, &QQuickFolderBreadcrumbBarPrivate::goUp); + } + + QQuickControlPrivate::hideOldItem(d->upButton); + d->upButton = upButton; + if (d->upButton) { + if (!d->upButton->parentItem()) + d->upButton->setParentItem(this); + + QObjectPrivate::connect(d->upButton.data(), &QQuickAbstractButton::clicked, + d, &QQuickFolderBreadcrumbBarPrivate::goUp); + } + if (!d->upButton.isExecuting()) + emit upButtonChanged(); +} + +int QQuickFolderBreadcrumbBar::upButtonSpacing() const +{ + Q_D(const QQuickFolderBreadcrumbBar); + return d->upButtonSpacing; +} + +void QQuickFolderBreadcrumbBar::setUpButtonSpacing(int upButtonSpacing) +{ + Q_D(QQuickFolderBreadcrumbBar); + if (upButtonSpacing == d->upButtonSpacing) + return; + + d->upButtonSpacing = upButtonSpacing; + emit upButtonSpacingChanged(); +} + +QQuickTextField *QQuickFolderBreadcrumbBar::textField() +{ + Q_D(QQuickFolderBreadcrumbBar); + return d->textField; +} + +void QQuickFolderBreadcrumbBar::setTextField(QQuickTextField *textField) +{ + Q_D(QQuickFolderBreadcrumbBar); + if (textField == d->textField) + return; + + if (!d->textField.isExecuting()) + d->cancelUpButton(); + + if (d->textField) + d->handleTextFieldHidden(); + + if (d->textField) { + QObjectPrivate::disconnect(d->textField.data(), &QQuickTextInput::visibleChanged, + d, &QQuickFolderBreadcrumbBarPrivate::textFieldVisibleChanged); + QObjectPrivate::disconnect(d->textField.data(), &QQuickTextInput::activeFocusChanged, + d, &QQuickFolderBreadcrumbBarPrivate::textFieldActiveFocusChanged); + QObjectPrivate::disconnect(d->textField.data(), &QQuickTextInput::accepted, + d, &QQuickFolderBreadcrumbBarPrivate::textFieldAccepted); + } + + QQuickControlPrivate::hideOldItem(d->textField); + d->textField = textField; + if (d->textField) { + if (!d->textField->parentItem()) + d->textField->setParentItem(this); + + d->textField->setVisible(false); + + QObjectPrivate::connect(d->textField.data(), &QQuickTextInput::visibleChanged, + d, &QQuickFolderBreadcrumbBarPrivate::textFieldVisibleChanged); + QObjectPrivate::connect(d->textField.data(), &QQuickTextInput::activeFocusChanged, + d, &QQuickFolderBreadcrumbBarPrivate::textFieldActiveFocusChanged); + QObjectPrivate::connect(d->textField.data(), &QQuickTextInput::accepted, + d, &QQuickFolderBreadcrumbBarPrivate::textFieldAccepted); + } + if (!d->textField.isExecuting()) + emit textFieldChanged(); +} + +bool QQuickFolderBreadcrumbBar::event(QEvent *event) +{ +#if QT_CONFIG(shortcut) + Q_D(QQuickFolderBreadcrumbBar); + if (event->type() == QEvent::Shortcut) { + QShortcutEvent *shortcutEvent = static_cast<QShortcutEvent *>(event); + if (shortcutEvent->shortcutId() == d->editPathToggleShortcutId + || shortcutEvent->shortcutId() == d->editPathBackShortcutId + || shortcutEvent->shortcutId() == d->editPathEscapeShortcutId) { + d->toggleTextFieldVisibility(); + return true; + } else if (shortcutEvent->shortcutId() == d->goUpShortcutId) { + d->goUp(); + } + } +#endif + return QQuickItem::event(event); +} + +void QQuickFolderBreadcrumbBar::componentComplete() +{ + Q_D(QQuickFolderBreadcrumbBar); + qCDebug(lcFolderBreadcrumbBar) << "componentComplete"; + QQuickContainer::componentComplete(); + d->repopulate(); + + if (d->textField) { + // Force it to be updated as setTextField() is too early to do it. + d->textFieldVisibleChanged(); + } +} + +void QQuickFolderBreadcrumbBar::itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &data) +{ + Q_D(QQuickFolderBreadcrumbBar); + QQuickContainer::itemChange(change, data); + + if (change == QQuickItem::ItemVisibleHasChanged && isComponentComplete()) { + if (data.boolValue && d->fileDialog->isVisible()) { + // It's visible. + d->handleTextFieldHidden(); + + d->goUpShortcutId = QGuiApplicationPrivate::instance()->shortcutMap.addShortcut( + this, QKeySequence(Qt::ALT | Qt::Key_Up), Qt::WindowShortcut, QQuickShortcutContext::matcher); + } else { + // It's hidden. + // Hide the text field so that when the dialog gets opened again, it's not still visible. + if (d->textField) + d->textField->setVisible(false); + + // Make the ListView visible again. + if (d->contentItem) + d->contentItem->setVisible(true); + + // We also need to ungrab all shortcuts when we're not visible. + d->ungrabEditPathShortcuts(); + + if (d->goUpShortcutId != 0) { + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->goUpShortcutId, this); + d->goUpShortcutId = 0; + } + } + } +} + +bool QQuickFolderBreadcrumbBar::isContent(QQuickItem *item) const +{ + if (!qmlContext(item)) + return false; + + if (QQuickItemPrivate::get(item)->isTransparentForPositioner()) + return false; + + return true; +} + +QFont QQuickFolderBreadcrumbBar::defaultFont() const +{ + // TODO + return QQuickTheme::font(QQuickTheme::TabBar); +} + +#if QT_CONFIG(accessibility) +QAccessible::Role QQuickFolderBreadcrumbBar::accessibleRole() const +{ + // TODO + return QAccessible::PageTabList; +} +#endif + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar_p.h new file mode 100644 index 0000000000..5e14f5b04f --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFOLDERBREADCRUMBBAR_P_H +#define QQUICKFOLDERBREADCRUMBBAR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQml/qqmlcomponent.h> +#include <QtQuickTemplates2/private/qquickcontainer_p.h> +#include <QtQuickTemplates2/private/qquicktextfield_p.h> + +#include "qquickfiledialogimpl_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFolderBreadcrumbBarPrivate; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFolderBreadcrumbBar : public QQuickContainer +{ + Q_OBJECT + Q_PROPERTY(QQuickFileDialogImpl *fileDialog READ fileDialog WRITE setFileDialog NOTIFY fileDialogChanged) + Q_PROPERTY(QQmlComponent *buttonDelegate READ buttonDelegate WRITE setButtonDelegate NOTIFY buttonDelegateChanged) + Q_PROPERTY(QQmlComponent *separatorDelegate READ separatorDelegate WRITE setSeparatorDelegate NOTIFY separatorDelegateChanged) + Q_PROPERTY(QQuickAbstractButton *upButton READ upButton WRITE setUpButton NOTIFY upButtonChanged) + Q_PROPERTY(QQuickTextField *textField READ textField WRITE setTextField NOTIFY textFieldChanged) + Q_PROPERTY(int upButtonSpacing READ upButtonSpacing WRITE setUpButtonSpacing NOTIFY upButtonSpacingChanged) + QML_NAMED_ELEMENT(FolderBreadcrumbBar) + QML_ADDED_IN_VERSION(6, 2) + +public: + explicit QQuickFolderBreadcrumbBar(QQuickItem *parent = nullptr); + + QQuickFileDialogImpl *fileDialog() const; + void setFileDialog(QQuickFileDialogImpl *fileDialog); + + QQmlComponent *buttonDelegate(); + void setButtonDelegate(QQmlComponent *delegate); + + QQmlComponent *separatorDelegate(); + void setSeparatorDelegate(QQmlComponent *delegate); + + QQuickAbstractButton *upButton(); + void setUpButton(QQuickAbstractButton *upButton); + + int upButtonSpacing() const; + void setUpButtonSpacing(int upButtonSpacing); + + QQuickTextField *textField(); + void setTextField(QQuickTextField *textField); + +Q_SIGNALS: + void fileDialogChanged(); + void buttonDelegateChanged(); + void separatorDelegateChanged(); + void upButtonChanged(); + void upButtonSpacingChanged(); + void textFieldChanged(); + +protected: + bool event(QEvent *event) override; + + void componentComplete() override; + + void itemChange(ItemChange change, const ItemChangeData &data) override; + + bool isContent(QQuickItem *item) const override; + + QFont defaultFont() const override; + +#if QT_CONFIG(accessibility) + QAccessible::Role accessibleRole() const override; +#endif + +private: + Q_DISABLE_COPY(QQuickFolderBreadcrumbBar) + Q_DECLARE_PRIVATE(QQuickFolderBreadcrumbBar) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickFolderBreadcrumbBar) + +#endif // QQUICKFOLDERBREADCRUMBBAR_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar_p_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar_p_p.h new file mode 100644 index 0000000000..4616b6a9c5 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfolderbreadcrumbbar_p_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFOLDERBREADCRUMBBAR_P_P_H +#define QQUICKFOLDERBREADCRUMBBAR_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuickTemplates2/private/qquickcontainer_p_p.h> +#include <QtQuickTemplates2/private/qquickdeferredexecute_p_p.h> + +#include "qquickfiledialogimpl_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickAbstractButton; +class QQuickTextField; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFolderBreadcrumbBarPrivate : public QQuickContainerPrivate +{ + Q_DECLARE_PUBLIC(QQuickFolderBreadcrumbBar) + +public: + QQuickItem *createDelegateItem(QQmlComponent *component, const QVariantMap &initialProperties); + static QString folderBaseName(const QString &folderPath); + static QStringList crumbPathsForFolder(const QUrl &folder); + void repopulate(); + void crumbClicked(); + void folderChanged(); + + void cancelUpButton(); + void executeUpButton(bool complete = false); + void goUp(); + + void cancelTextField(); + void executeTextField(bool complete = false); + void toggleTextFieldVisibility(); + void textFieldAccepted(); + + void textFieldVisibleChanged(); + void textFieldActiveFocusChanged(); + void handleTextFieldShown(); + void handleTextFieldHidden(); + void ungrabEditPathShortcuts(); + + qreal getContentWidth() const override; + qreal getContentHeight() const override; + void resizeContent() override; + + void itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) override; + void itemImplicitWidthChanged(QQuickItem *item) override; + void itemImplicitHeightChanged(QQuickItem *item) override; + +private: + QQuickFileDialogImpl *fileDialog = nullptr; + QList<QString> folderPaths; + QQmlComponent *buttonDelegate = nullptr; + QQmlComponent *separatorDelegate = nullptr; + QQuickDeferredPointer<QQuickAbstractButton> upButton; + QQuickDeferredPointer<QQuickTextField> textField; + int editPathToggleShortcutId = 0; + int editPathBackShortcutId = 0; + int editPathEscapeShortcutId = 0; + int goUpShortcutId = 0; + int upButtonSpacing = 0; + bool repopulating = false; +}; + +QT_END_NAMESPACE + +#endif // QQUICKFOLDERBREADCRUMBBAR_P_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl.cpp new file mode 100644 index 0000000000..3263b73ba9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl.cpp @@ -0,0 +1,836 @@ +/**************************************************************************** +** +** 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 "qquickfontdialogimpl_p.h" +#include "qquickfontdialogimpl_p_p.h" + +#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p_p.h> +#include <private/qfontdatabase_p.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcAttachedProperty, "qt.quick.dialogs.quickfontdialogimpl.attachedOrWarn") + +QQuickFontDialogImplPrivate::QQuickFontDialogImplPrivate() +{ +} + +QQuickFontDialogImplAttached *QQuickFontDialogImplPrivate::attachedOrWarn() +{ + Q_Q(QQuickFontDialogImpl); + QQuickFontDialogImplAttached *attached = static_cast<QQuickFontDialogImplAttached *>( + qmlAttachedPropertiesObject<QQuickFontDialogImpl>(q)); + if (!attached) { + qCWarning(lcAttachedProperty) + << "Expected FontDialogImpl attached object to be present on" << this; + } + return attached; +} + +void QQuickFontDialogImplPrivate::handleAccept() { } + +void QQuickFontDialogImplPrivate::handleClick(QQuickAbstractButton *button) +{ + Q_Q(QQuickFontDialogImpl); + if (buttonRole(button) == QPlatformDialogHelper::AcceptRole) { + q->accept(); + QQuickDialogPrivate::handleClick(button); + } +} + +QQuickFontDialogImpl::QQuickFontDialogImpl(QObject *parent) + : QQuickDialog(*(new QQuickFontDialogImplPrivate), parent) +{ +} + +QQuickFontDialogImplAttached *QQuickFontDialogImpl::qmlAttachedProperties(QObject *object) +{ + return new QQuickFontDialogImplAttached(object); +} + +QSharedPointer<QFontDialogOptions> QQuickFontDialogImpl::options() const +{ + Q_D(const QQuickFontDialogImpl); + + return d->options; +} + +void QQuickFontDialogImpl::setOptions(const QSharedPointer<QFontDialogOptions> &options) +{ + Q_D(QQuickFontDialogImpl); + + if (options == d->options) + return; + + d->options = options; + + emit optionsChanged(); +} + +QFont QQuickFontDialogImpl::currentFont() const +{ + Q_D(const QQuickFontDialogImpl); + return d->currentFont; +} + +void QQuickFontDialogImpl::setCurrentFont(const QFont &font) +{ + Q_D(QQuickFontDialogImpl); + + if (font == d->currentFont) + return; + + d->currentFont = font; + + emit currentFontChanged(font); +} + +void QQuickFontDialogImpl::updateListViews() +{ + Q_D(QQuickFontDialogImpl); + QQuickFontDialogImplAttached *attached = d->attachedOrWarn(); + if (!attached) + return; + + attached->updateFamilies(); + + attached->buttonBox()->setVisible(!(options()->options() & QFontDialogOptions::NoButtons)); +} + +void QQuickFontDialogImpl::keyReleaseEvent(QKeyEvent *event) +{ + Q_D(QQuickFontDialogImpl); + + QQuickDialog::keyReleaseEvent(event); + + QQuickFontDialogImplAttached *attached = d->attachedOrWarn(); + if (!attached) + return; + + // The family and style text edits are read-only so that they + // can show the current selection but also allow key input to "search". + // This is why we handle just the release event, and don't accept it. + if (window()->activeFocusItem() == attached->familyEdit()) + attached->searchFamily(event->text()); + else if (window()->activeFocusItem() == attached->styleEdit()) + attached->searchStyle(event->text()); +} + +void QQuickFontDialogImpl::focusOutEvent(QFocusEvent *event) +{ + Q_D(QQuickFontDialogImpl); + + QQuickDialog::focusOutEvent(event); + + QQuickFontDialogImplAttached *attached = d->attachedOrWarn(); + if (!attached) + return; + + attached->clearSearch(); +} + +QQuickFontDialogImplAttached::QQuickFontDialogImplAttached(QObject *parent) + : QObject(*(new QQuickFontDialogImplAttachedPrivate), parent), + m_writingSystem(QFontDatabase::Any), + m_selectedSize(-1), + m_smoothlyScalable(false), + m_isUpdatingStyles(false) +{ + if (!qobject_cast<QQuickFontDialogImpl *>(parent)) { + qmlWarning(this) << "FontDialogImpl attached properties should only be " + << "accessed through the root FileDialogImpl instance"; + } +} + +QQuickListView *QQuickFontDialogImplAttached::familyListView() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->familyListView; +} + +void QQuickFontDialogImplAttached::setFamilyListView(QQuickListView *familyListView) +{ + Q_D(QQuickFontDialogImplAttached); + if (d->familyListView == familyListView) + return; + + if (d->familyListView) { + disconnect(d->familyListView, &QQuickListView::currentIndexChanged, + this, &QQuickFontDialogImplAttached::_q_familyChanged); + } + + d->familyListView = familyListView; + + if (familyListView) { + connect(d->familyListView, &QQuickListView::currentIndexChanged, + this, &QQuickFontDialogImplAttached::_q_familyChanged); + } + + emit familyListViewChanged(); +} + +QQuickListView *QQuickFontDialogImplAttached::styleListView() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->styleListView; +} + +void QQuickFontDialogImplAttached::setStyleListView(QQuickListView *styleListView) +{ + Q_D(QQuickFontDialogImplAttached); + if (d->styleListView == styleListView) + return; + + if (d->styleListView) { + disconnect(d->styleListView, &QQuickListView::currentIndexChanged, + this, &QQuickFontDialogImplAttached::_q_styleChanged); + } + + d->styleListView = styleListView; + + if (styleListView) { + connect(d->styleListView, &QQuickListView::currentIndexChanged, + this, &QQuickFontDialogImplAttached::_q_styleChanged); + } + + emit styleListViewChanged(); +} + +QQuickListView *QQuickFontDialogImplAttached::sizeListView() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->sizeListView; +} + +void QQuickFontDialogImplAttached::setSizeListView(QQuickListView *sizeListView) +{ + Q_D(QQuickFontDialogImplAttached); + if (d->sizeListView == sizeListView) + return; + + if (d->sizeListView) { + disconnect(d->sizeListView, &QQuickListView::currentIndexChanged, + this, &QQuickFontDialogImplAttached::_q_sizeChanged); + } + + d->sizeListView = sizeListView; + + if (d->sizeListView) { + connect(d->sizeListView, &QQuickListView::currentIndexChanged, + this, &QQuickFontDialogImplAttached::_q_sizeChanged); + } + + emit sizeListViewChanged(); +} + +QQuickTextEdit *QQuickFontDialogImplAttached::sampleEdit() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->sampleEdit; +} + +void QQuickFontDialogImplAttached::setSampleEdit(QQuickTextEdit *sampleEdit) +{ + Q_D(QQuickFontDialogImplAttached); + + if (d->sampleEdit == sampleEdit) + return; + + if (d->sampleEdit) { + QObjectPrivate::disconnect(d->sampleEdit, &QQuickTextEdit::fontChanged, + d, &QQuickFontDialogImplAttachedPrivate::currentFontChanged); + } + + d->sampleEdit = sampleEdit; + + if (d->sampleEdit) { + QObjectPrivate::connect(d->sampleEdit, &QQuickTextEdit::fontChanged, + d, &QQuickFontDialogImplAttachedPrivate::currentFontChanged); + + d->sampleEdit->setText(QFontDatabase::writingSystemSample(m_writingSystem)); + } + + emit sampleEditChanged(); +} + +QQuickDialogButtonBox *QQuickFontDialogImplAttached::buttonBox() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->buttonBox; +} + +void QQuickFontDialogImplAttached::setButtonBox(QQuickDialogButtonBox *buttonBox) +{ + Q_D(QQuickFontDialogImplAttached); + if (buttonBox == d->buttonBox) + return; + + if (d->buttonBox) { + QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent()); + if (fontDialogImpl) { + auto dialogPrivate = QQuickDialogPrivate::get(fontDialogImpl); + 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) { + QQuickFontDialogImpl *fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent()); + if (fontDialogImpl) { + auto dialogPrivate = QQuickDialogPrivate::get(fontDialogImpl); + 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 *QQuickFontDialogImplAttached::writingSystemComboBox() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->writingSystemComboBox; +} + +void QQuickFontDialogImplAttached::setWritingSystemComboBox(QQuickComboBox *writingSystemComboBox) +{ + Q_D(QQuickFontDialogImplAttached); + + if (d->writingSystemComboBox == writingSystemComboBox) + return; + + if (d->writingSystemComboBox) { + disconnect(d->writingSystemComboBox, &QQuickComboBox::activated, + this, &QQuickFontDialogImplAttached::_q_writingSystemChanged); + } + + d->writingSystemComboBox = writingSystemComboBox; + + if (d->writingSystemComboBox) { + QStringList writingSystemModel; + for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { + QFontDatabase::WritingSystem ws = QFontDatabase::WritingSystem(i); + QString wsName = QFontDatabase::writingSystemName(ws); + if (wsName.isEmpty()) + break; + writingSystemModel.append(wsName); + } + + d->writingSystemComboBox->setModel(writingSystemModel); + + connect(d->writingSystemComboBox, &QQuickComboBox::activated, + this, &QQuickFontDialogImplAttached::_q_writingSystemChanged); + } + + emit writingSystemComboBoxChanged(); +} + +QQuickCheckBox *QQuickFontDialogImplAttached::underlineCheckBox() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->underlineCheckBox; +} + +void QQuickFontDialogImplAttached::setUnderlineCheckBox(QQuickCheckBox *underlineCheckBox) +{ + Q_D(QQuickFontDialogImplAttached); + + if (d->underlineCheckBox == underlineCheckBox) + return; + + if (d->underlineCheckBox) { + disconnect(d->underlineCheckBox, &QQuickCheckBox::checkStateChanged, + this, &QQuickFontDialogImplAttached::_q_updateSample); + } + + d->underlineCheckBox = underlineCheckBox; + + if (d->underlineCheckBox) { + connect(d->underlineCheckBox, &QQuickCheckBox::checkStateChanged, + this, &QQuickFontDialogImplAttached::_q_updateSample); + } + + emit underlineCheckBoxChanged(); +} + +QQuickCheckBox *QQuickFontDialogImplAttached::strikeoutCheckBox() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->strikeoutCheckBox; +} + +void QQuickFontDialogImplAttached::setStrikeoutCheckBox(QQuickCheckBox *strikeoutCheckBox) +{ + Q_D(QQuickFontDialogImplAttached); + + if (d->strikeoutCheckBox == strikeoutCheckBox) + return; + + if (d->strikeoutCheckBox) { + disconnect(d->strikeoutCheckBox, &QQuickCheckBox::checkStateChanged, + this, &QQuickFontDialogImplAttached::_q_updateSample); + } + + d->strikeoutCheckBox = strikeoutCheckBox; + + if (d->strikeoutCheckBox) { + connect(d->strikeoutCheckBox, &QQuickCheckBox::checkStateChanged, + this, &QQuickFontDialogImplAttached::_q_updateSample); + } + + emit strikeoutCheckBoxChanged(); +} + +QQuickTextField *QQuickFontDialogImplAttached::familyEdit() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->familyEdit; +} + +void QQuickFontDialogImplAttached::setFamilyEdit(QQuickTextField *familyEdit) +{ + Q_D(QQuickFontDialogImplAttached); + + if (d->familyEdit == familyEdit) + return; + + d->familyEdit = familyEdit; + + emit familyEditChanged(); +} + +QQuickTextField *QQuickFontDialogImplAttached::styleEdit() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->styleEdit; +} + +void QQuickFontDialogImplAttached::setStyleEdit(QQuickTextField *styleEdit) +{ + Q_D(QQuickFontDialogImplAttached); + + if (d->styleEdit == styleEdit) + return; + + d->styleEdit = styleEdit; + + emit styleEditChanged(); +} + +QQuickTextField *QQuickFontDialogImplAttached::sizeEdit() const +{ + Q_D(const QQuickFontDialogImplAttached); + return d->sizeEdit; +} + +void QQuickFontDialogImplAttached::setSizeEdit(QQuickTextField *sizeEdit) +{ + Q_D(QQuickFontDialogImplAttached); + + if (d->sizeEdit == sizeEdit) + return; + + if (d->sizeEdit) { + disconnect(d->sizeEdit, &QQuickTextField::textChanged, + this, &QQuickFontDialogImplAttached::_q_sizeEdited); + } + + d->sizeEdit = sizeEdit; + + if (d->sizeEdit) { + connect(d->sizeEdit, &QQuickTextField::textChanged, + this, &QQuickFontDialogImplAttached::_q_sizeEdited); + } + + emit sizeEditChanged(); +} + +/*! + \internal + + Updates the model for the family list view, and attempt + to reselect the previously selected font family. + + Calls updateStyles() + */ +void QQuickFontDialogImplAttached::updateFamilies() +{ + enum match_t { MATCH_NONE = 0, MATCH_LAST_RESORT = 1, MATCH_APP = 2, MATCH_FAMILY = 3 }; + + const QFontDialogOptions::FontDialogOptions scalableMask( + QFontDialogOptions::ScalableFonts | QFontDialogOptions::NonScalableFonts); + + const QFontDialogOptions::FontDialogOptions spacingMask(QFontDialogOptions::ProportionalFonts + | QFontDialogOptions::MonospacedFonts); + + const auto p = qobject_cast<QQuickFontDialogImpl *>(parent()); + + const auto options = p->options()->options(); + + QStringList familyNames; + const auto families = QFontDatabase::families(m_writingSystem); + for (const auto &family : families) { + if (QFontDatabase::isPrivateFamily(family)) + continue; + + if ((options & scalableMask) && (options & scalableMask) != scalableMask) { + if (bool(options & QFontDialogOptions::ScalableFonts) + != QFontDatabase::isSmoothlyScalable(family)) + continue; + } + + if ((options & spacingMask) && (options & scalableMask) != spacingMask) { + if (bool(options & QFontDialogOptions::MonospacedFonts) + != QFontDatabase::isFixedPitch(family)) + continue; + } + + familyNames << family; + } + + auto listView = familyListView(); + + // Index will be set to -1 on empty model, and 0 for non empty models. + // Will overwrite selectedFamily and selectedStyle + listView->setModel(familyNames); + + QString foundryName1, familyName1, foundryName2, familyName2; + int bestFamilyMatch = -1; + match_t bestFamilyType = MATCH_NONE; + const QFont f; + + QFontDatabasePrivate::parseFontName(m_selectedFamily, foundryName1, familyName1); + + int i = 0; + for (auto it = familyNames.constBegin(); it != familyNames.constEnd(); ++it, ++i) { + QFontDatabasePrivate::parseFontName(*it, foundryName2, familyName2); + + if (familyName1 == familyName2) { + bestFamilyType = MATCH_FAMILY; + if (foundryName1 == foundryName2) { + bestFamilyMatch = i; + break; + } + if (bestFamilyMatch < MATCH_FAMILY) { + bestFamilyMatch = i; + } + } + + match_t type = MATCH_NONE; + if (bestFamilyType <= MATCH_NONE && familyName2 == QStringLiteral("helvetica")) + type = MATCH_LAST_RESORT; + if (bestFamilyType <= MATCH_LAST_RESORT && familyName2 == f.families().constFirst()) + type = MATCH_APP; + if (type != MATCH_NONE) { + bestFamilyType = type; + bestFamilyMatch = i; + } + } + + if (!familyNames.isEmpty() && bestFamilyType != MATCH_NONE) { + listView->setCurrentIndex(bestFamilyMatch); + } else { + listView->setCurrentIndex(-1); + } + + updateStyles(); +} + +/*! + \internal + + Updates the model for the style list view, and + attempt to reselect the style that was previously selected. + + Calls updateSizes() + */ +void QQuickFontDialogImplAttached::updateStyles() +{ + const QString family = familyListView()->currentIndex() >= 0 ? m_selectedFamily : QString(); + const QStringList styles = QFontDatabase::styles(family); + + auto listView = styleListView(); + + m_isUpdatingStyles = true; + + listView->setModel(styles); + + if (styles.isEmpty()) { + styleEdit()->clear(); + m_smoothlyScalable = false; + } else { + int newIndex = 0; + + if (!m_selectedStyle.isEmpty()) { + bool redo = true, found = false; + QString cstyle = m_selectedStyle; + do { + for (int i = 0; i < styles.count(); ++i) { + if (cstyle.toLower() == styles.at(i).toLower()) { + newIndex = i; + found = true; + break; + } + } + + if (!found && redo) { + redo = false; + + if (cstyle.contains(QLatin1String("Italic"))) { + cstyle.replace(QLatin1String("Italic"), QLatin1String("Oblique")); + continue; + } else if (cstyle.contains(QLatin1String("Oblique"))) { + cstyle.replace(QLatin1String("Oblique"), QLatin1String("Italic")); + continue; + } else if (cstyle.contains(QLatin1String("Regular"))) { + cstyle.replace(QLatin1String("Regular"), QLatin1String("Normal")); + continue; + } else if (cstyle.contains(QLatin1String("Normal"))) { + cstyle.replace(QLatin1String("Normal"), QLatin1String("Regular")); + continue; + } + } + + } while (!found && redo); + } + + listView->setCurrentIndex(newIndex); + + m_selectedStyle = styles.at(newIndex); + styleEdit()->setText(m_selectedStyle); + + m_smoothlyScalable = QFontDatabase::isSmoothlyScalable(m_selectedFamily, m_selectedStyle); + } + + m_isUpdatingStyles = false; + + updateSizes(); +} + +/*! + \internal + + Updates the model for the size list view, + and attempts to reselect the size that was previously selected + */ +void QQuickFontDialogImplAttached::updateSizes() +{ + if (!m_selectedFamily.isEmpty()) { + const QList<int> sizes = QFontDatabase::pointSizes(m_selectedFamily, m_selectedStyle); + + QStringList str_sizes; + + str_sizes.reserve(sizes.size()); + + int idx = 0, current = -1; + for (QList<int>::const_iterator it = sizes.constBegin(); it != sizes.constEnd(); it++) { + str_sizes.append(QString::number(*it)); + if (current == -1 && m_selectedSize == *it) { + current = idx; + } + ++idx; + } + + auto listView = sizeListView(); + + listView->setModel(str_sizes); + if (current != -1) + listView->setCurrentIndex(current); + + sizeEdit()->setText(!m_smoothlyScalable && listView->currentIndex() > 0 + ? str_sizes.at(listView->currentIndex()) + : QString::number(m_selectedSize)); + } else { + qCWarning(lcAttachedProperty) << "Warning! selectedFamily is empty"; + sizeEdit()->clear(); + } + + _q_updateSample(); +} + +void QQuickFontDialogImplAttached::_q_updateSample() +{ + const int pSize = sizeEdit()->text().toInt(); + + QFont newFont = QFontDatabase::font(m_selectedFamily, m_selectedStyle, pSize); + + newFont.setUnderline(underlineCheckBox()->isChecked()); + newFont.setStrikeOut(strikeoutCheckBox()->isChecked()); + + if (!m_selectedFamily.isEmpty()) { + sampleEdit()->setFont(newFont); + } +} + +void QQuickFontDialogImplAttached::_q_writingSystemChanged(int index) +{ + m_writingSystem = QFontDatabase::WritingSystem(index); + sampleEdit()->setText(QFontDatabase::writingSystemSample(m_writingSystem)); + + updateFamilies(); +} + +void QQuickFontDialogImplAttached::searchListView(const QString &s, QQuickListView *listView) +{ + const QStringList model = listView->model().toStringList(); + + bool redo = false; + + do { + m_search.append(s); + + for (int i = 0; i < model.count(); ++i) { + if (model.at(i).startsWith(m_search, Qt::CaseInsensitive)) { + listView->setCurrentIndex(i); + return; + } + } + + clearSearch(); + + redo = !redo; + } while (redo); +} + +void QQuickFontDialogImplAttached::clearSearch() +{ + m_search.clear(); +} + +void QQuickFontDialogImplAttached::_q_familyChanged() +{ + const int index = familyListView()->currentIndex(); + + if (index < 0) { + familyEdit()->clear(); + return; + } + + m_selectedFamily = familyListView()->model().toStringList().at(index); + familyEdit()->setText(m_selectedFamily); + + updateStyles(); +} + +void QQuickFontDialogImplAttached::_q_styleChanged() +{ + if (m_isUpdatingStyles) + return; + + const int index = styleListView()->currentIndex(); + + if (index < 0) { + qCWarning(lcAttachedProperty) << "currentIndex changed to -1"; + return; + } + + m_selectedStyle = styleListView()->model().toStringList().at(index); + styleEdit()->setText(m_selectedStyle); + + updateSizes(); +} + +void QQuickFontDialogImplAttached::_q_sizeEdited() +{ + const int size = sizeEdit()->text().toInt(); + + if (size == m_selectedSize) + return; + + m_selectedSize = size; + + if (sizeListView()->count()) { + auto model = sizeListView()->model().toStringList(); + + int i; + for (i = 0; i < model.count() - 1; ++i) { + if (model.at(i).toInt() >= size) + break; + } + + QSignalBlocker blocker(sizeListView()); + if (model.at(i).toInt() == size) + sizeListView()->setCurrentIndex(i); + else + sizeListView()->setCurrentIndex(-1); + } + + _q_updateSample(); +} + +void QQuickFontDialogImplAttached::_q_sizeChanged() +{ + const int index = sizeListView()->currentIndex(); + + if (index < 0) { + qCWarning(lcAttachedProperty) << "currentIndex changed to -1"; + return; + } + + const QString s = sizeListView()->model().toStringList().at(index); + m_selectedSize = s.toInt(); + + sizeEdit()->setText(s); + + _q_updateSample(); +} + +void QQuickFontDialogImplAttachedPrivate::currentFontChanged(const QFont &font) +{ + + auto fontDialogImpl = qobject_cast<QQuickFontDialogImpl *>(parent); + + if (!fontDialogImpl) { + return; + } + + fontDialogImpl->setCurrentFont(font); + + if (fontDialogImpl->options()->testOption(QFontDialogOptions::NoButtons)) + emit fontDialogImpl->fontSelected(font); +} + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl_p.h new file mode 100644 index 0000000000..9856735336 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl_p.h @@ -0,0 +1,215 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFONTDIALOGIMPL_P_H +#define QQUICKFONTDIALOGIMPL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qfontdatabase.h> +#include <QtQuick/private/qquicklistview_p.h> +#include <QtQuick/private/qquicktextedit_p.h> +#include <QtQuickTemplates2/private/qquicktextfield_p.h> +#include <QtQuickTemplates2/private/qquickcombobox_p.h> +#include <QtQuickTemplates2/private/qquickcheckbox_p.h> +#include <QtQuickTemplates2/private/qquickdialog_p.h> +#include "qtquickdialogs2quickimplglobal_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickDialogButtonBox; + +class QQuickFontDialogImplAttached; +class QQuickFontDialogImplAttachedPrivate; +class QQuickFontDialogImplPrivate; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFontDialogImpl : public QQuickDialog +{ + Q_OBJECT + Q_PROPERTY(QFont currentFont READ currentFont WRITE setCurrentFont NOTIFY currentFontChanged FINAL) + QML_NAMED_ELEMENT(FontDialogImpl) + QML_ATTACHED(QQuickFontDialogImplAttached) + QML_ADDED_IN_VERSION(6, 2) + +public: + explicit QQuickFontDialogImpl(QObject *parent = nullptr); + + static QQuickFontDialogImplAttached *qmlAttachedProperties(QObject *object); + + QSharedPointer<QFontDialogOptions> options() const; + void setOptions(const QSharedPointer<QFontDialogOptions> &options); + + QFont currentFont() const; + void setCurrentFont(const QFont &font); + + void updateListViews(); + +Q_SIGNALS: + void optionsChanged(); + void currentFontChanged(const QFont &font); + void fontSelected(const QFont &font); + +private: + void keyReleaseEvent(QKeyEvent *event) override; + void focusOutEvent(QFocusEvent *event) override; + + Q_DISABLE_COPY(QQuickFontDialogImpl) + Q_DECLARE_PRIVATE(QQuickFontDialogImpl) +}; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickFontDialogImplAttached : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQuickListView *familyListView READ familyListView WRITE setFamilyListView + NOTIFY familyListViewChanged) + Q_PROPERTY(QQuickListView *styleListView READ styleListView WRITE setStyleListView + NOTIFY styleListViewChanged) + Q_PROPERTY(QQuickListView *sizeListView READ sizeListView WRITE setSizeListView + NOTIFY sizeListViewChanged) + Q_PROPERTY(QQuickTextEdit *sampleEdit READ sampleEdit WRITE setSampleEdit + NOTIFY sampleEditChanged) + Q_PROPERTY(QQuickDialogButtonBox *buttonBox READ buttonBox WRITE setButtonBox + NOTIFY buttonBoxChanged) + Q_PROPERTY(QQuickComboBox *writingSystemComboBox READ writingSystemComboBox + WRITE setWritingSystemComboBox NOTIFY writingSystemComboBoxChanged) + Q_PROPERTY(QQuickCheckBox *underlineCheckBox READ underlineCheckBox WRITE setUnderlineCheckBox + NOTIFY underlineCheckBoxChanged) + Q_PROPERTY(QQuickCheckBox *strikeoutCheckBox READ strikeoutCheckBox WRITE setStrikeoutCheckBox + NOTIFY strikeoutCheckBoxChanged) + + Q_PROPERTY(QQuickTextField *familyEdit READ familyEdit WRITE setFamilyEdit + NOTIFY familyEditChanged) + Q_PROPERTY(QQuickTextField *styleEdit READ styleEdit WRITE setStyleEdit NOTIFY styleEditChanged) + Q_PROPERTY(QQuickTextField *sizeEdit READ sizeEdit WRITE setSizeEdit NOTIFY sizeEditChanged) + + Q_MOC_INCLUDE(<QtQuickTemplates2 / private / qquickdialogbuttonbox_p.h>) + +public: + explicit QQuickFontDialogImplAttached(QObject *parent = nullptr); + + QQuickListView *familyListView() const; + void setFamilyListView(QQuickListView *familyListView); + + QQuickListView *styleListView() const; + void setStyleListView(QQuickListView *styleListView); + + QQuickListView *sizeListView() const; + void setSizeListView(QQuickListView *sizeListView); + + QQuickTextEdit *sampleEdit() const; + void setSampleEdit(QQuickTextEdit *sampleEdit); + + QQuickDialogButtonBox *buttonBox() const; + void setButtonBox(QQuickDialogButtonBox *buttonBox); + + QQuickComboBox *writingSystemComboBox() const; + void setWritingSystemComboBox(QQuickComboBox *writingSystemComboBox); + + QQuickCheckBox *underlineCheckBox() const; + void setUnderlineCheckBox(QQuickCheckBox *underlineCheckBox); + + QQuickCheckBox *strikeoutCheckBox() const; + void setStrikeoutCheckBox(QQuickCheckBox *strikethroughCheckBox); + + QQuickTextField *familyEdit() const; + void setFamilyEdit(QQuickTextField *familyEdit); + + QQuickTextField *styleEdit() const; + void setStyleEdit(QQuickTextField *styleEdit); + + QQuickTextField *sizeEdit() const; + void setSizeEdit(QQuickTextField *sizeEdit); + +Q_SIGNALS: + void buttonBoxChanged(); + void familyListViewChanged(); + void styleListViewChanged(); + void sizeListViewChanged(); + void sampleEditChanged(); + void writingSystemComboBoxChanged(); + void underlineCheckBoxChanged(); + void strikeoutCheckBoxChanged(); + void familyEditChanged(); + void styleEditChanged(); + void sizeEditChanged(); + +public: + void searchFamily(const QString &s) { searchListView(s, familyListView()); } + void searchStyle(const QString &s) { searchListView(s, styleListView()); } + void clearSearch(); + + void updateFamilies(); + +private: + void updateStyles(); + void updateSizes(); + + void _q_familyChanged(); + void _q_styleChanged(); + void _q_sizeEdited(); + void _q_sizeChanged(); + void _q_updateSample(); + + void _q_writingSystemChanged(int index); + + void searchListView(const QString &s, QQuickListView *listView); + + QFontDatabase::WritingSystem m_writingSystem; + QString m_selectedFamily; + QString m_selectedStyle; + QString m_search; + int m_selectedSize; + bool m_smoothlyScalable; + bool m_isUpdatingStyles; + + Q_DISABLE_COPY(QQuickFontDialogImplAttached) + Q_DECLARE_PRIVATE(QQuickFontDialogImplAttached) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickFontDialogImpl) + +#endif // QQUICKFONTDIALOGIMPL_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl_p_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl_p_p.h new file mode 100644 index 0000000000..8de3480dd9 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickfontdialogimpl_p_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFONTDIALOGIMPL_P_P_H +#define QQUICKFONTDIALOGIMPL_P_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQuickTemplates2/private/qquickcombobox_p.h> +#include <QtQuickTemplates2/private/qquickdialog_p_p.h> +#include <QtQuickTemplates2/private/qquickdialogbuttonbox_p.h> + +#include "qquickfontdialogimpl_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFontDialogImplPrivate : public QQuickDialogPrivate +{ + Q_DECLARE_PUBLIC(QQuickFontDialogImpl) +public: + QQuickFontDialogImplPrivate(); + + static QQuickFontDialogImplPrivate *get(QQuickFontDialogImpl *dialog) + { + return dialog->d_func(); + } + + QQuickFontDialogImplAttached *attachedOrWarn(); + + void updateEnabled(); + + void handleAccept() override; + void handleClick(QQuickAbstractButton *button) override; + + QSharedPointer<QFontDialogOptions> options; + + QFont currentFont; +}; + +class QQuickFontDialogImplAttachedPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QQuickFontDialogImplAttached) + + void currentFontChanged(const QFont &font); + +public: + QPointer<QQuickDialogButtonBox> buttonBox; + QPointer<QQuickListView> familyListView; + QPointer<QQuickListView> styleListView; + QPointer<QQuickListView> sizeListView; + QPointer<QQuickTextEdit> sampleEdit; + QPointer<QQuickComboBox> writingSystemComboBox; + QPointer<QQuickCheckBox> underlineCheckBox; + QPointer<QQuickCheckBox> strikeoutCheckBox; + QPointer<QQuickTextField> familyEdit; + QPointer<QQuickTextField> styleEdit; + QPointer<QQuickTextField> sizeEdit; +}; + +QT_END_NAMESPACE + +#endif // QQUICKFONTDIALOGIMPL_P_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfiledialog.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfiledialog.cpp new file mode 100644 index 0000000000..deccd9bbc3 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfiledialog.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** 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 "qquickplatformfiledialog_p.h" + +#include <QtCore/qloggingcategory.h> +#include <QtGui/qwindow.h> +#include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlinfo.h> +#include <QtQuick/qquickwindow.h> +#include <QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h> +#include <QtQuickTemplates2/private/qquickdialog_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p_p.h> +#include <QtQuickTemplates2/private/qquickpopupanchors_p.h> + +#include "qquickfiledialogimpl_p.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcQuickPlatformFileDialog, "qt.quick.dialogs.quickplatformfiledialog") + +/*! + \class QQuickPlatformFileDialog + \internal + + An interface that QQuickFileDialog can use to access the non-native Qt Quick FileDialog. + + Both this and the native implementations are created in QQuickAbstractDialog::create(). +*/ +QQuickPlatformFileDialog::QQuickPlatformFileDialog(QObject *parent) +{ + qCDebug(lcQuickPlatformFileDialog) << "creating non-native Qt Quick FileDialog with parent" << parent; + + // Set a parent so that we get deleted if we can't be shown for whatever reason. + // Our eventual parent should be the window, though. + setParent(parent); + + auto qmlContext = ::qmlContext(parent); + if (!qmlContext) { + qmlWarning(parent) << "No QQmlContext for QQuickPlatformFileDialog; can't create non-native FileDialog implementation"; + return; + } + + const auto dialogQmlUrl = QUrl(QStringLiteral("qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/qml/FileDialog.qml")); + QQmlComponent fileDialogComponent(qmlContext->engine(), dialogQmlUrl, parent); + if (!fileDialogComponent.isReady()) { + qmlWarning(parent) << "Failed to load non-native FileDialog implementation:\n" << fileDialogComponent.errorString(); + return; + } + m_dialog = qobject_cast<QQuickFileDialogImpl*>(fileDialogComponent.create()); + if (!m_dialog) { + qmlWarning(parent) << "Failed to create an instance of the non-native FileDialog:\n" << fileDialogComponent.errorString(); + return; + } + // Give it a parent until it's parented to the window in show(). + m_dialog->setParent(this); + + connect(m_dialog, &QQuickDialog::accepted, this, &QPlatformDialogHelper::accept); + connect(m_dialog, &QQuickDialog::rejected, this, &QPlatformDialogHelper::reject); + + connect(m_dialog, &QQuickFileDialogImpl::fileSelected, this, &QQuickPlatformFileDialog::fileSelected); + // TODO: add support for multiple file selection (QTBUG-92585) +// connect(m_dialog, &QQuickFileDialogImpl::filesSelected, [this](const QList<QString> &files) { +// QList<QUrl> urls; +// urls.reserve(files.count()); +// for (const QString &file : files) +// urls += QUrl::fromLocalFile(file); +// emit filesSelected(urls); +// }); + connect(m_dialog, &QQuickFileDialogImpl::currentFileChanged, this, &QQuickPlatformFileDialog::currentChanged); + connect(m_dialog, &QQuickFileDialogImpl::currentFolderChanged, this, &QQuickPlatformFileDialog::directoryEntered); + connect(m_dialog, &QQuickFileDialogImpl::filterSelected, this, &QQuickPlatformFileDialog::filterSelected); + + // We would do this in QQuickFileDialogImpl, but we need to ensure that folderChanged() + // is connected to directoryEntered() before setting it to ensure that the QQuickFileDialog is notified. + if (m_dialog->currentFolder().isEmpty()) + m_dialog->setCurrentFolder(QUrl::fromLocalFile(QDir().absolutePath())); +} + +bool QQuickPlatformFileDialog::isValid() const +{ + return m_dialog; +} + +bool QQuickPlatformFileDialog::defaultNameFilterDisables() const +{ + return false; +} + +void QQuickPlatformFileDialog::setDirectory(const QUrl &directory) +{ + if (!m_dialog) + return; + + m_dialog->setCurrentFolder(directory); +} + +QUrl QQuickPlatformFileDialog::directory() const +{ + if (!m_dialog) + return {}; + + return m_dialog->currentFolder(); +} + +void QQuickPlatformFileDialog::selectFile(const QUrl &file) +{ + if (!m_dialog) + return; + + m_dialog->setSelectedFile(file); +} + +QList<QUrl> QQuickPlatformFileDialog::selectedFiles() const +{ + // TODO: support for multiple selected files + return { m_dialog->currentFile() }; +} + +void QQuickPlatformFileDialog::setFilter() +{ +} + +void QQuickPlatformFileDialog::selectNameFilter(const QString &filter) +{ + // There is a bit of a problem with order here - QQuickFileDialog::onShow() + // is called before our show(), but it needs to set the selected filter + // (which we can't do in our show() because we don't know about QQuickFileDialog). + // So, delay setting the filter until we're shown. This shouldn't be an issue + // in practice, since it doesn't make sense for the filter to programmatically + // change while the dialog is visible. + m_pendingNameFilter = filter; +} + +QString QQuickPlatformFileDialog::selectedNameFilter() const +{ + return m_dialog->selectedNameFilter()->name(); +} + +void QQuickPlatformFileDialog::exec() +{ + qCWarning(lcQuickPlatformFileDialog) << "exec() is not supported for the Qt Quick FileDialog fallback"; +} + +bool QQuickPlatformFileDialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) +{ + qCDebug(lcQuickPlatformFileDialog) << "show called with flags" << flags << + "modality" << modality << "parent" << parent; + if (!m_dialog) + return false; + + if (!parent) + return false; + + auto quickWindow = qobject_cast<QQuickWindow*>(parent); + if (!quickWindow) { + qmlInfo(this->parent()) << "Parent window (" << parent << ") of non-native dialog is not a QQuickWindow"; + return false; + } + m_dialog->setParent(parent); + m_dialog->resetParentItem(); + + auto popupPrivate = QQuickPopupPrivate::get(m_dialog); + popupPrivate->getAnchors()->setCenterIn(m_dialog->parentItem()); + + QSharedPointer<QFileDialogOptions> options = QPlatformFileDialogHelper::options(); + m_dialog->setTitle(options->windowTitle()); + m_dialog->setOptions(options); + m_dialog->selectNameFilter(m_pendingNameFilter); + m_pendingNameFilter.clear(); + m_dialog->setAcceptLabel(options->isLabelExplicitlySet(QFileDialogOptions::Accept) + ? options->labelText(QFileDialogOptions::Accept) : QString()); + m_dialog->setRejectLabel(options->isLabelExplicitlySet(QFileDialogOptions::Reject) + ? options->labelText(QFileDialogOptions::Reject) : QString()); + + m_dialog->open(); + return true; +} + +void QQuickPlatformFileDialog::hide() +{ + if (!m_dialog) + return; + + m_dialog->close(); +} + +QQuickFileDialogImpl *QQuickPlatformFileDialog::dialog() const +{ + return m_dialog; +} + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfiledialog_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfiledialog_p.h new file mode 100644 index 0000000000..883b7ed9b7 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfiledialog_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKPLATFORMFILEDIALOG_P_H +#define QQUICKPLATFORMFILEDIALOG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qpa/qplatformdialoghelper.h> + +#include "qtquickdialogs2quickimplglobal_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFileDialogImpl; +class QWindow; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickPlatformFileDialog : public QPlatformFileDialogHelper +{ + Q_OBJECT + +public: + explicit QQuickPlatformFileDialog(QObject *parent); + ~QQuickPlatformFileDialog() = default; + + bool isValid() const; + bool defaultNameFilterDisables() const override; + void setDirectory(const QUrl &directory) override; + QUrl directory() const override; + void selectFile(const QUrl &file) override; + QList<QUrl> selectedFiles() const override; + void setFilter() override; + void selectNameFilter(const QString &filter) override; + QString selectedNameFilter() const override; + + void exec() override; + bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) override; + void hide() override; + + QQuickFileDialogImpl *dialog() const; + +private: + QQuickFileDialogImpl *m_dialog = nullptr; + QString m_pendingNameFilter; +}; + +QT_END_NAMESPACE + +#endif // QQUICKPLATFORMFILEDIALOG_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfontdialog.cpp b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfontdialog.cpp new file mode 100644 index 0000000000..9ae2c29a44 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfontdialog.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** 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 "qquickplatformfontdialog_p.h" + +#include <QtCore/qloggingcategory.h> +#include <QtGui/qwindow.h> +#include <QtQml/qqmlcontext.h> +#include <QtQml/qqmlinfo.h> +#include <QtQuick/qquickwindow.h> +#include <QtQuickTemplates2/private/qquickdialog_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p_p.h> +#include <QtQuickTemplates2/private/qquickpopupanchors_p.h> + +#include "qquickfontdialogimpl_p.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcQuickPlatformFontDialog, "qt.quick.dialogs.quickplatformfontdialog") + +/*! + \class QQuickPlatformFontDialog + \internal + + An interface that QQuickFontDialog can use to access the non-native Qt Quick FontDialog. + + Both this and the native implementations are created in QQuickAbstractDialog::create(). + +*/ +QQuickPlatformFontDialog::QQuickPlatformFontDialog(QObject *parent) +{ + qCDebug(lcQuickPlatformFontDialog) + << "creating non-native Qt Quick FontDialog with parent" << parent; + + // Set a parent so that we get deleted if we can't be shown for whatever reason. + // Our eventual parent should be the window, though. + setParent(parent); + + auto qmlContext = ::qmlContext(parent); + if (!qmlContext) { + qmlWarning(parent) << "No QQmlContext for QQuickPlatformFontDialog; can't create " + "non-native FontDialog implementation"; + return; + } + + const auto dialogQmlUrl = QUrl(QStringLiteral( + "qrc:/qt-project.org/imports/QtQuick/Dialogs/quickimpl/qml/FontDialog.qml")); + + QQmlComponent fontDialogComponent(qmlContext->engine(), dialogQmlUrl, parent); + if (!fontDialogComponent.isReady()) { + qmlWarning(parent) << "Failed to load non-native FontDialog implementation:\n" + << fontDialogComponent.errorString(); + return; + } + + m_dialog = qobject_cast<QQuickFontDialogImpl *>(fontDialogComponent.create()); + + if (!m_dialog) { + qmlWarning(parent) << "Failed to create an instance of the non-native FontDialog:\n" + << fontDialogComponent.errorString(); + return; + } + + m_dialog->setParent(this); + + connect(m_dialog, &QQuickDialog::accepted, this, &QPlatformDialogHelper::accept); + connect(m_dialog, &QQuickDialog::rejected, this, &QPlatformDialogHelper::reject); + + connect(m_dialog, &QQuickFontDialogImpl::currentFontChanged, + this, &QQuickPlatformFontDialog::currentFontChanged); + connect(m_dialog, &QQuickFontDialogImpl::fontSelected, this, &QQuickPlatformFontDialog::fontSelected); +} + +bool QQuickPlatformFontDialog::isValid() const +{ + return m_dialog; +} + +void QQuickPlatformFontDialog::setCurrentFont(const QFont &font) +{ + if (m_dialog) + m_dialog->setCurrentFont(font); +} + +QFont QQuickPlatformFontDialog::currentFont() const +{ + return m_dialog ? m_dialog->currentFont() : QFont(); +} + +void QQuickPlatformFontDialog::exec() +{ + qCWarning(lcQuickPlatformFontDialog) + << "exec() is not supported for the Qt Quick FontDialog fallback"; +} + +bool QQuickPlatformFontDialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, + QWindow *parent) +{ + qCDebug(lcQuickPlatformFontDialog) + << "show called with flags" << flags << "modality" << modality << "parent" << parent; + + if (!isValid()) + return false; + + if (!parent) + return false; + + auto quickWindow = qobject_cast<QQuickWindow *>(parent); + if (!quickWindow) { + qmlInfo(this->parent()) << "Parent window (" << parent + << ") of non-native dialog is not a QQuickWindow"; + return false; + } + m_dialog->setParent(parent); + m_dialog->resetParentItem(); + + auto popupPrivate = QQuickPopupPrivate::get(m_dialog); + popupPrivate->getAnchors()->setCenterIn(m_dialog->parentItem()); + + QSharedPointer<QFontDialogOptions> options = QPlatformFontDialogHelper::options(); + m_dialog->setTitle(options->windowTitle()); + m_dialog->setOptions(options); + m_dialog->updateListViews(); + + m_dialog->open(); + return true; +} + +void QQuickPlatformFontDialog::hide() +{ + if (isValid()) + m_dialog->close(); +} + +QQuickFontDialogImpl *QQuickPlatformFontDialog::dialog() const +{ + return m_dialog; +} + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfontdialog_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfontdialog_p.h new file mode 100644 index 0000000000..a5009facab --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qquickplatformfontdialog_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKPLATFORMFONTDIALOG_P_H +#define QQUICKPLATFORMFONTDIALOG_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/qpa/qplatformdialoghelper.h> + +#include "qtquickdialogs2quickimplglobal_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFontDialogImpl; +class QWindow; + +class Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT QQuickPlatformFontDialog + : public QPlatformFontDialogHelper +{ + Q_OBJECT + +public: + explicit QQuickPlatformFontDialog(QObject *parent); + ~QQuickPlatformFontDialog() = default; + + bool isValid() const; + + virtual void setCurrentFont(const QFont &font) override; + virtual QFont currentFont() const override; + + void exec() override; + bool show(Qt::WindowFlags flags, Qt::WindowModality modality, QWindow *parent) override; + void hide() override; + + QQuickFontDialogImpl *dialog() const; + +private: + QQuickFontDialogImpl *m_dialog = nullptr; +}; + +QT_END_NAMESPACE + +#endif // QQUICKPLATFORMFONTDIALOG_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qtquickdialogs2quickimplforeign_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qtquickdialogs2quickimplforeign_p.h new file mode 100644 index 0000000000..4564786f5a --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qtquickdialogs2quickimplforeign_p.h @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QTQUICKDIALOGS2QUICKIMPLFOREIGN_P_H +#define QTQUICKDIALOGS2QUICKIMPLFOREIGN_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtQml/qqml.h> +#include <QtQuickDialogs2Utils/private/qquickfilenamefilter_p.h> +#include <QtQuickTemplates2/private/qquickabstractbutton_p.h> +#include <QtQuickTemplates2/private/qquickcontrol_p.h> +#include <QtQuickTemplates2/private/qquickdialog_p.h> +#include <QtQuickTemplates2/private/qquickicon_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p.h> + +QT_BEGIN_NAMESPACE + +struct QQuickFileNameFilterForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QQuickFileNameFilter) + QML_ADDED_IN_VERSION(6, 2) +}; + +// TODO: remove these ones when not needed (QTBUG-88179) + +// verticalPadding, etc. +struct QQuickControlForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QQuickControl) + QML_ADDED_IN_VERSION(2, 0) +}; + +struct QQuickAbstractButtonForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QQuickAbstractButton) + QML_ADDED_IN_VERSION(2, 0) +}; + +struct QQuickIconForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QQuickIcon) + QML_ADDED_IN_VERSION(6, 2) +}; + +// For leftInset, etc. +struct QQuickPopupForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QQuickPopup) + QML_ADDED_IN_VERSION(2, 0) +}; + +struct QQuickDialogForeign +{ + Q_GADGET + QML_ANONYMOUS + QML_FOREIGN(QQuickDialog) + QML_ADDED_IN_VERSION(2, 1) +}; + +QT_END_NAMESPACE + +#endif // QTQUICKDIALOGS2QUICKIMPLFOREIGN_P_H diff --git a/src/quickdialogs2/quickdialogs2quickimpl/qtquickdialogs2quickimplglobal_p.h b/src/quickdialogs2/quickdialogs2quickimpl/qtquickdialogs2quickimplglobal_p.h new file mode 100644 index 0000000000..38b5a01bea --- /dev/null +++ b/src/quickdialogs2/quickdialogs2quickimpl/qtquickdialogs2quickimplglobal_p.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QTQUICKDIALOGS2QUICKIMPLGLOBAL_P_H +#define QTQUICKDIALOGS2QUICKIMPLGLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtQml/private/qqmlglobal_p.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_QUICKDIALOGS2QUICKIMPL_LIB) +# define Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT Q_DECL_EXPORT +# else +# define Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_QUICKDIALOGS2QUICKIMPL_PRIVATE_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // QTQUICKDIALOGS2QUICKIMPLGLOBAL_P_H diff --git a/src/quickdialogs2/quickdialogs2utils/CMakeLists.txt b/src/quickdialogs2/quickdialogs2utils/CMakeLists.txt new file mode 100644 index 0000000000..0242ffcf6c --- /dev/null +++ b/src/quickdialogs2/quickdialogs2utils/CMakeLists.txt @@ -0,0 +1,23 @@ +# This library exists because QuickDialogs2 and QuickDialogs2QuickImpl +# both need QQuickNameFilter. QQuickNameFilter was originally in +# QuickDialogs2. Since QuickDialogs2 already links to +# QuickDialogs2QuickImpl, making the latter link to the former (to get +# access to QQuickNameFilter) would result in a circular dependency, +# so we have this library as a result. + +qt_internal_add_module(QuickDialogs2Utils + SOURCES + qquickfilenamefilter.cpp + qquickfilenamefilter_p.h + qtquickdialogs2utilsglobal_p.h + DEFINES + QT_BUILD_QUICKDIALOGS2UTILS_LIB + QT_NO_CAST_FROM_ASCII + QT_NO_CAST_TO_ASCII + INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_SOURCE_DIR} + LIBRARIES + Qt::GuiPrivate + PUBLIC_LIBRARIES + Qt::Core +) diff --git a/src/quickdialogs2/quickdialogs2utils/qquickfilenamefilter.cpp b/src/quickdialogs2/quickdialogs2utils/qquickfilenamefilter.cpp new file mode 100644 index 0000000000..bada00d162 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2utils/qquickfilenamefilter.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** 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 "qquickfilenamefilter_p.h" + +#include <QtCore/qloggingcategory.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcFileNameFilter, "qt.quick.dialogs.qquickfilenamefilter") + +QQuickFileNameFilter::QQuickFileNameFilter(QObject *parent) + : QObject(parent), m_index(-1) +{ +} + +int QQuickFileNameFilter::index() const +{ + return m_index; +} + +void QQuickFileNameFilter::setIndex(int index) +{ + if (m_index == index) + return; + + m_index = index; + emit indexChanged(index); +} + +QString QQuickFileNameFilter::name() const +{ + return m_name; +} + +QStringList QQuickFileNameFilter::extensions() const +{ + return m_extensions; +} + +QStringList QQuickFileNameFilter::globs() const +{ + return m_globs; +} + +QSharedPointer<QFileDialogOptions> QQuickFileNameFilter::options() const +{ + return m_options; +} + +void QQuickFileNameFilter::setOptions(const QSharedPointer<QFileDialogOptions> &options) +{ + m_options = options; +} + +static QString extractName(const QString &filter) +{ + return filter.left(filter.indexOf(QLatin1Char('(')) - 1); +} + +static QString extractExtension(QStringView filter) +{ + return filter.mid(filter.indexOf(QLatin1Char('.')) + 1).toString(); +} + +static void extractExtensionsAndGlobs(QStringView filter, QStringList &extensions, QStringList &globs) +{ + extensions.clear(); + globs.clear(); + + const int from = filter.indexOf(QLatin1Char('(')); + const int to = filter.lastIndexOf(QLatin1Char(')')) - 1; + if (from >= 0 && from < to) { + const QStringView ref = filter.mid(from + 1, to - from); + const QList<QStringView> exts = ref.split(QLatin1Char(' '), Qt::SkipEmptyParts); + // For example, given the filter "HTML files (*.html *.htm)", + // "ref" would be "*.html" and "*.htm". + for (const QStringView &ref : exts) { + extensions += extractExtension(ref); + globs += ref.toString(); + } + } +} + +void QQuickFileNameFilter::update(const QString &filter) +{ + const QStringList filters = nameFilters(); + + const int oldIndex = m_index; + const QString oldName = m_name; + const QStringList oldExtensions = m_extensions; + const QStringList oldGlobs = m_globs; + + m_index = filters.indexOf(filter); + m_name = extractName(filter); + extractExtensionsAndGlobs(filter, m_extensions, m_globs); + + if (oldIndex != m_index) + emit indexChanged(m_index); + if (oldName != m_name) + emit nameChanged(m_name); + if (oldExtensions != m_extensions) + emit extensionsChanged(m_extensions); + if (oldGlobs != m_globs) + emit globsChanged(m_globs); + + qCDebug(lcFileNameFilter).nospace() << "update called on " << this << " of " << parent() + << " with filter " << filter << " (current filters are " << filters << "):" + << "\n old index=" << oldIndex << "new index=" << m_index + << "\n old name=" << oldName << "new name=" << m_name + << "\n old extensions=" << oldExtensions << "new extensions=" << m_extensions + << "\n old glob=s" << oldGlobs << "new globs=" << m_globs; +} + +QStringList QQuickFileNameFilter::nameFilters() const +{ + return m_options ? m_options->nameFilters() : QStringList(); +} + +QString QQuickFileNameFilter::nameFilter(int index) const +{ + return m_options ? m_options->nameFilters().value(index) : QString(); +} + +QT_END_NAMESPACE diff --git a/src/quickdialogs2/quickdialogs2utils/qquickfilenamefilter_p.h b/src/quickdialogs2/quickdialogs2utils/qquickfilenamefilter_p.h new file mode 100644 index 0000000000..586da8698a --- /dev/null +++ b/src/quickdialogs2/quickdialogs2utils/qquickfilenamefilter_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QQUICKFILENAMEFILTER_P_H +#define QQUICKFILENAMEFILTER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qobject.h> +#include <QtCore/qsharedpointer.h> +#include <QtCore/qstringlist.h> +#include <QtGui/qpa/qplatformdialoghelper.h> + +#include "qtquickdialogs2utilsglobal_p.h" + +QT_BEGIN_NAMESPACE + +class Q_QUICKDIALOGS2UTILS_PRIVATE_EXPORT QQuickFileNameFilter : public QObject +{ + Q_OBJECT + Q_PROPERTY(int index READ index WRITE setIndex NOTIFY indexChanged FINAL) + Q_PROPERTY(QString name READ name NOTIFY nameChanged FINAL) + Q_PROPERTY(QStringList extensions READ extensions NOTIFY extensionsChanged FINAL) + Q_PROPERTY(QStringList globs READ globs NOTIFY globsChanged FINAL) + +public: + explicit QQuickFileNameFilter(QObject *parent = nullptr); + + int index() const; + void setIndex(int index); + + QString name() const; + QStringList extensions() const; + QStringList globs() const; + + QSharedPointer<QFileDialogOptions> options() const; + void setOptions(const QSharedPointer<QFileDialogOptions> &options); + + void update(const QString &filter); + +Q_SIGNALS: + void indexChanged(int index); + void nameChanged(const QString &name); + void extensionsChanged(const QStringList &extensions); + void globsChanged(const QStringList &globs); + +private: + QStringList nameFilters() const; + QString nameFilter(int index) const; + + int m_index; + QString m_name; + QStringList m_extensions; + QStringList m_globs; + QSharedPointer<QFileDialogOptions> m_options; +}; + +QT_END_NAMESPACE + +#endif // QQUICKFILENAMEFILTER_P_H diff --git a/src/quickdialogs2/quickdialogs2utils/qtquickdialogs2utilsglobal_p.h b/src/quickdialogs2/quickdialogs2utils/qtquickdialogs2utilsglobal_p.h new file mode 100644 index 0000000000..52f7a39784 --- /dev/null +++ b/src/quickdialogs2/quickdialogs2utils/qtquickdialogs2utilsglobal_p.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QTQUICKDIALOGS2UTILSGLOBAL_P_H +#define QTQUICKDIALOGS2UTILSGLOBAL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> + +QT_BEGIN_NAMESPACE + +#ifndef QT_STATIC +# if defined(QT_BUILD_QUICKDIALOGS2UTILS_LIB) +# define Q_QUICKDIALOGS2UTILS_PRIVATE_EXPORT Q_DECL_EXPORT +# else +# define Q_QUICKDIALOGS2UTILS_PRIVATE_EXPORT Q_DECL_IMPORT +# endif +#else +# define Q_QUICKDIALOGS2UTILS_PRIVATE_EXPORT +#endif + +QT_END_NAMESPACE + +#endif // QTQUICKDIALOGS2UTILSUTILSGLOBAL_P_H |