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(
MdemoryApp
main.cpp
trainWindow.cpp
)
target_link_libraries(MdemoryApp Qt5::Widgets api)

View File

@@ -5,7 +5,11 @@
#include <qabstractbutton.h>
#include <qlabel.h>
#include <qlayoutitem.h>
#include <qmainwindow.h>
#include <qobjectdefs.h>
#include <qtoolbutton.h>
#include <qwindow.h>
#include <qwindowdefs.h>
#include <regex>
#include <string>
@@ -27,10 +31,12 @@
#include <QRegularExpression>
#include <QStringList>
#include <QListView>
#include <QWindow>
#include <qabstractitemmodel.h>
#include "api.h"
#include "parser.h"
#include "trainWindow.h"
struct Page {
int start;
@@ -131,6 +137,7 @@ public:
QString workingPath = "/home/jorenchik/Code/mdemory/memorybase";
std::string currentPath = "";
QList<Mdem*> mdems = QList<Mdem*>();
std::vector<Question*> questions = std::vector<Question*>();
QLabel *deckListLabel;
@@ -140,13 +147,17 @@ QSpacerItem *mdemSpacer;
const int PER_PAGE = 8;
int currentPage = -1;
std::vector<Page> pages;
QList<QToolButton*> paginationButtons;
QToolButton* prevButton;
QToolButton* firstButton;
QToolButton* lastButton;
QToolButton* nextButton;
QList<QToolButton*> paginationButtons;
QLabel* paginationLabel;
QToolButton *load;
QToolButton *practice;
const std::regex doubleSpaceExp(
" ",
std::regex_constants::ECMAScript | std::regex_constants::icase
@@ -313,6 +324,35 @@ void SwitchPage(int pageIdx) {
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[]) {
QApplication app(argc, argv);
QMainWindow window;
@@ -331,30 +371,16 @@ int main(int argc, char *argv[]) {
leftWidget->setLayout(leftLayout);
leftLayout->addWidget(mdemLabel);
model->setRootPath(workingPath);
// Hide all columns except the first one
mdemList->setModel(model);
QObject::connect(
mdemList,
&QTreeView::doubleClicked,
[model](const QModelIndex &index) {
auto fileInfo = model->fileInfo(index);
auto path = fileInfo.filePath().toStdString();
auto file = std::ifstream(path);
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;
}
currentPath = fileInfo.filePath().toStdString();
loadMdem();
}
);
@@ -362,8 +388,13 @@ int main(int argc, char *argv[]) {
"/home/jorenchik/Code/mdemory/memorybase"
);
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);
// DeckList
QLabel *deckLabel = new QLabel("Decks");
QListView *deckList = new QListView();
@@ -384,18 +415,16 @@ int main(int argc, char *argv[]) {
hTop->addWidget(deckListLabel);
hTop->addStretch(1);
QToolButton *refresh = new QToolButton();
QToolButton *practice = new QToolButton();
QToolButton *shuffle = new QToolButton();
load = new QToolButton();
practice = new QToolButton();
hTop->addWidget(refresh);
hTop->addWidget(shuffle);
hTop->addWidget(load);
hTop->addWidget(practice);
// Buttons
refresh->setText("Refresh");
shuffle->setText("Shuffle");
load->setText("Load");
practice->setText("Practice");
QObject::connect(load, &QToolButton::clicked, &loadMdem);
// Mdems
QScrollArea *mdemScroll = new QScrollArea();
@@ -477,7 +506,17 @@ int main(int argc, char *argv[]) {
hPagination->addWidget(paginationLabel);
rightLayout->addWidget(pagination);
initTrainWindow();
QObject::connect(
practice,
&QToolButton::clicked,
[](bool checked) {
trainWindow->show();
trainWindow->resize(600, 300);
});
window.setCentralWidget(hSplitter);
window.show();
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);
}