flashcard training widget drafts

This commit is contained in:
jorenchik
2024-09-22 16:32:53 +03:00
parent d84e7d9cd4
commit cde695da2a
6 changed files with 317 additions and 32 deletions

View File

@@ -0,0 +1,8 @@
#pragma once
#include <QMainWindow>
extern QMainWindow *trainWindow;
void initTrainWindow();

View File

@@ -15,6 +15,7 @@ find_package(Qt5 COMPONENTS Widgets REQUIRED)
add_executable( add_executable(
MdemoryApp MdemoryApp
main.cpp main.cpp
trainWindow.cpp
) )
target_link_libraries(MdemoryApp Qt5::Widgets api) target_link_libraries(MdemoryApp Qt5::Widgets api)

View File

@@ -5,7 +5,11 @@
#include <qabstractbutton.h> #include <qabstractbutton.h>
#include <qlabel.h> #include <qlabel.h>
#include <qlayoutitem.h> #include <qlayoutitem.h>
#include <qmainwindow.h>
#include <qobjectdefs.h> #include <qobjectdefs.h>
#include <qtoolbutton.h>
#include <qwindow.h>
#include <qwindowdefs.h>
#include <regex> #include <regex>
#include <string> #include <string>
@@ -27,10 +31,12 @@
#include <QRegularExpression> #include <QRegularExpression>
#include <QStringList> #include <QStringList>
#include <QListView> #include <QListView>
#include <QWindow>
#include <qabstractitemmodel.h> #include <qabstractitemmodel.h>
#include "api.h" #include "api.h"
#include "parser.h" #include "parser.h"
#include "trainWindow.h"
struct Page { struct Page {
int start; int start;
@@ -130,23 +136,28 @@ public:
}; };
QString workingPath = "/home/jorenchik/Code/mdemory/memorybase"; QString workingPath = "/home/jorenchik/Code/mdemory/memorybase";
QList<Mdem*> mdems = QList<Mdem*>(); std::string currentPath = "";
std::vector<Question*> questions = std::vector<Question*>(); QList<Mdem*> mdems = QList<Mdem*>();
QLabel *deckListLabel; std::vector<Question*> questions = std::vector<Question*>();
QVBoxLayout *hMdemScroll; QLabel *deckListLabel;
QSpacerItem *mdemSpacer; QVBoxLayout *hMdemScroll;
QSpacerItem *mdemSpacer;
const int PER_PAGE = 8; const int PER_PAGE = 8;
int currentPage = -1; int currentPage = -1;
std::vector<Page> pages; std::vector<Page> pages;
QList<QToolButton*> paginationButtons;
QToolButton* prevButton; QToolButton* prevButton;
QToolButton* firstButton; QToolButton* firstButton;
QToolButton* lastButton; QToolButton* lastButton;
QToolButton* nextButton; QToolButton* nextButton;
QList<QToolButton*> paginationButtons;
QLabel* paginationLabel; QLabel* paginationLabel;
QToolButton *load;
QToolButton *practice;
const std::regex doubleSpaceExp( const std::regex doubleSpaceExp(
" ", " ",
std::regex_constants::ECMAScript | std::regex_constants::icase std::regex_constants::ECMAScript | std::regex_constants::icase
@@ -313,6 +324,35 @@ void SwitchPage(int pageIdx) {
CreateMdems(pageSlice); CreateMdems(pageSlice);
} }
void loadMdem() {
auto file = std::ifstream(currentPath);
std::string content;
if (file) {
std::stringstream buffer;
buffer << file.rdbuf();
content = buffer.str();
auto parseRes = Transpile(content, true);
for (auto question: questions) {
delete question;
}
questions.clear();
if (parseRes.error == "") {
questions = parseRes.value;
makePages();
SwitchPage(0);
} else {
std::cout << "Compilation error." << std::endl;
for (auto mdem: mdems) {
if (mdem->wMdem->isVisible()) {
mdem->wMdem->hide();
}
}
}
} else {
std::cout << std::format("Could not open the file: {}", currentPath) << std::endl;
}
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
QApplication app(argc, argv); QApplication app(argc, argv);
QMainWindow window; QMainWindow window;
@@ -331,30 +371,16 @@ int main(int argc, char *argv[]) {
leftWidget->setLayout(leftLayout); leftWidget->setLayout(leftLayout);
leftLayout->addWidget(mdemLabel); leftLayout->addWidget(mdemLabel);
model->setRootPath(workingPath); model->setRootPath(workingPath);
// Hide all columns except the first one
mdemList->setModel(model); mdemList->setModel(model);
QObject::connect( QObject::connect(
mdemList, mdemList,
&QTreeView::doubleClicked, &QTreeView::doubleClicked,
[model](const QModelIndex &index) { [model](const QModelIndex &index) {
auto fileInfo = model->fileInfo(index); auto fileInfo = model->fileInfo(index);
auto path = fileInfo.filePath().toStdString(); currentPath = fileInfo.filePath().toStdString();
auto file = std::ifstream(path); loadMdem();
std::string content;
if (file) {
std::stringstream buffer;
buffer << file.rdbuf();
content = buffer.str();
auto parseRes = Transpile(content, true);
for (auto question: questions) {
delete question;
}
questions.clear();
questions = parseRes.value;
makePages();
SwitchPage(0);
} else {
std::cout << std::format("Could not open the file: {}", path) << std::endl;
}
} }
); );
@@ -362,8 +388,13 @@ int main(int argc, char *argv[]) {
"/home/jorenchik/Code/mdemory/memorybase" "/home/jorenchik/Code/mdemory/memorybase"
); );
mdemList->setRootIndex(rootIndex); mdemList->setRootIndex(rootIndex);
for (int col = 1; col < model->columnCount(); ++col) {
mdemList->hideColumn(col);
}
model->setHeaderData(0, Qt::Horizontal, QObject::tr("Custom Name"));
leftLayout->addWidget(mdemList); leftLayout->addWidget(mdemList);
// DeckList // DeckList
QLabel *deckLabel = new QLabel("Decks"); QLabel *deckLabel = new QLabel("Decks");
QListView *deckList = new QListView(); QListView *deckList = new QListView();
@@ -384,18 +415,16 @@ int main(int argc, char *argv[]) {
hTop->addWidget(deckListLabel); hTop->addWidget(deckListLabel);
hTop->addStretch(1); hTop->addStretch(1);
QToolButton *refresh = new QToolButton(); load = new QToolButton();
QToolButton *practice = new QToolButton(); practice = new QToolButton();
QToolButton *shuffle = new QToolButton();
hTop->addWidget(refresh); hTop->addWidget(load);
hTop->addWidget(shuffle);
hTop->addWidget(practice); hTop->addWidget(practice);
// Buttons // Buttons
refresh->setText("Refresh"); load->setText("Load");
shuffle->setText("Shuffle");
practice->setText("Practice"); practice->setText("Practice");
QObject::connect(load, &QToolButton::clicked, &loadMdem);
// Mdems // Mdems
QScrollArea *mdemScroll = new QScrollArea(); QScrollArea *mdemScroll = new QScrollArea();
@@ -477,7 +506,17 @@ int main(int argc, char *argv[]) {
hPagination->addWidget(paginationLabel); hPagination->addWidget(paginationLabel);
rightLayout->addWidget(pagination); rightLayout->addWidget(pagination);
initTrainWindow();
QObject::connect(
practice,
&QToolButton::clicked,
[](bool checked) {
trainWindow->show();
trainWindow->resize(600, 300);
});
window.setCentralWidget(hSplitter); window.setCentralWidget(hSplitter);
window.show(); window.show();
return app.exec(); return app.exec();
} }

View File

@@ -0,0 +1,237 @@
#include <QMainWindow>
#include <QWidget>
#include <QToolButton>
#include <qboxlayout.h>
#include <qlabel.h>
#include <qlistview.h>
#include <qnamespace.h>
#include <qstandarditemmodel.h>
#include <qstringlistmodel.h>
#include <qtoolbutton.h>
#include <Qt>
#include <qwidget.h>
#include <QStandardItemModel>
#include <QDropEvent>
#include "trainWindow.h"
QWidget *wMaster;
QVBoxLayout *hMaster;
QWidget *questionBox;
QVBoxLayout *vQuestionBox;
QLabel *lQuestionText;
QLabel *answerText;
QVBoxLayout *vButtonBox;
QWidget *actionButtons;
QHBoxLayout *hButtons;
QToolButton *btnPrev;
QToolButton *btnShowAnswer;
QToolButton *btnNext;
QMainWindow *trainWindow;
QWidget *trainWidget;
QVBoxLayout *vTrainWidget;
class CustomListView : public QListView
{
Q_OBJECT
public:
explicit CustomListView(QWidget *parent = nullptr) : QListView(parent) {}
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();
}
}
};
#include "trainWindow.moc"
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.
trainWindow = new QMainWindow();
trainWidget = new QWidget();
vTrainWidget = new QVBoxLayout();
/*wMaster = new QWidget();*/
/*hMaster = new QVBoxLayout();*/
trainWidget->setLayout(vTrainWidget);
trainWindow->setCentralWidget(trainWidget);
trainWidget->setLayout(vTrainWidget);
vTrainWidget->setAlignment(Qt::AlignCenter);
trainWidget->setObjectName("answer-question-widget");
{ // Make the question box.
vQuestionBox = new QVBoxLayout();
questionBox = new QWidget();
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);
}
{ // 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;"
" border: 1px solid black;"
"}"
"QListView::item::first {"
" padding: 5px 0 0 0;"
"}"
"QListView::item {"
" color: blue;"
" padding: 5px;"
" border: 1px solid gray;"
" background-color: white;"
"}"
"QListView::item:selected {"
"}"
"QListView::item:hover {"
" background-color: lightyellow;"
"}";
{ // Make multi-choice list.
auto *multiChoiceModel = new QStandardItemModel();
QListView *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);
}
{ // Make order list.
auto *orderModel = new QStandardItemModel();
QListView *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) {
if (sourceRow != destinationRow - 1) {
auto *movedItem = orderModel->takeItem(sourceRow);
orderModel->insertRow(destinationRow > sourceRow ? destinationRow - 1 : destinationRow, movedItem);
}
}
);
}
{ // Make buttons menu. There are left middle and right buttons.
vButtonBox = new QVBoxLayout();
actionButtons = new QWidget();
hButtons = new QHBoxLayout();
btnPrev = new QToolButton();
btnShowAnswer = new QToolButton();
btnNext = new QToolButton();
hButtons->addWidget(btnPrev);
hButtons->addWidget(btnShowAnswer);
hButtons->addWidget(btnNext);
vButtonBox->addWidget(actionButtons);
actionButtons->setLayout(hButtons);
btnPrev->setText("Previous");
btnShowAnswer->setText("Show answer");
btnNext->setText("Next");
QObject::connect(btnShowAnswer, &QToolButton::clicked, [](bool checked) {
answerText->show();
btnShowAnswer->hide();
});
actionButtons->setStyleSheet(QString(
"QToolButton {"
"padding: 4px 5px;"
"font-size: 15px;"
"}"
));
questionBox->setObjectName("question-box");
}
vTrainWidget->addWidget(questionBox);
vTrainWidget->addWidget(actionButtons);
vTrainWidget->addWidget(wMaster);
}