diff --git a/src/cpp/include/trainWindow.h b/src/cpp/include/trainWindow.h new file mode 100644 index 0000000..d8491a5 --- /dev/null +++ b/src/cpp/include/trainWindow.h @@ -0,0 +1,8 @@ +#pragma once + + +#include + +extern QMainWindow *trainWindow; + +void initTrainWindow(); diff --git a/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx b/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx index 1d9bd4f..f2fa273 100644 Binary files a/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx and b/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx differ diff --git a/src/cpp/qtapp/CMakeLists.txt b/src/cpp/qtapp/CMakeLists.txt index 0e0c272..31b450d 100644 --- a/src/cpp/qtapp/CMakeLists.txt +++ b/src/cpp/qtapp/CMakeLists.txt @@ -15,6 +15,7 @@ find_package(Qt5 COMPONENTS Widgets REQUIRED) add_executable( MdemoryApp main.cpp + trainWindow.cpp ) target_link_libraries(MdemoryApp Qt5::Widgets api) diff --git a/src/cpp/qtapp/main.cpp b/src/cpp/qtapp/main.cpp index b9aa857..5f49a18 100644 --- a/src/cpp/qtapp/main.cpp +++ b/src/cpp/qtapp/main.cpp @@ -5,7 +5,11 @@ #include #include #include +#include #include +#include +#include +#include #include #include @@ -27,10 +31,12 @@ #include #include #include +#include #include #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 mdems = QList(); -std::vector questions = std::vector(); -QLabel *deckListLabel; -QVBoxLayout *hMdemScroll; -QSpacerItem *mdemSpacer; +QString workingPath = "/home/jorenchik/Code/mdemory/memorybase"; +std::string currentPath = ""; +QList mdems = QList(); +std::vector questions = std::vector(); +QLabel *deckListLabel; +QVBoxLayout *hMdemScroll; +QSpacerItem *mdemSpacer; const int PER_PAGE = 8; int currentPage = -1; std::vector pages; +QList paginationButtons; QToolButton* prevButton; QToolButton* firstButton; QToolButton* lastButton; QToolButton* nextButton; -QList 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(); } diff --git a/src/cpp/qtapp/trainWindow.cpp b/src/cpp/qtapp/trainWindow.cpp new file mode 100644 index 0000000..6f01a59 --- /dev/null +++ b/src/cpp/qtapp/trainWindow.cpp @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(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); +} diff --git a/src/cpp/transpiler/.cache/clangd/index/parser.cpp.1DA6C31FD012A889.idx b/src/cpp/transpiler/.cache/clangd/index/parser.cpp.1DA6C31FD012A889.idx index 8e42f30..f1ff536 100644 Binary files a/src/cpp/transpiler/.cache/clangd/index/parser.cpp.1DA6C31FD012A889.idx and b/src/cpp/transpiler/.cache/clangd/index/parser.cpp.1DA6C31FD012A889.idx differ