mirror of
https://github.com/jorenchik/mdemory.git
synced 2026-03-22 00:26:21 +00:00
flashcard training widget drafts
This commit is contained in:
8
src/cpp/include/trainWindow.h
Normal file
8
src/cpp/include/trainWindow.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
extern QMainWindow *trainWindow;
|
||||
|
||||
void initTrainWindow();
|
||||
Binary file not shown.
@@ -15,6 +15,7 @@ find_package(Qt5 COMPONENTS Widgets REQUIRED)
|
||||
add_executable(
|
||||
MdemoryApp
|
||||
main.cpp
|
||||
trainWindow.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(MdemoryApp Qt5::Widgets api)
|
||||
|
||||
@@ -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;
|
||||
@@ -130,23 +136,28 @@ public:
|
||||
};
|
||||
|
||||
|
||||
QString workingPath = "/home/jorenchik/Code/mdemory/memorybase";
|
||||
QList<Mdem*> mdems = QList<Mdem*>();
|
||||
std::vector<Question*> questions = std::vector<Question*>();
|
||||
QLabel *deckListLabel;
|
||||
QVBoxLayout *hMdemScroll;
|
||||
QSpacerItem *mdemSpacer;
|
||||
QString workingPath = "/home/jorenchik/Code/mdemory/memorybase";
|
||||
std::string currentPath = "";
|
||||
QList<Mdem*> mdems = QList<Mdem*>();
|
||||
std::vector<Question*> questions = std::vector<Question*>();
|
||||
QLabel *deckListLabel;
|
||||
QVBoxLayout *hMdemScroll;
|
||||
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();
|
||||
}
|
||||
|
||||
237
src/cpp/qtapp/trainWindow.cpp
Normal file
237
src/cpp/qtapp/trainWindow.cpp
Normal 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);
|
||||
}
|
||||
Binary file not shown.
Reference in New Issue
Block a user