From 4dd75025f7bb380bcf98ccc57c30e0c6124821d4 Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 16 Jan 2022 19:51:07 +0300 Subject: [PATCH] added simple example --- src/Example/Main.qml | 5 ++ src/Example/main.cpp | 31 ++++++++++ src/Library/CMakeLists.txt | 6 +- src/Library/DoctorPillCore/doctor.cpp | 13 ++++- src/Library/DoctorPillCore/doctor.h | 10 +++- src/Library/DoctorPillCore/ipill.h | 7 +++ src/Library/DoctorPillGui/doctormodel.cpp | 63 ++++++++++++++++++++- src/Library/DoctorPillGui/doctormodel.h | 39 +++++++++++-- src/Library/DoctorPillModule/DoctorView.qml | 35 +++++++++++- src/Library/DoctorPillModule/qmldir | 2 +- src/Library/doctorpill.cpp | 1 - src/Library/doctorpill.h | 6 ++ 12 files changed, 197 insertions(+), 21 deletions(-) diff --git a/src/Example/Main.qml b/src/Example/Main.qml index 173bb1d..308a5a9 100644 --- a/src/Example/Main.qml +++ b/src/Example/Main.qml @@ -1,10 +1,15 @@ import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Controls.Material 2.15 +import DoctorPillModule 1.0 ApplicationWindow { width: 800 height: 600 visible: true + DoctorView { + anchors.fill: parent + model: (doctorPillMpdel)? doctorPillMpdel: null + } } diff --git a/src/Example/main.cpp b/src/Example/main.cpp index ab9646b..4f038a8 100644 --- a/src/Example/main.cpp +++ b/src/Example/main.cpp @@ -7,7 +7,32 @@ #include #include +#include #include +#include + +class EmptyPill: public DP::iPill { + + + // iPill interface +public: + QString name() const override { + return "EmptyPill"; + }; + + QString description() const override { + return "Pill For Test. This pill cant be fixed "; + }; + +protected: + bool diagnostic() const override { + std::this_thread::sleep_for(std::chrono::seconds(5)); + return true; + }; + bool fix() const override { + return false; + }; +}; int main(int argc, char *argv[]) { QCoreApplication::setOrganizationName("QuasarApp"); @@ -20,9 +45,15 @@ int main(int argc, char *argv[]) { return -1; } + DP::DoctorModel model({QSharedPointer::create()}); + engine.load("qrc:/Main.qml"); if (engine.rootObjects().isEmpty()) return -2; + QQmlContext* rootContext = engine.rootContext(); + if (rootContext) + rootContext->setContextProperty("doctorPillMpdel", &model); + return app.exec(); } diff --git a/src/Library/CMakeLists.txt b/src/Library/CMakeLists.txt index 60ffa06..cbf68cb 100644 --- a/src/Library/CMakeLists.txt +++ b/src/Library/CMakeLists.txt @@ -35,8 +35,8 @@ add_library(${PROJECT_NAME} ${SOURCE_CPP} ${SOURCE_QRC} ${SOURCE_CPP_GUI}) target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Core ) if (DOCTOR_PILL_GUI) - find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick REQUIRED) - target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Quick ) + find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick Concurrent REQUIRED) + target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Concurrent Qt${QT_VERSION_MAJOR}::Quick ) endif() target_include_directories(${PROJECT_NAME} PUBLIC ${PUBLIC_INCUDE_DIR}) @@ -56,5 +56,5 @@ set(LANGS ${CMAKE_CURRENT_SOURCE_DIR}/languages/en.ts prepareQM(${PROJECT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/../ "${LANGS}") -set(QML_IMPORT_PATH ${QML_IMPORT_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/src" CACHE STRING "" FORCE) +set(QML_IMPORT_PATH ${QML_IMPORT_PATH} "${CMAKE_CURRENT_SOURCE_DIR}" CACHE STRING "" FORCE) diff --git a/src/Library/DoctorPillCore/doctor.cpp b/src/Library/DoctorPillCore/doctor.cpp index 40ca973..10bbe57 100644 --- a/src/Library/DoctorPillCore/doctor.cpp +++ b/src/Library/DoctorPillCore/doctor.cpp @@ -13,6 +13,8 @@ namespace DP { Doctor::Doctor(const QList > &base) { _pillsData = base; + + qRegisterMetaType >>(); } void Doctor::diagnostic(bool fix) const { @@ -21,6 +23,10 @@ void Doctor::diagnostic(bool fix) const { QList > detected; QList > fixedSuccessful; + float progress = 0; + float progressStep = 1.0f / _pillsData.size(); + + emit sigDiagnosticProgressChanged(progress); for (const auto &pill: _pillsData) { if (pill->diagnostic()) { if (fix) { @@ -33,15 +39,16 @@ void Doctor::diagnostic(bool fix) const { detected.push_back(pill); } } + + progress += progressStep; + emit sigDiagnosticProgressChanged(progress); } if (failed.size()) { emit sigFixesFailed(failed); } - if (detected.count()) { - emit sigTroubleDetected(detected); - } + emit sigDiagnosticFinished(detected); if (fixedSuccessful.count()) { emit sigFixesFinishedSuccessful(fixedSuccessful); diff --git a/src/Library/DoctorPillCore/doctor.h b/src/Library/DoctorPillCore/doctor.h index 88b14f7..cfe0129 100644 --- a/src/Library/DoctorPillCore/doctor.h +++ b/src/Library/DoctorPillCore/doctor.h @@ -39,6 +39,7 @@ public: * @see Doctor::addPill * @see Doctor::sigFixesFailed * @see Doctor::sigFixesFinishedSuccessful + * @see Doctor::sigDiagnosticFinished */ void diagnostic(bool fix = false) const; @@ -64,14 +65,14 @@ public: void addPill(const QSharedPointer& pill); signals: /** - * @brief sigTroubleDetected This signal will emited when The doctor object found issues in this application. + * @brief sigDiagnosticFinished This signal will emited when The doctor object found issues in this application. * @param issues this is list of detected issues. * @see Doctor::diagnostic * @see Doctor::fix * @see Doctor::sigFixesFailed * @see Doctor::sigFixesFinishedSuccessful */ - void sigTroubleDetected(QList> issues) const; + void sigDiagnosticFinished(QList> issues) const; /** * @brief sigFixesFailed This signal emited when the doctor can't fix foundet issues. @@ -85,6 +86,11 @@ signals: */ void sigFixesFinishedSuccessful(QList> issues) const; + /** + * @brief sigDiagnosticProgressChanged This signal emitted when progress of diagnstic changed. + * @param progress This is ptogress of diagnostic process from 0 to 1 + */ + void sigDiagnosticProgressChanged(float progress) const; private: QList> _pillsData; }; diff --git a/src/Library/DoctorPillCore/ipill.h b/src/Library/DoctorPillCore/ipill.h index a0c452b..71fb504 100644 --- a/src/Library/DoctorPillCore/ipill.h +++ b/src/Library/DoctorPillCore/ipill.h @@ -11,6 +11,8 @@ #include #include "doctorpill_global.h" +#include +#include namespace DP { @@ -70,5 +72,10 @@ protected: friend class DoctorTest; }; + } + +Q_DECLARE_METATYPE(QSharedPointer); +Q_DECLARE_METATYPE(QList>); + #endif // IPILL_H diff --git a/src/Library/DoctorPillGui/doctormodel.cpp b/src/Library/DoctorPillGui/doctormodel.cpp index b25e7aa..bad445b 100644 --- a/src/Library/DoctorPillGui/doctormodel.cpp +++ b/src/Library/DoctorPillGui/doctormodel.cpp @@ -7,13 +7,30 @@ #include "doctormodel.h" #include +#include namespace DP { DoctorModel::DoctorModel(const QList> &base): _doctor(base) { + connect(&_doctor, &Doctor::sigDiagnosticFinished, + this, &DoctorModel::handleDiagnostcFinished, + Qt::QueuedConnection); + connect(&_doctor, &Doctor::sigDiagnosticProgressChanged, + this, &DoctorModel::handleDiagnosticProgressChanged, + Qt::QueuedConnection); + + connect(&_doctor, &Doctor::sigFixesFailed, + this, &DoctorModel::handleFixFailed, + Qt::QueuedConnection); + + connect(&_doctor, &Doctor::sigFixesFinishedSuccessful, + this, &DoctorModel::handleFixSuccessful, + Qt::QueuedConnection); + + setState(ViewState::BeginDiagnostic); } int DoctorModel::rowCount(const QModelIndex &) const { @@ -67,7 +84,16 @@ void DoctorModel::usePill(QString pillName) { } void DoctorModel::diagnostic() { + _doctor.diagnostic(); + + auto work = [this](){ + _doctor.diagnostic(); + }; + + setState(ViewState::SearchBugs); + + auto val = QtConcurrent::run(work); } void DoctorModel::handleFixFailed(QList> failed) { @@ -84,15 +110,46 @@ void DoctorModel::handleFixSuccessful(QList> successful) { } } -void DoctorModel::handleBugDetected(QList> bugDetected) { - +void DoctorModel::handleDiagnostcFinished(QList > issues) { beginResetModel(); _viewData.clear(); - for (const auto &pill : qAsConst(bugDetected)) { + for (const auto &pill : qAsConst(issues)) { _viewData[pill->name()] = Issue{0, pill}; } endResetModel(); + + if (_viewData.size()) + setState(ViewState::BugFound); + else + setState(ViewState::AllIsFine); + +} + +void DoctorModel::handleDiagnosticProgressChanged(float progress) { + setProgress(progress); +} + +double DoctorModel::progress() const { + return _progress; +} + +void DoctorModel::setProgress(double newProgress) { + if (qFuzzyCompare(_progress, newProgress)) + return; + _progress = newProgress; + emit progressChanged(); +} + +int DoctorModel::state() const { + return _state; +} + +void DoctorModel::setState(int newState) { + if (_state == newState) + return; + _state = newState; + emit stateChanged(); } } diff --git a/src/Library/DoctorPillGui/doctormodel.h b/src/Library/DoctorPillGui/doctormodel.h index e4309cf..fb71ba8 100644 --- a/src/Library/DoctorPillGui/doctormodel.h +++ b/src/Library/DoctorPillGui/doctormodel.h @@ -9,23 +9,27 @@ #define PILLSMODEL_H #include +#include #include namespace DP { -struct Issue { - int _status = 0; - QSharedPointer _pill = nullptr; -}; - /** * @brief The PillsModel class This is gui model of available pills. */ class DoctorModel: public QAbstractListModel { Q_OBJECT + Q_PROPERTY(double progress READ progress WRITE setProgress NOTIFY progressChanged) + Q_PROPERTY(int state READ state WRITE setState NOTIFY stateChanged) + + struct Issue { + int _status = 0; + QSharedPointer _pill = nullptr; + }; enum Roles { + Name = Qt::UserRole, Description, Status @@ -37,7 +41,15 @@ class DoctorModel: public QAbstractListModel Failed }; + enum ViewState { + BeginDiagnostic, + SearchBugs, + BugFound, + AllIsFine, + }; + public: + DoctorModel(const QList> &base); void addPill(const QSharedPointer& pill); @@ -48,14 +60,29 @@ public: Q_INVOKABLE void usePill(QString pillName); Q_INVOKABLE void diagnostic(); + double progress() const; + int state() const; + +signals: + void progressChanged(); + + void stateChanged(); + private slots: void handleFixFailed(QList>); void handleFixSuccessful(QList>); - void handleBugDetected(QList>); + void handleDiagnostcFinished(QList>); + void handleDiagnosticProgressChanged(float); private: + void setProgress(double newProgress); + void setState(int newState); + + int _state; Doctor _doctor; QHash _viewData; + double _progress; + QFuture _diagnosticWork; }; } diff --git a/src/Library/DoctorPillModule/DoctorView.qml b/src/Library/DoctorPillModule/DoctorView.qml index 78f4404..2ced958 100644 --- a/src/Library/DoctorPillModule/DoctorView.qml +++ b/src/Library/DoctorPillModule/DoctorView.qml @@ -10,26 +10,42 @@ Page { signal contactWithDevsPressed(); - ColumnLayout { + contentItem: ColumnLayout { Label { id: atansionMsg text: qsTr("Attention: Please use this page only if you knows what you do. If your application works correctly then please - do nothing."); + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + wrapMode: Label.WordWrap + Layout.fillWidth: true + } Label { id: descriptionMsg text: qsTr("This is your personal application doctor room! The doctor automatically check your application to exits errors. If the Doctor found any errors he suggest solution of your issue"); + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + wrapMode: Label.WordWrap + Layout.fillWidth: true + } Label { id: allIsFineMsg text: qsTr("The Doctor not found any issues. If you sure that application is works wrong then you can contact with developers."); + horizontalAlignment: Qt.AlignHCenter + verticalAlignment: Qt.AlignVCenter + wrapMode: Label.WordWrap + Layout.fillWidth: true + } Button { id: contactButton text: qsTr("Contact with Developers"); + Layout.alignment: Qt.AlignHCenter onClicked: { contactWithDevsPressed(); } @@ -43,6 +59,7 @@ Page { Button { id: diagnosticButton text: qsTr("Diagnostic"); + Layout.alignment: Qt.AlignHCenter onClicked: { if (root.model) { @@ -102,7 +119,8 @@ Page { } } - state: "beginDiagnostic" + state: (root.model)? privateRoot.getState(root.model.state): "beginDiagnostic" + //beginDiagnostic //searchBugs @@ -261,4 +279,17 @@ Page { } } ] + + Item { + id: privateRoot + + function getState(state) { + switch(state) { + case 0: return "beginDiagnostic"; + case 1: return "searchBugs"; + case 2: return "bugFound"; + case 3: return "allIsFine"; + } + } + } } diff --git a/src/Library/DoctorPillModule/qmldir b/src/Library/DoctorPillModule/qmldir index d2aca21..84b999f 100644 --- a/src/Library/DoctorPillModule/qmldir +++ b/src/Library/DoctorPillModule/qmldir @@ -1,3 +1,3 @@ -module QuasarAppCreditsModule +module DoctorPillModule DoctorView 1.0 DoctorView.qml diff --git a/src/Library/doctorpill.cpp b/src/Library/doctorpill.cpp index ec88c9e..a324a8c 100644 --- a/src/Library/doctorpill.cpp +++ b/src/Library/doctorpill.cpp @@ -26,5 +26,4 @@ bool init(QQmlApplicationEngine *engine) { return true; } - } diff --git a/src/Library/doctorpill.h b/src/Library/doctorpill.h index 98d8424..5fbaac9 100644 --- a/src/Library/doctorpill.h +++ b/src/Library/doctorpill.h @@ -10,11 +10,14 @@ #include "DoctorPillCore/ipill.h" #include "DoctorPillCore/doctortest.h" +#include "DoctorPillGui/doctormodel.h" + inline void initDoctorPillResources() { Q_INIT_RESOURCE(DoctorPill); } class QQmlApplicationEngine; +class DoctorModel; /** * @brief DP This is base name space of the DoctorPill(DP) library. Please if you use the gui application and gui models then invoke the DP::init method before use this library. @@ -25,7 +28,10 @@ namespace DP { * @brief init This function initialize the qml gui classes of the DoctorPill library. * @note if you do not use GUI then this function do nothing. * @param engine This is qml engine pointer if this pointer is invalid then finction return false. + * @param customModel This is a custom c++ nodel of qml view. IF this option sets to nullptr then doctorpill will use default model. * @return return true if the library initialized successful else false. + * + * @see DoctorModel */ bool DOCTOR_PILL_EXPORT init(QQmlApplicationEngine *engine);