diff options
Diffstat (limited to 'src/imports/dialogs')
19 files changed, 1927 insertions, 0 deletions
diff --git a/src/imports/dialogs/DefaultFileDialog.qml b/src/imports/dialogs/DefaultFileDialog.qml new file mode 100644 index 0000000000..80bf6b5cb1 --- /dev/null +++ b/src/imports/dialogs/DefaultFileDialog.qml @@ -0,0 +1,366 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Dialogs 1.0 +import Qt.labs.folderlistmodel 2.0 +import "qml" + +AbstractFileDialog { + id: root + onVisibleChanged: { + if (visible) { + selectedIndices = [] + lastClickedIdx = -1 + currentPathField.visible = false + } + } + + property bool showFocusHighlight: false + property real textX: 28 + property SystemPalette palette + property var selectedIndices: [] + property int lastClickedIdx: -1 + folder: urlToPath(view.model.folder) + + function dirDown(path) { + view.model.folder = path + lastClickedIdx = -1 + selectedIndices = [] + } + function dirUp() { + view.model.folder = view.model.parentFolder + lastClickedIdx = -1 + selectedIndices = [] + } + function up(extend) { + if (view.currentIndex > 0) + --view.currentIndex + else + view.currentIndex = 0 + if (extend) { + if (selectedIndices.indexOf(view.currentIndex) < 0) { + var selCopy = selectedIndices + selCopy.push(view.currentIndex) + selectedIndices = selCopy + } + } else + selectedIndices = [view.currentIndex] + } + function down(extend) { + if (view.currentIndex < view.model.count - 1) + ++view.currentIndex + else + view.currentIndex = view.model.count - 1 + if (extend) { + if (selectedIndices.indexOf(view.currentIndex) < 0) { + var selCopy = selectedIndices + selCopy.push(view.currentIndex) + selectedIndices = selCopy + } + } else + selectedIndices = [view.currentIndex] + } + function acceptSelection() { + clearSelection() + if (selectFolder && selectedIndices.length == 0) + addSelection(folder) + else { + selectedIndices.map(function(idx) { + if (view.model.isFolder(idx)) { + if (selectFolder) + addSelection(view.model.get(idx, "filePath")) + } else { + if (!selectFolder) + addSelection(view.model.get(idx, "filePath")) + } + }) + } + accept() + } + + Rectangle { + width: 480 // TODO: QTBUG-29817 geometry from AbstractFileDialog + height: 320 + id: window + color: palette.window + anchors.centerIn: Qt.application.supportsMultipleWindows ? null : parent + + SystemPalette { id: palette } + + Component { + id: folderDelegate + Rectangle { + id: wrapper + function launch() { + if (view.model.isFolder(index)) { + dirDown(filePath) + } else { + root.acceptSelection() + } + } + width: window.width + height: nameText.implicitHeight * 1.5 + color: "transparent" + Rectangle { + id: itemHighlight + visible: root.selectedIndices.indexOf(index) >= 0 + anchors.fill: parent + color: palette.highlight + } + Image { + id: icon + source: "images/folder.png" + height: wrapper.height - y * 2; width: height + x: (root.textX - width) / 2 + y: 2 + visible: view.model.isFolder(index) + } + Text { + id: nameText + anchors.fill: parent; verticalAlignment: Text.AlignVCenter + text: fileName + anchors.leftMargin: root.textX + color: itemHighlight.visible ? palette.highlightedText : palette.windowText + elide: Text.ElideRight + } + MouseArea { + id: mouseRegion + anchors.fill: parent + onDoubleClicked: { + selectedIndices = [index] + root.lastClickedIdx = index + launch() + } + onClicked: { + view.currentIndex = index + if (mouse.modifiers & Qt.ControlModifier && root.selectMultiple) { + // modifying the contents of selectedIndices doesn't notify, + // so we have to re-assign the variable + var selCopy = selectedIndices + var existingIdx = selCopy.indexOf(index) + if (existingIdx >= 0) + selCopy.splice(existingIdx, 1) + else + selCopy.push(index) + selectedIndices = selCopy + } else if (mouse.modifiers & Qt.ShiftModifier && root.selectMultiple) { + if (root.lastClickedIdx >= 0) { + var sel = [] + if (index > lastClickedIdx) { + for (var i = root.lastClickedIdx; i <= index; i++) + sel.push(i) + } else { + for (var i = root.lastClickedIdx; i >= index; i--) + sel.push(i) + } + selectedIndices = sel + } + } else { + selectedIndices = [index] + root.lastClickedIdx = index + } + } + } + } + } + + ListView { + id: view + anchors.top: titleBar.bottom + anchors.bottom: bottomBar.top + clip: true + x: 0 + width: parent.width + model: FolderListModel { } + delegate: folderDelegate + highlight: Rectangle { + color: "transparent" + border.color: palette.midlight + } + highlightMoveDuration: 0 + highlightMoveVelocity: -1 + focus: !currentPathField.visible + Keys.onPressed: { + event.accepted = true + switch (event.key) { + case Qt.Key_Up: + root.up(event.modifiers & Qt.ShiftModifier && root.selectMultiple) + break + case Qt.Key_Down: + root.down(event.modifiers & Qt.ShiftModifier && root.selectMultiple) + break + case Qt.Key_Left: + root.dirUp() + break + case Qt.Key_Return: + case Qt.Key_Select: + case Qt.Key_Right: + if (view.currentItem) + view.currentItem.launch() + else + root.acceptSelection() + break + default: + // do nothing + event.accepted = false + break + } + } + } + + MouseArea { + anchors.fill: view + enabled: currentPathField.visible + onClicked: currentPathField.visible = false + } + + + Item { + id: titleBar + width: parent.width + height: currentPathField.height * 1.5 + BorderImage { + source: "images/titlebar.sci" + anchors.fill: parent + anchors.topMargin: -7 + anchors.bottomMargin: -7 + } + Rectangle { + id: upButton + width: root.textX + height: titleBar.height + color: "transparent" + + Image { + id: upButtonImage + anchors.centerIn: parent; source: "images/up.png" + } + MouseArea { id: upRegion; anchors.centerIn: parent + width: 56 + height: parent.height + onClicked: if (view.model.parentFolder != "") dirUp() + } + states: [ + State { + name: "pressed" + when: upRegion.pressed + PropertyChanges { target: upButton; color: palette.highlight } + } + ] + } + Text { + id: currentPathText + anchors.left: parent.left; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: textX; anchors.rightMargin: 4 + text: root.urlToPath(view.model.folder) + color: "white" + elide: Text.ElideLeft; horizontalAlignment: Text.AlignRight; verticalAlignment: Text.AlignVCenter + MouseArea { + anchors.fill: parent + onClicked: currentPathField.visible = true + } + } + TextField { + id: currentPathField + anchors.left: parent.left; anchors.right: parent.right; anchors.verticalCenter: parent.verticalCenter + anchors.leftMargin: textX; anchors.rightMargin: 4 + visible: false + focus: visible + text: root.urlToPath(view.model.folder) + onAccepted: { + root.clearSelection() + if (root.addSelection(text)) + root.accept() + else + view.model.folder = root.pathFolder(text) + } + onDownPressed: currentPathField.visible = false + } + } + Rectangle { + id: bottomBar + width: parent.width + height: buttonRow.height + buttonRow.spacing * 2 + anchors.bottom: parent.bottom + gradient: Gradient { + GradientStop { position: 0.0; color: palette.dark } + GradientStop { position: 0.3; color: palette.mid } + GradientStop { position: 0.85; color: palette.mid } + GradientStop { position: 1.0; color: palette.light } + } + + Row { + id: buttonRow + anchors.right: parent.right + anchors.rightMargin: spacing + anchors.verticalCenter: parent.verticalCenter + spacing: 4 + TextField { + id: filterField + text: root.selectedNameFilter + visible: !selectFolder + width: bottomBar.width - cancelButton.width - okButton.width - parent.spacing * 5 + anchors.verticalCenter: parent.verticalCenter + onAccepted: { + root.selectNameFilter(text) + view.model.nameFilters = text + } + } + Button { + id: cancelButton + text: "Cancel" + onClicked: root.reject() + } + Button { + id: okButton + text: "OK" + onClicked: { + if (view.model.isFolder(view.currentIndex) && !selectFolder) + dirDown(view.model.get(view.currentIndex, "filePath")) + else + root.acceptSelection() + } + } + } + } + } +} diff --git a/src/imports/dialogs/WidgetFileDialog.qml b/src/imports/dialogs/WidgetFileDialog.qml new file mode 100644 index 0000000000..837c7f8a57 --- /dev/null +++ b/src/imports/dialogs/WidgetFileDialog.qml @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.PrivateWidgets 1.0 + +QtFileDialog { } diff --git a/src/imports/dialogs/dialogs.pro b/src/imports/dialogs/dialogs.pro new file mode 100644 index 0000000000..1a8ec05b85 --- /dev/null +++ b/src/imports/dialogs/dialogs.pro @@ -0,0 +1,30 @@ +CXX_MODULE = qml +TARGET = dialogplugin +TARGETPATH = QtQuick/Dialogs +IMPORT_VERSION = 1.0 + +SOURCES += \ + plugin.cpp \ + qquickabstractfiledialog.cpp \ + qquickplatformfiledialog.cpp \ + qquickfiledialog.cpp + +HEADERS += \ + qquickabstractfiledialog_p.h \ + qquickplatformfiledialog_p.h \ + qquickfiledialog_p.h + +QML_FILES += \ + DefaultFileDialog.qml \ + WidgetFileDialog.qml \ + qml/Button.qml \ + qml/TextField.qml \ + qml/qmldir \ + images/folder.png \ + images/titlebar.png \ + images/titlebar.sci \ + images/up.png + +QT += quick-private gui-private core-private + +load(qml_plugin) diff --git a/src/imports/dialogs/images/folder.png b/src/imports/dialogs/images/folder.png Binary files differnew file mode 100644 index 0000000000..e53e2ad464 --- /dev/null +++ b/src/imports/dialogs/images/folder.png diff --git a/src/imports/dialogs/images/titlebar.png b/src/imports/dialogs/images/titlebar.png Binary files differnew file mode 100644 index 0000000000..51c90082d0 --- /dev/null +++ b/src/imports/dialogs/images/titlebar.png diff --git a/src/imports/dialogs/images/titlebar.sci b/src/imports/dialogs/images/titlebar.sci new file mode 100644 index 0000000000..0418d94cd6 --- /dev/null +++ b/src/imports/dialogs/images/titlebar.sci @@ -0,0 +1,5 @@ +border.left: 10 +border.top: 12 +border.bottom: 12 +border.right: 10 +source: titlebar.png diff --git a/src/imports/dialogs/images/up.png b/src/imports/dialogs/images/up.png Binary files differnew file mode 100644 index 0000000000..b05f8025d0 --- /dev/null +++ b/src/imports/dialogs/images/up.png diff --git a/src/imports/dialogs/plugin.cpp b/src/imports/dialogs/plugin.cpp new file mode 100644 index 0000000000..46bd0dcb9d --- /dev/null +++ b/src/imports/dialogs/plugin.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtQml/qqml.h> +#include <QtQml/qqmlextensionplugin.h> +#include "qquickfiledialog_p.h" +#include "qquickabstractfiledialog_p.h" +#include "qquickplatformfiledialog_p.h" +#include <private/qguiapplication_p.h> + +//#define PURE_QML_ONLY + +QT_BEGIN_NAMESPACE + +/*! + \qmlmodule QtQuick.Dialogs 1 + \title Qt Quick Dialog QML Types + \ingroup qmlmodules + \brief Provides QML types for standard file, color picker and message dialogs + + This QML module contains types for creating and interacting with system dialogs. + + To use the types in this module, import the module with the following line: + + \code + import QtQuick.Dialogs 1.0 + \endcode +*/ + +class QtQuick2DialogsPlugin : public QQmlExtensionPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") + +public: + QtQuick2DialogsPlugin() : QQmlExtensionPlugin() { } + + virtual void initializeEngine(QQmlEngine *, const char *uri) { + bool needQml = false; + QDir qmlDir(baseUrl().toLocalFile()); + // If there is no support for native dialogs on the platform, we need to + // either re-use QFileDialog, or register a QML implementation instead. +#ifdef PURE_QML_ONLY + needQml = true; +#else + if (!QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::FileDialog)) { + needQml = true; + // If there is not a QApplication, there's no point in trying to load + // widget-based dialogs, because a runtime error will occur. + if (QCoreApplication::instance()->metaObject()->className() == QLatin1String("QApplication")) { + // Test whether PrivateWidgets can load. It's not currently possible + // to use the given engine for that, so we need to create a temporary one. + // That doesn't work in registerTypes either, which is why it's done here. + QString dialogQmlPath(qmlDir.filePath("WidgetFileDialog.qml")); + QQmlEngine tempEngine; + QQmlComponent widgetDialogComponent(&tempEngine); + QFile widgetDialogQmlFile(dialogQmlPath); + widgetDialogQmlFile.open(QIODevice::ReadOnly); + widgetDialogComponent.setData(widgetDialogQmlFile.readAll(), QUrl()); + + switch (widgetDialogComponent.status()) { + case QQmlComponent::Ready: + needQml = (qmlRegisterType(QUrl::fromLocalFile(dialogQmlPath), uri, 1, 0, "FileDialog") < 0); + // returns -1 unless we omit the module from qmldir, because otherwise + // QtQuick.Dialogs is already a protected namespace + // after the qmldir having been parsed. (QQmlImportDatabase::importPlugin) + // But omitting the module from qmldir results in this warning: + // "Module 'QtQuick.Dialogs' does not contain a module identifier directive - + // it cannot be protected from external registrations." + // TODO register all types in registerTypes, to avoid the warning + // But, in that case we cannot check for existence by trying to instantiate the component. + // So it will have to just look for a file (qmldir?) and assume + // that whatever modules are installed are also in working order. + break; + default: + break; + } + } + } +#endif + if (needQml) { + QString dialogQmlPath = qmlDir.filePath("DefaultFileDialog.qml"); + qmlRegisterType<QQuickFileDialog>(uri, 1, 0, "AbstractFileDialog"); // implementation wrapper + // qDebug() << "registering FileDialog as " << dialogQmlPath << "success?" << + qmlRegisterType(QUrl::fromLocalFile(dialogQmlPath), uri, 1, 0, "FileDialog"); + } + } + + virtual void registerTypes(const char *uri) { + Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Dialogs")); + +#ifndef PURE_QML_ONLY + // Prefer the QPA file dialog helper if the platform supports it + if (QGuiApplicationPrivate::platformTheme()->usePlatformNativeDialog(QPlatformTheme::FileDialog)) + qmlRegisterType<QQuickPlatformFileDialog>(uri, 1, 0, "FileDialog"); +#endif + } +}; + +QT_END_NAMESPACE + +#include "plugin.moc" diff --git a/src/imports/dialogs/plugins.qmltypes b/src/imports/dialogs/plugins.qmltypes new file mode 100644 index 0000000000..faf68de909 --- /dev/null +++ b/src/imports/dialogs/plugins.qmltypes @@ -0,0 +1,72 @@ +import QtQuick.tooling 1.1 + +// This file describes the plugin-supplied types contained in the library. +// It is used for QML tooling purposes only. +// +// This file was auto-generated with the command 'qmlplugindump QtQuick.Dialogs 1.0'. + +Module { + Component { + name: "QQuickAbstractFileDialog" + prototype: "QObject" + Property { name: "visible"; type: "bool" } + Property { name: "modality"; type: "Qt::WindowModality" } + Property { name: "title"; type: "string" } + Property { name: "selectExisting"; type: "bool" } + Property { name: "selectMultiple"; type: "bool" } + Property { name: "selectFolder"; type: "bool" } + Property { name: "folder"; type: "string" } + Property { name: "nameFilters"; type: "QStringList" } + Property { name: "selectedNameFilter"; type: "string" } + Property { name: "filePath"; type: "string"; isReadonly: true } + Property { name: "filePaths"; type: "QStringList"; isReadonly: true } + Signal { name: "visibilityChanged" } + Signal { name: "filterSelected" } + Signal { name: "fileModeChanged" } + Signal { name: "accepted" } + Signal { name: "rejected" } + Method { name: "open" } + Method { name: "close" } + Method { + name: "setVisible" + Parameter { name: "v"; type: "bool" } + } + Method { + name: "setModality" + Parameter { name: "m"; type: "Qt::WindowModality" } + } + Method { + name: "setTitle" + Parameter { name: "t"; type: "string" } + } + Method { + name: "setSelectExisting" + Parameter { name: "s"; type: "bool" } + } + Method { + name: "setSelectMultiple" + Parameter { name: "s"; type: "bool" } + } + Method { + name: "setSelectFolder" + Parameter { name: "s"; type: "bool" } + } + Method { + name: "setFolder" + Parameter { name: "f"; type: "string" } + } + Method { + name: "setNameFilters" + Parameter { name: "f"; type: "QStringList" } + } + Method { + name: "selectNameFilter" + Parameter { name: "f"; type: "string" } + } + } + Component { + name: "QQuickQFileDialog" + prototype: "QQuickAbstractFileDialog" + exports: ["QtQuick.PrivateWidgets/QtFileDialog 1.0"] + } +} diff --git a/src/imports/dialogs/qml/Button.qml b/src/imports/dialogs/qml/Button.qml new file mode 100644 index 0000000000..42ee9f79e8 --- /dev/null +++ b/src/imports/dialogs/qml/Button.qml @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 + +Item { + height: label.implicitHeight * 2 + width: Math.max(label.implicitWidth * 1.2, height * 2.5); + anchors.verticalCenter: parent.verticalCenter + property alias text: label.text + property string tooltip + signal clicked + SystemPalette { id: palette } + Rectangle { + antialiasing: true + border.color: mouseArea.pressed ? palette.highlight : palette.light + color: "transparent" + anchors.fill: parent + anchors.rightMargin: 1 + anchors.bottomMargin: 1 + radius: 3 + } + Rectangle { + border.color: palette.dark + anchors.fill: parent + anchors.leftMargin: 1 + anchors.topMargin: 1 + radius: 3 + } + Rectangle { + gradient: Gradient { + GradientStop { position: 0.0; color: mouseArea.pressed ? palette.dark : palette.light } + GradientStop { position: 0.2; color: palette.button } + GradientStop { position: 0.8; color: palette.button } + GradientStop { position: 1.0; color: mouseArea.pressed ? palette.light : palette.dark } + } + anchors.fill: parent + anchors.margins: 1 + radius: 3 + } + Text { + id: label + anchors.centerIn: parent + color: palette.buttonText + } + + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: parent.clicked() + } +} diff --git a/src/imports/dialogs/qml/TextField.qml b/src/imports/dialogs/qml/TextField.qml new file mode 100644 index 0000000000..204eef71b9 --- /dev/null +++ b/src/imports/dialogs/qml/TextField.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 + +Item { + id: root + + property alias textInput: textInput + property alias text: textInput.text + signal accepted + signal downPressed + + SystemPalette { id: palette } + height: textInput.implicitHeight + 4 + Rectangle { + id: rect + anchors.fill: parent + anchors.leftMargin: -radius + border.color: palette.light + radius: height / 4 + antialiasing: true + gradient: Gradient { + GradientStop { position: 0.0; color: palette.dark } + GradientStop { position: 0.2; color: palette.button } + GradientStop { position: 0.8; color: palette.button } + GradientStop { position: 1.0; color: palette.light } + } + } + + TextInput { + id: textInput + color: palette.text + anchors.fill: parent + verticalAlignment: Text.AlignVCenter + onAccepted: root.accepted() + Keys.onDownPressed: root.downPressed() + } +} diff --git a/src/imports/dialogs/qml/qmldir b/src/imports/dialogs/qml/qmldir new file mode 100644 index 0000000000..85575c738a --- /dev/null +++ b/src/imports/dialogs/qml/qmldir @@ -0,0 +1,2 @@ +Button 1.0 Button.qml +TextField 1.0 TextField.qml diff --git a/src/imports/dialogs/qmldir b/src/imports/dialogs/qmldir new file mode 100644 index 0000000000..50867d7361 --- /dev/null +++ b/src/imports/dialogs/qmldir @@ -0,0 +1,2 @@ +plugin dialogplugin +typeinfo plugins.qmltypes diff --git a/src/imports/dialogs/qquickabstractfiledialog.cpp b/src/imports/dialogs/qquickabstractfiledialog.cpp new file mode 100644 index 0000000000..905cb5d030 --- /dev/null +++ b/src/imports/dialogs/qquickabstractfiledialog.cpp @@ -0,0 +1,233 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickabstractfiledialog_p.h" +#include "qquickitem.h" + +#include <private/qguiapplication_p.h> +#include <QWindow> +#include <QQuickWindow> + +QT_BEGIN_NAMESPACE + +QQuickAbstractFileDialog::QQuickAbstractFileDialog(QObject *parent) + : QObject(parent) + , m_dlgHelper(0) + , m_parentWindow(0) + , m_options(QSharedPointer<QFileDialogOptions>(new QFileDialogOptions())) + , m_visible(false) + , m_modality(Qt::WindowModal) + , m_selectExisting(true) + , m_selectMultiple(false) + , m_selectFolder(false) +{ +} + +QQuickAbstractFileDialog::~QQuickAbstractFileDialog() +{ +} + +void QQuickAbstractFileDialog::setVisible(bool v) +{ + if (m_visible == v) return; + m_visible = v; + if (helper()) { + if (v) { + helper()->setOptions(m_options); + helper()->setFilter(); + m_visible = helper()->show(Qt::Dialog, m_modality, parentWindow()); + emit filterSelected(); + } else { + helper()->hide(); + } + } + + emit visibilityChanged(); +} + +void QQuickAbstractFileDialog::setModality(Qt::WindowModality m) +{ + if (m_modality == m) return; + m_modality = m; + emit modalityChanged(); +} + +void QQuickAbstractFileDialog::setTitle(QString t) +{ + if (m_options->windowTitle() == t) return; + m_options->setWindowTitle(t); + emit titleChanged(); +} + +void QQuickAbstractFileDialog::setSelectExisting(bool selectExisting) +{ + if (selectExisting == m_selectExisting) return; + m_selectExisting = selectExisting; + updateModes(); +} + +void QQuickAbstractFileDialog::setSelectMultiple(bool selectMultiple) +{ + if (selectMultiple == m_selectMultiple) return; + m_selectMultiple = selectMultiple; + updateModes(); +} + +void QQuickAbstractFileDialog::setSelectFolder(bool selectFolder) +{ + if (selectFolder == m_selectFolder) return; + m_selectFolder = selectFolder; + updateModes(); +} + +QString QQuickAbstractFileDialog::folder() +{ + if (m_dlgHelper && !m_dlgHelper->directory().isEmpty()) + return m_dlgHelper->directory(); + return m_options->initialDirectory(); +} + +void QQuickAbstractFileDialog::setFolder(QString f) +{ + if (m_dlgHelper) + m_dlgHelper->setDirectory(f); + m_options->setInitialDirectory(f); + emit folderChanged(); +} + +void QQuickAbstractFileDialog::setNameFilters(const QStringList &f) +{ + m_options->setNameFilters(f); + if (f.isEmpty()) + selectNameFilter(QString()); + else if (!f.contains(selectedNameFilter())) + selectNameFilter(f.first()); + emit nameFiltersChanged(); +} + +QString QQuickAbstractFileDialog::selectedNameFilter() +{ + QString ret; + if (m_dlgHelper) + ret = m_dlgHelper->selectedNameFilter(); + if (ret.isEmpty()) + return m_options->initiallySelectedNameFilter(); + return ret; +} + +void QQuickAbstractFileDialog::selectNameFilter(QString f) +{ + // This should work whether the dialog is currently being shown already, or ahead of time. + m_options->setInitiallySelectedNameFilter(f); + if (m_dlgHelper) + m_dlgHelper->selectNameFilter(f); + emit filterSelected(); +} + +QUrl QQuickAbstractFileDialog::fileUrl() +{ + QList<QUrl> urls = fileUrls(); + return (urls.count() == 1) ? urls[0] : QUrl(); +} + +QList<QUrl> QQuickAbstractFileDialog::fileUrls() +{ + QList<QUrl> ret; + if (m_dlgHelper) + foreach (QString path, m_dlgHelper->selectedFiles()) + ret << QUrl::fromLocalFile(path); + return ret; +} + +void QQuickAbstractFileDialog::accept() +{ + setVisible(false); + emit accepted(); +} + +void QQuickAbstractFileDialog::reject() +{ + setVisible(false); + emit rejected(); +} + +void QQuickAbstractFileDialog::visibleChanged(bool v) +{ + m_visible = v; + emit visibilityChanged(); +} + +void QQuickAbstractFileDialog::updateModes() +{ + // The 4 possible modes are AnyFile, ExistingFile, Directory, ExistingFiles + // Assume AnyFile until we find a reason to the contrary + QFileDialogOptions::FileMode mode = QFileDialogOptions::AnyFile; + + if (m_selectFolder) { + mode = QFileDialogOptions::Directory; + m_options->setOption(QFileDialogOptions::ShowDirsOnly); + m_selectMultiple = false; + m_selectExisting = true; + setNameFilters(QStringList()); + } else if (m_selectExisting) { + mode = m_selectMultiple ? + QFileDialogOptions::ExistingFiles : QFileDialogOptions::ExistingFile; + m_options->setOption(QFileDialogOptions::ShowDirsOnly, false); + } else if (m_selectMultiple) { + m_selectExisting = true; + } + if (!m_selectExisting) + m_selectMultiple = false; + m_options->setFileMode(mode); + m_options->setAcceptMode(m_selectExisting ? + QFileDialogOptions::AcceptOpen : QFileDialogOptions::AcceptSave); + emit fileModeChanged(); +} + +QQuickWindow *QQuickAbstractFileDialog::parentWindow() +{ + QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); + if (parentItem) + m_parentWindow = parentItem->window(); + return m_parentWindow; +} + +QT_END_NAMESPACE diff --git a/src/imports/dialogs/qquickabstractfiledialog_p.h b/src/imports/dialogs/qquickabstractfiledialog_p.h new file mode 100644 index 0000000000..e9565108d6 --- /dev/null +++ b/src/imports/dialogs/qquickabstractfiledialog_p.h @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQUICKABSTRACTFILEDIALOG_P_H +#define QQUICKABSTRACTFILEDIALOG_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> +#include <QQuickView> +#include <QtGui/qpa/qplatformdialoghelper.h> +#include <qpa/qplatformtheme.h> + +QT_BEGIN_NAMESPACE + +class QQuickAbstractFileDialog : public QObject +{ + Q_OBJECT + Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibilityChanged) + Q_PROPERTY(Qt::WindowModality modality READ modality WRITE setModality NOTIFY modalityChanged) + Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) + Q_PROPERTY(bool selectExisting READ selectExisting WRITE setSelectExisting NOTIFY fileModeChanged) + Q_PROPERTY(bool selectMultiple READ selectMultiple WRITE setSelectMultiple NOTIFY fileModeChanged) + Q_PROPERTY(bool selectFolder READ selectFolder WRITE setSelectFolder NOTIFY fileModeChanged) + Q_PROPERTY(QString folder READ folder WRITE setFolder NOTIFY folderChanged) + Q_PROPERTY(QStringList nameFilters READ nameFilters WRITE setNameFilters NOTIFY nameFiltersChanged) + Q_PROPERTY(QString selectedNameFilter READ selectedNameFilter WRITE selectNameFilter NOTIFY filterSelected) + Q_PROPERTY(QUrl fileUrl READ fileUrl NOTIFY accepted) + Q_PROPERTY(QList<QUrl> fileUrls READ fileUrls NOTIFY accepted) + // TODO: QTBUG-29817: provide x y width and height (after QPlatformDialogHelper provides it) + +public: + QQuickAbstractFileDialog(QObject *parent = 0); + virtual ~QQuickAbstractFileDialog(); + + bool isVisible() const { return m_visible; } + Qt::WindowModality modality() const { return m_modality; } + QString title() const { return m_options->windowTitle(); } + bool selectExisting() const { return m_selectExisting; } + bool selectMultiple() const { return m_selectMultiple; } + bool selectFolder() const { return m_selectFolder; } + QString folder(); + QStringList nameFilters() const { return m_options->nameFilters(); } + QString selectedNameFilter(); + QUrl fileUrl(); + virtual QList<QUrl> fileUrls(); + +public Q_SLOTS: + void open() { setVisible(true); } + void close() { setVisible(false); } + virtual void setVisible(bool v); + void setModality(Qt::WindowModality m); + void setTitle(QString t); + void setSelectExisting(bool s); + void setSelectMultiple(bool s); + void setSelectFolder(bool s); + void setFolder(QString f); + void setNameFilters(const QStringList &f); + void selectNameFilter(QString f); + +Q_SIGNALS: + void visibilityChanged(); + void modalityChanged(); + void titleChanged(); + void folderChanged(); + void nameFiltersChanged(); + void filterSelected(); + void fileModeChanged(); + void accepted(); + void rejected(); + +protected Q_SLOTS: + void accept(); + void reject(); + void visibleChanged(bool v); + +protected: + virtual QPlatformFileDialogHelper *helper() = 0; + void updateModes(); + QQuickWindow *parentWindow(); + +protected: + QPlatformFileDialogHelper *m_dlgHelper; + QQuickWindow *m_parentWindow; + QSharedPointer<QFileDialogOptions> m_options; + bool m_visible; + Qt::WindowModality m_modality; + bool m_selectExisting; + bool m_selectMultiple; + bool m_selectFolder; + + Q_DISABLE_COPY(QQuickAbstractFileDialog) +}; + +QT_END_NAMESPACE + +#endif // QQUICKABSTRACTFILEDIALOG_P_H diff --git a/src/imports/dialogs/qquickfiledialog.cpp b/src/imports/dialogs/qquickfiledialog.cpp new file mode 100644 index 0000000000..89b8b4cc5b --- /dev/null +++ b/src/imports/dialogs/qquickfiledialog.cpp @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickfiledialog_p.h" +#include <QQuickItem> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype AbstractFileDialog + \instantiates QQuickFileDialog + \inqmlmodule QtQuick.Dialogs 1 + \ingroup qtquick-visual + \brief API wrapper for QML file dialog implementations + \since 5.1 + \internal + + AbstractFileDialog provides only the API for implementing a file dialog. + The implementation (e.g. a Window or Item) can be provided as \l implementation, + which is the default property (the only allowed child element). +*/ + +/*! + \qmlsignal QtQuick::Dialogs::AbstractFileDialog::accepted + + The \a accepted signal is emitted by \l accept(). +*/ + +/*! + \qmlsignal QtQuick::Dialogs::AbstractFileDialog::rejected + + The \a accepted signal is emitted by \l reject(). +*/ + +/*! + \class QQuickFileDialog + \inmodule QtQuick.Dialogs + \internal + + The QQuickFileDialog class is a concrete subclass of \l + QQuickAbstractFileDialog, but it is abstract from the QML perspective + because it needs to enclose a graphical implementation. It exists in order + to provide accessors and helper functions which the QML implementation will + need. + + \since 5.1 +*/ + +/*! + Constructs a file dialog wrapper with parent window \a parent. +*/ +QQuickFileDialog::QQuickFileDialog(QObject *parent) + : QQuickAbstractFileDialog(parent) + , m_implementation(0) + , m_dialogWindow(0) +{ +} + + +/*! + Destroys the file dialog wrapper. +*/ +QQuickFileDialog::~QQuickFileDialog() +{ +} + +QList<QUrl> QQuickFileDialog::fileUrls() +{ + QList<QUrl> ret; + foreach (QString path, m_selections) + ret << QUrl::fromLocalFile(path); + return ret; +} + +/*! + \qmlproperty bool AbstractFileDialog::visible + + This property holds whether the dialog is visible. By default this is false. +*/ +void QQuickFileDialog::setVisible(bool v) +{ + if (m_visible == v) return; + m_visible = v; + // For a pure QML implementation, there is no helper. + // But m_implementation is probably either an Item or a Window at this point. + if (!m_dialogWindow) { + m_dialogWindow = qobject_cast<QWindow *>(m_implementation); + if (!m_dialogWindow) { + QQuickItem *dlgItem = qobject_cast<QQuickItem *>(m_implementation); + if (dlgItem) { + m_dialogWindow = dlgItem->window(); + // An Item-based dialog implementation doesn't come with a window, so + // we have to instantiate one iff the platform allows it. + if (!m_dialogWindow && QGuiApplicationPrivate::platformIntegration()-> + hasCapability(QPlatformIntegration::MultipleWindows)) { + QQuickWindow *win = new QQuickWindow; + m_dialogWindow = win; + dlgItem->setParentItem(win->contentItem()); + m_dialogWindow->setMinimumSize(QSize(dlgItem->width(), dlgItem->height())); + } + + QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); + // qDebug() << "item implementation" << dlgItem << "has window" << m_dialogWindow << "and parent" << parentItem; + + // If the platform does not support multiple windows, but the dialog is + // implemented as an Item, then just reparent it and make it visible. + // TODO QTBUG-29818: put it into a fake Item-based window, when we have a reusable self-decorated one. + if (parentItem && !m_dialogWindow) + dlgItem->setParentItem(parentItem); + } + } + if (m_dialogWindow) + connect(m_dialogWindow, SIGNAL(visibleChanged(bool)), this, SLOT(visibleChanged(bool))); + } + if (m_dialogWindow) { + if (v) { + m_dialogWindow->setTransientParent(parentWindow()); + m_dialogWindow->setTitle(title()); + m_dialogWindow->setModality(m_modality); + } + m_dialogWindow->setVisible(v); + } + emit visibilityChanged(); +} + +/*! + \qmlproperty bool AbstractFileDialog::filePaths + + A list of files to be populated as the user chooses. +*/ + +/*! + \brief Clears \l filePaths +*/ +void QQuickFileDialog::clearSelection() +{ + m_selections.clear(); +} + +/*! + \brief Adds one file to \l filePaths + + \l path should be given as an absolute file system path. If it is given as a + file:// URL, it will be converted to a path. Returns true on success, + false if the given path is not valid given the current setting properties. +*/ +bool QQuickFileDialog::addSelection(QString path) +{ + if (path.startsWith("file:")) + path = QUrl(path).toLocalFile(); + QFileInfo info(path); + if (info.exists() && ((info.isDir() && m_selectFolder) || !info.isDir())) { + if (m_selectFolder) + m_selections.append(pathFolder(path).toLocalFile()); + else + m_selections.append(path); + return true; + } + return false; +} + +/*! + \brief get a file's directory as a URL + + If \a path points to a directory, just convert it to a URL. + If \a path points to a file, convert the file's directory to a URL. +*/ +QUrl QQuickFileDialog::pathFolder(const QString &path) +{ + QFileInfo info(path); + if (info.exists() && info.isDir()) + return QUrl::fromLocalFile(path); + return QUrl::fromLocalFile(QFileInfo(path).absolutePath()); +} + +/*! + \qmlproperty QObject AbstractFileDialog::implementation + + The QML object which implements the actual file dialog. Should be either a + \l Window or an \l Item. +*/ +void QQuickFileDialog::setImplementation(QObject *obj) +{ + m_implementation = obj; + if (m_dialogWindow) + disconnect(this, SLOT(visibleChanged(bool))); + m_dialogWindow = 0; +} + +QT_END_NAMESPACE diff --git a/src/imports/dialogs/qquickfiledialog_p.h b/src/imports/dialogs/qquickfiledialog_p.h new file mode 100644 index 0000000000..0a660b316b --- /dev/null +++ b/src/imports/dialogs/qquickfiledialog_p.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.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 "qquickabstractfiledialog_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickFileDialog : public QQuickAbstractFileDialog +{ + Q_OBJECT + Q_PROPERTY(QObject* implementation READ implementation WRITE setImplementation DESIGNABLE false) + Q_CLASSINFO("DefaultProperty", "implementation") // AbstractFileDialog in QML can have only one child + +public: + explicit QQuickFileDialog(QObject *parent = 0); + ~QQuickFileDialog(); + QObject* implementation() { return m_implementation; } + virtual QList<QUrl> fileUrls(); + +signals: + +public Q_SLOTS: + void setImplementation(QObject* obj); + virtual void setVisible(bool v); + + void clearSelection(); + bool addSelection(QString path); + +protected: + virtual QPlatformFileDialogHelper *helper() { return 0; } + Q_INVOKABLE QString urlToPath(const QUrl &url) { return url.toLocalFile(); } + Q_INVOKABLE QUrl pathToUrl(const QString &path) { return QUrl::fromLocalFile(path); } + Q_INVOKABLE QUrl pathFolder(const QString &path); + +private: + QObject *m_implementation; + QWindow *m_dialogWindow; + QStringList m_selections; + + Q_DISABLE_COPY(QQuickFileDialog) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickFileDialog *) + +#endif // QQUICKFILEDIALOG_P_H diff --git a/src/imports/dialogs/qquickplatformfiledialog.cpp b/src/imports/dialogs/qquickplatformfiledialog.cpp new file mode 100644 index 0000000000..f2bd279d7b --- /dev/null +++ b/src/imports/dialogs/qquickplatformfiledialog.cpp @@ -0,0 +1,314 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qquickplatformfiledialog_p.h" +#include "qquickitem.h" + +#include <private/qguiapplication_p.h> +#include <QWindow> +#include <QQuickView> +#include <QQuickWindow> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype FileDialog + \instantiates QQuickPlatformFileDialog + \inqmlmodule QtQuick.Dialogs 1 + \ingroup qtquick-visual + \brief Dialog component for choosing files from a local filesystem. + \since 5.1 + + FileDialog provides a basic file chooser: it allows the user to select + existing files and/or directories, or create new filenames. The dialog is + initially invisible. You need to set the properties as desired first, then + set \l visible to true or call \l open(). + + Here is a minimal example to open a file dialog and exit after the user + chooses a file: + + \qml + import QtQuick 2.0 + import QtQuick.Dialogs 1.0 + + FileDialog { + id: fileDialog + title: "Please choose a file" + onAccepted: { + console.log("You chose: " + fileDialog.filePaths) + Qt.quit() + } + onRejected: { + console.log("Cancelled") + Qt.quit() + } + Component.onCompleted: visible = true + } + \endqml + + A FileDialog window is automatically transient for its parent window. So + whether you declare the dialog inside an \l Item or inside a \l Window, the + dialog will appear centered over the window containing the item, or over + the Window that you declared. + + The implementation of FileDialog will be a platform file dialog if + possible. If that isn't possible, then it will try to instantiate a + \l QFileDialog. If that also isn't possible, then it will fall back to a QML + implementation, DefaultFileDialog.qml. In that case you can customize the + appearance by editing this file. DefaultFileDialog.qml contains a Rectangle + to hold the dialog's contents, because certain embedded systems do not + support multiple top-level windows. When the dialog becomes visible, it + will automatically be wrapped in a Window if possible, or simply reparented + on top of the main window if there can only be one window. +*/ + +/*! + \qmlsignal QtQuick::Dialogs::FileDialog::accepted + + The \a accepted signal is emitted when the user has finished using the + dialog. You can then inspect the \a filePath or \a filePaths properties to + get the selection. + + Example: + + \qml + FileDialog { + onAccepted: { console.log("Selected file: " + filePath) } + } + \endqml +*/ + +/*! + \qmlsignal QtQuick::Dialogs::FileDialog::rejected + + The \a rejected signal is emitted when the user has dismissed the dialog, + either by closing the dialog window or by pressing the Cancel button. +*/ + +/*! + \class QQuickPlatformFileDialog + \inmodule QtQuick.Dialogs + \internal + + \brief The QQuickPlatformFileDialog class provides a file dialog + + The dialog is implemented via the QPlatformFileDialogHelper when possible; + otherwise it falls back to a QFileDialog or a QML implementation. + + \since 5.1 +*/ + +/*! + Constructs a file dialog with parent window \a parent. +*/ +QQuickPlatformFileDialog::QQuickPlatformFileDialog(QObject *parent) : + QQuickAbstractFileDialog(parent) +{ +} + +/*! + Destroys the file dialog. +*/ +QQuickPlatformFileDialog::~QQuickPlatformFileDialog() +{ + if (m_dlgHelper) + m_dlgHelper->hide(); + delete m_dlgHelper; +} + +QPlatformFileDialogHelper *QQuickPlatformFileDialog::helper() +{ + QQuickItem *parentItem = qobject_cast<QQuickItem *>(parent()); + if (parentItem) + m_parentWindow = parentItem->window(); + + if ( !m_dlgHelper && QGuiApplicationPrivate::platformTheme()-> + usePlatformNativeDialog(QPlatformTheme::FileDialog) ) { + m_dlgHelper = static_cast<QPlatformFileDialogHelper *>(QGuiApplicationPrivate::platformTheme() + ->createPlatformDialogHelper(QPlatformTheme::FileDialog)); + if (!m_dlgHelper) + return m_dlgHelper; + connect(m_dlgHelper, SIGNAL(directoryEntered(QString)), this, SIGNAL(folderChanged())); + connect(m_dlgHelper, SIGNAL(filterSelected(QString)), this, SIGNAL(filterSelected())); + connect(m_dlgHelper, SIGNAL(accept()), this, SLOT(accept())); + connect(m_dlgHelper, SIGNAL(reject()), this, SLOT(reject())); + } + + return m_dlgHelper; +} + +/*! + \qmlproperty bool FileDialog::visible + + This property holds whether the dialog is visible. By default this is + false. + + \sa modality +*/ + +/*! + \qmlproperty Qt::WindowModality FileDialog::modality + + Whether the dialog should be shown modal with respect to the window + containing the dialog's parent Item, modal with respect to the whole + application, or non-modal. + + By default it is \l WindowModal. + + Modality does not mean that there are any blocking calls to wait for the + dialog to be accepted or rejected; it's only that the user will be + prevented from interacting with the parent window and/or the application + windows at the same time. You probably need to write an onAccepted handler + to actually load or save the chosen file. +*/ + +/*! + \qmlmethod void FileDialog::open() + + Shows the dialog to the user. It is equivalent to setting \l visible to + true. +*/ + +/*! + \qmlmethod void FileDialog::close() + + Closes the dialog. +*/ + +/*! + \qmlproperty string FileDialog::title + + The title of the dialog window. +*/ + +/*! + \qmlproperty bool FileDialog::selectExisting + + Whether only existing files or directories can be selected. + + By default, this property is true. This property must be set to the desired + value before opening the dialog. Setting this property to false implies + that the dialog is for naming a file to which to save something, or naming + a folder to be created; therefore \l selectMultiple must be false. +*/ + +/*! + \qmlproperty bool FileDialog::selectMultiple + + Whether more than one filename can be selected. + + By default, this property is false. This property must be set to the + desired value before opening the dialog. Setting this property to true + implies that \l selectExisting must be true. +*/ + +/*! + \qmlproperty bool FileDialog::selectFolder + + Whether the selected item should be a folder. + + By default, this property is false. This property must be set to the + desired value before opening the dialog. Setting this property to true + implies that \l selectMultiple must be false and \l selectExisting must be + true. +*/ + +/*! + \qmlproperty string FileDialog::folder + + The path to the currently selected folder. Setting this property before + invoking open() will cause the file browser to be initially positioned on + the specified folder. + + The value of this property is also updated after the dialog is closed. + + By default, this property is false. +*/ + +/*! + \qmlproperty list<string> FileDialog::nameFilters + + A list of strings to be used as file name filters. Each string can be a + space-separated list of filters; filters may include the ? and * wildcards. + The list of filters can also be enclosed in parentheses and a textual + description of the filter can be provided. + + For example: + + \qml + FileDialog { + nameFilters: [ "Image files (*.jpg *.png)", "All files (*)" ] + } + \endqml + + \note Directories are not excluded by filters. + \sa selectedNameFilter +*/ + +/*! + \qmlproperty string FileDialog::selectedNameFilter + + Which of the \l nameFilters is currently selected. + + This property can be set before the dialog is visible, to set the default + name filter, and can also be set while the dialog is visible to set the + current name filter. It is also updated when the user selects a different + filter. +*/ + +/*! + \qmlproperty string FileDialog::filePath + + The path of the file which was selected by the user. + + \note This property is set only if exactly one file was selected. In all + other cases, it will return an empty string. + + \sa filePaths +*/ + +/*! + \qmlproperty list<string> FileDialog::filePaths + + The list of file paths which were selected by the user. +*/ + +QT_END_NAMESPACE diff --git a/src/imports/dialogs/qquickplatformfiledialog_p.h b/src/imports/dialogs/qquickplatformfiledialog_p.h new file mode 100644 index 0000000000..3559543319 --- /dev/null +++ b/src/imports/dialogs/qquickplatformfiledialog_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** 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 Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 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 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.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 "qquickabstractfiledialog_p.h" + +QT_BEGIN_NAMESPACE + +class QQuickPlatformFileDialog : public QQuickAbstractFileDialog +{ + Q_OBJECT + +public: + QQuickPlatformFileDialog(QObject *parent = 0); + virtual ~QQuickPlatformFileDialog(); + +protected: + QPlatformFileDialogHelper *helper(); + + Q_DISABLE_COPY(QQuickPlatformFileDialog) +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QQuickPlatformFileDialog *) + +#endif // QQUICKPLATFORMFILEDIALOG_P_H |