refactoring, shortcuts, layout changes

This commit is contained in:
jorenchik
2024-10-27 11:10:58 +02:00
parent 3db328a51c
commit 3eaa1ee04b
4 changed files with 325 additions and 247 deletions

View File

@@ -5,6 +5,10 @@
#include <iostream>
#include <map>
#include <filesystem>
#include <regex>
#include <sstream>
#include <string>
#include <qabstractbutton.h>
#include <qapplication.h>
#include <qboxlayout.h>
@@ -22,9 +26,6 @@
#include <qwidget.h>
#include <qwindow.h>
#include <qwindowdefs.h>
#include <regex>
#include <sstream>
#include <string>
#include <Qsci/qsciscintilla.h>
#include <Qsci/qscilexercpp.h>
@@ -70,54 +71,32 @@
#include "parser.h"
#include "qscilexer.h"
#define TEXT_LG = 20
#define ERROR_POOL_CHUNK 50
#define DISTANCE 2
#define PER_PAGE 8
#define MDEM_BACKGROUND "#F7F7F7"
// Memorybase info.
// @Improve: set the default directory for convenience. It should be configured by user
// or set to "".
QString currentPath = "";
std::string currentMdem = "";
QFileSystemModel *model;
QTreeView *mdemList;
QLabel *membaseLabel;
// Memorybase.
QString currentPath = "";
std::string currentMdem = "";
QFileSystemModel *model;
QTreeView *mdemList;
std::map<std::string, MdemBuffer*> buffers;
MdemBuffer *currentMdemBuffer = nullptr;
MdemBuffer *currentMdemBuffer;
// Mdem scroll list.
std::vector<Mdem*> mdems = std::vector<Mdem*>();
QVBoxLayout *hMdemScroll;
QSpacerItem *mdemSpacer;
ErrorView* errorView;
// Mdem list.
std::vector<Mdem*> mdems = std::vector<Mdem*>();
QVBoxLayout *hMdemScroll;
QSpacerItem *mdemSpacer;
ErrorView *errorView;
Pagination *pagination;
// Editor
Mdem* editMdem;
// Pagination
int currentPage = -1;
std::vector<Page> pages;
QList<QToolButton*> paginationButtons;
QToolButton* prevButton;
QToolButton* firstButton;
QToolButton* lastButton;
QToolButton* nextButton;
QLabel* paginationLabel;
// Top layout.
QLabel *deckListLabel;
QToolButton *add;
QToolButton *btnSaveFile;
QToolButton *load;
QToolButton *practice;
QsciScintilla *editor;
QMainWindow* editorWindow;
QMainWindow *editorWindow;
Mdem *editMdem;
const std::regex lastPathElementExp = std::regex("(.+\\/)*(.+)");
// Top labels.
QLabel *membaseLabel;
QLabel *mdemLabel;
QLabel *lastPracticeLabel;
QMainWindow *trainWindow;
void showBacklabels(Mdem *mdem) {
for (size_t i = 0; i < mdem->backLabels.size(); ++i) {
@@ -208,7 +187,7 @@ std::string outputMdem(std::vector<Question*> questions, time_t time = 0) {
}
void makePages() {
pages.clear();
pagination->pages.clear();
auto len = currentMdemBuffer->questions.size();
auto pageAmount = len / PER_PAGE;
if (len % PER_PAGE != 0) {
@@ -220,7 +199,9 @@ void makePages() {
if (i == currentMdemBuffer->questions.size() / PER_PAGE) {
amount = currentMdemBuffer->questions.size() % PER_PAGE;
}
pages.push_back(Page{startingIndex, startingIndex + amount});
pagination->pages.push_back(
Page{startingIndex, startingIndex + amount}
);
}
}
@@ -289,6 +270,7 @@ void setupMdem(Mdem *mdem, Question *question) {
void SwitchPage(int pageIdx);
std::string getFilename(std::string path) {
static const std::regex lastPathElementExp = std::regex("(.+\\/)*(.+)");
std::smatch matches;
auto filenameMatched = std::regex_search(path, matches, lastPathElementExp);
return matches[2].str();
@@ -302,15 +284,19 @@ void updateMdemInfo(std::string filename, bool isChanged) {
if (isChanged) {
ss << "*";
}
mdemLabel->setText(QString::fromStdString(ss.str()));
ss.str("");
if (currentMdemBuffer->trainedAt > 0) {
std::tm* tm = std::localtime(&currentMdemBuffer->trainedAt);
char buffer[100];
std::strftime(buffer, sizeof(buffer), "%d.%m.%Y %H:%M", tm);
ss << std::endl << "Last practiced: " << std::string(buffer);
ss << "Last practiced: " << std::string(buffer);
}
deckListLabel->setText(QString::fromStdString(ss.str()));
lastPracticeLabel->setText(QString::fromStdString(ss.str()));
} else {
deckListLabel->setText("");
mdemLabel->setText("");
lastPracticeLabel->setText("");
}
}
@@ -377,7 +363,7 @@ Mdem* makeMdem() {
}
}
makePages();
SwitchPage(currentPage);
SwitchPage(pagination->currentPage);
}
if (editMdem == mdem) {
editorWindow->hide();
@@ -455,8 +441,8 @@ void CreateMdems(std::vector<Question*>& questions) {
}
void update(bool isChanged) {
if (currentPage > -1) {
SwitchPage(currentPage);
if (pagination->currentPage > -1) {
SwitchPage(pagination->currentPage);
}
if (currentMdem.length() > 0) {
updateMdemInfo(getFilename(currentMdem), isChanged);
@@ -464,17 +450,17 @@ void update(bool isChanged) {
}
void SwitchPage(int pageIdx) {
currentPage = pageIdx;
pagination->currentPage = pageIdx;
// Hide all pagination buttons
for (auto& button : paginationButtons) {
for (auto& button : pagination->paginationButtons) {
button->hide();
}
int l = 0;
char buffer[50];
snprintf(buffer, sizeof(buffer), "Page: %d", pageIdx + 1);
paginationLabel->setText(buffer);
pagination->paginationLabel.setText(buffer);
// Hide widgets in mdems
for (auto& mdem : mdems) {
@@ -486,8 +472,8 @@ void SwitchPage(int pageIdx) {
// Update pagination buttons
for (int k = -DISTANCE; k <= DISTANCE; ++k) {
if (pageIdx + k >= 0 && pageIdx + k < pages.size()) {
auto button = paginationButtons[l];
if (pageIdx + k >= 0 && pageIdx + k < pagination->pages.size()) {
auto button = pagination->paginationButtons[l];
snprintf(buffer, sizeof(buffer), "%d", pageIdx + k + 1);
button->setText(buffer);
@@ -501,41 +487,41 @@ void SwitchPage(int pageIdx) {
}
// Handle first and last buttons
if (pageIdx > 0 && pages.size() > 1) {
firstButton->show();
if (pageIdx > 0 && pagination->pages.size() > 1) {
pagination->firstButton.show();
} else {
firstButton->hide();
pagination->firstButton.hide();
}
if (pageIdx < pages.size() - 1 && pages.size() > 1) {
lastButton->show();
if (pageIdx < pagination->pages.size() - 1 && pagination->pages.size() > 1) {
pagination->lastButton.show();
} else {
lastButton->hide();
pagination->lastButton.hide();
}
// Handle next and previous buttons
if (!pages.empty() && currentPage < pages.size() - 1) {
nextButton->show();
if (!pagination->pages.empty() && pagination->currentPage < pagination->pages.size() - 1) {
pagination->nextButton.show();
} else {
nextButton->hide();
pagination->nextButton.hide();
}
if (!pages.empty() && currentPage >= 1) {
prevButton->show();
if (!pagination->pages.empty() && pagination->currentPage >= 1) {
pagination->prevButton.show();
} else {
prevButton->hide();
pagination->prevButton.hide();
}
Page page;
if (pages.size() <= 0) {
if (pagination->pages.size() <= 0) {
page = Page();
} else if (pageIdx < pages.size()){
page = pages[pageIdx];
} else if (pageIdx < pagination->pages.size()){
page = pagination->pages[pageIdx];
} else {
if (pageIdx - 1 < pages.size()) {
page = pages[pageIdx -1];
if (pageIdx - 1 < pagination->pages.size()) {
page = pagination->pages[pageIdx -1];
} else {
page = pages[0];
page = pagination->pages[0];
}
}
@@ -651,7 +637,6 @@ void reloadMdem(std::string path) {
}
hideQuestionElements();
trainWindow->close();
}
void pickDirectory(QString directory) {
@@ -764,7 +749,12 @@ void saveMdem() {
QMainWindow *initMdemListWindow() {
QMainWindow* window = new QMainWindow;
pagination = new Pagination;
auto *toolbar = new Toolbar();
// Setup related windows
auto *settingsWindow = initSettings();
trainWindow = initTrainWindow();
{ // Menu bar.
QMenuBar *menuBar = new QMenuBar;
@@ -796,7 +786,7 @@ QMainWindow *initMdemListWindow() {
window->setMenuBar(menuBar);
}
{ // Setup editor.
{ // Editor.
editorWindow = new QMainWindow;
editorWindow->setWindowTitle("QScintilla Simple Editor");
@@ -838,33 +828,127 @@ QMainWindow *initMdemListWindow() {
editorWindow->setCentralWidget(wEditor);
}
QSplitter *hSplitter = new QSplitter();
auto *wTop = new QWidget();
{ // Top.
// Main top layout.
QHBoxLayout *hlTop = new QHBoxLayout();
wTop->setLayout(hlTop);
// Labels
auto *wLabels = new QWidget();
auto *vlLeftTop = new QVBoxLayout();
wLabels->setLayout(vlLeftTop);
wLabels->setMinimumSize(0, 40);
QString labelStyle = "font-size: 17px; font-weight: 400;";
// Memorybase label.
membaseLabel = new QLabel();
membaseLabel->setStyleSheet(labelStyle);
vlLeftTop->addWidget(membaseLabel);
// Memorybase label.
mdemLabel = new QLabel();
mdemLabel->setStyleSheet(labelStyle);
vlLeftTop->addWidget(mdemLabel);
lastPracticeLabel = new QLabel();
lastPracticeLabel->setStyleSheet(labelStyle);
vlLeftTop->addWidget(lastPracticeLabel);
// Button layout.
auto buttons = new QWidget();
auto vlButtons = new QVBoxLayout();
buttons->setLayout(vlButtons);
auto buttonsTop = new QWidget();
auto hlButtonsTop = new QHBoxLayout();
buttonsTop->setLayout(hlButtonsTop);
auto buttonsBottom = new QWidget();
auto hlButtonsBottom = new QHBoxLayout();
buttonsBottom->setLayout(hlButtonsBottom);
// Define buttons.
QObject::connect(&toolbar->btnAdd, &QToolButton::clicked, []() {
editMdem = nullptr;
editorWindow->show();
editor->setText("");
});
QObject::connect(&toolbar->btnLoad, &QToolButton::clicked, []() {
reloadMdem(currentMdem);
});
QObject::connect(&toolbar->btnSave, &QToolButton::clicked, []() {
saveMdem();
});
QObject::connect(
&toolbar->btnPractice,
&QToolButton::clicked,
[toolbar]() {
if (currentMdemBuffer) {
trainWindow->show();
trainWindow->resize(600, 300);
initiatePractice(
currentMdemBuffer,
static_cast<PracticeAlgorithm>(
toolbar->cbAlgorithm.currentData().toInt()
)
);
}
}
);
// Button content.
toolbar->btnAdd.setText("Add");
toolbar->btnSave.setText("Save");
toolbar->btnLoad.setText("Load");
toolbar->btnPractice.setText("Practice");
toolbar->cbAlgorithm.addItem("Spaced", SPACED);
toolbar->cbAlgorithm.addItem("Random", RANDOM);
toolbar->cbAlgorithm.addItem("Primary", PRIMARY);
// Add buttons.
hlButtonsTop->addWidget(&toolbar->btnAdd);
hlButtonsTop->addWidget(&toolbar->btnSave);
hlButtonsTop->addWidget(&toolbar->btnLoad);
hlButtonsBottom->addWidget(&toolbar->cbAlgorithm);
hlButtonsBottom->addWidget(&toolbar->btnPractice);
vlButtons->addWidget(buttonsTop);
vlButtons->addWidget(buttonsBottom);
// Style buttons
hlButtonsTop->setContentsMargins(0, 0, 0, 0);
hlButtonsBottom->setContentsMargins(0, 5, 0, 0);
// Add top components.
hlTop->addWidget(wLabels);
hlTop->addStretch(1);
hlTop->addWidget(buttons);
}
QWidget *leftWidget = new QWidget();
{ // Left side.
QVBoxLayout *leftLayout = new QVBoxLayout();
QWidget *leftTop = new QWidget();
QVBoxLayout *vLeftTop = new QVBoxLayout();
mdemList = new QTreeView();
membaseLabel = new QLabel();
model = new QFileSystemModel();
membaseLabel->setStyleSheet(
"font-size: 17px;"
"font-weight: 400;"
);
mdemSpacer = new QSpacerItem(50, 50, QSizePolicy::Minimum, QSizePolicy::Expanding);
leftWidget->setLayout(leftLayout);
leftLayout->addWidget(leftTop);
leftTop->setLayout(vLeftTop);
leftTop->setMinimumSize(0, 40);
vLeftTop->addWidget(membaseLabel);
// Hide all columns except the first one
model = new QFileSystemModel();
mdemList = new QTreeView();
mdemList->setModel(model);
currentPath = settings->value(SETTING_MEMORYBASE).toString();
if (currentPath.size() > 0) {
pickDirectory(currentPath);
}
/*leftLayout->addWidget(leftTop);*/
QObject::connect(
mdemList,
&QTreeView::doubleClicked,
[](const QModelIndex &index) {
trainWindow->close();
auto fileInfo = model->fileInfo(index);
reloadMdem(fileInfo.filePath().toStdString());
}
@@ -877,89 +961,23 @@ QMainWindow *initMdemListWindow() {
leftLayout->addWidget(mdemList);
}
auto wMain = new QWidget;
auto *rightWidget = new QWidget();
auto *rightLayout = new QVBoxLayout();
{ // Main layout.
auto vlMain = new QVBoxLayout;
wMain->setLayout(vlMain);
// RightSide
QWidget *rightWidget = new QWidget();
QVBoxLayout *rightLayout = new QVBoxLayout();
rightWidget->setLayout(rightLayout);
rightWidget->setLayout(rightLayout);
{ // Mdem list top.
QWidget *top = new QWidget();
QHBoxLayout *hTop = new QHBoxLayout();
deckListLabel = new QLabel();
deckListLabel->setStyleSheet(
"font-size: 17px;"
"font-weight: 400;"
);
top->setMinimumSize(0, 40);
top->setLayout(hTop);
rightLayout->addWidget(top);
auto *hSplitter = new QSplitter();
hSplitter->addWidget(leftWidget);
hSplitter->addWidget(rightWidget);
hSplitter->setStretchFactor(1, 3);
hSplitter->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
hTop->addWidget(deckListLabel);
hTop->addStretch(1);
add = new QToolButton;
btnSaveFile = new QToolButton;
load = new QToolButton;
auto cbAlgorithm = new QComboBox;
practice = new QToolButton;
// Buttons
auto buttons = new QWidget();
auto vlButtons = new QVBoxLayout();
buttons->setLayout(vlButtons);
auto buttonsTop = new QWidget();
auto hlButtonsTop = new QHBoxLayout();
buttonsTop->setLayout(hlButtonsTop);
auto buttonsBottom = new QWidget();
auto hlButtonsBottom = new QHBoxLayout();
buttonsBottom->setLayout(hlButtonsBottom);
add->setText("Add");
btnSaveFile->setText("Save");
load->setText("Load");
hlButtonsTop->addWidget(add);
hlButtonsTop->addWidget(btnSaveFile);
hlButtonsTop->addWidget(load);
cbAlgorithm->addItem("Spaced", SPACED);
cbAlgorithm->addItem("Random", RANDOM);
cbAlgorithm->addItem("Primary", PRIMARY);
practice->setText("Practice");
hlButtonsBottom->addWidget(cbAlgorithm);
hlButtonsBottom->addWidget(practice);
vlButtons->addWidget(buttonsTop);
vlButtons->addWidget(buttonsBottom);
hlButtonsTop->setContentsMargins(0, 0, 0, 0);
hlButtonsBottom->setContentsMargins(0, 5, 0, 0);
hTop->addWidget(buttons);
QObject::connect(add, &QToolButton::clicked, []() {
editMdem = nullptr;
editorWindow->show();
editor->setText("");
});
QObject::connect(load, &QToolButton::clicked, []() {
reloadMdem(currentMdem);
});
QObject::connect(btnSaveFile, &QToolButton::clicked, []() {
saveMdem();
});
QObject::connect(
practice,
&QToolButton::clicked,
[cbAlgorithm]() {
if (currentMdemBuffer) {
trainWindow->show();
trainWindow->resize(600, 300);
initiatePractice(
currentMdemBuffer,
static_cast<PracticeAlgorithm>(
cbAlgorithm->currentData().toInt()
)
);
}
}
);
vlMain->addWidget(wTop);
vlMain->addWidget(hSplitter);
}
{ // Error.
@@ -982,41 +1000,41 @@ QMainWindow *initMdemListWindow() {
{ // Mdems
QScrollArea *mdemScroll = new QScrollArea();
QWidget *mdemContainer = new QWidget();
hMdemScroll = new QVBoxLayout();
hMdemScroll = new QVBoxLayout();
mdemScroll->setWidget(mdemContainer);
mdemScroll->setWidgetResizable(true);
mdemContainer->setLayout(hMdemScroll);
rightLayout->addWidget(mdemScroll);
hMdemScroll->addItem(mdemSpacer);
mdemSpacer = new QSpacerItem(
50,
50,
QSizePolicy::Minimum,
QSizePolicy::Expanding
);
/*hMdemScroll->addItem(mdemSpacer);*/
}
{ // Pagination
hSplitter->addWidget(leftWidget);
hSplitter->addWidget(rightWidget);
hSplitter->setStretchFactor(0, 1);
hSplitter->setStretchFactor(1, 3);
auto pagination = new QWidget();
auto wPagination = new QWidget();
auto hPagination = new QHBoxLayout();
pagination->setLayout(hPagination);
wPagination->setLayout(hPagination);
firstButton = new QToolButton();
firstButton->setText(QString::fromStdString("<<"));
hPagination->addWidget(firstButton);
firstButton->hide();
QObject::connect(firstButton, &QToolButton::clicked, []() {
if (pages.size() > 0) {
pagination->firstButton.setText(QString::fromStdString("<<"));
hPagination->addWidget(&pagination->firstButton);
pagination->firstButton.hide();
QObject::connect(&pagination->firstButton, &QToolButton::clicked, []() {
if (pagination->pages.size() > 0) {
SwitchPage(0);
}
});
prevButton = new QToolButton();
prevButton->setText(QString::fromStdString("<"));
hPagination->addWidget(prevButton);
prevButton->hide();
QObject::connect(prevButton, &QToolButton::clicked, []() {
if (pages.size() > 0) {
SwitchPage(currentPage - 1);
pagination->prevButton.setText(QString::fromStdString("<"));
hPagination->addWidget(&pagination->prevButton);
pagination->prevButton.hide();
QObject::connect(&pagination->prevButton, &QToolButton::clicked, []() {
if (pagination->pages.size() > 0) {
SwitchPage(pagination->currentPage - 1);
}
});
@@ -1028,57 +1046,61 @@ QMainWindow *initMdemListWindow() {
QObject::connect(elButton, &QToolButton::clicked, [elButton]() {
auto pageNum = std::stoi(elButton->text().toStdString().c_str());
auto pageIdx = pageNum - 1;
if (pageIdx < pages.size()) {
if (pageIdx < pagination->pages.size()) {
SwitchPage(pageIdx);
}
});
paginationButtons.push_back(elButton);
pagination->paginationButtons.push_back(elButton);
}
nextButton = new QToolButton();
nextButton->setText(QString::fromStdString(">"));
hPagination->addWidget(nextButton);
nextButton->hide();
QObject::connect(nextButton, &QToolButton::clicked, []() {
if (pages.size() > 0) {
SwitchPage(currentPage + 1);
pagination->nextButton.setText(QString::fromStdString(">"));
hPagination->addWidget(&pagination->nextButton);
pagination->nextButton.hide();
QObject::connect(&pagination->nextButton, &QToolButton::clicked, []() {
if (pagination->pages.size() > 0) {
SwitchPage(pagination->currentPage + 1);
}
});
lastButton = new QToolButton();
lastButton->setText(QString::fromStdString(">>"));
hPagination->addWidget(lastButton);
lastButton->hide();
QObject::connect(lastButton, &QToolButton::clicked, []() {
if (pages.size() > 0) {
SwitchPage(pages.size() - 1);
pagination->lastButton.setText(QString::fromStdString(">>"));
hPagination->addWidget(&pagination->lastButton);
pagination->lastButton.hide();
QObject::connect(&pagination->lastButton, &QToolButton::clicked, []() {
if (pagination->pages.size() > 0) {
SwitchPage(pagination->pages.size() - 1);
}
});
hPagination->addStretch(1);
paginationLabel = new QLabel();
hPagination->addWidget(paginationLabel);
rightLayout->addWidget(pagination);
hPagination->addWidget(&pagination->paginationLabel);
rightLayout->addWidget(wPagination);
}
initTrainWindow();
{ // Setup shortcuts.
auto addShortcut = [window](QString key, std::function<void()> func) {
QShortcut* shortcut = new QShortcut(QKeySequence(key), window);
QObject::connect(shortcut, &QShortcut::activated, [func]() {
func();
});
};
window->setCentralWidget(hSplitter);
addShortcut("Ctrl+S", []() {
saveMdem();
});
addShortcut("Ctrl+,", [settingsWindow]() {
settingsWindow->show();
});
addShortcut("Ctrl+P", [toolbar]() {
toolbar->btnPractice.click();
});
addShortcut("Ctrl+A", [toolbar]() {
toolbar->btnAdd.click();
});
addShortcut("Ctrl+L", [toolbar]() {
toolbar->btnLoad.click();
});
}
window->setCentralWidget(wMain);
window->show();
currentPath = settings->value(SETTING_MEMORYBASE).toString();
if (currentPath.size() > 0) {
pickDirectory(currentPath);
}
QShortcut* shortcutSaveFile = new QShortcut(QKeySequence("Ctrl+S"), window);
QObject::connect(shortcutSaveFile, &QShortcut::activated, []() {
saveMdem();
});
QShortcut* shortcutSettings = new QShortcut(QKeySequence("Ctrl+C"), window);
QObject::connect(shortcutSettings, &QShortcut::activated, [settingsWindow]() {
settingsWindow->show();
});
return window;
}