diff --git a/qml/page/T_LessonPic.qml b/qml/page/T_LessonPic.qml index edcf44d..05da1b3 100644 --- a/qml/page/T_LessonPic.qml +++ b/qml/page/T_LessonPic.qml @@ -10,7 +10,7 @@ FluScrollablePage { Rectangle { id: lesson_pic width: 1080 - height: 1920 + (lesson_detail.num - 2) * 430 + height: 1920 + (LessonModel.num - 2) * 430 color: "#EAEAEA" Image { @@ -84,12 +84,9 @@ FluScrollablePage { spacing: 100 Repeater { - id: lesson_detail - property int num: 2 - property var dep: ["C++", "软件研发中心"] - model: num - delegate: Rectangle { + model: LessonModel + delegate: Item { height: 330 anchors { left: parent.left @@ -122,7 +119,7 @@ FluScrollablePage { bottom: parent.bottom bottomMargin: 5 } - source: "qrc:/res/image/department/cpp_1.svg" + source: icon fillMode: Image.PreserveAspectFit } @@ -130,7 +127,7 @@ FluScrollablePage { leftPadding: 20 rightPadding: 40 height: dep_title_block_rect.height - text: lesson_detail.dep[index] + text: title font.pixelSize: 50 verticalAlignment: Text.AlignVCenter font.bold: true @@ -138,15 +135,39 @@ FluScrollablePage { } Text { - id: txt + id: time_txt anchors { top: dep_title_block_rect.bottom topMargin: 20 left: dep_title_block_rect.left right: parent.right - bottom: parent.bottom } - text: qsTr("%1").arg(index) + text: qsTr("时间:%1").arg(time) + font.pixelSize: 36 + } + + Text { + id: loc_txt + anchors { + top: time_txt.bottom + topMargin: 10 + left: dep_title_block_rect.left + right: parent.right + } + text: qsTr("地点:%1").arg(loc) + font.pixelSize: 36 + } + + Text { + id: topic_txt + anchors { + top: loc_txt.bottom + topMargin: 10 + left: dep_title_block_rect.left + right: parent.right + } + text: qsTr("主题:%1").arg(topic) + font.pixelSize: 36 } } } diff --git a/src/controller/evento_service.cpp b/src/controller/evento_service.cpp index 50212f1..7a21d0e 100644 --- a/src/controller/evento_service.cpp +++ b/src/controller/evento_service.cpp @@ -11,6 +11,7 @@ #include "feedback_service.h" #include "image.h" #include "latest_evento_model.h" +#include "lesson.h" #include "my_page.h" #include "plaza.h" #include "repository.h" @@ -454,3 +455,9 @@ EventoBlock::EventoBlock(const DTO_Evento& src, const std::set& permit editable(permitted.count(src.id)) { init(); } + +EventoLesson::EventoLesson(const DTO_Evento& src) + : id(src.id), topic(src.description), time(src.gmtEventStart.toString("ddd h:m")) { + for (const auto& i : src.departments) + departments << i.name; +} diff --git a/src/controller/ui/calendar.cpp b/src/controller/ui/calendar.cpp index 803875a..05f42e4 100644 --- a/src/controller/ui/calendar.cpp +++ b/src/controller/ui/calendar.cpp @@ -1,6 +1,24 @@ #include "calendar.h" #include "evento_block_model.h" #include "evento_service.h" +#include "lesson_model.h" + +void CalendarController::generateLessonPic(DepartmentEnum dep) { + std::vector data; + auto& test = data.emplace_back(); + test.departments.push_back("C++组"); + test.time = "周日 17:00"; + test.topic = "?"; + test.image = "qrc:/res/image/department/cpp_1.svg"; + { + auto& test = data.emplace_back(); + test.departments.push_back("C++组"); + test.time = "周日 17:00"; + test.topic = "?"; + test.image = "qrc:/res/image/department/cpp_1.svg"; + } + LessonModel::getInstance()->resetModel(std::move(data)); +} void CalendarController::loadAllEventoInfo(QString date) { EventoService::getInstance().load_Block(QDate::fromString(date, "yyyy-M-d")); diff --git a/src/controller/ui/calendar.h b/src/controller/ui/calendar.h index bd50b67..12f76f2 100644 --- a/src/controller/ui/calendar.h +++ b/src/controller/ui/calendar.h @@ -24,7 +24,7 @@ class CalendarController : public QObject { Q_INVOKABLE void deleteEvento(EventoID eventId); Q_INVOKABLE void cancelEvento(EventoID eventId); Q_INVOKABLE void loadCheckCode(EventoID eventId); - Q_INVOKABLE void generateLessonPic(DepartmentEnum dep) {} + Q_INVOKABLE void generateLessonPic(DepartmentEnum dep); signals: void loadAllEventoSuccessEvent(); diff --git a/src/domain/entity/lesson.h b/src/domain/entity/lesson.h new file mode 100644 index 0000000..0e8f83a --- /dev/null +++ b/src/domain/entity/lesson.h @@ -0,0 +1,21 @@ +#ifndef LESSON_H +#define LESSON_H + +#include "types.h" + +struct DTO_Evento; + +struct EventoLesson { + EventoID id; + QStringList departments; + QString topic; + QString time; + QString location; + Image image; + + EventoLesson() = default; + EventoLesson(const DTO_Evento&); +}; + + +#endif // LESSON_H diff --git a/src/domain/model/lesson_model.cpp b/src/domain/model/lesson_model.cpp new file mode 100644 index 0000000..f0f7e0b --- /dev/null +++ b/src/domain/model/lesson_model.cpp @@ -0,0 +1,74 @@ +#include "lesson_model.h" + +#include "movable_lambda.h" + +int LessonModel::rowCount(const QModelIndex& parent) const { + // For list models only the root node (an invalid parent) should return the list's size. For all + // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. + if (parent.isValid()) + return 0; + + return m_data.size(); +} + +QVariant LessonModel::data(const QModelIndex& index, int role) const { + if (!index.isValid() || index.row() >= m_data.size()) + return QVariant(); + + const auto& element = m_data.at(index.row()); + + switch (role) { + case Role::Id: + return element.id; + case Role::DepTitle: + return element.departments.size() == 1 ? element.departments.front() : element.departments.join('/') + "联合授课"; + case Role::Topic: + return element.topic; + case Role::Time: + return element.time; + case Role::Location: + return element.location; + case Role::Icon: + return element.image; + default: + break; + } + + return QVariant(); +} + +QHash LessonModel::roleNames() const { + static QHash roles; + if (roles.isEmpty()) { + roles.insert(Id, "id"); + roles.insert(DepTitle, "title"); + roles.insert(Topic, "topic"); + roles.insert(Time, "time"); + roles.insert(Location, "loc"); + roles.insert(Icon, "icon"); + } + return roles; +} + +void LessonModel::resetModel(std::vector&& model) { + QMetaObject::invokeMethod( + this, + MovableLambda(std::move(model), [this](std::vector&& data) { + beginResetModel(); + m_data = std::move(data); + emit numChanged(); + endResetModel(); + }) + ); +} + +LessonModel* LessonModel::create(QQmlEngine* qmlEngine, QJSEngine* jsEngine) { + auto pInstance = getInstance(); + QJSEngine::setObjectOwnership(pInstance, QQmlEngine::CppOwnership); + return pInstance; +} + +LessonModel* LessonModel::getInstance() { + static LessonModel instance; + return &instance; +} diff --git a/src/domain/model/lesson_model.h b/src/domain/model/lesson_model.h new file mode 100644 index 0000000..f1959e0 --- /dev/null +++ b/src/domain/model/lesson_model.h @@ -0,0 +1,47 @@ +#ifndef LESSON_MODEL_H +#define LESSON_MODEL_H + +#include +#include + +#include "lesson.h" + +class LessonModel : public QAbstractListModel { + Q_OBJECT + QML_SINGLETON + QML_NAMED_ELEMENT(LessonModel) + + Q_PROPERTY(int num READ rowCount NOTIFY numChanged) + +signals: + void numChanged(); + +public: + enum Role { + Id = Qt::UserRole + 1, + DepTitle, + Topic, + Time, + Location, + Icon, + }; + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + + QVariant data(const QModelIndex& index, int role) const override; + + QHash roleNames() const override; + + void resetModel(std::vector&& model); + +private: + LessonModel() = default; + + std::vector m_data; + +public: + static LessonModel* create(QQmlEngine* qmlEngine, QJSEngine* jsEngine); + static LessonModel* getInstance(); +}; + +#endif // LESSON_MODEL_H diff --git a/src/include/movable_lambda.h b/src/include/movable_lambda.h new file mode 100644 index 0000000..7f3d40d --- /dev/null +++ b/src/include/movable_lambda.h @@ -0,0 +1,20 @@ +#ifndef MOVABLE_LAMBDA_H +#define MOVABLE_LAMBDA_H + +#include +#include + +template +class MovableLambda { + std::remove_reference_t stored; + std::function&&)> func; +public: + template + MovableLambda(T&& arg, Fun&& f) : stored(std::move(arg)), func(f) {} + + ReturnType operator()() { + return func(std::move(stored)); + } +}; + +#endif // MOVABLE_LAMBDA_H diff --git a/src/include/types.h b/src/include/types.h index 8a87c08..16ac399 100644 --- a/src/include/types.h +++ b/src/include/types.h @@ -6,6 +6,7 @@ using UserID = QString; using EventoID = int; +using EventTypeID = int; using LocationID = int; using Image = QString; using Tag = QString; @@ -26,7 +27,7 @@ enum class EventState : int { }; struct EventType { - int id; + EventTypeID id; QString name; bool allowConflict; };