Browse Source

added labs based file dialog implementation

pull/2/head
Skycoder42 7 years ago
parent
commit
eed8fd4fab
  1. 2
      examples/mvvmquick/SampleQuick/SampleQuick.pro
  2. 4
      examples/mvvmquick/SampleQuick/main.cpp
  3. 5
      src/imports/mvvmcore/plugins.qmltypes
  4. 5
      src/imports/mvvmquick/AndroidFileDialog.qml
  5. 5
      src/imports/mvvmquick/AndroidFolderDialog.qml
  6. 65
      src/imports/mvvmquick/DialogPresenter.qml
  7. 55
      src/imports/mvvmquick/FileDialog.qml
  8. 39
      src/imports/mvvmquick/FolderDialog.qml
  9. 5
      src/imports/mvvmquick/MsgBoxBase.qml
  10. 1
      src/imports/mvvmquick/mvvmquick.pro
  11. 89
      src/imports/mvvmquick/plugins.qmltypes
  12. 12
      src/imports/mvvmquick/qqmlquickpresenter.cpp
  13. 1
      src/imports/mvvmquick/qqmlquickpresenter.h
  14. 3
      src/imports/mvvmquick/qtmvvmquick_plugin.cpp
  15. 6
      src/imports/mvvmquick/qtmvvmquick_plugin.qrc
  16. 14
      src/mvvmcore/message.cpp
  17. 1
      src/mvvmcore/message.h

2
examples/mvvmquick/SampleQuick/SampleQuick.pro

@ -1,6 +1,6 @@
TEMPLATE = app
QT += core gui qml quick mvvmquick
QT += core gui qml quick mvvmquick widgets
TARGET = SampleQuick

4
examples/mvvmquick/SampleQuick/main.cpp

@ -1,4 +1,4 @@
#include <QGuiApplication>
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtMvvmCore/ServiceRegistry>
#include <QtMvvmQuick/QuickPresenter>
@ -22,7 +22,7 @@ int main(int argc, char *argv[])
#endif
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QApplication app(argc, argv);
qmlRegisterUncreatableType<SampleViewModel>("de.skycoder42.QtMvvm.Sample", 1, 0, "SampleViewModel", QStringLiteral("ViewModels cannot be created"));
qmlRegisterUncreatableType<ResultViewModel>("de.skycoder42.QtMvvm.Sample", 1, 0, "ResultViewModel", QStringLiteral("ViewModels cannot be created"));

5
src/imports/mvvmcore/plugins.qmltypes

@ -71,6 +71,11 @@ Module {
name: "setAutoDelete"
Parameter { name: "autoDelete"; type: "bool" }
}
Method {
name: "setCloseTarget"
Parameter { name: "closeObject"; type: "QObject"; isPointer: true }
Parameter { name: "closeMethod"; type: "string" }
}
Method {
name: "setCloseTarget"
Parameter { name: "closeObject"; type: "QObject"; isPointer: true }

5
src/imports/mvvmquick/AndroidFileDialog.qml

@ -0,0 +1,5 @@
import QtQuick 2.0
Item {
}

5
src/imports/mvvmquick/AndroidFolderDialog.qml

@ -0,0 +1,5 @@
import QtQuick 2.0
Item {
}

65
src/imports/mvvmquick/DialogPresenter.qml

@ -1,6 +1,7 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import de.skycoder42.QtMvvm.Core 1.0
import de.skycoder42.QtMvvm.Quick 1.0
QtObject {
id: _dialogPresenter
@ -8,13 +9,13 @@ QtObject {
property Item rootItem: null
function showDialog(config, result) {
if(config.type == "msgbox") {
createMsgBox(config, result)
return true;
} else if(config.type == "input") {
createInput(config, result)
return true;
} else
if(config.type == "msgbox")
return createMsgBox(config, result)
else if(config.type == "input")
return createInput(config, result)
else if(config.type == "file")
return createFile(config, result)
else
return false;
}
@ -65,6 +66,44 @@ QtObject {
}
}
property Component _fileComponent: Component {
FileDialog {
id: __file
onClosed: {
var index = _popups.indexOf(__file);
if(index > -1) {
__file.destroy();
_dialogPresenter._popups.splice(index, 1);
}
}
Component.onCompleted: {
_popups.push(__file)
__file.open()
}
}
}
property Component _folderComponent: Component {
FolderDialog {
id: __folder
onClosed: {
var index = _popups.indexOf(__folder);
if(index > -1) {
__folder.destroy();
_dialogPresenter._popups.splice(index, 1);
}
}
Component.onCompleted: {
_popups.push(__folder)
__folder.open()
}
}
}
function createMsgBox(config, result) {
var props = config.viewProperties;
props["msgConfig"] = config;
@ -80,4 +119,16 @@ QtObject {
var incubator = _inputComponent.incubateObject(rootItem, props);
return incubator.status !== Component.Error;
}
function createFile(config, result) {
var props = config.viewProperties;
props["msgConfig"] = config;
props["msgResult"] = result;
var incubator = null;
if(config.subType == "folder")
incubator = _folderComponent.incubateObject(rootItem, props);
else
incubator = _fileComponent.incubateObject(rootItem, props);
return incubator.status !== Component.Error;
}
}

55
src/imports/mvvmquick/FileDialog.qml

@ -0,0 +1,55 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import Qt.labs.platform 1.0 as Labs
import de.skycoder42.QtMvvm.Core 1.0
import de.skycoder42.QtMvvm.Quick 1.0
Labs.FileDialog {
id: _fileDialog
property var msgConfig
property MessageResult msgResult
signal closed()
title: msgConfig.title
modality: Qt.WindowModal
folder: msgConfig.defaultValue
fileMode: {
if(msgConfig.subType == "open")
return Labs.FileDialog.OpenFile;
else if(msgConfig.subType == "files")
return Labs.FileDialog.OpenFiles;
else if(msgConfig.subType == "save")
return Labs.FileDialog.SaveFile;
else {
return Labs.FileDialog.OpenFile; //fallback
}
}
nameFilters: QuickPresenter.mimeTypeFilters(msgConfig.viewProperties["mimeTypes"])
Component.onCompleted: {
if(msgResult)
msgResult.setCloseTarget(_fileDialog, "reject()");
}
onAccepted: {
if(msgResult) {
if(msgConfig.subType == "files")
msgResult.result = _fileDialog.files;
else
msgResult.result = _fileDialog.file;
msgResult.complete(MessageConfig.Ok);
msgResult = null;
}
closed();
}
onRejected: {
if(msgResult) {
msgResult.complete(MessageConfig.Cancel);
msgResult = null;
}
closed();
}
}

39
src/imports/mvvmquick/FolderDialog.qml

@ -0,0 +1,39 @@
import QtQuick 2.10
import QtQuick.Controls 2.3
import Qt.labs.platform 1.0 as Labs
import de.skycoder42.QtMvvm.Core 1.0
import de.skycoder42.QtMvvm.Quick 1.0
Labs.FolderDialog {
id: _folderDialog
property var msgConfig
property MessageResult msgResult
signal closed()
title: msgConfig.title
modality: Qt.WindowModal
folder: msgConfig.defaultValue
Component.onCompleted: {
if(msgResult)
msgResult.setCloseTarget(_folderDialog, "reject()");
}
onAccepted: {
if(msgResult) {
msgResult.complete(MessageConfig.Ok, _folderDialog.currentFolder);
msgResult = null;
}
closed();
}
onRejected: {
if(msgResult) {
msgResult.complete(MessageConfig.Cancel);
msgResult = null;
}
closed();
}
}

5
src/imports/mvvmquick/MsgBoxBase.qml

@ -107,4 +107,9 @@ Dialog {
msgResult = null;
}
}
Component.onCompleted: {
if(msgResult)
msgResult.setCloseTarget(_msgBoxBase, "reject()");
}
}

1
src/imports/mvvmquick/mvvmquick.pro

@ -41,6 +41,7 @@ load(qml_plugin)
generate_qmltypes {
qmltypes.depends = ../../../qml/$$TARGETPATH/$(TARGET) #overwrite the target deps
qmltypes.commands += "2>/dev/null" # kill invalid qml warnings
mfirst.target = all
mfirst.depends += qmltypes

89
src/imports/mvvmquick/plugins.qmltypes

@ -33,10 +33,14 @@ Module {
}
Method {
name: "addSimpleView"
type: "bool"
Parameter { name: "type"; type: "QByteArray" }
Parameter { name: "qmlFileUrl"; type: "QUrl" }
}
Method {
name: "addAlias"
Parameter { name: "alias"; type: "QByteArray" }
Parameter { name: "targetType"; type: "QByteArray" }
}
}
Component {
name: "QtMvvm::QQmlQuickPresenter"
@ -66,5 +70,88 @@ Module {
name: "inputViewFactoryChanged"
Parameter { name: "inputViewFactory"; type: "InputViewFactory"; isPointer: true }
}
Method {
name: "mimeTypeFilters"
type: "QStringList"
Parameter { name: "mimeTypes"; type: "QStringList" }
}
}
Component {
prototype: "QObject"
name: "de.skycoder42.QtMvvm.Quick/FileDialog 1.0"
exports: ["de.skycoder42.QtMvvm.Quick/FileDialog 1.0"]
exportMetaObjectRevisions: [0]
isComposite: true
defaultProperty: "data"
Property { name: "msgConfig"; type: "QVariant" }
Property { name: "msgResult"; type: "QtMvvm::MessageResult"; isPointer: true }
Signal { name: "closed" }
Property { name: "fileMode"; type: "FileMode" }
Property { name: "file"; type: "QUrl" }
Property { name: "files"; type: "QList<QUrl>" }
Property { name: "currentFile"; type: "QUrl" }
Property { name: "currentFiles"; type: "QList<QUrl>" }
Property { name: "folder"; type: "QUrl" }
Property { name: "options"; type: "QFileDialogOptions::FileDialogOptions" }
Property { name: "nameFilters"; type: "QStringList" }
Property {
name: "selectedNameFilter"
type: "QQuickPlatformFileNameFilter"
isReadonly: true
isPointer: true
}
Property { name: "defaultSuffix"; type: "string" }
Property { name: "acceptLabel"; type: "string" }
Property { name: "rejectLabel"; type: "string" }
Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "parentWindow"; type: "QWindow"; isPointer: true }
Property { name: "title"; type: "string" }
Property { name: "flags"; type: "Qt::WindowFlags" }
Property { name: "modality"; type: "Qt::WindowModality" }
Property { name: "visible"; type: "bool" }
Property { name: "result"; type: "int" }
Signal { name: "accepted" }
Signal { name: "rejected" }
Method { name: "open" }
Method { name: "close" }
Method { name: "accept" }
Method { name: "reject" }
Method {
name: "done"
Parameter { name: "result"; type: "int" }
}
}
Component {
prototype: "QObject"
name: "de.skycoder42.QtMvvm.Quick/FolderDialog 1.0"
exports: ["de.skycoder42.QtMvvm.Quick/FolderDialog 1.0"]
exportMetaObjectRevisions: [0]
isComposite: true
defaultProperty: "data"
Property { name: "msgConfig"; type: "QVariant" }
Property { name: "msgResult"; type: "QtMvvm::MessageResult"; isPointer: true }
Signal { name: "closed" }
Property { name: "folder"; type: "QUrl" }
Property { name: "currentFolder"; type: "QUrl" }
Property { name: "options"; type: "QFileDialogOptions::FileDialogOptions" }
Property { name: "acceptLabel"; type: "string" }
Property { name: "rejectLabel"; type: "string" }
Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
Property { name: "parentWindow"; type: "QWindow"; isPointer: true }
Property { name: "title"; type: "string" }
Property { name: "flags"; type: "Qt::WindowFlags" }
Property { name: "modality"; type: "Qt::WindowModality" }
Property { name: "visible"; type: "bool" }
Property { name: "result"; type: "int" }
Signal { name: "accepted" }
Signal { name: "rejected" }
Method { name: "open" }
Method { name: "close" }
Method { name: "accept" }
Method { name: "reject" }
Method {
name: "done"
Parameter { name: "result"; type: "int" }
}
}
}

12
src/imports/mvvmquick/qqmlquickpresenter.cpp

@ -42,6 +42,18 @@ qreal QQmlQuickPresenter::loadingProgress() const
return _latestComponent ? _latestComponent->progress() : -1.0;
}
QStringList QQmlQuickPresenter::mimeTypeFilters(const QStringList &mimeTypes) const
{
QMimeDatabase db;
QStringList filters;
for(auto mime : mimeTypes) {
auto mType = db.mimeTypeForName(mime);
if(mType.isValid())
filters.append(mType.filterString());
}
return filters;
}
void QQmlQuickPresenter::present(ViewModel *viewModel, const QVariantHash &params, const QUrl &viewUrl, QPointer<ViewModel> parent)
{
auto component = _componentCache.object(viewUrl);

1
src/imports/mvvmquick/qqmlquickpresenter.h

@ -38,6 +38,7 @@ public:
bool isViewLoading() const;
qreal loadingProgress() const;
Q_INVOKABLE QStringList mimeTypeFilters(const QStringList &mimeTypes) const;
Q_SIGNALS:
void qmlPresenterChanged(QObject* qmlPresenter);

3
src/imports/mvvmquick/qtmvvmquick_plugin.cpp

@ -36,6 +36,9 @@ void QtMvvmQuickDeclarativeModule::registerTypes(const char *uri)
qmlRegisterUncreatableType<QtMvvm::InputViewFactory>(uri, 1, 0, "InputViewFactory", QStringLiteral("InputViewFactories can only be created from C++ via the QuickPresenter"));
qmlRegisterSingletonType<QtMvvm::QQmlQuickPresenter>(uri, 1, 0, "QuickPresenter", createQuickPresenterQmlSingleton);
qmlRegisterType(QUrl(QStringLiteral("qrc:/de/skycoder42/qtmvvm/quick/qml/FileDialog.qml")), uri, 1, 0, "FileDialog");
qmlRegisterType(QUrl(QStringLiteral("qrc:/de/skycoder42/qtmvvm/quick/qml/FolderDialog.qml")), uri, 1, 0, "FolderDialog");
// Check to make shure no module update is forgotten
static_assert(VERSION_MAJOR == 1 && VERSION_MINOR == 0, "QML module version needs to be updated");
}

6
src/imports/mvvmquick/qtmvvmquick_plugin.qrc

@ -5,4 +5,10 @@
<file alias="ic_info.svg">icons/ic_info_white_24px.svg</file>
<file alias="ic_warning.svg">icons/ic_warning_white_24px.svg</file>
</qresource>
<qresource prefix="/de/skycoder42/qtmvvm/quick/qml">
<file>FileDialog.qml</file>
<file>FolderDialog.qml</file>
<file alias="+android/FileDialog.qml">AndroidFileDialog.qml</file>
<file alias="+android/FolderDialog.qml">AndroidFolderDialog.qml</file>
</qresource>
</RCC>

14
src/mvvmcore/message.cpp

@ -1,6 +1,7 @@
#include "message.h"
#include "message_p.h"
#include "coreapp.h"
#include "qtmvvm_logging_p.h"
#include <QtGui/QGuiApplication>
@ -198,6 +199,19 @@ bool MessageResult::autoDelete() const
return d->autoDelete;
}
void MessageResult::setCloseTarget(QObject *closeObject, const QString &closeMethod)
{
Q_ASSERT_X(closeObject, Q_FUNC_INFO, "closeObject must not be null");
auto mo = closeObject->metaObject();
auto mIndex = mo->indexOfMethod(qUtf8Printable(closeMethod));
if(mIndex != -1)
setCloseTarget(closeObject, mo->method(mIndex));
else {
logWarning() << "Object of type" << mo->className()
<< "has no method with signature:" << closeMethod;
}
}
void MessageResult::setCloseTarget(QObject *closeObject, const QMetaMethod &closeMethod)
{
Q_ASSERT_X(closeObject, Q_FUNC_INFO, "closeObject must not be null");

1
src/mvvmcore/message.h

@ -126,6 +126,7 @@ public:
//USE IN GUI ONLY
//TODO USE IN GUI ONLY in doc
Q_INVOKABLE void setCloseTarget(QObject *closeObject, const QString &closeMethod);
Q_INVOKABLE void setCloseTarget(QObject *closeObject, const QMetaMethod &closeMethod);
Q_INVOKABLE void complete(QtMvvm::MessageConfig::StandardButton result);
Q_INVOKABLE inline void complete(QtMvvm::MessageConfig::StandardButton result, const QVariant &resultValue) {

Loading…
Cancel
Save