mirror of
https://github.com/jorenchik/mdemory.git
synced 2026-03-22 00:26:21 +00:00
restrutured removing the go source
This commit is contained in:
698
src/qtapp/trainWindow.cpp
Normal file
698
src/qtapp/trainWindow.cpp
Normal file
@@ -0,0 +1,698 @@
|
||||
#include <QMainWindow>
|
||||
#include <QWidget>
|
||||
#include <QToolButton>
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <format>
|
||||
#include <cstdlib>
|
||||
#include <exception>
|
||||
#include <format>
|
||||
#include <qabstractitemview.h>
|
||||
#include <qboxlayout.h>
|
||||
#include <qcoreevent.h>
|
||||
#include <qlabel.h>
|
||||
#include <qlayoutitem.h>
|
||||
#include <qlistview.h>
|
||||
#include <qnamespace.h>
|
||||
#include <qscrollarea.h>
|
||||
#include <qstandarditemmodel.h>
|
||||
#include <qstringlistmodel.h>
|
||||
#include <qtoolbutton.h>
|
||||
#include <Qt>
|
||||
#include <random>
|
||||
#include <qwidget.h>
|
||||
#include <QStandardItemModel>
|
||||
#include <QDropEvent>
|
||||
#include <QDrag>
|
||||
#include <iostream>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QPainter>
|
||||
|
||||
#include "trainWindow.h"
|
||||
#include "parser.h"
|
||||
|
||||
enum ElementState {
|
||||
NEUTRAL = 0,
|
||||
CORRECT,
|
||||
INCORRECT
|
||||
};
|
||||
|
||||
const auto listStyle =
|
||||
"QListView {"
|
||||
" background-color: white;"
|
||||
" border: 0px solid black;"
|
||||
"}"
|
||||
"QListView::item::first {"
|
||||
" padding: 5px 0 0 0;"
|
||||
"}"
|
||||
"QListView::item {"
|
||||
" color: black;"
|
||||
" padding: 5px;"
|
||||
" background-color: none;"
|
||||
"}"
|
||||
"QListView::item:selected {"
|
||||
" background-color: transparent;"
|
||||
" padding-left: 0px;"
|
||||
" margin-left: 0px;"
|
||||
"}"
|
||||
"QListView::item:hover {"
|
||||
" background-color: lightyellow;"
|
||||
" padding-left: 0px;"
|
||||
" margin-left: 0px;"
|
||||
"}";
|
||||
|
||||
class CustomItemDelegate : public QStyledItemDelegate {
|
||||
public:
|
||||
CustomItemDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
|
||||
|
||||
// Override the paint method to apply custom styling
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override {
|
||||
painter->save();
|
||||
Qt::GlobalColor color;
|
||||
auto colorIdx = index.data(Qt::UserRole + 1).toInt() ;
|
||||
switch (colorIdx) {
|
||||
case NEUTRAL:
|
||||
color = Qt::lightGray;
|
||||
break;
|
||||
case INCORRECT:
|
||||
color = Qt::red;
|
||||
break;
|
||||
case CORRECT:
|
||||
color = Qt::green;
|
||||
break;
|
||||
}
|
||||
painter->setOpacity(0.5);
|
||||
if (color) {
|
||||
painter->fillRect(option.rect, color);
|
||||
}
|
||||
painter->restore();
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
}
|
||||
};
|
||||
|
||||
class MultiChoiceListView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MultiChoiceListView(QWidget *parent = nullptr) : QListView(parent) {
|
||||
setStyleSheet(listStyle);
|
||||
setAcceptDrops(true);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setSelectionMode(QAbstractItemView::NoSelection);
|
||||
}
|
||||
};
|
||||
|
||||
class OrderListView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit OrderListView(QWidget *parent = nullptr) : QListView(parent) {
|
||||
setStyleSheet(listStyle);
|
||||
setAcceptDrops(true);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setDragDropMode(QAbstractItemView::InternalMove);
|
||||
}
|
||||
|
||||
protected:
|
||||
void dropEvent(QDropEvent *event) override
|
||||
{
|
||||
QModelIndex sourceIndex = currentIndex();
|
||||
QModelIndex targetIndex = indexAt(event->pos());
|
||||
|
||||
if (sourceIndex.isValid() && targetIndex.isValid()) {
|
||||
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(this->model());
|
||||
if (model) {
|
||||
QVariant sourceData = model->data(sourceIndex);
|
||||
QVariant targetData = model->data(targetIndex);
|
||||
model->setData(sourceIndex, targetData);
|
||||
model->setData(targetIndex, sourceData);
|
||||
event->ignore();
|
||||
}
|
||||
} else {
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MoveListView : public QListView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MoveListView(QWidget *parent = nullptr) : QListView(parent) {
|
||||
setStyleSheet(listStyle);
|
||||
setAcceptDrops(true);
|
||||
setDragDropMode(QAbstractItemView::DragDrop);
|
||||
setDefaultDropAction(Qt::MoveAction);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
|
||||
protected:
|
||||
void dragEnterEvent(QDragEnterEvent *event) override {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void dragMoveEvent(QDragMoveEvent *event) override {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void dropEvent(QDropEvent *event) override {
|
||||
QListView *source = qobject_cast<QListView *>(event->source());
|
||||
QStandardItemModel *sourceModel = qobject_cast<QStandardItemModel *>(source->model());
|
||||
QStandardItemModel *targetModel = qobject_cast<QStandardItemModel *>(this->model());
|
||||
|
||||
if (source != this) {
|
||||
QList<QStandardItem *> items = sourceModel->takeRow(source->currentIndex().row());
|
||||
targetModel->appendRow(items);
|
||||
}
|
||||
|
||||
event->ignore();
|
||||
}
|
||||
};
|
||||
|
||||
#include "trainWindow.moc"
|
||||
|
||||
struct GroupView {
|
||||
QWidget widget;
|
||||
QVBoxLayout vWidget;
|
||||
QLabel label;
|
||||
QScrollArea itemScroll;
|
||||
QStandardItemModel itemModel;
|
||||
MoveListView itemList;
|
||||
};
|
||||
|
||||
|
||||
// Main components
|
||||
QMainWindow *trainWindow;
|
||||
QWidget *trainWidget;
|
||||
QVBoxLayout *vTrainWidget;
|
||||
CustomItemDelegate *itemDelegate;
|
||||
|
||||
// Question
|
||||
QWidget *questionBox;
|
||||
QVBoxLayout *vQuestionBox;
|
||||
QLabel *lQuestionText;
|
||||
|
||||
// Bottom buttons
|
||||
QVBoxLayout *vButtonBox;
|
||||
QWidget *actionButtons;
|
||||
QHBoxLayout *hButtons;
|
||||
QToolButton *btnPrev;
|
||||
QSpacerItem *leftSpacer;
|
||||
QToolButton *btnTriggerAnswer;
|
||||
QSpacerItem *rightSpacer;
|
||||
QToolButton *btnNext;
|
||||
|
||||
// Answer question
|
||||
QLabel *answerText;
|
||||
|
||||
// Multi-choice question
|
||||
QStandardItemModel *multiChoiceModel;
|
||||
QListView *multiChoiceList;
|
||||
|
||||
// Order question
|
||||
OrderListView *orderList;
|
||||
QStandardItemModel *orderModel;
|
||||
|
||||
// Group question
|
||||
QStandardItemModel *groupItemModel;
|
||||
QListView *groupItemList;
|
||||
QWidget *wGroupQuestion;
|
||||
QVBoxLayout *vGroups;
|
||||
std::vector<QStandardItemModel*> groupModels;
|
||||
|
||||
// Questions & State
|
||||
std::vector<Question*> trainQuestions = std::vector<Question*>();
|
||||
int32_t currentQuestionIndex = -1;
|
||||
std::vector<GroupView*> groupViews;
|
||||
|
||||
std::default_random_engine rng;
|
||||
std::vector<QStandardItem*> itemPool;
|
||||
|
||||
/*QStandardItem *makeItem(std::string content, bool isCheckable) {*/
|
||||
/* auto *item = new QStandardItem(); */
|
||||
/* item->setText(QString::fromStdString(content));*/
|
||||
/* item->setCheckable(isCheckable);*/
|
||||
/* return item;*/
|
||||
/*};*/
|
||||
|
||||
#define ITEM_POOL_CHUNK 200
|
||||
|
||||
QStandardItem* acquireItem() {
|
||||
if (itemPool.size() <= 0) {
|
||||
for (int i = 0; i < ITEM_POOL_CHUNK; ++i) {
|
||||
itemPool.push_back(new QStandardItem);
|
||||
}
|
||||
}
|
||||
auto item = itemPool.back();
|
||||
itemPool.pop_back();
|
||||
return item;
|
||||
}
|
||||
|
||||
void releaseItem(QStandardItem** item) {
|
||||
itemPool.push_back(*item);
|
||||
(*item) = nullptr;
|
||||
}
|
||||
|
||||
void releaseAllItems() {
|
||||
std::cout <<
|
||||
std::format("Starting release, currently in the pool: {}", itemPool.size()) <<
|
||||
std::endl;
|
||||
auto releaseAllInModel = [](QStandardItemModel *model) {
|
||||
auto itemCount = model->rowCount();
|
||||
for (int i = 0; i < itemCount; ++i) {
|
||||
auto item = model->item(0);
|
||||
model->takeRow(item->row());
|
||||
releaseItem(&item);
|
||||
}
|
||||
};
|
||||
releaseAllInModel(multiChoiceModel);
|
||||
releaseAllInModel(groupItemModel);
|
||||
releaseAllInModel(orderModel);
|
||||
for (auto groupView: groupViews) {
|
||||
releaseAllInModel(&groupView->itemModel);
|
||||
}
|
||||
std::cout << std::format("All items released, currently in the pool: {}", itemPool.size()) << std::endl;
|
||||
}
|
||||
|
||||
void hideQuestionElements() {
|
||||
lQuestionText->hide();
|
||||
answerText->hide();
|
||||
orderList->hide();
|
||||
multiChoiceList->hide();
|
||||
wGroupQuestion->hide();
|
||||
}
|
||||
|
||||
void setupAnswerQuestion(MultiElementQuestion *question) {
|
||||
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();
|
||||
}
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[](bool checked) {
|
||||
answerText->show();
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupOrderQuestion(MultiElementQuestion *question) {
|
||||
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) {
|
||||
auto *item = acquireItem();
|
||||
item->setData(NEUTRAL, Qt::UserRole + 1);
|
||||
item->setData(QVariant(), Qt::CheckStateRole);
|
||||
item->setCheckable(false);
|
||||
item->setText(QString::fromStdString(answerEl.Answer));
|
||||
orderModel->appendRow(item);
|
||||
}
|
||||
orderList->show();
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[question](bool checked) {
|
||||
for (int i = 0; i < orderModel->rowCount(); ++i) {
|
||||
auto item = orderModel->item(i, 0);
|
||||
auto text = item->text();
|
||||
auto isCorrect = question->Choices[i].Answer.compare(text.toStdString()) == 0;
|
||||
if (isCorrect) {
|
||||
item->setData(CORRECT, Qt::UserRole + 1);
|
||||
} else {
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
orderList->update();
|
||||
}
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupMultiChoiceQuestion(MultiElementQuestion *question) {
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
|
||||
multiChoiceModel->clear();
|
||||
for (auto answerEl: question->Choices) {
|
||||
auto *item = acquireItem();
|
||||
item->setText(QString::fromStdString(answerEl.Answer));
|
||||
item->setData(NEUTRAL, Qt::UserRole + 1);
|
||||
item->setCheckable(true);
|
||||
item->setCheckState(Qt::CheckState::Unchecked);
|
||||
multiChoiceModel->appendRow(item);
|
||||
}
|
||||
multiChoiceList->show();
|
||||
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[question](bool checked) {
|
||||
for (int i = 0; i < multiChoiceModel->rowCount(); ++i) {
|
||||
auto item = multiChoiceModel->item(i, 0);
|
||||
auto isCorrect = question->Choices[i].IsCorrect == (item->checkState() == Qt::Checked);
|
||||
if (isCorrect) {
|
||||
item->setData(CORRECT, Qt::UserRole + 1);
|
||||
} else {
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
multiChoiceList->update();
|
||||
}
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupGroupQuestion(GroupQuestion *question) {
|
||||
auto groupSpacer = new QSpacerItem(
|
||||
50, 50,
|
||||
QSizePolicy::Minimum,
|
||||
QSizePolicy::Expanding
|
||||
);
|
||||
|
||||
lQuestionText->setText(
|
||||
QString::fromStdString(question->QuestionText)
|
||||
);
|
||||
lQuestionText->show();
|
||||
wGroupQuestion->show();
|
||||
|
||||
for (auto group: question->Groups) {
|
||||
for (auto itemText: group.elements) {
|
||||
auto *qItem = acquireItem();
|
||||
qItem->setData(NEUTRAL, Qt::UserRole + 1);
|
||||
qItem->setCheckable(false);
|
||||
qItem->setData(QVariant(), Qt::CheckStateRole);
|
||||
qItem->setText(QString::fromStdString(itemText));
|
||||
groupItemModel->appendRow(qItem);
|
||||
}
|
||||
}
|
||||
groupItemList->update();
|
||||
|
||||
auto makeGroup = []() {
|
||||
auto groupView = new GroupView;
|
||||
vGroups->addWidget(&groupView->label);
|
||||
vGroups->addWidget(&groupView->itemList);
|
||||
groupView->itemList.setModel(&groupView->itemModel);
|
||||
groupView->itemList.setMaximumHeight(100);
|
||||
groupView->itemList.setItemDelegate(itemDelegate);
|
||||
/*groupView->itemScroll.setWidget(&groupView->itemScroll);*/
|
||||
groupView->widget.setLayout(&groupView->vWidget);
|
||||
groupView->widget.layout()->addWidget(&groupView->label);
|
||||
groupView->widget.layout()->addWidget(&groupView->itemList);
|
||||
return groupView;
|
||||
};
|
||||
|
||||
for (int k = 0; k < groupViews.size(); k++) {
|
||||
groupViews[k]->widget.hide();
|
||||
}
|
||||
for (int i = 0; i < question->Groups.size(); i++) {
|
||||
GroupView *groupView;
|
||||
if (i < groupViews.size()) {
|
||||
groupView = groupViews[i];
|
||||
} else {
|
||||
groupView = makeGroup();
|
||||
groupViews.push_back(groupView);
|
||||
}
|
||||
groupView->label.setText(
|
||||
QString::fromStdString(question->Groups[i].name)
|
||||
);
|
||||
vGroups->addWidget(&groupView->widget);
|
||||
groupView->widget.show();
|
||||
}
|
||||
vGroups->addItem(groupSpacer);
|
||||
|
||||
QObject::connect(
|
||||
btnTriggerAnswer,
|
||||
&QToolButton::clicked,
|
||||
[question](bool checked) {
|
||||
for (int i = 0; i < groupItemModel->rowCount(); ++i) {
|
||||
auto item = groupItemModel->item(i, 0);
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
for (int i = 0; i < groupViews.size(); i++) {
|
||||
auto groupView = groupViews[i];
|
||||
auto group = question->Groups[i];
|
||||
for (int j = 0; j < groupView->itemModel.rowCount(); ++j) {
|
||||
auto item = groupView->itemModel.item(j, 0);
|
||||
auto itemText = item->text().toStdString();
|
||||
bool found = false;
|
||||
for (int k = 0; k < group.elements.size(); ++k) {
|
||||
if (group.elements[k].compare(itemText) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
item->setData(CORRECT, Qt::UserRole + 1);
|
||||
} else {
|
||||
item->setData(INCORRECT, Qt::UserRole + 1);
|
||||
}
|
||||
}
|
||||
groupView->itemList.update();
|
||||
}
|
||||
btnTriggerAnswer->hide();
|
||||
}
|
||||
);
|
||||
btnTriggerAnswer->show();
|
||||
}
|
||||
|
||||
void setupQuestion(Question *question) {
|
||||
hideQuestionElements();
|
||||
releaseAllItems();
|
||||
QObject::disconnect(btnTriggerAnswer, 0, 0, 0);
|
||||
if (auto *question = dynamic_cast<MultiElementQuestion*>(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<GroupQuestion*>(trainQuestions[currentQuestionIndex])) {
|
||||
setupGroupQuestion(question);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePaginationVisibility() {
|
||||
if (currentQuestionIndex == 0) {
|
||||
btnPrev->hide();
|
||||
} else {
|
||||
btnPrev->show();
|
||||
}
|
||||
if (currentQuestionIndex == trainQuestions.size() - 1) {
|
||||
btnNext->hide();
|
||||
} else {
|
||||
btnNext->show();
|
||||
}
|
||||
}
|
||||
|
||||
void setQuestions(std::vector<Question*> questions) {
|
||||
trainQuestions = questions;
|
||||
if (questions.size() <= 0) {
|
||||
return;
|
||||
}
|
||||
currentQuestionIndex = 0;
|
||||
updatePaginationVisibility();
|
||||
setupQuestion(trainQuestions[currentQuestionIndex]);
|
||||
}
|
||||
|
||||
void initTrainWindow() {
|
||||
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();
|
||||
|
||||
trainWidget->setLayout(vTrainWidget);
|
||||
trainWindow->setCentralWidget(trainWidget);
|
||||
trainWidget->setLayout(vTrainWidget);
|
||||
vTrainWidget->setAlignment(Qt::AlignCenter);
|
||||
trainWidget->setObjectName("answer-question-widget");
|
||||
|
||||
itemDelegate = new CustomItemDelegate(multiChoiceList);
|
||||
|
||||
{ // Make the question box.
|
||||
questionBox = new QWidget();
|
||||
vQuestionBox = new QVBoxLayout();
|
||||
questionBox->setLayout(vQuestionBox);
|
||||
questionBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding);
|
||||
vQuestionBox->setAlignment(Qt::AlignCenter);
|
||||
}
|
||||
|
||||
{ // Make question text.
|
||||
lQuestionText = new QLabel();
|
||||
lQuestionText->setText("What is the capital of Latvia?");
|
||||
lQuestionText->setWordWrap(true);
|
||||
lQuestionText->setStyleSheet(QString(
|
||||
"QLabel {"
|
||||
"font-size: 20px;"
|
||||
"}"
|
||||
));
|
||||
lQuestionText->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
vQuestionBox->addWidget(lQuestionText);
|
||||
lQuestionText->hide();
|
||||
}
|
||||
|
||||
{ // Make multi-choice list.
|
||||
multiChoiceModel = new QStandardItemModel();
|
||||
multiChoiceList = new MultiChoiceListView();
|
||||
multiChoiceList->setModel(multiChoiceModel);
|
||||
multiChoiceList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
questionBox->layout()->addWidget(multiChoiceList);
|
||||
multiChoiceList->hide();
|
||||
multiChoiceList->setItemDelegate(itemDelegate);
|
||||
}
|
||||
|
||||
{ // 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.
|
||||
orderModel = new QStandardItemModel();
|
||||
orderList = new OrderListView();
|
||||
orderList->setModel(orderModel);
|
||||
orderList->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
orderList->setItemDelegate(itemDelegate);
|
||||
|
||||
// Connect to handle the drop event properly
|
||||
QObject::connect(
|
||||
orderModel,
|
||||
&QStandardItemModel::rowsMoved,
|
||||
[](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();
|
||||
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(btnTriggerAnswer);
|
||||
hButtons->addItem(rightSpacer);
|
||||
hButtons->addWidget(btnNext);
|
||||
vButtonBox->addWidget(actionButtons);
|
||||
actionButtons->setLayout(hButtons);
|
||||
btnPrev->setText("Previous");
|
||||
QObject::connect(btnPrev, &QToolButton::clicked, []() {
|
||||
currentQuestionIndex--;
|
||||
if (currentQuestionIndex > -1) {
|
||||
setupQuestion(trainQuestions[currentQuestionIndex]);
|
||||
}
|
||||
updatePaginationVisibility();
|
||||
});
|
||||
|
||||
btnTriggerAnswer->setText("Show answer");
|
||||
|
||||
btnNext->setText("Next");
|
||||
QObject::connect(btnNext, &QToolButton::clicked, []() {
|
||||
currentQuestionIndex++;
|
||||
if (currentQuestionIndex < trainQuestions.size()) {
|
||||
setupQuestion(trainQuestions[currentQuestionIndex]);
|
||||
}
|
||||
updatePaginationVisibility();
|
||||
});
|
||||
questionBox->setObjectName("question-box");
|
||||
actionButtons->setStyleSheet(QString(
|
||||
"QToolButton {"
|
||||
"padding: 4px 5px;"
|
||||
"font-size: 15px;"
|
||||
"}"
|
||||
));
|
||||
}
|
||||
|
||||
{ // Make group question view.
|
||||
wGroupQuestion = new QWidget();
|
||||
wGroupQuestion->setStyleSheet(
|
||||
"border:none;"
|
||||
);
|
||||
auto hGroupQuestion = new QHBoxLayout();
|
||||
wGroupQuestion->setLayout(hGroupQuestion);
|
||||
|
||||
|
||||
// Items on the left.
|
||||
auto itemScroll = new QScrollArea();
|
||||
auto vItems = new QVBoxLayout();
|
||||
itemScroll->setLayout(vItems);
|
||||
groupItemModel = new QStandardItemModel();
|
||||
groupItemList = new MoveListView();
|
||||
groupItemList->setItemDelegate(itemDelegate);
|
||||
groupItemList->setModel(groupItemModel);
|
||||
vItems->addWidget(groupItemList);
|
||||
hGroupQuestion->addWidget(itemScroll);
|
||||
|
||||
// Items on the right.
|
||||
auto groupScroll = new QScrollArea();
|
||||
auto wGroupContainer = new QWidget();
|
||||
vGroups = new QVBoxLayout();
|
||||
groupScroll->setWidget(wGroupContainer);
|
||||
groupScroll->setWidgetResizable(true);
|
||||
wGroupContainer->setLayout(vGroups);
|
||||
hGroupQuestion->addWidget(groupScroll);
|
||||
|
||||
|
||||
wGroupQuestion->setStyleSheet("padding: 0; margin: 0;");
|
||||
wGroupQuestion->hide();
|
||||
questionBox->layout()->addWidget(wGroupQuestion);
|
||||
}
|
||||
|
||||
vTrainWidget->addWidget(questionBox);
|
||||
vTrainWidget->addWidget(actionButtons);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user