diff --git a/src/include/mdemList.h b/src/include/mdemList.h index 9995489..a1f57c2 100644 --- a/src/include/mdemList.h +++ b/src/include/mdemList.h @@ -67,6 +67,7 @@ struct Toolbar { void update(bool isChanged = false); void saveMdem(); +void saveMdem(MdemBuffer* mdemBuffer, std::string path); void updateMdemInfo(std::string filename = "", bool isChanged = true); QMainWindow *initMdemListWindow(); std::string outputMdem( diff --git a/src/qtapp/mdemList.cpp b/src/qtapp/mdemList.cpp index 7e3e9b2..67a2764 100644 --- a/src/qtapp/mdemList.cpp +++ b/src/qtapp/mdemList.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -50,7 +51,7 @@ std::string currentMdemPath = ""; QFileSystemModel *model; QTreeView *mdemList; std::map buffers; -MdemBuffer *currentMdemBuffer; +MdemBuffer *currentMdemBuffer = nullptr; // Atmiņas kaartīšu saraksts. std::vector mdems = std::vector(); @@ -71,6 +72,58 @@ QLabel *mdemLabel; QLabel *lastPracticeLabel; QMainWindow *trainWindow; +// Pielāgots lodziņa objekts, kas izveido ziņojuma +// lodziņu ar objektu pirms lietotne tiek aizvērta. +class CloseableMainWindow : public QMainWindow { + Q_OBJECT + +public: + explicit CloseableMainWindow(QWidget *parent = nullptr) + : QMainWindow(parent) { + setWindowTitle("Exit Confirmation"); + } + +protected: + // Apstrādā aizveršanas notikumu. + void closeEvent(QCloseEvent *event) override { + QMessageBox msgBox; + + // Pievieno tekstu un pogas. + msgBox.setWindowTitle("Darba beigšana"); + msgBox.setText("Vai tiešām beigt darbu?"); + auto *saveButton = msgBox.addButton( + "Saglabāt un beigt", + QMessageBox::AcceptRole + ); + auto *exitButton = msgBox.addButton( + "Beigt bez saglabāšanas", + QMessageBox::DestructiveRole + ); + auto *cancelButton = msgBox.addButton( + "Atcelt", + QMessageBox::RejectRole + ); + msgBox.exec(); + + // Apstrādā izvēli. + if (msgBox.clickedButton() == saveButton) { + for (auto buffer: buffers) { + saveMdem(buffer.second, buffer.first); + } + QApplication::exit(); + } else if (msgBox.clickedButton() == exitButton) { + QApplication::exit(); + } else if (msgBox.clickedButton() == cancelButton) { + msgBox.close(); + event->ignore(); + } else { + // Ja izvēle nav izdarīta - izvēli atceļ. + event->ignore(); + } + } +}; +#include "mdemList.moc" + /* * Atmiņas kartītei parāda visus slēptos elementus. * */ @@ -179,6 +232,10 @@ std::string outputMdem( * */ void makePages() { pagination->pages.clear(); + if (!currentMdemBuffer) { + return; + } + auto len = currentMdemBuffer->questions.size(); perPage = settings->value(SETTING_PER_PAGE).toInt(); auto pageAmount = len / perPage; @@ -189,15 +246,15 @@ void makePages() { } // Veido lappuses objektus. - for (size_t i = 0; i < pageAmount; i++) { - size_t startingIndex = perPage * i ; - size_t amount = perPage; - if (i == currentMdemBuffer->questions.size() / perPage) { + for (size_t i = 0; i < pageAmount; i++) { + size_t startingIndex = perPage * i ; + size_t amount = perPage; + if (i == currentMdemBuffer->questions.size() / perPage) { amount = currentMdemBuffer->questions.size() % perPage; } pagination->pages.push_back( - Page{startingIndex, startingIndex + amount} - ); + Page{startingIndex, startingIndex + amount} + ); } // Ja tiek noņemts pēdējais lappuses elements, pārliek lappusi uz iepriekšējo. @@ -303,7 +360,9 @@ std::string getFilename(std::string path) { * Atjauno atmiņas kartīšu faila augšējo informāciju. * */ void updateMdemInfo(std::string filename, bool isChanged) { - currentMdemBuffer->isModified = isChanged; + if (currentMdemBuffer) { + currentMdemBuffer->isModified = isChanged; + } if (filename.length() > 0) { std::stringstream ss; ss << std::format("Atmiņas kartīšu fails: {}", filename); @@ -313,7 +372,7 @@ void updateMdemInfo(std::string filename, bool isChanged) { mdemLabel->setText(QString::fromStdString(ss.str())); ss.str(""); - if (currentMdemBuffer->trainedAt > 0) { + if (currentMdemBuffer && currentMdemBuffer->trainedAt > 0) { std::tm* tm = std::localtime(¤tMdemBuffer->trainedAt); char buffer[100]; std::strftime(buffer, sizeof(buffer), "%d.%m.%Y %H:%M", tm); @@ -581,12 +640,16 @@ void switchPage(int pageIdx) { createMdems(pageSlice); } +/* + * Ielādē atmiņas kartītes un metadatus no norādītā faila ceļa. + * Ja eksistē bufferis, kam atbilst norādītais ceļš - ielādē + * no atmiņas. + * + * Ja tiek padots "", tad atmiņas kartīšu fails tiek atiestatīts. + * */ void reloadMdem(std::string path) { - if (path == "") { - return; - } - - auto toRemove = std::vector(); + // Izņem bufferus, kas nav mainīti un nesakrīt ar tagadējo ceļu. + auto toRemove = std::vector(); for (auto it = buffers.begin(); it != buffers.end(); ++it) { auto pair = *it; if (currentMdemPath.compare(path) != 0 && @@ -600,23 +663,29 @@ void reloadMdem(std::string path) { MdemBuffer *buffer; auto filename = getFilename(path); - if (currentMdemPath.compare(path) == 0) { - currentMdemPath = path; + if (path == "") { + // Atiesta atmiņas kartīšu failus. + currentMdemBuffer = nullptr; + currentMdemPath = path; + } else if (currentMdemPath == path) { + // Pārlādē tagadējo failu - izdzēš esošo bufferi. if (buffers.contains(path)) { buffers.erase(path); } } else if (!buffers.contains(path)) { + // Izveido bufferi, ja tāds neeksistē. buffer = new MdemBuffer; buffers[path] = buffer; currentMdemBuffer = buffer; - currentMdemPath = path; + currentMdemPath = path; } else { + // Bufferis eksistē, ielādē to no atmiņas. buffer = buffers[path]; currentMdemBuffer = buffer; + currentMdemPath = path; makePages(); switchPage(0); updateMdemInfo(getFilename(filename), buffer->isModified); - currentMdemPath = path; errorView->box.hide(); return; } @@ -629,72 +698,93 @@ void reloadMdem(std::string path) { for (auto mdem: mdems) { mdem->wMdem.hide(); } - for (auto question: currentMdemBuffer->questions) { - delete question; - } - currentMdemBuffer->questions.clear(); + if (currentMdemBuffer) { + for (auto question: currentMdemBuffer->questions) { + delete question; + } + currentMdemBuffer->questions.clear(); + } - if (file) { - std::stringstream buffer; - buffer << file.rdbuf(); - content = buffer.str(); - end = std::chrono::high_resolution_clock::now(); - showTimes = settings->value(SETTING_SHOW_TIMES).toBool(); - if (showTimes) { - std::cout << showTime("I/O laiks") << std::endl; - } - debug = settings->value(SETTING_DEBUG).toBool(); - auto res = transpile(content); + // TODO comment + if (currentMdemBuffer) { + if (file) { + // Ielādē faila saturu buferī. + std::stringstream buffer; + buffer << file.rdbuf(); + content = buffer.str(); + currentMdemPath = path; - currentMdemBuffer->error = res.error.length() > 0; - if (res.error == "") { - if (res.value.lastTrainedAt == 0) { - currentMdemBuffer->trainedAt = 0; - } else { - auto timezoneOffset = settings->value("timezone").toInt(); - currentMdemBuffer->trainedAt = res.value.lastTrainedAt - 3600 * timezoneOffset; - } + end = std::chrono::high_resolution_clock::now(); + showTimes = settings->value(SETTING_SHOW_TIMES).toBool(); + if (showTimes) { + std::cout << showTime("I/O laiks") << std::endl; + } + debug = settings->value(SETTING_DEBUG).toBool(); - if (settings->value(SETTING_DEBUG).toBool()) { - std::cout << std::format("Pēdējās mācīšanās reize: {}", currentMdemBuffer->trainedAt) - << std::endl; - } + // Transpilē saturu. + auto res = transpile(content); + currentMdemBuffer->error = res.error.length() > 0; - currentMdemBuffer->questions = res.value.questions; - errorView->box.hide(); - } else { - currentMdemBuffer->trainedAt = 0; - std::cout << std::format("Transpilācijas kļūda: {}", res.error) << std::endl; + if (res.error == "") { + // Aizpilda pēdējo mācīšanās laiku. + if (res.value.lastTrainedAt == 0) { + currentMdemBuffer->trainedAt = 0; + } else { + auto timezoneOffset = settings->value("timezone").toInt(); + currentMdemBuffer->trainedAt = res.value.lastTrainedAt - 3600 * timezoneOffset; + } + if (settings->value(SETTING_DEBUG).toBool()) { + std::cout << std::format( + "Pēdējās mācīšanās reize: {}", + currentMdemBuffer->trainedAt + ) + << std::endl; + } - for (auto question: res.value.questions) { - delete question; - } + // Uzstādā jautājumus. + currentMdemBuffer->questions = res.value.questions; + errorView->box.hide(); + } else { + // Apstrādā un izveido kļūdu. + currentMdemBuffer->trainedAt = 0; + for (auto question: res.value.questions) { + delete question; + } + hMdemScroll->removeItem(mdemSpacer); + errorView->label.setText( + QString::fromStdString( + std::format( + "Kļūda, transpilējot {}: {} ({}:{})", + filename, + res.error, + res.row, + res.column + ) + ) + ); + errorView->box.show(); + hMdemScroll->addWidget(&errorView->box); + hMdemScroll->addItem(mdemSpacer); + } - // Parāda kļūdu. - hMdemScroll->removeItem(mdemSpacer); - errorView->label.setText( - QString::fromStdString( - std::format( - "Kļūda, transpilējot {}: {} ({}:{})", - filename, - res.error, - res.row, - res.column - ) - ) - ); - errorView->box.show(); - - hMdemScroll->addWidget(&errorView->box); - hMdemScroll->addItem(mdemSpacer); - } - makePages(); - switchPage(0); - updateMdemInfo(filename, false); - } else { - std::cout << std::format("Nevar atvert failu: {}", currentMbasePath.toStdString()) << std::endl; - } + // Uzstāda sarakstu. + makePages(); + switchPage(0); + updateMdemInfo(filename, false); + } else { + std::cout + << std::format( + "Nevar atvert failu: {}", + currentMbasePath.toStdString() + ) + << std::endl; + } + } else { + updateMdemInfo("", false); + } + // Visām kartītēm paslēp elementus un mācīšanās + // logā paslēp visus elementus. for (auto mdem: mdems) { mdem->wBack.hide(); mdem->toggleVisibility.setText("Parādīt"); @@ -702,8 +792,12 @@ void reloadMdem(std::string path) { hideQuestionElements(); } +/* + * Atvēr direktoriju - atmiņas bāzi. + * */ void pickDirectory(QString directory) { + // Pārbauda eksistenci. auto path = std::filesystem::path(directory.toStdString()); if ( !std::filesystem::exists(directory.toStdString()) || @@ -742,9 +836,33 @@ void pickDirectory(QString directory) { currentMbasePath = ""; return; } - currentMbasePath = directory; + // Atbrīvo nevajadzīgos bufferus. + for (auto pair: buffers) { + bool isFileAChild; + // Pārbauda, vai bufferis ir izvēlētās direktorijas pēctacis. + try { + auto filePath = std::filesystem::absolute(pair.first).string(); + auto dirPath = std::filesystem::absolute(currentMbasePath.toStdString()).string(); + if (dirPath.back() != '/') { + dirPath += '/'; + } + isFileAChild = filePath.rfind(dirPath, 0) == 0; + } catch (const std::filesystem::filesystem_error& e) { + isFileAChild = false; + } + + // Ja bufferis nav pēctacis, to atbrīvo. + if (!isFileAChild) { + for (auto question: pair.second->questions) { + delete question; + } + pair.second->questions.clear(); + buffers.erase(pair.first); + } + } + // Atjauno failu sarakstu. if (directory.length() <= 0) { membaseLabel->setText(directory); @@ -761,15 +879,27 @@ void pickDirectory(QString directory) { ) )); + // Atiestata direktoriju. reloadMdem(""); } +/* + * Saglabā kartīti(/-es) redigēšanai vai pievienošanai. + * */ void setupEditorSave() { - const QString title = editMdem ? "Rediģēšanas kļūda" : "Pievienošanas kļūda"; + if (!currentMdemBuffer) { + return; + } + debug = settings->value(SETTING_DEBUG).toBool(); showTimes = settings->value(SETTING_SHOW_TIMES).toBool(); + + + // Transpilē. auto res = transpile(editor->text().toStdString()); + const QString title = editMdem ? "Rediģēšanas kļūda" : "Pievienošanas kļūda"; if (res.error.length() > 0) { + // Apstrādā un parāda kļūdu. currentMdemBuffer->trainedAt = 0; for (auto question: res.value.questions) { delete question; @@ -781,6 +911,7 @@ void setupEditorSave() { ); } else { if (editMdem) { + // Jautājuma redigēšana. if (res.value.questions.size() <= 0) { QMessageBox::information( nullptr, @@ -792,9 +923,14 @@ void setupEditorSave() { editMdem->question = res.value.questions[0]; for (size_t i = 0; i < currentMdemBuffer->questions.size(); ++i) { if (currentMdemBuffer->questions[i] == oldQuestion) { - currentMdemBuffer->questions.erase(currentMdemBuffer->questions.begin() + i); + currentMdemBuffer->questions.erase( + currentMdemBuffer->questions.begin() + i + ); delete oldQuestion; - currentMdemBuffer->questions.insert(currentMdemBuffer->questions.begin() + i, res.value.questions[0]); + currentMdemBuffer->questions.insert( + currentMdemBuffer->questions.begin() + i, + res.value.questions[0] + ); break; } } @@ -810,6 +946,7 @@ void setupEditorSave() { ); } } else { + // Jautājuma pievienošana. if (res.value.questions.size() <= 0) { QMessageBox::information( nullptr, @@ -831,10 +968,25 @@ void setupEditorSave() { } }; +/* + * Saglabā tagadējo bufferi. + * */ void saveMdem() { + saveMdem(currentMdemBuffer, currentMdemPath); +} + +/* + * Saglabā noteikto bufferi ar doto ceļu. + * Failā ieliek detraspilētās kartītes un datumu ar laiku. + * */ +void saveMdem(MdemBuffer* buffer, std::string path) { + if (!buffer) { + return; + } start = std::chrono::high_resolution_clock::now(); - std::filesystem::path dir(currentMdemPath); + // Izveido direktoriju, ja gadījuma tāda nav saglabājamam ceļam. + std::filesystem::path dir(path); auto parentPath = dir.parent_path(); if (!parentPath.empty() && !std::filesystem::exists(parentPath)) { if (!std::filesystem::create_directories(parentPath)) { @@ -846,9 +998,7 @@ void saveMdem() { } } - auto filename = getFilename(currentMdemPath); - std::ofstream out(currentMdemPath); - + // Iegūst parametrus, kas ietekmē detranspilēšanu. int wrap_width = 80; if (settings->contains(SETTING_CHARACTER_WRAP)) { wrap_width = settings->value(SETTING_CHARACTER_WRAP).toInt(); @@ -857,15 +1007,20 @@ void saveMdem() { if (settings->contains(SETTING_TIMEZONE)) { timezoneOffset = settings->value(SETTING_TIMEZONE).toInt(); } + + // Detranspilē un saglabā saturu failā. + auto filename = getFilename(path); + std::ofstream out(path); out << outputMdem( - currentMdemBuffer->questions, - currentMdemBuffer->trainedAt, + buffer->questions, + buffer->trainedAt, wrap_width, timezoneOffset ); - updateMdemInfo(getFilename(currentMdemPath), false); - end = std::chrono::high_resolution_clock::now(); + // Indikators - kartīšu faila saturs nav mainīts pēc pēdējās saglabāšanas. + updateMdemInfo(getFilename(path), false); + end = std::chrono::high_resolution_clock::now(); showTimes = settings->value(SETTING_SHOW_TIMES).toBool(); if (showTimes) { std::cout << showTime("Saglabāšanas laiks") << std::endl; @@ -876,11 +1031,13 @@ void saveMdem() { * Inicializē visus atmiņas kartīšu saraksta elementus un izvēlni. */ QMainWindow *initMdemListWindow() { - QMainWindow* window = new QMainWindow; - pagination = new Pagination; - auto *toolbar = new Toolbar(); - // Saistīti logi. + // Pamata objekti + auto window = new CloseableMainWindow; + auto *toolbar = new Toolbar(); + pagination = new Pagination; + + // Saistītie logi. auto *settingsWindow = initSettings(); trainWindow = initTrainWindow(); trainWindow->resize(800, 600); @@ -906,9 +1063,12 @@ QMainWindow *initMdemListWindow() { QMenuBar *menuBar = new QMenuBar; QFileDialog *fileDialog = new QFileDialog; + // Darbību saraksts. QMenu *menu = new QMenu("Darbības"); menu->setStyleSheet("font-size: 15px;"); actionOpen = menu->addAction("Atvērt atmiņas bāzi (Ctrl+O)"); + + // Bāzes atvēršana. QObject::connect( actionOpen, &QAction::triggered, @@ -931,6 +1091,7 @@ QMainWindow *initMdemListWindow() { } ); + // Parādīt failu pārlūkā. revealMbase = menu->addAction("Atvērt atmiņas bāzi failu pārlūkā (Ctrl+M)"); QObject::connect( revealMbase, @@ -949,6 +1110,7 @@ QMainWindow *initMdemListWindow() { } ); + // Konfigurācija. openSettings = menu->addAction("Iestatījumi (Ctrl+,)"); QObject::connect( openSettings, @@ -957,6 +1119,7 @@ QMainWindow *initMdemListWindow() { settingsWindow->show(); }); + // Palīdzība. actionHelp = menu->addAction("Palīdzība (Ctrl+H)"); QObject::connect( actionHelp, @@ -979,6 +1142,7 @@ QMainWindow *initMdemListWindow() { QVBoxLayout *vlEditor = new QVBoxLayout; wEditor->setLayout(vlEditor); + // C++ lekseris - iekrāso elementus atbilstoši C++ sintaksei. QsciLexerCPP *lexer = new QsciLexerCPP; editor = new QsciScintilla; editor->setLexer(lexer); @@ -1002,6 +1166,7 @@ QMainWindow *initMdemListWindow() { vlEditor->addWidget(editor); vlEditor->addWidget(editorButtons); + // Saglabāšanas funkcija izsauc vienu funkciju redigēšanai vai pievienošanai. QShortcut* shortcutSave = new QShortcut(QKeySequence("Ctrl+S"), editorWindow); QObject::connect(shortcutSave, &QShortcut::activated, []() { if (editor->isVisible()) { @@ -1073,9 +1238,6 @@ QMainWindow *initMdemListWindow() { reloadMdem(currentMdemPath); }); QObject::connect(&toolbar->btnSave, &QToolButton::clicked, []() { - if (!currentMdemBuffer) { - return; - } saveMdem(); }); QObject::connect(