diff --git a/src/imports/mvvmcore/plugins.qmltypes b/src/imports/mvvmcore/plugins.qmltypes index 45ad036..882319a 100644 --- a/src/imports/mvvmcore/plugins.qmltypes +++ b/src/imports/mvvmcore/plugins.qmltypes @@ -96,10 +96,15 @@ Module { prototype: "QObject" exports: ["de.skycoder42.QtMvvm.Core/ProgressControl 1.1"] exportMetaObjectRevisions: [0] + Property { name: "autoDelete"; type: "bool" } Property { name: "indeterminate"; type: "bool" } Property { name: "minimum"; type: "int" } Property { name: "maximum"; type: "int" } Property { name: "progress"; type: "int" } + Signal { + name: "autoDeleteChanged" + Parameter { name: "autoDelete"; type: "bool" } + } Signal { name: "indeterminateChanged" Parameter { name: "indeterminate"; type: "bool" } @@ -120,6 +125,10 @@ Module { Signal { name: "canceled" } Signal { name: "closed" } Method { name: "close" } + Method { + name: "setAutoDelete" + Parameter { name: "autoDelete"; type: "bool" } + } Method { name: "setIndeterminate" Parameter { name: "indeterminate"; type: "bool" } diff --git a/src/mvvmcore/message.cpp b/src/mvvmcore/message.cpp index 9bb1116..a208041 100644 --- a/src/mvvmcore/message.cpp +++ b/src/mvvmcore/message.cpp @@ -120,17 +120,32 @@ MessageConfig &MessageConfig::setText(const QString &text) MessageConfig &MessageConfig::setButtons(StandardButtons buttons) { d->buttons = buttons; + for(auto it = d->buttonTexts.begin(); it != d->buttonTexts.end();) { + if(d->buttons.testFlag(it.key())) + it++; + else + it = d->buttonTexts.erase(it); + } + return (*this); +} + +MessageConfig &MessageConfig::addButton(StandardButton button) +{ + d->buttons |= button; return (*this); } MessageConfig &MessageConfig::setButtonTexts(const QHash &buttonTexts) { d->buttonTexts = buttonTexts; + for(auto it = d->buttonTexts.constBegin(); it != d->buttonTexts.constEnd(); it++) + d->buttons |= it.key(); return (*this); } MessageConfig &MessageConfig::setButtonText(MessageConfig::StandardButton button, const QString &text) { + d->buttons |= button; d->buttonTexts.insert(button, text); return (*this); } @@ -196,7 +211,7 @@ void MessageConfig::setButtonTextsMap(const QVariantMap &buttonTexts) QHash map; for(auto it = buttonTexts.constBegin(); it != buttonTexts.constEnd(); it++) map.insert(static_cast(it.key().toInt()), it.value().toString()); - d->buttonTexts = map; + setButtonTexts(map); } @@ -287,6 +302,11 @@ ProgressControl::ProgressControl(QObject *parent) : d{new ProgressControlPrivate{}} {} +bool ProgressControl::autoDelete() const +{ + return d->autoDelete; +} + bool ProgressControl::isIndeterminate() const { return d->indeterminate; @@ -317,6 +337,8 @@ void ProgressControl::requestCancel() void ProgressControl::notifyClosed() { emit closed({}); + if(d->autoDelete) + deleteLater(); } void ProgressControl::close() @@ -324,13 +346,22 @@ void ProgressControl::close() emit closeRequested({}); } +void ProgressControl::setAutoDelete(bool autoDelete) +{ + if (d->autoDelete == autoDelete) + return; + + d->autoDelete = autoDelete; + emit autoDeleteChanged(d->autoDelete, {}); +} + void ProgressControl::setIndeterminate(bool indeterminate) { if (d->indeterminate == indeterminate) return; d->indeterminate = indeterminate; - emit indeterminateChanged(d->indeterminate); + emit indeterminateChanged(d->indeterminate, {}); } void ProgressControl::setMinimum(int minimum) @@ -339,7 +370,7 @@ void ProgressControl::setMinimum(int minimum) return; d->minimum = minimum; - emit minimumChanged(d->minimum); + emit minimumChanged(d->minimum, {}); } void ProgressControl::setMaximum(int maximum) @@ -348,7 +379,7 @@ void ProgressControl::setMaximum(int maximum) return; d->maximum = maximum; - emit maximumChanged(d->maximum); + emit maximumChanged(d->maximum, {}); } void ProgressControl::setProgress(int progress) @@ -357,7 +388,7 @@ void ProgressControl::setProgress(int progress) return; d->progress = progress; - emit progressChanged(d->progress); + emit progressChanged(d->progress, {}); } void ProgressControl::setProgress(double progressPercent) @@ -704,7 +735,7 @@ MessageResult *QtMvvm::showProgress(const QString &title, const QString &label, config.setTitle(title); config.setText(label); config.setDefaultValue(QVariant::fromValue>(control)); - config.setViewProperty(QStringLiteral("allowCancel"), allowCancel); + config.setButtons(allowCancel ? MessageConfig::Cancel : MessageConfig::NoButton); return CoreApp::showDialog(config); } diff --git a/src/mvvmcore/message.h b/src/mvvmcore/message.h index 790be7f..1f5f18e 100644 --- a/src/mvvmcore/message.h +++ b/src/mvvmcore/message.h @@ -157,6 +157,7 @@ public: MessageConfig &setText(const QString &text); //! @writeAcFn{MessageConfig::buttons} MessageConfig &setButtons(StandardButtons buttons); + MessageConfig &addButton(StandardButton button); //! @writeAcFn{MessageConfig::buttonTexts} MessageConfig &setButtonTexts(const QHash &buttonTexts); //! @writeAcFn{MessageConfig::buttonTexts} @@ -245,6 +246,8 @@ class Q_MVVMCORE_EXPORT ProgressControl : public QObject { Q_OBJECT + Q_PROPERTY(bool autoDelete READ autoDelete WRITE setAutoDelete NOTIFY autoDeleteChanged) + Q_PROPERTY(bool indeterminate READ isIndeterminate WRITE setIndeterminate NOTIFY indeterminateChanged) Q_PROPERTY(int minimum READ minimum WRITE setMinimum NOTIFY minimumChanged) Q_PROPERTY(int maximum READ maximum WRITE setMaximum NOTIFY maximumChanged) @@ -254,6 +257,7 @@ public: explicit ProgressControl(QObject *parent = nullptr); ~ProgressControl() override; + bool autoDelete() const; bool isIndeterminate() const; int minimum() const; int maximum() const; @@ -265,6 +269,7 @@ public: public Q_SLOTS: void close(); + void setAutoDelete(bool autoDelete); void setIndeterminate(bool indeterminate); void setMinimum(int minimum); void setMaximum(int maximum); @@ -272,10 +277,11 @@ public Q_SLOTS: void setProgress(double progressPercent); Q_SIGNALS: - void indeterminateChanged(bool indeterminate); - void minimumChanged(int minimum); - void maximumChanged(int maximum); - void progressChanged(int progress); + void autoDeleteChanged(bool autoDelete, QPrivateSignal); + void indeterminateChanged(bool indeterminate, QPrivateSignal); + void minimumChanged(int minimum, QPrivateSignal); + void maximumChanged(int maximum, QPrivateSignal); + void progressChanged(int progress, QPrivateSignal); void closeRequested(QPrivateSignal); diff --git a/src/mvvmcore/message_p.h b/src/mvvmcore/message_p.h index 37fccdb..4003196 100644 --- a/src/mvvmcore/message_p.h +++ b/src/mvvmcore/message_p.h @@ -5,6 +5,7 @@ #include #include #include +#include #include "qtmvvmcore_global.h" #include "message.h" @@ -41,10 +42,15 @@ public: class ProgressControlPrivate { public: - bool indeterminate = false; - int minimum = 0; - int maximum = 100; - int progress = -1; + bool autoDelete = true; +#ifdef Q_ATOMIC_INT8_IS_SUPPORTED + QAtomicInteger indeterminate = false; +#else + QAtomicInteger indeterminate = false; //use 16 bit, as 8 bit is not atomic on all platforms +#endif + QAtomicInt minimum = 0; + QAtomicInt maximum = 100; + QAtomicInt progress = -1; }; } diff --git a/src/mvvmwidgets/widgetspresenter.cpp b/src/mvvmwidgets/widgetspresenter.cpp index d1c6013..1a52669 100644 --- a/src/mvvmwidgets/widgetspresenter.cpp +++ b/src/mvvmwidgets/widgetspresenter.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -120,6 +121,8 @@ void WidgetsPresenter::showDialog(const MessageConfig &config, MessageResult *re presentFileDialog(config, result); else if(config.type() == MessageConfig::TypeColorDialog) presentColorDialog(config, result); + else if(config.type() == MessageConfig::TypeProgressDialog) + presentProgressDialog(config, result); else presentOtherDialog(config, result); logDebug() << "Presented dialog of type" << config.type(); @@ -347,18 +350,17 @@ void WidgetsPresenter::presentInputDialog(const MessageConfig &config, QPointer< auto btns = config.buttonTexts(); for(auto it = btns.constBegin(); it != btns.constEnd(); it++){ auto sBtn = static_cast(it.key()); - if(!btnBox->standardButtons().testFlag(sBtn)) - btnBox->addButton(sBtn); + Q_ASSERT(btnBox->standardButtons().testFlag(sBtn)); //Must be the case now because of the change in MessageConfig btnBox->button(sBtn)->setText(it.value()); } layout->addWidget(btnBox); //connect stuff - QObject::connect(btnBox, &QDialogButtonBox::clicked, + connect(btnBox, &QDialogButtonBox::clicked, dialog, [dialog, btnBox](QAbstractButton *btn){ dialog->done(btnBox->standardButton(btn)); }); - QObject::connect(dialog, &QDialog::finished, + connect(dialog, &QDialog::finished, dialog, [input, property, result](int resCode){ if(result) { result->complete(static_cast(resCode), @@ -412,7 +414,7 @@ void WidgetsPresenter::presentFileDialog(const MessageConfig &config, QPointersetProperty(qUtf8Printable(it.key()), it.value()); //connect stuff - QObject::connect(dialog, &QDialog::finished, + connect(dialog, &QDialog::finished, dialog, [dialog, isMultiFile, result](int resCode){ if(result) { if(resCode == QDialog::Accepted) { @@ -432,7 +434,7 @@ void WidgetsPresenter::presentFileDialog(const MessageConfig &config, QPointeropen(); } -void WidgetsPresenter::presentColorDialog(const MessageConfig &config, QPointer result) +void WidgetsPresenter::presentColorDialog(const MessageConfig &config, const QPointer &result) { auto props = config.viewProperties(); @@ -461,7 +463,7 @@ void WidgetsPresenter::presentColorDialog(const MessageConfig &config, QPointer< dialog->setProperty(qUtf8Printable(it.key()), it.value()); //connect stuff - QObject::connect(dialog, &QDialog::finished, + connect(dialog, &QDialog::finished, dialog, [dialog, result](int resCode){ if(result) { if(resCode == QDialog::Accepted) { @@ -478,6 +480,77 @@ void WidgetsPresenter::presentColorDialog(const MessageConfig &config, QPointer< dialog->open(); } +void WidgetsPresenter::presentProgressDialog(const MessageConfig &config, const QPointer &result) +{ + auto control = config.defaultValue().value>(); + if(!control) { + logWarning() << "ProgressControl was destroyed before a progress dialog could be shown"; + return; + } + auto props = config.viewProperties(); + + //TODO implement difference to busy dialog? + + QWidget *parent = nullptr; //TODO move to seperate method + if(!props.value(QStringLiteral("modal"), false).toBool()) + parent = QApplication::activeWindow(); + auto dialog = DialogMaster::createProgress(parent, + config.text(), + control->isIndeterminate() ? 0 : control->maximum(), + control->isIndeterminate() ? 0 : control->minimum(), + config.buttons().testFlag(MessageConfig::Cancel), + config.title(), + props.value(QStringLiteral("minimumDuration"), 0).toInt(), + config.buttonTexts().value(MessageConfig::Cancel)); + dialog->setAttribute(Qt::WA_DeleteOnClose); + dialog->setAutoReset(false); + dialog->setAutoClose(false); + + //set extra props + for(auto it = props.constBegin(); it != props.constEnd(); it++) + dialog->setProperty(qUtf8Printable(it.key()), it.value()); + + //connect stuff + connect(control, &ProgressControl::closeRequested, + dialog, &QProgressDialog::close); + connect(control, &ProgressControl::minimumChanged, + dialog, &QProgressDialog::setMinimum); + connect(control, &ProgressControl::maximumChanged, + dialog, &QProgressDialog::setMaximum); + connect(control, &ProgressControl::progressChanged, + dialog, &QProgressDialog::setValue); + connect(control, &ProgressControl::indeterminateChanged, + dialog, [dialog, control](bool indeterminate){ + if(indeterminate) + dialog->setRange(0, 0); + else if(control) { + dialog->setRange(control->minimum(), control->maximum()); + dialog->setValue(control->progress()); + } else + dialog->setRange(0, 1); + }); + + connect(dialog, &QProgressDialog::canceled, + dialog, &QProgressDialog::show); //TODO check if working, disable cancel button + connect(dialog, &QProgressDialog::canceled, + control, &ProgressControl::requestCancel); + connect(dialog, &QDialog::finished, + dialog, [dialog, result, control](int){ + if(control) + control->notifyClosed(); + if(result) { + if(dialog->wasCanceled()) + result->complete(MessageConfig::Cancel); + else + result->complete(MessageConfig::Close); + } + }); + + //show + dialog->open(); + dialog->setValue(control->progress()); //do after open, as set value causes open +} + void WidgetsPresenter::presentOtherDialog(const MessageConfig &config, QPointer result) { Q_UNUSED(result) diff --git a/src/mvvmwidgets/widgetspresenter.h b/src/mvvmwidgets/widgetspresenter.h index 82c9750..0addc95 100644 --- a/src/mvvmwidgets/widgetspresenter.h +++ b/src/mvvmwidgets/widgetspresenter.h @@ -77,7 +77,8 @@ protected: virtual void presentInputDialog(const MessageConfig &config, QPointer result); //! Called to present a dialog of MessageConfig::TypeFileDialog virtual void presentFileDialog(const MessageConfig &config, QPointer result); - void presentColorDialog(const MessageConfig &config, QPointer result); //MAJOR make virtual + void presentColorDialog(const MessageConfig &config, const QPointer &result); //MAJOR make virtual + void presentProgressDialog(const MessageConfig &config, const QPointer &result); //MAJOR make virtual //! Called to present a dialog of a non standard MessageConfig::type virtual void presentOtherDialog(const MessageConfig &config, QPointer result);