added simple example

This commit is contained in:
Andrei Yankovich 2022-01-16 19:51:07 +03:00
parent ff6c7ae397
commit 4dd75025f7
12 changed files with 197 additions and 21 deletions

View File

@ -1,10 +1,15 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.15 import QtQuick.Controls 2.15
import QtQuick.Controls.Material 2.15 import QtQuick.Controls.Material 2.15
import DoctorPillModule 1.0
ApplicationWindow { ApplicationWindow {
width: 800 width: 800
height: 600 height: 600
visible: true visible: true
DoctorView {
anchors.fill: parent
model: (doctorPillMpdel)? doctorPillMpdel: null
}
} }

View File

@ -7,7 +7,32 @@
#include <QGuiApplication> #include <QGuiApplication>
#include <QQmlApplicationEngine> #include <QQmlApplicationEngine>
#include <QQmlContext>
#include <doctorpill.h> #include <doctorpill.h>
#include <thread>
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[]) { int main(int argc, char *argv[]) {
QCoreApplication::setOrganizationName("QuasarApp"); QCoreApplication::setOrganizationName("QuasarApp");
@ -20,9 +45,15 @@ int main(int argc, char *argv[]) {
return -1; return -1;
} }
DP::DoctorModel model({QSharedPointer<EmptyPill>::create()});
engine.load("qrc:/Main.qml"); engine.load("qrc:/Main.qml");
if (engine.rootObjects().isEmpty()) if (engine.rootObjects().isEmpty())
return -2; return -2;
QQmlContext* rootContext = engine.rootContext();
if (rootContext)
rootContext->setContextProperty("doctorPillMpdel", &model);
return app.exec(); return app.exec();
} }

View File

@ -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 ) target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Core )
if (DOCTOR_PILL_GUI) if (DOCTOR_PILL_GUI)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick REQUIRED) find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Quick Concurrent REQUIRED)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Quick ) target_link_libraries(${PROJECT_NAME} PUBLIC Qt${QT_VERSION_MAJOR}::Concurrent Qt${QT_VERSION_MAJOR}::Quick )
endif() endif()
target_include_directories(${PROJECT_NAME} PUBLIC ${PUBLIC_INCUDE_DIR}) 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}") 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)

View File

@ -13,6 +13,8 @@ namespace DP {
Doctor::Doctor(const QList<QSharedPointer<iPill> > &base) { Doctor::Doctor(const QList<QSharedPointer<iPill> > &base) {
_pillsData = base; _pillsData = base;
qRegisterMetaType<QList<QSharedPointer<iPill> >>();
} }
void Doctor::diagnostic(bool fix) const { void Doctor::diagnostic(bool fix) const {
@ -21,6 +23,10 @@ void Doctor::diagnostic(bool fix) const {
QList<QSharedPointer<iPill> > detected; QList<QSharedPointer<iPill> > detected;
QList<QSharedPointer<iPill> > fixedSuccessful; QList<QSharedPointer<iPill> > fixedSuccessful;
float progress = 0;
float progressStep = 1.0f / _pillsData.size();
emit sigDiagnosticProgressChanged(progress);
for (const auto &pill: _pillsData) { for (const auto &pill: _pillsData) {
if (pill->diagnostic()) { if (pill->diagnostic()) {
if (fix) { if (fix) {
@ -33,15 +39,16 @@ void Doctor::diagnostic(bool fix) const {
detected.push_back(pill); detected.push_back(pill);
} }
} }
progress += progressStep;
emit sigDiagnosticProgressChanged(progress);
} }
if (failed.size()) { if (failed.size()) {
emit sigFixesFailed(failed); emit sigFixesFailed(failed);
} }
if (detected.count()) { emit sigDiagnosticFinished(detected);
emit sigTroubleDetected(detected);
}
if (fixedSuccessful.count()) { if (fixedSuccessful.count()) {
emit sigFixesFinishedSuccessful(fixedSuccessful); emit sigFixesFinishedSuccessful(fixedSuccessful);

View File

@ -39,6 +39,7 @@ public:
* @see Doctor::addPill * @see Doctor::addPill
* @see Doctor::sigFixesFailed * @see Doctor::sigFixesFailed
* @see Doctor::sigFixesFinishedSuccessful * @see Doctor::sigFixesFinishedSuccessful
* @see Doctor::sigDiagnosticFinished
*/ */
void diagnostic(bool fix = false) const; void diagnostic(bool fix = false) const;
@ -64,14 +65,14 @@ public:
void addPill(const QSharedPointer<iPill>& pill); void addPill(const QSharedPointer<iPill>& pill);
signals: 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. * @param issues this is list of detected issues.
* @see Doctor::diagnostic * @see Doctor::diagnostic
* @see Doctor::fix * @see Doctor::fix
* @see Doctor::sigFixesFailed * @see Doctor::sigFixesFailed
* @see Doctor::sigFixesFinishedSuccessful * @see Doctor::sigFixesFinishedSuccessful
*/ */
void sigTroubleDetected(QList<QSharedPointer<iPill>> issues) const; void sigDiagnosticFinished(QList<QSharedPointer<iPill>> issues) const;
/** /**
* @brief sigFixesFailed This signal emited when the doctor can't fix foundet issues. * @brief sigFixesFailed This signal emited when the doctor can't fix foundet issues.
@ -85,6 +86,11 @@ signals:
*/ */
void sigFixesFinishedSuccessful(QList<QSharedPointer<iPill>> issues) const; void sigFixesFinishedSuccessful(QList<QSharedPointer<iPill>> 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: private:
QList<QSharedPointer<iPill>> _pillsData; QList<QSharedPointer<iPill>> _pillsData;
}; };

View File

@ -11,6 +11,8 @@
#include <QString> #include <QString>
#include "doctorpill_global.h" #include "doctorpill_global.h"
#include <QMetaType>
#include <QSharedPointer>
namespace DP { namespace DP {
@ -70,5 +72,10 @@ protected:
friend class DoctorTest; friend class DoctorTest;
}; };
} }
Q_DECLARE_METATYPE(QSharedPointer<DP::iPill>);
Q_DECLARE_METATYPE(QList<QSharedPointer<DP::iPill>>);
#endif // IPILL_H #endif // IPILL_H

View File

@ -7,13 +7,30 @@
#include "doctormodel.h" #include "doctormodel.h"
#include <QHash> #include <QHash>
#include <QtConcurrent>
namespace DP { namespace DP {
DoctorModel::DoctorModel(const QList<QSharedPointer<iPill>> &base): DoctorModel::DoctorModel(const QList<QSharedPointer<iPill>> &base):
_doctor(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 { int DoctorModel::rowCount(const QModelIndex &) const {
@ -67,7 +84,16 @@ void DoctorModel::usePill(QString pillName) {
} }
void DoctorModel::diagnostic() { void DoctorModel::diagnostic() {
_doctor.diagnostic(); _doctor.diagnostic();
auto work = [this](){
_doctor.diagnostic();
};
setState(ViewState::SearchBugs);
auto val = QtConcurrent::run(work);
} }
void DoctorModel::handleFixFailed(QList<QSharedPointer<iPill>> failed) { void DoctorModel::handleFixFailed(QList<QSharedPointer<iPill>> failed) {
@ -84,15 +110,46 @@ void DoctorModel::handleFixSuccessful(QList<QSharedPointer<iPill>> successful) {
} }
} }
void DoctorModel::handleBugDetected(QList<QSharedPointer<iPill>> bugDetected) { void DoctorModel::handleDiagnostcFinished(QList<QSharedPointer<iPill> > issues) {
beginResetModel(); beginResetModel();
_viewData.clear(); _viewData.clear();
for (const auto &pill : qAsConst(bugDetected)) { for (const auto &pill : qAsConst(issues)) {
_viewData[pill->name()] = Issue{0, pill}; _viewData[pill->name()] = Issue{0, pill};
} }
endResetModel(); 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();
} }
} }

View File

@ -9,23 +9,27 @@
#define PILLSMODEL_H #define PILLSMODEL_H
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QFuture>
#include <DoctorPillCore/doctor.h> #include <DoctorPillCore/doctor.h>
namespace DP { namespace DP {
struct Issue {
int _status = 0;
QSharedPointer<iPill> _pill = nullptr;
};
/** /**
* @brief The PillsModel class This is gui model of available pills. * @brief The PillsModel class This is gui model of available pills.
*/ */
class DoctorModel: public QAbstractListModel class DoctorModel: public QAbstractListModel
{ {
Q_OBJECT 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<iPill> _pill = nullptr;
};
enum Roles { enum Roles {
Name = Qt::UserRole, Name = Qt::UserRole,
Description, Description,
Status Status
@ -37,7 +41,15 @@ class DoctorModel: public QAbstractListModel
Failed Failed
}; };
enum ViewState {
BeginDiagnostic,
SearchBugs,
BugFound,
AllIsFine,
};
public: public:
DoctorModel(const QList<QSharedPointer<iPill>> &base); DoctorModel(const QList<QSharedPointer<iPill>> &base);
void addPill(const QSharedPointer<iPill>& pill); void addPill(const QSharedPointer<iPill>& pill);
@ -48,14 +60,29 @@ public:
Q_INVOKABLE void usePill(QString pillName); Q_INVOKABLE void usePill(QString pillName);
Q_INVOKABLE void diagnostic(); Q_INVOKABLE void diagnostic();
double progress() const;
int state() const;
signals:
void progressChanged();
void stateChanged();
private slots: private slots:
void handleFixFailed(QList<QSharedPointer<iPill>>); void handleFixFailed(QList<QSharedPointer<iPill>>);
void handleFixSuccessful(QList<QSharedPointer<iPill>>); void handleFixSuccessful(QList<QSharedPointer<iPill>>);
void handleBugDetected(QList<QSharedPointer<iPill>>); void handleDiagnostcFinished(QList<QSharedPointer<iPill>>);
void handleDiagnosticProgressChanged(float);
private: private:
void setProgress(double newProgress);
void setState(int newState);
int _state;
Doctor _doctor; Doctor _doctor;
QHash<QString, Issue> _viewData; QHash<QString, Issue> _viewData;
double _progress;
QFuture<void> _diagnosticWork;
}; };
} }

View File

@ -10,26 +10,42 @@ Page {
signal contactWithDevsPressed(); signal contactWithDevsPressed();
ColumnLayout { contentItem: ColumnLayout {
Label { Label {
id: atansionMsg 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."); 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 { Label {
id: descriptionMsg 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"); 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 { Label {
id: allIsFineMsg id: allIsFineMsg
text: qsTr("The Doctor not found any issues. If you sure that application is works wrong then you can contact with developers."); 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 { Button {
id: contactButton id: contactButton
text: qsTr("Contact with Developers"); text: qsTr("Contact with Developers");
Layout.alignment: Qt.AlignHCenter
onClicked: { onClicked: {
contactWithDevsPressed(); contactWithDevsPressed();
} }
@ -43,6 +59,7 @@ Page {
Button { Button {
id: diagnosticButton id: diagnosticButton
text: qsTr("Diagnostic"); text: qsTr("Diagnostic");
Layout.alignment: Qt.AlignHCenter
onClicked: { onClicked: {
if (root.model) { if (root.model) {
@ -102,7 +119,8 @@ Page {
} }
} }
state: "beginDiagnostic" state: (root.model)? privateRoot.getState(root.model.state): "beginDiagnostic"
//beginDiagnostic //beginDiagnostic
//searchBugs //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";
}
}
}
} }

View File

@ -1,3 +1,3 @@
module QuasarAppCreditsModule module DoctorPillModule
DoctorView 1.0 DoctorView.qml DoctorView 1.0 DoctorView.qml

View File

@ -26,5 +26,4 @@ bool init(QQmlApplicationEngine *engine) {
return true; return true;
} }
} }

View File

@ -10,11 +10,14 @@
#include "DoctorPillCore/ipill.h" #include "DoctorPillCore/ipill.h"
#include "DoctorPillCore/doctortest.h" #include "DoctorPillCore/doctortest.h"
#include "DoctorPillGui/doctormodel.h"
inline void initDoctorPillResources() { inline void initDoctorPillResources() {
Q_INIT_RESOURCE(DoctorPill); Q_INIT_RESOURCE(DoctorPill);
} }
class QQmlApplicationEngine; 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. * @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. * @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. * @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 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. * @return return true if the library initialized successful else false.
*
* @see DoctorModel
*/ */
bool DOCTOR_PILL_EXPORT init(QQmlApplicationEngine *engine); bool DOCTOR_PILL_EXPORT init(QQmlApplicationEngine *engine);