From 67ea97809bafc264483c802994590bddd01b3908 Mon Sep 17 00:00:00 2001 From: jorenchik Date: Sun, 29 Sep 2024 17:01:44 +0300 Subject: [PATCH] different question type practice setup & parts of group train widget --- src/cpp/include/trainWindow.h | 4 +- src/cpp/qtapp/main.cpp | 15 +- src/cpp/qtapp/trainWindow.cpp | 306 ++++++++++++++++++++++++++-------- 3 files changed, 244 insertions(+), 81 deletions(-) diff --git a/src/cpp/include/trainWindow.h b/src/cpp/include/trainWindow.h index d8491a5..9eb3fdf 100644 --- a/src/cpp/include/trainWindow.h +++ b/src/cpp/include/trainWindow.h @@ -1,8 +1,10 @@ #pragma once - #include +#include "parser.h" + extern QMainWindow *trainWindow; void initTrainWindow(); +void setQuestions(std::vector questions); diff --git a/src/cpp/qtapp/main.cpp b/src/cpp/qtapp/main.cpp index 7f91161..6262b3b 100644 --- a/src/cpp/qtapp/main.cpp +++ b/src/cpp/qtapp/main.cpp @@ -346,6 +346,7 @@ void loadMdem() { questions = parseRes.value; makePages(); SwitchPage(0); + setQuestions(questions); } else { std::cout << "Compilation error." << std::endl; for (auto mdem: mdems) { @@ -381,13 +382,13 @@ int main(int argc, char *argv[]) { mdemList->setModel(model); QObject::connect( - mdemList, - &QTreeView::doubleClicked, - [model](const QModelIndex &index) { - auto fileInfo = model->fileInfo(index); - currentPath = fileInfo.filePath().toStdString(); - loadMdem(); - } + mdemList, + &QTreeView::doubleClicked, + [model](const QModelIndex &index) { + auto fileInfo = model->fileInfo(index); + currentPath = fileInfo.filePath().toStdString(); + loadMdem(); + } ); QModelIndex rootIndex = model->index( diff --git a/src/cpp/qtapp/trainWindow.cpp b/src/cpp/qtapp/trainWindow.cpp index 7743259..7bfd695 100644 --- a/src/cpp/qtapp/trainWindow.cpp +++ b/src/cpp/qtapp/trainWindow.cpp @@ -1,20 +1,26 @@ #include #include #include +#include +#include +#include #include #include #include #include #include +#include #include #include #include #include +#include #include #include #include #include "trainWindow.h" +#include "parser.h" QWidget *wMaster; QVBoxLayout *hMaster; @@ -28,13 +34,25 @@ QVBoxLayout *vButtonBox; QWidget *actionButtons; QHBoxLayout *hButtons; QToolButton *btnPrev; -QToolButton *btnShowAnswer; +QSpacerItem *leftSpacer; +QToolButton *btnTriggerAnswer; +QSpacerItem *rightSpacer; QToolButton *btnNext; QMainWindow *trainWindow; QWidget *trainWidget; QVBoxLayout *vTrainWidget; +std::default_random_engine rng; + +QStandardItemModel *multiChoiceModel; +QListView *listView; + +QStandardItemModel *itemModel; +QListView *itemListView; + +QStandardItemModel *orderModel; + class CustomListView : public QListView { Q_OBJECT @@ -62,26 +80,26 @@ protected: } } }; + #include "trainWindow.moc" +CustomListView *orderList; + +QStandardItem *makeItem(std::string content, bool isCheckable) { + auto *item = new QStandardItem(); + item->setText(QString::fromStdString(content)); + item->setCheckable(isCheckable); + return item; +}; + void initTrainWindow() { - // # Types of question - // - // - AnswerQuestion: - // One answer (could be on multiple lines). - // - ChoiceQuestion: - // One or many correct answers that are showed to user. - // - OrderQuestion: - // Many items that should be ordered in a list. - // - MatchQuestion: - // Match some items to other items. + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + rng = std::default_random_engine(seed); trainWindow = new QMainWindow(); trainWidget = new QWidget(); vTrainWidget = new QVBoxLayout(); - /*wMaster = new QWidget();*/ - /*hMaster = new QVBoxLayout();*/ trainWidget->setLayout(vTrainWidget); trainWindow->setCentralWidget(trainWidget); trainWidget->setLayout(vTrainWidget); @@ -107,23 +125,9 @@ void initTrainWindow() { )); lQuestionText->setTextInteractionFlags(Qt::TextSelectableByMouse); vQuestionBox->addWidget(lQuestionText); + lQuestionText->hide(); } - { // Make answer text. - answerText = new QLabel(); - answerText->setText("- Riga\n- Second line"); - answerText->setWordWrap(true); - answerText->hide(); - answerText->setStyleSheet(QString( - "QLabel {" - "font-size: 15px;" - "}" - )); - answerText->setTextInteractionFlags(Qt::TextSelectableByMouse); - vQuestionBox->addWidget(answerText); - } - - auto listStyle = "QListView {" " background-color: white;" @@ -133,7 +137,7 @@ void initTrainWindow() { " padding: 5px 0 0 0;" "}" "QListView::item {" - " color: blue;" + " color: black;" " padding: 5px;" " border: 1px solid gray;" " background-color: white;" @@ -145,98 +149,254 @@ void initTrainWindow() { "}"; { // Make multi-choice list. - auto *multiChoiceModel = new QStandardItemModel(); - QListView *listView = new QListView(); + multiChoiceModel = new QStandardItemModel(); + listView = new QListView(); listView->setModel(multiChoiceModel); - auto *firstItem = new QStandardItem(); - firstItem->setText("Item 1"); - firstItem->setCheckable(true); - auto *secondItem = new QStandardItem(); - secondItem->setText("Item 2"); - secondItem->setCheckable(true); - multiChoiceModel->setItem(0, firstItem); - multiChoiceModel->setItem(1, secondItem); - listView->setStyleSheet(listStyle); - - questionBox->layout()->addWidget(listView); listView->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); listView->setEditTriggers(QAbstractItemView::NoEditTriggers); + listView->setFocusPolicy(Qt::NoFocus); + questionBox->layout()->addWidget(listView); + listView->hide(); + } + + { // Make answer text. + answerText = new QLabel(); + answerText->setText("- Riga\n- Second line"); + answerText->setWordWrap(true); + answerText->setStyleSheet(QString( + "QLabel {" + "font-size: 15px;" + "}" + )); + answerText->setTextInteractionFlags(Qt::TextSelectableByMouse); + + vQuestionBox->addWidget(answerText); + answerText->hide(); } { // Make order list. - auto *orderModel = new QStandardItemModel(); - QListView *orderList = new CustomListView(); + orderModel = new QStandardItemModel(); + orderList = new CustomListView(); orderList->setModel(orderModel); - auto *firstItem = new QStandardItem(); - firstItem->setText("Item 1"); - auto *secondItem = new QStandardItem(); - secondItem->setText("Item 2"); - auto *thirdItem = new QStandardItem(); - thirdItem->setText("Item 3"); - orderModel->setItem(0, firstItem); - orderModel->setItem(1, secondItem); - orderModel->setItem(2, thirdItem); - - - questionBox->layout()->addWidget(orderList); orderList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); orderList->setEditTriggers(QAbstractItemView::NoEditTriggers); orderList->setDragDropMode(QAbstractItemView::InternalMove); orderList->setFocusPolicy(Qt::NoFocus); - orderList->setStyleSheet(listStyle); // Connect to handle the drop event properly QObject::connect( orderModel, &QStandardItemModel::rowsMoved, - [orderModel](const QModelIndex &, int sourceRow, int, const QModelIndex &, int destinationRow) { + [](const QModelIndex &, int sourceRow, int, const QModelIndex &, int destinationRow) { if (sourceRow != destinationRow - 1) { auto *movedItem = orderModel->takeItem(sourceRow); orderModel->insertRow(destinationRow > sourceRow ? destinationRow - 1 : destinationRow, movedItem); } } ); + + questionBox->layout()->addWidget(orderList); + orderList->hide(); } { // Make buttons menu. There are left middle and right buttons. - vButtonBox = new QVBoxLayout(); - actionButtons = new QWidget(); - hButtons = new QHBoxLayout(); - btnPrev = new QToolButton(); - auto *leftSpacer = new QSpacerItem(50, 50, QSizePolicy::Expanding, QSizePolicy::Minimum); - btnShowAnswer = new QToolButton(); - auto *rightSpacer = new QSpacerItem(50, 50, QSizePolicy::Expanding, QSizePolicy::Minimum); - btnNext = new QToolButton(); + vButtonBox = new QVBoxLayout(); + actionButtons = new QWidget(); + hButtons = new QHBoxLayout(); + btnPrev = new QToolButton(); + leftSpacer = new QSpacerItem(50, 50, QSizePolicy::Expanding, QSizePolicy::Minimum); + btnTriggerAnswer = new QToolButton(); + rightSpacer = new QSpacerItem(50, 50, QSizePolicy::Expanding, QSizePolicy::Minimum); + btnNext = new QToolButton(); hButtons->addWidget(btnPrev); hButtons->addItem(leftSpacer); - hButtons->addWidget(btnShowAnswer); + hButtons->addWidget(btnTriggerAnswer); hButtons->addItem(rightSpacer); hButtons->addWidget(btnNext); vButtonBox->addWidget(actionButtons); actionButtons->setLayout(hButtons); btnPrev->setText("Previous"); - btnShowAnswer->setText("Show answer"); + btnTriggerAnswer->setText("Show answer"); btnNext->setText("Next"); - QObject::connect(btnShowAnswer, &QToolButton::clicked, [](bool checked) { - answerText->show(); - btnShowAnswer->hide(); - }); + + questionBox->setObjectName("question-box"); actionButtons->setStyleSheet(QString( "QToolButton {" "padding: 4px 5px;" "font-size: 15px;" "}" )); - questionBox->setObjectName("question-box"); } + { // Make group question view. + auto wGroupQuestion = new QWidget(); + auto hGroupQuestion = new QHBoxLayout(); + wGroupQuestion->setLayout(hGroupQuestion); + + auto itemScroll = new QScrollArea(); + auto vItems = new QVBoxLayout(); + itemScroll->setLayout(vItems); + itemModel = new QStandardItemModel(); + itemListView = new QListView(); + itemListView->setModel(itemModel); + itemListView->setStyleSheet(listStyle); + for (int i = 0; i < 50; ++i) { + itemModel->appendRow(makeItem("Item I", false)); + } + vItems->addWidget(itemListView); + hGroupQuestion->addWidget(itemScroll); + + auto wGroupBox = new QWidget(); + auto vGroupBox = new QVBoxLayout(); + auto groupScroll = new QScrollArea(); + auto vGroups = new QVBoxLayout(); + wGroupBox->setLayout(vGroupBox); + vGroupBox->addWidget(groupScroll); + groupScroll->setLayout(vGroups); + hGroupQuestion->addWidget(wGroupBox); + + itemListView->setEditTriggers(QAbstractItemView::NoEditTriggers); + questionBox->layout()->addWidget(wGroupQuestion); + } vTrainWidget->addWidget(questionBox); vTrainWidget->addWidget(actionButtons); vTrainWidget->addWidget(wMaster); } + +std::vector trainQuestions = std::vector(); +int32_t currentQuestionIndex = -1; + +void hideQuestionElements() { + lQuestionText->hide(); + answerText->hide(); + orderList->hide(); + listView->hide(); +} + +void setupAnswerQuestion(MultiElementQuestion *question) { + hideQuestionElements(); + + lQuestionText->setText( + QString::fromStdString(question->QuestionText) + ); + lQuestionText->show(); + auto ss = std::stringstream(); + for (auto answerEl: question->Choices) { + ss << std::format("- {}", answerEl.Answer) << std::endl; + } + answerText->setText( + QString::fromStdString(ss.str()) + ); + if (answerText->isVisible()) { + answerText->hide(); + } + auto showAnswer = [](bool checked) { + answerText->show(); + btnTriggerAnswer->hide(); + QObject::disconnect(btnTriggerAnswer, 0, 0, 0); + }; + QObject::connect( + btnTriggerAnswer, + &QToolButton::clicked, + showAnswer + ); + btnTriggerAnswer->show(); +} + +void setupOrderQuestion(MultiElementQuestion *question) { + hideQuestionElements(); + + lQuestionText->setText( + QString::fromStdString(question->QuestionText) + ); + lQuestionText->show(); + orderModel->clear(); + auto shuffledAnswers = question->Choices; + std::shuffle(shuffledAnswers.begin(), shuffledAnswers.end(), rng); + for (auto answerEl: shuffledAnswers) { + orderModel->appendRow(makeItem(answerEl.Answer, false)); + } + orderList->show(); + auto showAnswer = [](bool checked) { + QObject::disconnect(btnTriggerAnswer, 0, 0, 0); + }; + QObject::connect( + btnTriggerAnswer, + &QToolButton::clicked, + showAnswer + ); + btnTriggerAnswer->show(); +} + +void setupMultiChoiceQuestion(MultiElementQuestion *question) { + hideQuestionElements(); + + lQuestionText->setText( + QString::fromStdString(question->QuestionText) + ); + lQuestionText->show(); + + multiChoiceModel->clear(); + for (auto answerEl: question->Choices) { + multiChoiceModel->appendRow(makeItem(answerEl.Answer, true)); + } + listView->show(); + + auto showAnswer = [](bool checked) { + QObject::disconnect(btnTriggerAnswer, 0, 0, 0); + }; + QObject::connect( + btnTriggerAnswer, + &QToolButton::clicked, + showAnswer + ); + btnTriggerAnswer->show(); +} + +void setupGroupQuestion(GroupQuestion *question) { + hideQuestionElements(); + + // TODO + + auto showAnswer = [](bool checked) { + QObject::disconnect(btnTriggerAnswer, 0, 0, 0); + }; + QObject::connect( + btnTriggerAnswer, + &QToolButton::clicked, + showAnswer + ); + btnTriggerAnswer->show(); +} + +void setQuestions(std::vector questions) { + trainQuestions = questions; + if (questions.size() <= 0) { + return; + } + + // setupFirstQuestion + currentQuestionIndex = 0; + if (auto *question = dynamic_cast(trainQuestions[currentQuestionIndex])) { + switch (question->type) { + case MultiElementType::Order: + setupOrderQuestion(question); + break; + case MultiElementType::MultiChoice: + setupMultiChoiceQuestion(question); + break; + case MultiElementType::Regular: + setupAnswerQuestion(question); + break; + } + } else if (auto *question = dynamic_cast(trainQuestions[currentQuestionIndex])) { + setupGroupQuestion(question); + } + +}