diff --git a/.gitignore b/.gitignore index 0ff8f19..77e4c99 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ build-* */build-* release/ debug/ +protobuf/ *.exe *.dll *.so @@ -12,6 +13,7 @@ debug/ *.o *.obj *.app +translations/*.qm moc_*.cpp ui_*.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 821a0f3..b8ae4ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,9 +13,14 @@ find_package(Qt6 COMPONENTS Widgets Core Gui Sql REQUIRED) add_subdirectory(scripts) add_subdirectory(database) +add_subdirectory(ui/profile-window) add_subdirectory(ui/main-window) add_subdirectory(ui/authorization-windows) add_subdirectory(ui/note-widget) +add_subdirectory(ui/style-manager) +add_subdirectory(ui/settings-window) +add_subdirectory(ui/analytics-window) +add_subdirectory(ui/language-manager) add_subdirectory(proto) add_executable(EfficioTaskTracker main.cpp) @@ -28,7 +33,12 @@ target_link_libraries(EfficioTaskTracker PRIVATE efficio-rpc Database Scripts + StyleManager + LanguageManager AuthorizationWindows + ProfileWindow MainWindow NoteWidget -) \ No newline at end of file + SettingsWindow + AnalyticsWindow +) diff --git a/README.md b/README.md index d2242e4..cbfcd75 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,8 @@ git clone git@github.com:toximu/efficio-task-tracker.git sudo service postgresql start && sudo -u postgres psql ``` +> If you use fish shell, replace `service` with `systemctl` + 3. Create **efficio** user ```SQL @@ -39,15 +41,7 @@ GRANT ALL PRIVILEGES ON DATABASE efficio TO efficio; \q ``` -4. Enter under **efficio** profile - -```bash -psql -U efficio -d efficio -h localhost -``` - -> After that run the server on address **localhost** and **port** 5432 in your pgAdmin4 - -5. Build and start app +4. Build and start app ```bash mkdir -p build && cd build @@ -56,6 +50,11 @@ make ./EfficioTaskTracker -platform xcb ``` +## Current result + + + + ## Technologies Used - Qt 6.8.2 - PostgreSQL 17.4 @@ -64,4 +63,4 @@ make ## License -This project is licensed under the **MIT License**. See the [LICENSE](https://github.com/toximu/efficio-task-tracker/blob/main/LICENSE) file for details. \ No newline at end of file +This project is licensed under the **MIT License**. See the [LICENSE](https://github.com/toximu/efficio-task-tracker/blob/main/LICENSE) file for details. diff --git a/database/include/lr_dao.hpp b/database/include/lr_dao.hpp index de8d5fb..d4eed41 100644 --- a/database/include/lr_dao.hpp +++ b/database/include/lr_dao.hpp @@ -7,6 +7,7 @@ class LRDao { public: LRDao() = default; static int try_register_user(const QString &login, const QString &password); + static bool try_delete_user(const QString &login); static bool validate_user(const QString &login, const QString &password); static bool add_project_to_user(std::string user_login, int project_id); static bool diff --git a/database/src/database_manager.cpp b/database/src/database_manager.cpp index ad5b9ec..72a801a 100644 --- a/database/src/database_manager.cpp +++ b/database/src/database_manager.cpp @@ -13,10 +13,12 @@ DatabaseManager::DatabaseManager() { database_.open(); QSqlQuery query(database_); + query.exec( "CREATE TABLE IF NOT EXISTS notes (" "id SERIAL PRIMARY KEY, " "title TEXT NOT NULL, " + "type TEXT NOT NULL, " "content TEXT, " "members VARCHAR(50)[], " "date VARCHAR(50), " diff --git a/database/src/lr_dao.cpp b/database/src/lr_dao.cpp index 3107f5b..5c60887 100644 --- a/database/src/lr_dao.cpp +++ b/database/src/lr_dao.cpp @@ -29,6 +29,15 @@ int LRDao::try_register_user(const QString &login, const QString &password) { ); } +bool LRDao::try_delete_user(const QString &login) { + QSqlQuery query; + + return DatabaseManager::get_instance().execute_query( + query, "DELETE FROM users WHERE login = ?", + {login} + ); +} + bool LRDao::validate_user(const QString &login, const QString &password) { QSqlQuery query; diff --git a/database/src/note_dao.cpp b/database/src/note_dao.cpp index 369f192..950bd3c 100644 --- a/database/src/note_dao.cpp +++ b/database/src/note_dao.cpp @@ -6,8 +6,8 @@ bool NoteDao::initialize_note(int &id) { QSqlQuery query; const auto is_successful = DatabaseManager::get_instance().execute_query( query, - "INSERT INTO notes (title, content) " - "VALUES ('Пустая заметка', '')" + "INSERT INTO notes (title, type, content) " + "VALUES ('Пустая заметка', 'actual', '')" "RETURNING id" ); if (is_successful && query.next()) { @@ -23,6 +23,7 @@ bool NoteDao::update_note(const Note ¬e) { const QString sql_query = "UPDATE notes SET " "title = :title, " + "type = :type, " "content = :content, " "members = :members, " "date = :date, " @@ -31,6 +32,7 @@ bool NoteDao::update_note(const Note ¬e) { const QVariantList params = { QString::fromStdString(note.get_title()), QString::fromStdString(note.get_text()), + QString::fromStdString(note.get_type()), convert_string_set_to_postgres_array(note.get_members()), QString::fromStdString(note.get_date()), convert_tags_to_postgres_array(note.get_tags()), @@ -58,6 +60,7 @@ std::vector NoteDao::get_all_notes() { while (query.next()) { auto id = query.value("id").toUInt(); auto title = query.value("title").toString().toStdString(); + auto type = query.value("type").toString().toStdString(); auto text = query.value("content").toString().toStdString(); notes.emplace_back(id, title, text); } @@ -68,14 +71,15 @@ std::vector NoteDao::get_all_notes() { Note NoteDao::get_note_by_id(int id) { QSqlQuery query; DatabaseManager::get_instance().execute_query( - query, "SELECT title, content, array_to_string(tags, ','), date, array_to_string(members, ',') FROM notes WHERE id = ?", {id} + query, "SELECT title, type, content, array_to_string(tags, ','), date, array_to_string(members, ',') FROM notes WHERE id = ?", {id} ); query.next(); auto title = query.value(0).toString().toStdString(); - auto text = query.value(1).toString().toStdString(); - auto date = query.value(3).toString().toStdString(); + auto type = query.value(1).toString().toStdString(); + auto text = query.value(2).toString().toStdString(); + auto date = query.value(4).toString().toStdString(); Note result{id, title, text}; - auto tags_list = query.value(2).toString().split(","); + auto tags_list = query.value(3).toString().split(","); if (!tags_list.empty() && tags_list[0] != "") { for (const auto& tag_str : tags_list) { @@ -83,7 +87,7 @@ Note NoteDao::get_note_by_id(int id) { result.add_tag(tag_str.split(':')[0].toStdString(), tag_str.split(':')[1].toStdString()); } } - auto member_list = query.value(4).toString().split(","); + auto member_list = query.value(5).toString().split(","); if (!member_list.empty() && member_list[0] != "") { for (const auto& member : member_list) { result.add_member(member.toStdString()); diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..f16cc7c --- /dev/null +++ b/main.cpp @@ -0,0 +1,50 @@ +#include +#include +#include +#include +#include +#include "applicationwindow.h" +#include "login_window.h" +#include "style_manager.h" +#include "language_manager.h" +#include + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + + app.setApplicationName("EFFICIO"); + app.setApplicationDisplayName("EFFICIO"); + app.setOrganizationName("EFFICIO"); + app.setWindowIcon(QIcon(":/icons/app_icon.png")); + + QTranslator appTranslator; + QTranslator qtTranslator; + + QSettings settings; + QString language = settings.value("Language", QLocale::system().name()).toString(); + + if (appTranslator.load(":/translations/app_" + language + ".qm")) { + app.installTranslator(&appTranslator); + } + + if (qtTranslator.load("qt_" + language, QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { + app.installTranslator(&qtTranslator); + } + + StyleManager* style_manager = StyleManager::instance(); + LanguageManager* language_manager = LanguageManager::instance(); + + QMainWindow *app_window = new QMainWindow(); + app_window->setWindowTitle("EFFICIO"); + auto *login_window = new LoginWindow(app_window); + + app_window->setCentralWidget(login_window); + const QRect screen_geometry = QApplication::primaryScreen()->availableGeometry(); + const int x = (screen_geometry.width() - login_window->width()) / 2; + const int y = (screen_geometry.height() - login_window->height()) / 2; + app_window->move(x, y); + app_window->show(); + + return app.exec(); + +} \ No newline at end of file diff --git a/scripts/include/note.hpp b/scripts/include/note.hpp index e54e01a..4568a6f 100644 --- a/scripts/include/note.hpp +++ b/scripts/include/note.hpp @@ -20,11 +20,13 @@ class Note { [[nodiscard]] const std::string &get_title() const; [[nodiscard]] const std::string &get_text() const; [[nodiscard]] const std::string &get_date() const; + [[nodiscard]] const std::string &get_type() const; [[nodiscard]] const std::vector &get_tags() const; [[nodiscard]] const std::unordered_set &get_members() const; void set_title(const std::string &title); void set_text(const std::string &text); + void set_type(const std::string &type); void add_tag(const std::string &tag, const std::string &color = "#e7624b"); void set_date(const std::string &date); void add_member(const std::string &member); @@ -37,6 +39,7 @@ class Note { std::string title_; std::string text_; std::string date_; + std::string type_; std::vector tags_; std::unordered_set members_; }; diff --git a/scripts/src/note.cpp b/scripts/src/note.cpp index dcb8391..8ea7d0e 100644 --- a/scripts/src/note.cpp +++ b/scripts/src/note.cpp @@ -20,6 +20,10 @@ Note::Note(const int id, std::string title, std::string text) return text_; } +[[nodiscard]] const std::string &Note::get_type() const { + return type_; +} + const std::string &Note::get_date() const { return date_; } @@ -40,6 +44,10 @@ void Note::set_text(const std::string &text) { text_ = text; } +void Note::set_type(const std::string &type) { + type_ = type; +} + void Note::add_tag(const std::string &tag, const std::string &color) { tags_.push_back({tag, color}); } diff --git a/ui/analytics-window/CMakeLists.txt b/ui/analytics-window/CMakeLists.txt new file mode 100644 index 0000000..9c3798e --- /dev/null +++ b/ui/analytics-window/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.16) + +project(AnalyticsWindow LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 COMPONENTS Widgets Core Gui Sql Charts REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(SOURCES + src/analytics_window.cpp +) + +set(HEADERS + include/analytics_window.h + include/analytics_window_style_sheet.h +) + +add_library(AnalyticsWindow STATIC ${SOURCES} ${HEADERS}) + +target_include_directories(AnalyticsWindow + PUBLIC + $ + $ +) + +target_link_libraries(AnalyticsWindow + PRIVATE + Qt6::Core + Qt6::Gui + Qt6::Sql + Database + StyleManager + LanguageManager + PUBLIC + Qt6::Widgets + Qt6::Charts +) \ No newline at end of file diff --git a/ui/analytics-window/include/analytics_window.h b/ui/analytics-window/include/analytics_window.h new file mode 100644 index 0000000..63dddd5 --- /dev/null +++ b/ui/analytics-window/include/analytics_window.h @@ -0,0 +1,45 @@ +#ifndef ANALYTICS_DIALOG_H +#define ANALYTICS_DIALOG_H + +#include +#include +#include +#include +#include + +class AnalyticsWindow : public QDialog +{ + Q_OBJECT + +public: + explicit AnalyticsWindow( + QWidget *parent = nullptr, + int created_count = 3, + int completed_count = 4, + int expired_count = 5 + ); + ~AnalyticsWindow(); + + static const std::vector THEMES; + +private: + + void handle_theme_changed(int theme); + void handle_font_size_changed(std::string font_size); + void handle_language_changed(std::string new_language); + void on_switch_theme_clicked(); + void setup_chart(); + + int m_created_count; + int m_completed_count; + int m_expired_count; + + QChartView *chart_view; + QPieSeries *series; + QChart *chart; + QPieSlice *completed_slice; + QPieSlice *expired_slice; + QPieSlice *created_slice; +}; + +#endif // ANALYTICS_DIALOG_H \ No newline at end of file diff --git a/ui/analytics-window/include/analytics_window_style_sheet.h b/ui/analytics-window/include/analytics_window_style_sheet.h new file mode 100644 index 0000000..fb146a7 --- /dev/null +++ b/ui/analytics-window/include/analytics_window_style_sheet.h @@ -0,0 +1,380 @@ +#ifndef ANALYTICS_WINDOW_STYLE_SHEET_H +#define ANALYTICS_WINDOW_STYLE_SHEET_H + +#include + +namespace Ui { + +const QString analytics_window_light_autumn_theme = R"( +#AnalyticsWindow { + background-color: #f5f5f5; + color: #444444; + font-family: 'Arial'; +} + +QTabWidget::pane { + border: 1px solid #d0d0d0; + border-radius: 4px; + margin: 5px; + background: #ffffff; +} + +QTabBar::tab { + background: #e0e0e0; + color: #666666; + border: 1px solid #d0d0d0; + border-bottom: none; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding: 8px 15px; + margin-right: 2px; +} + +QTabBar::tab:selected { + background: #ffffff; + color: #222222; + border-color: #d0d0d0; + font-weight: bold; +} + +QTabBar::tab:hover { + background: #f0f0f0; +} + +QDialogButtonBox { + border-top: 1px solid #d0d0d0; + padding-top: 10px; +} + +QDialogButtonBox QPushButton { + background-color: #fea36b; + color: white; + border: 1px solid #e08c52; + border-radius: 3px; + padding: 5px 15px; + min-width: 80px; +} + +QDialogButtonBox QPushButton:hover { + background-color: #f58c50; +} + +QDialogButtonBox QPushButton:pressed { + background-color: #e07c40; +} + +QChartView { + background-color: #ffffff; + border-radius: 5px; + border: 1px solid #d0d0d0; + margin: 10px; +} + +QLegend::label { + color: #666666; +} + +QAbstractAxis { + color: #888888; +} +)"; + +const QString analytics_window_dark_autumn_theme = R"( +#AnalyticsWindow { + background-color: #202020; + color: #BDD1BD; + font-family: 'Arial'; +} + +QTabWidget::pane { + border: 1px solid #333333; + border-radius: 4px; + margin: 5px; + background: #282828; +} + +QTabBar::tab { + background: #323232; + color: #8a8a8a; + border: 1px solid #333333; + border-bottom: none; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding: 8px 15px; + margin-right: 2px; +} + +QTabBar::tab:selected { + background: #3a3a3a; + color: #BDD1BD; + border-color: #333333; + font-weight: bold; +} + +QTabBar::tab:hover { + background: #363636; +} + +QDialogButtonBox { + border-top: 1px solid #333333; + padding-top: 10px; +} + +QDialogButtonBox QPushButton { + background-color: #d38b5f; + color: #263238; + border: 1px solid #b3754d; + border-radius: 3px; + padding: 5px 15px; + min-width: 80px; +} + +QDialogButtonBox QPushButton:hover { + background-color: #c07b4f; +} + +QDialogButtonBox QPushButton:pressed { + background-color: #a86b3f; +} + +QChartView { + background-color: #282828; + border-radius: 5px; + border: 1px solid #333333; + margin: 10px; +} + +QLegend::label { + color: #a0a0a0; +} + +QAbstractAxis { + color: #8a8a8a; +} +)"; + +const QString analytics_window_light_purple_theme = R"( +#AnalyticsWindow { + background-color: #9882B9; + color: rgb(42, 10, 25); + font-family: 'Arial'; +} + +QTabWidget::pane { + border: 1px solid #7a5d9b; + border-radius: 4px; + margin: 5px; + background: #b9a2d9; +} + +QTabBar::tab { + background: #a992c9; + color: rgb(62, 20, 35); + border: 1px solid #7a5d9b; + border-bottom: none; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding: 8px 15px; + margin-right: 2px; +} + +QTabBar::tab:selected { + background: #d9c2f9; + color: rgb(42, 10, 25); + border-color: #7a5d9b; + font-weight: bold; +} + +QTabBar::tab:hover { + background: #c9b2e9; +} + +QDialogButtonBox { + border-top: 1px solid #7a5d9b; + padding-top: 10px; +} + +QDialogButtonBox QPushButton { + background-color: #722548; + color: #f5e5ff; + border: 1px solid #5a1538; + border-radius: 3px; + padding: 5px 15px; + min-width: 80px; +} + +QDialogButtonBox QPushButton:hover { + background-color: #5a1538; +} + +QDialogButtonBox QPushButton:pressed { + background-color: #4a0528; +} + +QChartView { + background-color: #d9c2f9; + border-radius: 5px; + border: 1px solid #7a5d9b; + margin: 10px; +} + +QLegend::label { + color: rgb(62, 20, 35); +} + +QAbstractAxis { + color: rgb(82, 40, 55); +} +)"; + +const QString analytics_window_dark_purple_theme = R"( +#AnalyticsWindow { + background-color: #221932; + color: #9882B9; + font-family: 'Arial'; +} + +QTabWidget::pane { + border: 1px solid #3a2a4a; + border-radius: 4px; + margin: 5px; + background: #2a1f3a; +} + +QTabBar::tab { + background: #322242; + color: #7a6a9a; + border: 1px solid #3a2a4a; + border-bottom: none; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding: 8px 15px; + margin-right: 2px; +} + +QTabBar::tab:selected { + background: #4a3a5a; + color: #c9b2e9; + border-color: #5a4a6a; + font-weight: bold; +} + +QTabBar::tab:hover { + background: #3a2a4a; +} + +QDialogButtonBox { + border-top: 1px solid #3a2a4a; + padding-top: 10px; +} + +QDialogButtonBox QPushButton { + background-color: #722548; + color: #d9c2f9; + border: 1px solid #5a1538; + border-radius: 3px; + padding: 5px 15px; + min-width: 80px; +} + +QDialogButtonBox QPushButton:hover { + background-color: #5a1538; +} + +QDialogButtonBox QPushButton:pressed { + background-color: #4a0528; +} + +QChartView { + background-color: #322242; + border-radius: 5px; + border: 1px solid #3a2a4a; + margin: 10px; +} + +QLegend::label { + color: #9a82b9; +} + +QAbstractAxis { + color: #8a7aa9; +} +)"; + +const QString analytics_window_blue_theme = R"( +#AnalyticsWindow { + background-color: #07142B; + color: #BDD1BD; + font-family: 'Arial'; +} + +QTabWidget::pane { + border: 1px solid #1a2c4b; + border-radius: 4px; + margin: 5px; + background: #0f1c35; +} + +QTabBar::tab { + background: #173C4C; + color: #8dacbd; + border: 1px solid #1a2c4b; + border-bottom: none; + border-top-left-radius: 4px; + border-top-right-radius: 4px; + padding: 8px 15px; + margin-right: 2px; +} + +QTabBar::tab:selected { + background: #1f4c5c; + color: #BDD1BD; + border-color: #1a2c4b; + font-weight: bold; +} + +QTabBar::tab:hover { + background: #1b4454; +} + +QDialogButtonBox { + border-top: 1px solid #1a2c4b; + padding-top: 10px; +} + +QDialogButtonBox QPushButton { + background-color: #568F7C; + color: #07142B; + border: 1px solid #3a6f5c; + border-radius: 3px; + padding: 5px 15px; + min-width: 80px; +} + +QDialogButtonBox QPushButton:hover { + background-color: #3a6f5c; +} + +QDialogButtonBox QPushButton:pressed { + background-color: #2a5f4c; +} + +QChartView { + background-color: #0f1c35; + border-radius: 5px; + border: 1px solid #1a2c4b; + margin: 10px; +} + +QLegend::label { + color: #9dbdcd; +} + +QAbstractAxis { + color: #7d9cad; +} +)"; + +} // namespace Ui + +#endif // ANALYTICS_WINDOW_STYLE_SHEET_H \ No newline at end of file diff --git a/ui/analytics-window/src/analytics_window.cpp b/ui/analytics-window/src/analytics_window.cpp new file mode 100644 index 0000000..e20c464 --- /dev/null +++ b/ui/analytics-window/src/analytics_window.cpp @@ -0,0 +1,158 @@ +#include "analytics_window.h" +#include "style_manager.h" +#include "language_manager.h" +#include "analytics_window_style_sheet.h" +#include + +const std::vector AnalyticsWindow::THEMES = { + Ui::analytics_window_light_autumn_theme, + Ui::analytics_window_dark_autumn_theme, + Ui::analytics_window_dark_purple_theme, + Ui::analytics_window_light_purple_theme, + Ui::analytics_window_blue_theme +}; + +AnalyticsWindow::AnalyticsWindow(QWidget *parent, + int created_count, + int completed_count, + int expired_count) + : QDialog(parent), + m_created_count(created_count), + m_completed_count(completed_count), + m_expired_count(expired_count), + chart_view(new QChartView(this)), + series(new QPieSeries()), + chart(new QChart()) +{ + setFixedSize(700, 400); + + QVBoxLayout *main_layout = new QVBoxLayout(this); + + completed_slice = new QPieSlice(); + completed_slice->setValue(m_completed_count); + completed_slice->setColor(QColor(46, 204, 113)); + + expired_slice = new QPieSlice(); + expired_slice->setValue(m_expired_count); + expired_slice->setColor(QColor(231, 76, 60)); + + created_slice = new QPieSlice(); + created_slice->setValue(m_created_count); + created_slice->setColor(QColor(52, 152, 219)); + + series->append(completed_slice); + series->append(expired_slice); + series->append(created_slice); + + chart->addSeries(series); + chart->legend()->setAlignment(Qt::AlignBottom); + chart->setAnimationOptions(QChart::AllAnimations); + + chart_view->setRenderHint(QPainter::Antialiasing); + chart_view->setChart(chart); + + main_layout->addWidget(chart_view); + setLayout(main_layout); + + connect( + StyleManager::instance(), &StyleManager::theme_changed, + this, &AnalyticsWindow::handle_theme_changed + ); + connect( + StyleManager::instance(), &StyleManager::font_size_changed, + this, &AnalyticsWindow::handle_font_size_changed + ); + connect(LanguageManager::instance(), &LanguageManager::language_changed, + this, &AnalyticsWindow::handle_language_changed + ); + handle_font_size_changed(StyleManager::instance()->current_font_size()); + handle_theme_changed(StyleManager::instance()->current_theme()); + handle_language_changed(LanguageManager::instance()->current_language()); +} + +void AnalyticsWindow::setup_chart() +{ + series->append("Завершенные", m_completed_count); + series->append("Просроченные", m_expired_count); + series->append("Созданные", m_created_count); + + QPieSlice *completed_slice = series->slices().at(0); + completed_slice->setColor(QColor(46, 204, 113)); + completed_slice->setLabelVisible(true); + + QPieSlice *expired_slice = series->slices().at(1); + expired_slice->setColor(QColor(231, 76, 60)); + expired_slice->setLabelVisible(true); + + QPieSlice *created_slice = series->slices().at(2); + created_slice->setColor(QColor(52, 152, 219)); + created_slice->setLabelVisible(true); + + for(QPieSlice *slice : series->slices()) { + slice->setLabel(slice->label() + + QString(": %1 (%2%)") + .arg(slice->value()) + .arg(100 * slice->percentage(), 0, 'f', 1)); + } + + QChart *chart = new QChart(); + chart->addSeries(series); + chart->setTitle("Статистика заметок"); + chart->setTitleFont(QFont("Arial", 14, QFont::Bold)); + chart->legend()->setAlignment(Qt::AlignBottom); + chart->setAnimationOptions(QChart::AllAnimations); + + chart_view->setChart(chart); +} + +AnalyticsWindow::~AnalyticsWindow(){} + +void AnalyticsWindow::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + chart->setTitle("Статистика заметок"); + completed_slice->setLabel("Завершенные"); + expired_slice->setLabel("Просроченные"); + created_slice->setLabel("Созданные"); + setWindowTitle("Аналитическая панель"); + } + else if (new_language == "EN") { + chart->setTitle("Notes Statistics"); + completed_slice->setLabel("Completed"); + expired_slice->setLabel("Expired"); + created_slice->setLabel("Created"); + setWindowTitle("Analytics Panel"); + } + for (QPieSlice *slice : series->slices()) { + slice->setLabelVisible(true); + QString label = slice->label() + + QString(": %1 (%2%)") + .arg(slice->value()) + .arg(100 * slice->percentage(), 0, 'f', 1); + slice->setLabel(label); + } +} + +void AnalyticsWindow::handle_font_size_changed(std::string font_size) { + + QString font_size_rule; + if(font_size == "small") { + font_size_rule = "QPushButton { font-size: 11px; }"; + } + else if(font_size == "medium") { + font_size_rule = "QPushButton { font-size: 13px; }"; + } + else if(font_size == "big") { + font_size_rule = "QPushButton { font-size: 15px; }"; + } + + this->setStyleSheet(THEMES[StyleManager::instance()->current_theme()] + font_size_rule); +} + +void AnalyticsWindow::handle_theme_changed(int theme) { + this->setStyleSheet(THEMES[theme]); +} + +void AnalyticsWindow::on_switch_theme_clicked() { + int next_theme = (StyleManager::instance()->current_theme() + 1) % 5; + StyleManager::instance()->apply_theme(next_theme); +} \ No newline at end of file diff --git a/ui/authorization-windows/CMakeLists.txt b/ui/authorization-windows/CMakeLists.txt index e61f562..566818b 100644 --- a/ui/authorization-windows/CMakeLists.txt +++ b/ui/authorization-windows/CMakeLists.txt @@ -16,6 +16,7 @@ set(CMAKE_AUTOUIC_SEARCH_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/ui) set(UI_FILES ${CMAKE_CURRENT_SOURCE_DIR}/ui/login_window.ui ${CMAKE_CURRENT_SOURCE_DIR}/ui/registration_window.ui + ${CMAKE_CURRENT_BINARY_DIR} ) set(SOURCES @@ -40,4 +41,4 @@ target_include_directories(AuthorizationWindows $ ) -target_link_libraries(AuthorizationWindows PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Sql Database Scripts MainWindow) \ No newline at end of file +target_link_libraries(AuthorizationWindows PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Sql Database LanguageManager Scripts MainWindow StyleManager ProfileWindow) \ No newline at end of file diff --git a/ui/authorization-windows/include/login_window.h b/ui/authorization-windows/include/login_window.h index 5aed300..21e2028 100644 --- a/ui/authorization-windows/include/login_window.h +++ b/ui/authorization-windows/include/login_window.h @@ -1,32 +1,35 @@ #pragma once -#include -#include -#include -#include #include -#include "database_manager.hpp" -#include "lr_dao.hpp" +#include +#include +#include QT_BEGIN_NAMESPACE - -namespace Ui { -class LoginWindow; -} - + namespace Ui { + class LoginWindow; + } QT_END_NAMESPACE -class LoginWindow : public QWidget { +class LoginWindow : public QWidget +{ Q_OBJECT public: explicit LoginWindow(QWidget *parent = nullptr); - ~LoginWindow(); + ~LoginWindow() override; + + void handle_language_changed(std::string new_language); private slots: void on_switch_mode_clicked(); void on_push_enter_clicked(); + void on_switch_language_clicked(); private: - Ui::LoginWindow *ui; + std::shared_ptr ui; + int counter_on_switch_theme_clicks = 0; + void switch_window(QMainWindow *app_window, QWidget *new_window, int width, int height); + void switch_to_login_window(QMainWindow *app_window); + void switch_to_registration_window(QMainWindow *app_window); }; \ No newline at end of file diff --git a/ui/authorization-windows/include/login_window_style_sheet.h b/ui/authorization-windows/include/login_window_style_sheet.h index 3a6d776..68fa3c4 100644 --- a/ui/authorization-windows/include/login_window_style_sheet.h +++ b/ui/authorization-windows/include/login_window_style_sheet.h @@ -3,58 +3,73 @@ #include "ui_login_window.h" namespace Ui { -QString login_window_light_theme = R"( - QWidget { - background-color: #f5f5f5; - } + QString login_window_light_autumn_theme = R"( + QWidget { + background-color: #f5f5f5; + } + + QLabel { + background-color: transparent; + font-family: 'Arial'; + font-size: 13px; + color: #089083; + padding: 1px; + } + + QPushButton#push_enter { + font-family: 'Arial'; + border-radius: 10px; + background-color: #fea36b; + color: white; + padding: 5px 10px; + } + + QPushButton#switch_mode { + font-family: 'Arial'; + border-radius: 10px; + background-color: white; + color: #fea36b; + padding: 5px 10px; + } + + QPushButton#push_enter:hover { + background-color: #d58745; + } + + QPushButton#switch_mode:hover { + background-color: #dadada; + } + + QLineEdit { + border-radius: 10px; + border: 1px solid white; + background: white; + color: black; + padding: 5px; + } + + QLineEdit::placeholder { + color: #727272; + } - QLabel { - font-family: 'Arial'; - font-weight: bold; - font-size: 13px; - color: #089083; - padding: 1px; - background-color: transparent; - } - - QPushButton#pushEnter { - font-family: 'Arial'; - font-weight: bold; - border-radius: 10px; - background-color: #fea36b; - color: white; - padding: 5px 10px; - } - - QPushButton#switchMode { - font-family: 'Arial'; - font-weight: bold; - border-radius: 10px; - background-color: white; - color: #fea36b; - padding: 5px 10px; - } - - QPushButton#pushEnter:hover { - background-color: #d58745; - } - - QPushButton#switchMode:hover { - background-color: #dadada; - } - - QLineEdit { - border-radius: 10px; - border: 1px solid white; - background: white; - color: black; - padding: 5px; - } - - QLineEdit::placeholder { - color: #727272; - } - -)"; + QPushButton#switch_theme { + background-color: #089083; + min-width: 20px; + min-height: 20px; + color: #f5f5f5; + padding: 2px; + font-size: 13px; + border-radius: 7px; + font-family: 'Arial' bold; + } + QPushButton#switch_theme:hover { + background-color: rgb(8, 82, 74); + color: #f5f5f5; + } + QPushButton::pressed#switch_theme { + background-color:rgb(3, 58, 54); + color: #f5f5f5; + } + )"; } // namespace Ui \ No newline at end of file diff --git a/ui/authorization-windows/include/registration_window.h b/ui/authorization-windows/include/registration_window.h index 35f4bc4..61c1ef6 100644 --- a/ui/authorization-windows/include/registration_window.h +++ b/ui/authorization-windows/include/registration_window.h @@ -1,31 +1,28 @@ #pragma once -#include -#include #include -#include "database_manager.hpp" -#include "lr_dao.hpp" - -QT_BEGIN_NAMESPACE +#include namespace Ui { -class RegistrationWindow; + class RegistrationWindow; } -QT_END_NAMESPACE - class RegistrationWindow : public QWidget { Q_OBJECT public: explicit RegistrationWindow(QWidget *parent = nullptr); - ~RegistrationWindow(); + ~RegistrationWindow() override; + bool is_strong_and_valid_password(const QString &password); + void handle_language_changed(std::string new_language); private slots: void on_switch_mode_clicked(); void on_push_registration_clicked(); + void on_switch_language_clicked(); private: - Ui::RegistrationWindow *ui; + std::shared_ptr ui; + int counter_on_switch_theme_clicks = 0; }; \ No newline at end of file diff --git a/ui/authorization-windows/include/registration_window_style_sheet.h b/ui/authorization-windows/include/registration_window_style_sheet.h index dc7a1ca..21e2491 100644 --- a/ui/authorization-windows/include/registration_window_style_sheet.h +++ b/ui/authorization-windows/include/registration_window_style_sheet.h @@ -3,56 +3,73 @@ #include "ui_registration_window.h" namespace Ui { -QString registration_window_light_theme = R"( - QWidget { - background-color: #f5f5f5; - } - - QLabel { - font-family: 'Arial'; - background-color: transparent; - font-size: 13px; - color: #089083; - padding: 1px; - } - - QPushButton#pushRegistration { - font-weight: bold; - font-family: 'Arial'; - border-radius: 8px; - background-color: #fea36b; - color: white; - padding: 5px 10px; - } - - QPushButton#switchMode { - font-family: 'Arial'; - border-radius: 10px; - background-color: white; - color: #fea36b; - padding: 5px 10px; - } - - QPushButton#pushRegistration:hover { - background-color: #d58745; - } - - QPushButton#switchMode:hover { - background-color: #dadada; - } - - QLineEdit { - border-radius: 10px; - border: 1px solid white; - background: white; - color: black; - padding: 5px; - } - - QLineEdit::placeholder { - color: #727272; - } - -)"; + QString registration_window_light_autumn_theme = R"( + QWidget { + background-color: #f5f5f5; + } + + QLabel { + font-family: 'Arial'; + background-color: transparent; + color: #089083; + font-size: 14px; + padding: 12px; + } + + QPushButton#push_registration { + font-family: 'Arial'; + border-radius: 10px; + background-color: #fea36b; + color: white; + padding: 5px 10px; + } + + QPushButton#switch_mode { + font-family: 'Arial' bold; + border-radius: 10px; + background-color: white; + color: #fea36b; + padding: 5px 10px; + } + + QPushButton#push_registration:hover { + background-color: #d58745; + } + + QPushButton#switch_mode:hover { + background-color: #dadada; + } + + QLineEdit { + border-radius: 10px; + border: 1px solid white; + background: white; + color: black; + padding: 5px; + } + + QLineEdit::placeholder { + color: #727272; + } + + QPushButton#switch_theme { + background-color: #089083; + min-width: 20px; + min-height: 20px; + color: #f5f5f5; + padding: 2px; + font-size: 13px; + border-radius: 7px; + font-family: 'Arial' bold; + } + QPushButton#switch_theme:hover { + background-color: rgb(8, 82, 74); + color: #f5f5f5; + } + QPushButton::pressed#switch_theme { + background-color:rgb(3, 58, 54); + color: #f5f5f5; + } + )"; } // namespace Ui \ No newline at end of file diff --git a/ui/authorization-windows/src/login_window.cpp b/ui/authorization-windows/src/login_window.cpp index 0583ef5..0f85af3 100644 --- a/ui/authorization-windows/src/login_window.cpp +++ b/ui/authorization-windows/src/login_window.cpp @@ -1,118 +1,169 @@ #include "login_window.h" -#include -#include -#include -#include -#include -#include -#include -#include #include "applicationwindow.h" -#include "bottombar.h" -#include "database_manager.hpp" -#include "login_window_style_sheet.h" #include "lr_dao.hpp" #include "mainwindow.h" -#include "notelist.h" #include "registration_window.h" +#include "login_window_style_sheet.h" #include "serialization.hpp" +#include "style_manager.h" +#include "language_manager.h" +#include +#include +#include LoginWindow::LoginWindow(QWidget *parent) : QWidget(parent), ui(new Ui::LoginWindow) { ui->setupUi(this); setFixedSize(380, 480); - ui->inputLogin->setPlaceholderText("Введите логин:"); - ui->inputPassword->setPlaceholderText("Введите пароль:"); - setStyleSheet(Ui::login_window_light_theme); - ui->inputPassword->setEchoMode(QLineEdit::Password); - - connect( - ui->switchMode, &QPushButton::clicked, this, - &LoginWindow::on_switch_mode_clicked - ); - connect( - ui->pushEnter, &QPushButton::clicked, this, - &LoginWindow::on_push_enter_clicked + ui->input_login->setPlaceholderText(tr("Введите логин:")); + ui->input_password->setPlaceholderText(tr("Введите пароль:")); + ui->input_password->setEchoMode(QLineEdit::Password); + + connect(ui->switch_mode, &QPushButton::clicked, this, + &LoginWindow::on_switch_mode_clicked); + connect(ui->push_enter, &QPushButton::clicked, this, + &LoginWindow::on_push_enter_clicked); + connect(LanguageManager::instance(), &LanguageManager::language_changed, + this, &LoginWindow::handle_language_changed ); + connect(ui->switch_theme, &QPushButton::clicked, this, + &LoginWindow::on_switch_language_clicked, Qt::UniqueConnection); + handle_language_changed(LanguageManager::instance()->current_language()); + setStyleSheet(Ui::login_window_light_autumn_theme); } -LoginWindow::~LoginWindow() { - delete ui; +void LoginWindow::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + ui->input_login->setPlaceholderText(tr("Введите логин:")); + ui->enter_label->setText(tr("Вход")); + ui->input_password->setPlaceholderText(tr("Введите пароль:")); + ui->switch_mode->setText(tr("Еще нет аккаунта? Зарегестрируйтесь!")); + ui->switch_theme->setText(tr("RU")); + ui->push_enter->setText(tr("Войти")); + } + else if (new_language == "EN") { + ui->input_login->setPlaceholderText(tr("Enter login:")); + ui->enter_label->setText(tr("Enter")); + ui->input_password->setPlaceholderText(tr("Enter password:")); + ui->switch_mode->setText(tr("Don't have an account yet? Register!")); + ui->switch_theme->setText(tr("EN")); + ui->push_enter->setText(tr("Login")); + } } -void LoginWindow::on_switch_mode_clicked() { - QWidget *parent = this->parentWidget(); - - QMainWindow *app_window = qobject_cast(parent); - - if (QWidget *old = app_window->centralWidget()) { - old->deleteLater(); +void LoginWindow::on_switch_language_clicked() { + if (ui->switch_theme->text() == tr("RU")) { + ui->switch_theme->setText(tr("EN")); + LanguageManager::instance()->apply_language("EN"); + } else { + ui->switch_theme->setText(tr("RU")); + LanguageManager::instance()->apply_language("RU"); } - project_storage_model::Storage storage; - RegistrationWindow *registration_window = - new RegistrationWindow(app_window); +} - app_window->setCentralWidget(registration_window); - QRect screenGeometry = QApplication::primaryScreen()->availableGeometry(); - int x = (screenGeometry.width() - registration_window->width()) / 2; - int y = (screenGeometry.height() - registration_window->height()) / 2; - app_window->move(x, y); +LoginWindow::~LoginWindow() = default; - this->close(); +void LoginWindow::on_switch_mode_clicked() { + if (QMainWindow *app_window = qobject_cast(this->parentWidget())) { + RegistrationWindow *registration_window = new RegistrationWindow(app_window); + switch_window(app_window, registration_window, 380, 480); + this->close(); + } } - void LoginWindow::on_push_enter_clicked() { - QString login = ui->inputLogin->text(); - QString password = ui->inputPassword->text(); - - if (!login.isEmpty() && !password.isEmpty()) { - if (login.size() > 50) { - QMessageBox::warning( - this, "Ошибка", - "Длина логина не должна превышать пятидесяти символов" - ); - } else if (password.size() > 50) { - QMessageBox::warning( - this, "Ошибка", - "Длина пароля не должна превышать пятидесяти символов" - ); - } else if (LRDao::validate_user(login, password)) { - QMessageBox::information( - this, "Вход", "Вы успешно вошли! Добро пожаловать :)" - ); - QWidget *parent = this->parentWidget(); - - QMainWindow *app_window = qobject_cast(parent); - - if (QWidget *old = app_window->centralWidget()) { - old->deleteLater(); - } - // todo load all projects of user to storage - project_storage_model::Storage *storage = - new project_storage_model::Storage(); + if ((this->counter_on_switch_theme_clicks++) % 2) { + QString login = ui->input_login->text().trimmed(); + QString password = ui->input_password->text(); + std::string lang = LanguageManager::instance()->current_language(); + + // if (login.isEmpty() || password.isEmpty()) { + // if (lang == "RU") { + // QMessageBox::warning(this, "Ошибка ввода данных", "Пожалуйста, заполните все поля!"); + // } else { + // QMessageBox::warning(this, "Input Error", "Please fill in all the fields!"); + // } + // return; + // } + + // if (login.size() > 50) { + // if (lang == "RU") { + // QMessageBox::warning(this, "Ошибка", "Длина логина не должна превышать пятидесяти символов"); + // } else { + // QMessageBox::warning(this, "Error", "Login must not exceed fifty characters"); + // } + // return; + // } + + // if (password.size() > 50) { + // if (lang == "RU") { + // QMessageBox::warning(this, "Ошибка", "Длина пароля не должна превышать пятидесяти символов"); + // } else { + // QMessageBox::warning(this, "Error", "Password must not exceed fifty characters"); + // } + // return; + // } + + // if (!LRDao::validate_user(login, password)) { + // if (lang == "RU") { + // QMessageBox::warning(this, "Ошибка ввода данных", "Неверный логин или пароль!"); + // } else { + // QMessageBox::warning(this, "Login Error", "Incorrect login or password!"); + // } + // return; + // } + + if (lang == "RU") { + QMessageBox::information(this, "Вход", "Вы успешно вошли. Добро пожаловать!"); + } else { + QMessageBox::information(this, "Login", "You have successfully logged in. Welcome!"); + } + + if (QMainWindow *app_window = qobject_cast(this->parentWidget())) { + this->deleteLater(); + project_storage_model::Storage *storage = new project_storage_model::Storage(); Serialization::get_storage(*storage, login.toStdString()); - Ui::MainWindow *main_window = - new Ui::MainWindow(app_window, login.toStdString(), storage); + Ui::MainWindow *main_window = new Ui::MainWindow(app_window, login.toStdString(), storage); + + connect(main_window, &Ui::MainWindow::logout_requested, app_window, [app_window, this]() { + switch_to_login_window(app_window); + }); + + connect(main_window, &Ui::MainWindow::delete_account_requested, app_window, [app_window, this]() { + switch_to_registration_window(app_window); + }); + + switch_window(app_window, main_window, 800, 600); + } + } +} - app_window->setCentralWidget(main_window); - app_window->resize(800, 600); - QRect screenGeometry = - QApplication::primaryScreen()->availableGeometry(); - int x = (screenGeometry.width() - main_window->width()) / 2; - int y = (screenGeometry.height() - main_window->height()) / 2; - app_window->move(x, y); - this->close(); - } else { - QMessageBox::warning( - this, "Ошибка ввода данных", "Неверный логин или пароль!" - ); - } - } else { - QMessageBox::warning( - this, "Ошибка ввода данных", "Пожалуйста, заполните все поля!" - ); +void LoginWindow::switch_window(QMainWindow *app_window, QWidget *new_window, int width, int height) { + if (QWidget *old = app_window->centralWidget()) { + old->deleteLater(); } + + app_window->setCentralWidget(new_window); + if (width > 0 && height > 0) { + app_window->resize(width, height); + } + + QRect screen_geometry = QApplication::primaryScreen()->availableGeometry(); + app_window->move( + (screen_geometry.width() - width) / 2, + (screen_geometry.height() - height) / 2 + ); + app_window->show(); +} + +void LoginWindow::switch_to_login_window(QMainWindow *app_window) { + LoginWindow *login_window = new LoginWindow(app_window); + switch_window(app_window, login_window, 380, 480); +} + +void LoginWindow::switch_to_registration_window(QMainWindow *app_window) { + RegistrationWindow *registration_window = new RegistrationWindow(app_window); + switch_window(app_window, registration_window, 380, 480); } \ No newline at end of file diff --git a/ui/authorization-windows/src/registration_window.cpp b/ui/authorization-windows/src/registration_window.cpp index f30f7d8..13cce80 100644 --- a/ui/authorization-windows/src/registration_window.cpp +++ b/ui/authorization-windows/src/registration_window.cpp @@ -1,86 +1,114 @@ #include "registration_window.h" -#include -#include -#include -#include +#include #include -#include -#include -#include "applicationwindow.h" -#include "bottombar.h" -#include "database_manager.hpp" -#include "login_window.h" #include "lr_dao.hpp" -#include "mainwindow.h" -#include "notelist.h" -#include "registration_window.h" +#include "login_window.h" +#include "style_manager.h" +#include "language_manager.h" #include "registration_window_style_sheet.h" +#include RegistrationWindow::RegistrationWindow(QWidget *parent) : QWidget(parent), ui(new Ui::RegistrationWindow) { ui->setupUi(this); - setFixedSize(380, 480); - ui->createLogin->setPlaceholderText("Введите логин:"); - ui->createPassword->setPlaceholderText("Введите пароль:"); - ui->repeatPassword->setPlaceholderText("Повторите пароль:"); - setStyleSheet(Ui::registration_window_light_theme); - ui->createPassword->setEchoMode(QLineEdit::Password); - ui->repeatPassword->setEchoMode(QLineEdit::Password); + ui->create_login->setPlaceholderText(tr("Введите логин:")); + ui->create_password->setPlaceholderText(tr("Введите пароль:")); + ui->repeat_password->setPlaceholderText(tr("Повторите пароль:")); + ui->create_password->setEchoMode(QLineEdit::Password); + ui->repeat_password->setEchoMode(QLineEdit::Password); - connect( - ui->pushRegistration, &QPushButton::clicked, this, - &RegistrationWindow::on_push_registration_clicked - ); - connect( - ui->switchMode, &QPushButton::clicked, this, - &RegistrationWindow::on_switch_mode_clicked + setAttribute(Qt::WA_StyledBackground, true); + + connect(ui->push_registration, &QPushButton::clicked, this, + &RegistrationWindow::on_push_registration_clicked, Qt::UniqueConnection); + connect(ui->switch_mode, &QPushButton::clicked, this, + &RegistrationWindow::on_switch_mode_clicked, Qt::UniqueConnection); + connect(ui->switch_theme, &QPushButton::clicked, this, + &RegistrationWindow::on_switch_language_clicked, Qt::UniqueConnection); + + connect(LanguageManager::instance(), &LanguageManager::language_changed, + this, &RegistrationWindow::handle_language_changed ); + handle_language_changed(LanguageManager::instance()->current_language()); + this->setStyleSheet(Ui::registration_window_light_autumn_theme); } -RegistrationWindow::~RegistrationWindow() { - delete ui; +void RegistrationWindow::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + ui->create_login->setPlaceholderText(tr("Введите логин:")); + ui->registration_label->setText(tr("Регистрация")); + ui->create_password->setPlaceholderText(tr("Введите пароль:")); + ui->repeat_password->setPlaceholderText(tr("Повторите пароль:")); + ui->switch_mode->setText(tr("Уже есть аккаунт? Войдите!")); + ui->switch_theme->setText(tr("RU")); + ui->push_registration->setText(tr("Зарегистрироваться")); + } + else if (new_language == "EN") { + ui->create_login->setPlaceholderText(tr("Enter login:")); + ui->registration_label->setText(tr("Registration")); + ui->create_password->setPlaceholderText(tr("Enter password:")); + ui->repeat_password->setPlaceholderText(tr("Repeat password:")); + ui->switch_mode->setText(tr("Already have an account? Login!")); + ui->switch_theme->setText(tr("EN")); + ui->push_registration->setText(tr("Register")); + } } -void RegistrationWindow::on_switch_mode_clicked() { - QWidget *parent = this->parentWidget(); - - QMainWindow *app_window = qobject_cast(parent); - - if (QWidget *old = app_window->centralWidget()) { - old->deleteLater(); +void RegistrationWindow::on_switch_language_clicked() { + if (ui->switch_theme->text() == tr("RU")) { + ui->switch_theme->setText(tr("EN")); + LanguageManager::instance()->apply_language("EN"); + } else { + ui->switch_theme->setText(tr("RU")); + LanguageManager::instance()->apply_language("RU"); } - project_storage_model::Storage storage; - LoginWindow *login_window = new LoginWindow(app_window); +} - app_window->setCentralWidget(login_window); - QRect screenGeometry = QApplication::primaryScreen()->availableGeometry(); - int x = (screenGeometry.width() - login_window->width()) / 2; - int y = (screenGeometry.height() - login_window->height()) / 2; - app_window->move(x, y); +RegistrationWindow::~RegistrationWindow() = default; - this->close(); +void RegistrationWindow::on_switch_mode_clicked() { + if (QMainWindow *app_window = qobject_cast(this->parentWidget())) { + if (QWidget *old = app_window->centralWidget()) { + old->deleteLater(); + } + + LoginWindow *login_window = new LoginWindow(app_window); + app_window->setCentralWidget(login_window); + + QRect screen_geometry = QApplication::primaryScreen()->availableGeometry(); + app_window->move( + (screen_geometry.width() - login_window->width()) / 2, + (screen_geometry.height() - login_window->height()) / 2 + ); + + this->close(); + } } bool RegistrationWindow::is_strong_and_valid_password(const QString &password) { + std::string lang = LanguageManager::instance()->current_language(); + if (password.length() < 8) { - QMessageBox::warning( - nullptr, "Ошибка: недостаточно надежный пароль", - "Пароль должен содержать не менее восьми символов" - ); + if (lang == "RU") { + QMessageBox::warning(nullptr, "Ошибка: недостаточно надежный пароль", "Пароль должен содержать не менее восьми символов"); + } else { + QMessageBox::warning(nullptr, "Error: Weak Password", "Password must be at least 8 characters long"); + } return false; } bool has_digit = false; bool has_latin_letter = false; - for (const QChar ch : password) { + for (const QChar &ch : password) { if (!ch.isLetter() && !ch.isDigit()) { - QMessageBox::warning( - nullptr, "Ошибка", - "Пароль должен содержать только символы латиницы и цифры" - ); + if (lang == "RU") { + QMessageBox::warning(nullptr, "Ошибка", "Пароль должен содержать только символы латиницы и цифры"); + } else { + QMessageBox::warning(nullptr, "Error", "Password must contain only Latin letters and digits"); + } return false; } else if (ch.isLetter()) { has_latin_letter = true; @@ -90,17 +118,20 @@ bool RegistrationWindow::is_strong_and_valid_password(const QString &password) { } if (!has_latin_letter) { - QMessageBox::warning( - nullptr, "Ошибка: недостаточно надежный пароль", - "Пароль должен содержать хотя бы одну букву" - ); + if (lang == "RU") { + QMessageBox::warning(nullptr, "Ошибка: недостаточно надежный пароль", "Пароль должен содержать хотя бы одну букву"); + } else { + QMessageBox::warning(nullptr, "Error: Weak Password", "Password must contain at least one letter"); + } return false; } + if (!has_digit) { - QMessageBox::warning( - nullptr, "Ошибка: недостаточно надежный пароль", - "Пароль должен содержать хотя бы одну цифру" - ); + if (lang == "RU") { + QMessageBox::warning(nullptr, "Ошибка: недостаточно надежный пароль", "Пароль должен содержать хотя бы одну цифру"); + } else { + QMessageBox::warning(nullptr, "Error: Weak Password", "Password must contain at least one digit"); + } return false; } @@ -108,47 +139,77 @@ bool RegistrationWindow::is_strong_and_valid_password(const QString &password) { } void RegistrationWindow::on_push_registration_clicked() { - QString created_login = ui->createLogin->text(); - QString created_password = ui->createPassword->text(); - QString repeated_password = ui->repeatPassword->text(); + if ((this->counter_on_switch_theme_clicks++) % 2) { + QString created_login = ui->create_login->text().trimmed(); + QString created_password = ui->create_password->text(); + QString repeated_password = ui->repeat_password->text(); + + std::string lang = LanguageManager::instance()->current_language(); + + if (created_login.isEmpty() || created_password.isEmpty() || repeated_password.isEmpty()) { + if (lang == "RU") { + QMessageBox::warning(this, "Ошибка", "Пожалуйста, заполните все поля."); + } else { + QMessageBox::warning(this, "Error", "Please fill in all the fields."); + } + return; + } - if (!created_login.isEmpty() && !created_password.isEmpty() && - !repeated_password.isEmpty()) { if (created_password != repeated_password) { - QMessageBox::warning(this, "Ошибка", "Пароли не совпадают!"); - } else if (created_login.size() > 50) { - QMessageBox::warning( - this, "Ошибка", - "Длина логина не должна превышать пятидесяти символов" - ); - } else if (created_password.size() > 50) { - QMessageBox::warning( - this, "Ошибка", - "Длина пароля не должна превышать пятидесяти символов" - ); - } else if (is_strong_and_valid_password(created_password)) { - int try_register_user = - LRDao::try_register_user(created_login, created_password); - if (try_register_user == 0) { - QMessageBox::warning( - this, "Ошибка", - "Извините, разрабы дауны и не подключили толком бд." - ); - } else if (try_register_user == -1) { - QMessageBox::warning( - this, "Ошибка", - "Пользователь с таким именем уже существует. Пожалуйста, " - "придумайте другое!" - ); + if (lang == "RU") { + QMessageBox::warning(this, "Ошибка", "Пароли не совпадают!"); } else { - QMessageBox::information( - this, "Регистрация", - "Вы успешно зарегистрировались! Пожалуйста, выполните вход." - ); - on_switch_mode_clicked(); // TODO: fix + QMessageBox::warning(this, "Error", "Passwords do not match!"); } + return; + } + + if (created_login.size() > 50) { + if (lang == "RU") { + QMessageBox::warning(this, "Ошибка", "Длина логина не должна превышать пятидесяти символов"); + } else { + QMessageBox::warning(this, "Error", "Login must not exceed fifty characters."); + } + return; + } + + if (created_password.size() > 50) { + if (lang == "RU") { + QMessageBox::warning(this, "Ошибка", "Длина пароля не должна превышать пятидесяти символов"); + } else { + QMessageBox::warning(this, "Error", "Password must not exceed fifty characters."); + } + return; + } + + if (!is_strong_and_valid_password(created_password)) { + return; + } + + int try_register_user = LRDao::try_register_user(created_login, created_password); + switch (try_register_user) { + case 0: + if (lang == "RU") { + QMessageBox::warning(this, "Ошибка", "Извините, внутренняя ошибка с базами данных."); + } else { + QMessageBox::warning(this, "Error", "Sorry, an internal database error occurred."); + } + break; + case -1: + if (lang == "RU") { + QMessageBox::warning(this, "Ошибка", "Пользователь с таким именем уже существует. Пожалуйста, придумайте другое!"); + } else { + QMessageBox::warning(this, "Error", "A user with this name already exists. Please choose a different one!"); + } + break; + default: + if (lang == "RU") { + QMessageBox::information(this, "Регистрация", "Вы успешно зарегистрировались! Пожалуйста, выполните вход."); + } else { + QMessageBox::information(this, "Registration", "You have successfully registered! Please log in."); + } + on_switch_mode_clicked(); + break; } - } else { - QMessageBox::warning(this, "Ошибка", "Пожалуйста, заполните все поля."); } -} \ No newline at end of file +} diff --git a/ui/authorization-windows/ui/login_window.ui b/ui/authorization-windows/ui/login_window.ui index 02ffce3..a9ea57e 100644 --- a/ui/authorization-windows/ui/login_window.ui +++ b/ui/authorization-windows/ui/login_window.ui @@ -22,7 +22,7 @@ 501 - + 120 @@ -39,10 +39,10 @@ border-radius: 10px; Войти - + - 140 + 133 130 91 41 @@ -55,7 +55,7 @@ border-radius: 10px; Вход - + 62 @@ -71,7 +71,7 @@ border-radius: 10px; Логин - + 62 @@ -87,7 +87,7 @@ border-radius: 10px; Пароль - + 80 @@ -104,6 +104,28 @@ border-radius: 10px; Еще нет аккаунта? Зарегистрируйтесь! + + + + 350 + 455 + 20 + 20 + + + + + 20 + 20 + + + + + 20 + 20 + + + diff --git a/ui/authorization-windows/ui/registration_window.ui b/ui/authorization-windows/ui/registration_window.ui index d0b20d4..0ba3e34 100644 --- a/ui/authorization-windows/ui/registration_window.ui +++ b/ui/authorization-windows/ui/registration_window.ui @@ -13,12 +13,34 @@ Dialog - + - 90 + 350 + 455 + 20 + 20 + + + + + 20 + 20 + + + + + 20 + 20 + + + + + + + 85 290 - 201 + 210 51 @@ -30,7 +52,7 @@ border-radius: 10px; Зарегистрироваться - + 110 @@ -47,7 +69,7 @@ border-radius: 10px; Уже есть аккаунт? Войдите! - + 60 @@ -57,7 +79,7 @@ border-radius: 10px; - + 60 @@ -67,7 +89,7 @@ border-radius: 10px; - + 60 @@ -77,10 +99,10 @@ border-radius: 10px; - + - 100 + 94 90 201 51 diff --git a/ui/language-manager/CMakeLists.txt b/ui/language-manager/CMakeLists.txt new file mode 100644 index 0000000..151f92e --- /dev/null +++ b/ui/language-manager/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.16) + +project(LanguageManager LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 COMPONENTS Core Gui Widgets Core Gui Sql REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + + +set(SOURCES + src/language_manager.cpp +) + +set(HEADERS + include/language_manager.h +) + +add_library(LanguageManager STATIC ${SOURCES} ${HEADERS}) + +target_include_directories(LanguageManager + PUBLIC + $ + $ +) + +target_link_libraries(LanguageManager PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Sql Database Scripts) + diff --git a/ui/language-manager/include/language_manager.h b/ui/language-manager/include/language_manager.h new file mode 100644 index 0000000..88ee68d --- /dev/null +++ b/ui/language-manager/include/language_manager.h @@ -0,0 +1,29 @@ +#ifndef style_manager_H +#define style_manager_H + +#include +#include +#include +#include +#include +#include + +class LanguageManager : public QObject { + Q_OBJECT + +public: + static LanguageManager* instance(); + + void apply_language(std::string new_language_); + std::string current_language() const; + +signals: + void language_changed(std::string new_language_); + +private: + explicit LanguageManager(QObject *parent = nullptr); + static LanguageManager* m_instance; + std::string current_language_; +}; + +#endif // style_manager_H \ No newline at end of file diff --git a/ui/language-manager/src/language_manager.cpp b/ui/language-manager/src/language_manager.cpp new file mode 100644 index 0000000..f0b52ea --- /dev/null +++ b/ui/language-manager/src/language_manager.cpp @@ -0,0 +1,28 @@ +#include "language_manager.h" +#include +#include +#include + +LanguageManager* LanguageManager::m_instance = nullptr; + +LanguageManager::LanguageManager(QObject *parent) + : QObject(parent) { + std::string language = "RU"; + apply_language(language); +} + +LanguageManager* LanguageManager::instance() { + if (!m_instance) { + m_instance = new LanguageManager(); + } + return m_instance; +} + +void LanguageManager::apply_language(std::string new_language_) { + this->current_language_ = new_language_; + emit language_changed(this->current_language_); +} + +std::string LanguageManager::current_language() const { + return current_language_; +} \ No newline at end of file diff --git a/ui/main-window/CMakeLists.txt b/ui/main-window/CMakeLists.txt index c8e1f85..c36aa37 100644 --- a/ui/main-window/CMakeLists.txt +++ b/ui/main-window/CMakeLists.txt @@ -36,4 +36,8 @@ target_link_libraries(MainWindow PRIVATE Scripts Database NoteWidget + StyleManager + ProfileWindow + AuthorizationWindows + LanguageManager ) \ No newline at end of file diff --git a/ui/main-window/include/bottombar.h b/ui/main-window/include/bottombar.h index cc7945c..8ac2cb7 100644 --- a/ui/main-window/include/bottombar.h +++ b/ui/main-window/include/bottombar.h @@ -3,21 +3,30 @@ #include #include +#include +#include #include #include namespace Ui { class BottomBar : public QWidget { - QHBoxLayout *main_layout_; - QLabel *project_name_; - QLabel *username_; + Q_OBJECT public: BottomBar( - QWidget *parent_, - std::string username_, - std::string project_name_ + QWidget *parent, + const std::string &username, + QString project_name ); + +signals: + void profile_button_clicked(); + +private: + QHBoxLayout *main_layout_; + QLabel *project_name_; + QLabel *username_; + QPushButton *profile_button_; }; } // namespace Ui diff --git a/ui/main-window/include/main_window_style.hpp b/ui/main-window/include/main_window_style.hpp index 3e594c1..5651dc5 100644 --- a/ui/main-window/include/main_window_style.hpp +++ b/ui/main-window/include/main_window_style.hpp @@ -4,7 +4,7 @@ namespace Ui { -QString main_window_style = R"( +QString main_window_light_autumn_theme = R"( #main-window { background-color : #f5f5f5; } @@ -14,22 +14,31 @@ QString main_window_style = R"( } QScrollBar:vertical { + width: 7px; +} +QScrollBar:horizontal { + height: 7px; +} +QScrollBar:vertical, QScrollBar:horizontal { border: none; background: transparent; - width: 10px; margin: 0; } -QScrollBar::handle:vertical { +QScrollBar::handle:vertical, QScrollBar::handle:horizontal { background: #c0c0c0; - border-radius: 5px; + border-radius: 3px; min-height: 20px; + min-width: 20px; } - QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, - QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical { - background: none; - height: 0px; - } +QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; + height: 0; + width: 0; +} + QScrollArea { border: none; background: transparent; @@ -42,7 +51,7 @@ QScrollArea { outline: 0; font-family: 'Arial'; font-weight: bold; - font-size: 14px; + font-size: 13px; color:rgb(44, 44, 44); } @@ -64,30 +73,37 @@ QScrollArea { } #ProjectList QScrollBar:vertical { + width: 7px; +} +#ProjectList QScrollBar:horizontal { + height: 7px; +} +#ProjectList QScrollBar:vertical, +#ProjectList QScrollBar:horizontal { border: none; - background: #FED6BC; - width: 10px; + background: transparent; margin: 0; } - -#ProjectList QScrollBar::handle:vertical { +#ProjectList QScrollBar::handle:vertical, +#ProjectList QScrollBar::handle:horizontal { background: #c0c0c0; - border-radius: 5px; + border-radius: 3px; min-height: 20px; + min-width: 20px; } - #ProjectList QScrollBar::add-line:vertical, -#ProjectList QScrollBar::sub-line:vertical { - background: none; -} - +#ProjectList QScrollBar::sub-line:vertical, +#ProjectList QScrollBar::add-line:horizontal, +#ProjectList QScrollBar::sub-line:horizontal, #ProjectList QScrollBar::add-page:vertical, -#ProjectList QScrollBar::sub-page:vertical { +#ProjectList QScrollBar::sub-page:vertical, +#ProjectList QScrollBar::add-page:horizontal, +#ProjectList QScrollBar::sub-page:horizontal { background: none; } #BottomBar { - background-color: rgb(33, 44, 50); + background-color: #212c32; border-radius: 8px; padding: 8px; outline: 0; @@ -96,12 +112,66 @@ QScrollArea { #BottomBar QLabel { color : white; font-family: 'Arial'; - font-size: 14px; + font-size: 13px; +} + +#BottomBar QPushButton { + background-color: transparent; + color: white; + font-family: 'Arial'; + font-size: 13px; + padding: 0px 0px; + min-width: 0px; + min-height: 0px; +} + +#BottomBar QPushButton:hover { + color:rgb(182, 181, 181); + font-family: 'Arial'; + font-size: 13px; +} + +QTabWidget { + background-color: white; + border-radius: 8px; + padding: 5px; +} + +QTabWidget::pane { + background-color: white; + border-radius: 8px; + margin-top: 5px; +} + +QTabBar::tab { + color: rgb(33, 44, 50); + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + background: #e0e0e0; + padding: 6px 8px; + border-top-right-radius: 4px; + border-top-left-radius: 4px; + margin-right: 2px; +} + +QTabBar::tab:hover { + background: #e8e8e8; +} + +QTabBar::tab:selected { + background: white; + border-bottom-color: white; +} + +QTabBar::tab:pressed { + background: white; + border-bottom-color: white; } #NoteList { - border-radius : 8px; background-color: white; + border-radius: 8px; } #NoteWidget { @@ -119,6 +189,10 @@ QScrollArea { padding: 5px 10px; } +#NoteWidget QPushButton:hover { + background-color:rgb(213, 167, 88); +} + QPushButton { font-family: 'Arial'; font-size: 13px; @@ -126,13 +200,820 @@ QPushButton { border-radius: 10px; background-color: #fea36b; color: white; + padding: 10px 10px; + min-width: 40px; +} + +QPushButton::hover { + background-color:rgb(245, 148, 89); +} + +QPushButton::pressed { + background-color:rgb(238, 122, 50); +} + +QPushButton#switch_theme_button_ { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + border-radius: 7px; + padding: 0; + margin-bottom: 2px; + border: 2px solid #fea36b; + background-color: transparent; +} +QPushButton::hover#switch_theme_button_ { + background-color: #fea36b; +} +QPushButton::pressed#switch_theme_button_ { + background-color: rgb(185, 117, 61); +} +)"; + +QString main_window_dark_autumn_theme = R"( + #main-window { + background-color: #202020; + } + + #main-window QLabel { + font-weight: bold; + color: #BDD1BD; + } + + QScrollBar:vertical { + width: 7px; + } + QScrollBar:horizontal { + height: 7px; + } + QScrollBar:vertical, QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; + } + QScrollBar::handle:vertical, QScrollBar::handle:horizontal { + background: #c0c0c0; + border-radius: 3px; + min-height: 20px; + min-width: 20px; + } + QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, + QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, + QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, + QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; + height: 0; + width: 0; + } + + QScrollArea { + border: none; + background: transparent; + } + + #ProjectList { + background-color: black; + border-radius: 8px; + padding: 8px; + outline: 0; + font-family: 'Arial'; + font-weight: bold; + font-size: 13px; + color: #BDD1BD; + } + + #ProjectList::item { + background-color: rgb(32, 53, 51); + color: #ffffff; + border: none; + padding: 10px; + margin: 2px; + border-radius: 6px; + } + + #ProjectList::item:hover { + background-color: rgb(64, 89, 87); + } + + #ProjectList::item:selected { + background-color: #089083; + color: rgb(33, 44, 50); + } + + #ProjectList QScrollBar:vertical { + width: 7px; + } + #ProjectList QScrollBar:horizontal { + height: 7px; + } + #ProjectList QScrollBar:vertical, + #ProjectList QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; + } + #ProjectList QScrollBar::handle:vertical, + #ProjectList QScrollBar::handle:horizontal { + background: #c0c0c0; + border-radius: 3px; + min-height: 20px; + min-width: 20px; + } + #ProjectList QScrollBar::add-line:vertical, + #ProjectList QScrollBar::sub-line:vertical, + #ProjectList QScrollBar::add-line:horizontal, + #ProjectList QScrollBar::sub-line:horizontal, + #ProjectList QScrollBar::add-page:vertical, + #ProjectList QScrollBar::sub-page:vertical, + #ProjectList QScrollBar::add-page:horizontal, + #ProjectList QScrollBar::sub-page:horizontal { + background: none; + } + + #BottomBar { + background-color:rgb(0, 0, 0); + border-radius: 8px; + padding: 8px; + outline: 0; + } + + #BottomBar QLabel { + color: #c0c0c0; + font-family: 'Arial'; + font-size: 13px; + } + + #BottomBar QPushButton { + background-color: transparent; + color: #c0c0c0; + font-family: 'Arial'; + font-size: 13px; + padding: 0px 0px; + min-width: 0px; + min-height: 0px; + } + + #BottomBar QPushButton:hover { + color:rgb(236, 234, 234); + font-family: 'Arial'; + font-size: 13px; + } + + + #NoteList { + border-radius: 8px; + background-color: black; + } + + #NoteWidget { + background-color:rgb(179, 156, 116); + border-radius: 8px; + } + + #NoteWidget QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color: #ffdda2; + color: #202020; + padding: 5px 10px; + } + + #NoteWidget QPushButton:hover { + background-color:rgb(255, 236, 203); + } + + QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color:rgb(211, 139, 95); + color: #263238; + padding: 10px 10px; + min-width: 40px; + + } + + QPushButton:hover { + background-color:rgb(181, 114, 59); + } + + QPushButton:pressed { + background-color:rgb(143, 88, 44); + } + + QPushButton#switch_theme_button_ { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + border-radius: 7px; + padding: 0; + margin-bottom: 2px; + border: 2px solid rgb(211, 139, 95); + background-color: transparent; + } + QPushButton::hover#switch_theme_button_ { + background-color: rgb(211, 139, 95); + } + QPushButton::pressed#switch_theme_button_ { + background-color: rgb(211, 139, 95); + } + )"; + +QString main_window_light_purple_theme = R"( +#main-window { + background: #9882B9; +} + +#main-window QLabel { + font-weight: bold; + color: rgb(42, 10, 25); +} + +QScrollBar:vertical { + width: 7px; +} +QScrollBar:horizontal { + height: 7px; +} +QScrollBar:vertical, QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; +} +QScrollBar::handle:vertical, QScrollBar::handle:horizontal { + background: white; + border-radius: 3px; + min-height: 20px; + min-width: 20px; +} +QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, +QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; + height: 0; + width: 0; +} + +QScrollArea { + border: none; + background: transparent; +} + +#ProjectList { + background-color: rgb(221, 210, 238); + border-radius: 8px; + padding: 8px; + outline: 0; + font-family: 'Arial'; + font-weight: bold; + font-size: 13px; + color: rgb(42, 10, 25); +} + +#ProjectList::item { + background-color: rgb(206, 193, 224); + border: none; + padding: 10px; + margin: 2px; + border-radius: 6px; +} + +#ProjectList::item:hover { + background-color: rgb(163, 148, 184); +} + +#ProjectList::item:selected { + background-color:rgb(121, 103, 148); + color: rgb(221, 210, 238); +} + +#ProjectList QScrollBar:vertical { + width: 7px; +} +#ProjectList QScrollBar:horizontal { + height: 7px; +} +#ProjectList QScrollBar:vertical, +#ProjectList QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; +} +#ProjectList QScrollBar::handle:vertical, +#ProjectList QScrollBar::handle:horizontal { + background: white; + border-radius: 3px; + min-height: 20px; + min-width: 20px; +} +#ProjectList QScrollBar::add-line:vertical, +#ProjectList QScrollBar::sub-line:vertical, +#ProjectList QScrollBar::add-line:horizontal, +#ProjectList QScrollBar::sub-line:horizontal, +#ProjectList QScrollBar::add-page:vertical, +#ProjectList QScrollBar::sub-page:vertical, +#ProjectList QScrollBar::add-page:horizontal, +#ProjectList QScrollBar::sub-page:horizontal { + background: none; +} + +#BottomBar { + background-color: rgb(42, 10, 25); + border-radius: 8px; + padding: 8px; + outline: 0; +} + +#BottomBar QLabel { + color: #9882B9; + font-family: 'Arial'; + font-size: 13px; +} + +#BottomBar QPushButton { + background-color: transparent; + color: #9882B9; + font-family: 'Arial'; + font-size: 13px; + padding: 0px 0px; + min-width: 0px; + min-height: 0px; +} + +#BottomBar QPushButton:hover { + color:rgb(208, 193, 231); + font-family: 'Arial'; + font-size: 13px; +} + + + +#NoteList { + border-radius: 8px; + background-color: rgb(221, 210, 238); +} + +#NoteWidget { + background-color: #D4A5C9; + border-radius: 8px; +} + +#NoteWidget QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color: #C98BB8; + color: rgb(42, 10, 25); + padding: 5px 10px; +} + +#NoteWidget QPushButton:hover { + background-color:rgb(134, 82, 120); +} + +QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color: #722548; + color: #9882B9; + padding: 10px 10px; + min-width: 40px; + +} + +QPushButton:hover { + background-color:rgb(69, 24, 44); +} + +QPushButton:pressed { + background-color:rgb(47, 16, 30); +} + +QPushButton#switch_theme_button_ { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + border-radius: 7px; + padding: 0; + margin-bottom: 2px; + border: 2px solid #722548; + background-color: transparent; +} + +QPushButton::hover#switch_theme_button_ { + background-color:rgb(86, 26, 53); +} +QPushButton::pressed#switch_theme_button_ { + background-color: rgb(80, 27, 51); +} +)"; + +QString main_window_dark_purple_theme = R"( +#main-window { + background-color: rgb(9, 6, 10); +} + +#main-window QLabel { + font-weight: bold; + color: #9882B9; +} + +QScrollBar:vertical { + width: 7px; +} +QScrollBar:horizontal { + height: 7px; +} +QScrollBar:vertical, QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; +} +QScrollBar::handle:vertical, QScrollBar::handle:horizontal { + background: #775E88; + border-radius: 3px; + min-height: 20px; + min-width: 20px; +} +QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, +QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; + height: 0; + width: 0; +} + +QScrollArea { + border: none; + background: transparent; +} + +#ProjectList { + background-color: #221932; + border-radius: 8px; + padding: 8px; + outline: 0; + font-family: 'Arial'; + font-weight: bold; + font-size: 13px; + color: #9882B9; +} + +#ProjectList::item { + background-color:rgb(50, 41, 66); + border: none; + padding: 10px; + margin: 2px; + border-radius: 6px; +} + +#ProjectList::item:hover { + background-color:rgb(97, 82, 123); +} + +#ProjectList::item:selected { + background-color:rgb(205, 146, 172); + color: #221932; +} + +#ProjectList QScrollBar:vertical { + width: 7px; +} +#ProjectList QScrollBar:horizontal { + height: 7px; +} +#ProjectList QScrollBar:vertical, +#ProjectList QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; +} +#ProjectList QScrollBar::handle:vertical, +#ProjectList QScrollBar::handle:horizontal { + background: #775E88; + border-radius: 3px; + min-height: 20px; + min-width: 20px; +} +#ProjectList QScrollBar::add-line:vertical, +#ProjectList QScrollBar::sub-line:vertical, +#ProjectList QScrollBar::add-line:horizontal, +#ProjectList QScrollBar::sub-line:horizontal, +#ProjectList QScrollBar::add-page:vertical, +#ProjectList QScrollBar::sub-page:vertical, +#ProjectList QScrollBar::add-page:horizontal, +#ProjectList QScrollBar::sub-page:horizontal { + background: none; +} + +#BottomBar { + background-color: #221932; + border-radius: 8px; + padding: 8px; + outline: 0; +} + +#BottomBar QLabel { + color: #9882B9; + font-family: 'Arial'; + font-size: 13px; +} + +#BottomBar QPushButton { + background-color: transparent; + color: #9882B9; + font-family: 'Arial'; + font-size: 13px; + padding: 0px 0px; + min-width: 0px; + min-height: 0px; +} + +#BottomBar QPushButton:hover { + color:rgb(198, 183, 221); + font-family: 'Arial'; + font-size: 13px; +} + +#NoteList { + border-radius: 8px; + background-color: #221932; +} + +#NoteWidget { + background-color: #9882B9; + border-radius: 8px; +} + +#NoteWidget QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color:rgb(113, 97, 137); + color: #221932; padding: 5px 10px; - min-width: 60px; - min-height: 25px; } +#NoteWidget QPushButton:hover { + background-color:rgb(69, 58, 87); +} + +QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color: #722548; + color: #060407; + padding: 10px 10px; + min-width: 40px; + +} + +QPushButton:hover { + background-color: rgb(79, 25, 50); +} + +QPushButton:pressed { + background-color:rgb(59, 16, 35); +} +QPushButton#switch_theme_button_ { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + border-radius: 7px; + padding: 0; + margin-bottom: 2px; + border: 2px solid #722548; + background-color: transparent; +} +QPushButton::hover#switch_theme_button_ { + background-color: #722548; +} +QPushButton::pressed#switch_theme_button_ { + background-color:rgb(80, 27, 51); +} )"; +QString main_window_blue_theme = R"( +#main-window { + background: #173C4C; +} + +#main-window QLabel { + font-weight: bold; + color: #BDD1BD; +} + +QScrollBar:vertical { + width: 7px; +} +QScrollBar:horizontal { + height: 7px; +} +QScrollBar:vertical, QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; +} +QScrollBar::handle:vertical, QScrollBar::handle:horizontal { + background: rgb(103, 155, 177); + border-radius: 3px; + min-height: 20px; + min-width: 20px; +} +QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical, +QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal, +QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical, +QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal { + background: none; + height: 0; + width: 0; +} + +QScrollArea { + border: none; + background: transparent; +} + +#ProjectList { + background-color: #07142B; + border-radius: 8px; + padding: 8px; + outline: 0; + font-family: 'Arial'; + font-weight: bold; + font-size: 13px; + color: #BDD1BD; + border: 1px solid; +} + +#ProjectList::item { + background-color: #173C4C; + border: none; + padding: 10px; + margin: 2px; + border-radius: 6px; +} + +#ProjectList::item:hover { + background-color:rgb(37, 92, 115); +} + +#ProjectList::item:selected { + background-color:rgb(73, 159, 158); + color: #07142B; +} + +#ProjectList QScrollBar:vertical { + width: 7px; +} +#ProjectList QScrollBar:horizontal { + height: 7px; +} +#ProjectList QScrollBar:vertical, +#ProjectList QScrollBar:horizontal { + border: none; + background: transparent; + margin: 0; +} +#ProjectList QScrollBar::handle:vertical, +#ProjectList QScrollBar::handle:horizontal { + background: rgb(103, 155, 177); + border-radius: 3px; + min-height: 20px; + min-width: 20px; +} +#ProjectList QScrollBar::add-line:vertical, +#ProjectList QScrollBar::sub-line:vertical, +#ProjectList QScrollBar::add-line:horizontal, +#ProjectList QScrollBar::sub-line:horizontal, +#ProjectList QScrollBar::add-page:vertical, +#ProjectList QScrollBar::sub-page:vertical, +#ProjectList QScrollBar::add-page:horizontal, +#ProjectList QScrollBar::sub-page:horizontal { + background: none; +} + +#BottomBar { + background-color: #07142B; + border-radius: 8px; + padding: 8px; + outline: 0; + border: 1px solid; +} + +#BottomBar QLabel { + color: #BDD1BD; + font-family: 'Arial'; + font-size: 13px; +} + +#BottomBar QPushButton { + background-color: transparent; + color: #BDD1BD; + font-family: 'Arial'; + font-size: 13px; + padding: 0px 0px; + min-width: 0px; + min-height: 0px; +} + +#BottomBar QPushButton:hover { + color:rgb(238, 242, 238); + font-family: 'Arial'; + font-size: 13px; +} + +#NoteList { + border-radius: 8px; + background-color: #07142B; + border: 1px solid; +} + +#NoteWidget { + background-color:rgb(103, 155, 177); + border-radius: 8px; + border: 1px solid; +} + +#NoteWidget QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color:rgb(61, 104, 122); + color: #BDD1BD; + padding: 5px 10px; +} + +#NoteWidget QPushButton:hover { + background-color:rgb(24, 54, 66); +} + +QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + background-color: #568F7C; + color: #07142B; + padding: 10px 10px; + min-width: 40px; + + border: none; +} + +QPushButton:hover { + background-color: #326D6C; +} + +QPushButton:pressed { + background-color: #173C4C; +} + +QPushButton#switch_theme_button_ { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + border-radius: 7px; + padding: 0; + margin-bottom: 2px; + border: 2px solid #568F7C; + background-color: transparent; +} + +QPushButton::hover#switch_theme_button_ { + background-color: #568F7C; +} +QPushButton::pressed#switch_theme_button_ { + background-color:rgb(68, 107, 94); +} +)"; } // namespace Ui diff --git a/ui/main-window/include/mainwindow.h b/ui/main-window/include/mainwindow.h index e5242f7..24fb581 100644 --- a/ui/main-window/include/mainwindow.h +++ b/ui/main-window/include/mainwindow.h @@ -6,22 +6,34 @@ #include #include #include +#include #include #include +#include #include "bottombar.h" #include "notelist.h" +#include "profile_window.h" #include "projectlist.h" #include "storage.hpp" +namespace Ui { +class MainWindow; +} + namespace Ui { class MainWindow : public QWidget { Q_OBJECT std::string username; + std::string font_size_ = "medium"; QVBoxLayout *main_layout_; + QTabWidget *tab_widget_; BottomBar *top_bar_; QHBoxLayout *content_layout_; ProjectList *project_list_; - NoteList *note_list_; + NoteList *actual_notes_; + NoteList *overdue_notes_; + NoteList *completed_notes_; + NoteList *deleted_notes_; QWidget *content_widget_; QPushButton *new_project_button_; QPushButton *new_note_button_; @@ -31,6 +43,10 @@ class MainWindow : public QWidget { private slots: void add_project(); void add_note(); + void on_profile_button_click(); +signals: + void logout_requested(); + void delete_account_requested(); public: explicit MainWindow( @@ -38,6 +54,13 @@ private slots: std::string username = "none", project_storage_model::Storage *storage = nullptr ); + static const std::vector THEMES; + void on_logout_button_click(); + void on_delete_account_button_click(); + void handle_theme_changed(int theme); + void handle_language_changed(std::string new_language); + void handle_font_size_changed(std::string font_size_); + QScrollArea *create_scroll_area(NoteList *note_list); }; } // namespace Ui #endif // MAINWINDOW_H \ No newline at end of file diff --git a/ui/main-window/include/notelist.h b/ui/main-window/include/notelist.h index f406536..534d837 100644 --- a/ui/main-window/include/notelist.h +++ b/ui/main-window/include/notelist.h @@ -5,6 +5,8 @@ #include #include #include "note.hpp" +#include "notewidget.h" +#include "projectitem.h" namespace Ui { class NoteList : public QWidget { @@ -16,11 +18,15 @@ class NoteList : public QWidget { std::vector vertical_layouts_; int note_counter_ = 0; + const std::string type_; public: - void add_note_widget(const project_storage_model::Note *note); + void add_note_widget( + const project_storage_model::Note *note, + QListWidgetItem *p + ); void clear_note_list(); - NoteList(QWidget *parent); + NoteList(QWidget *parent, const std::string type_); public slots: void load_project_notes(QListWidgetItem *project); diff --git a/ui/main-window/include/notewidget.h b/ui/main-window/include/notewidget.h index f1f8f6a..a0f31b9 100644 --- a/ui/main-window/include/notewidget.h +++ b/ui/main-window/include/notewidget.h @@ -7,6 +7,7 @@ #include #include #include "note.hpp" +#include "projectitem.h" namespace Ui { class NoteWidget : public QWidget { @@ -14,18 +15,30 @@ class NoteWidget : public QWidget { const project_storage_model::Note *model_note_; QVBoxLayout *main_layout_; QPushButton *open_button_; + QPushButton *delete_button_; QLabel *title_label_; QLabel *text_label_; public: explicit NoteWidget( QWidget *parent = nullptr, - const project_storage_model::Note *model_note = nullptr + const project_storage_model::Note *model_note = nullptr, + const std::string type = "actual", + QListWidgetItem *p = nullptr ); + std::string type_; + QListWidgetItem *project_; + void handle_font_size_changed(std::string font_size_); + void handle_language_changed(std::string new_language); + QListWidgetItem *get_project() const; private slots: void open_note_window() const; + void delete_note(); + void change_type(std::string new_type); +signals: + void change_type_requested(QListWidgetItem *project); }; } // namespace Ui #endif // NOTEWIDGET_H \ No newline at end of file diff --git a/ui/main-window/include/projectitem.h b/ui/main-window/include/projectitem.h index 8b4a4a2..c74ceef 100644 --- a/ui/main-window/include/projectitem.h +++ b/ui/main-window/include/projectitem.h @@ -7,10 +7,14 @@ #include "project.hpp" namespace Ui { + +class NoteWidget; + class ProjectItem : public QListWidgetItem { project_storage_model::Project *project_; - friend NoteList; + friend class NoteList; friend class MainWindow; + friend class NoteWidget; public: ProjectItem(QListWidget *listview, project_storage_model::Project *project); diff --git a/ui/main-window/src/bottombar.cpp b/ui/main-window/src/bottombar.cpp index ee63c71..1407c5d 100644 --- a/ui/main-window/src/bottombar.cpp +++ b/ui/main-window/src/bottombar.cpp @@ -1,31 +1,36 @@ #include "bottombar.h" #include #include -#include -#include +#include namespace Ui { BottomBar::BottomBar( QWidget *parent, - std::string username, - std::string project_name + const std::string &username, + QString project_name ) : QWidget(parent), main_layout_(new QHBoxLayout()), - username_(new QLabel(username.c_str())), - project_name_(new QLabel(project_name.c_str())) { + project_name_(new QLabel(project_name)), + profile_button_(new QPushButton(username.c_str())) { this->setObjectName("BottomBar"); this->setLayout(main_layout_); this->setFixedHeight(40); + profile_button_->setObjectName("profile_button"); + project_name_->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); - username_->setAlignment(Qt::AlignVCenter | Qt::AlignRight); - this->setSizePolicy( - QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum) + main_layout_->addWidget(project_name_); + main_layout_->addStretch(); + main_layout_->addWidget(profile_button_); + + connect( + profile_button_, &QPushButton::clicked, this, + &BottomBar::profile_button_clicked ); - main_layout_->addWidget(project_name_); - main_layout_->addWidget(username_); + this->setLayout(main_layout_); + this->setAttribute(Qt::WA_StyledBackground); } } // namespace Ui \ No newline at end of file diff --git a/ui/main-window/src/mainwindow.cpp b/ui/main-window/src/mainwindow.cpp index 907f902..d956e3e 100644 --- a/ui/main-window/src/mainwindow.cpp +++ b/ui/main-window/src/mainwindow.cpp @@ -1,15 +1,22 @@ #include "mainwindow.h" +#include #include #include #include #include +#include #include #include +#include +#include #include #include -#include #include +#include +#include "applicationwindow.h" #include "bottombar.h" +#include "language_manager.h" +#include "login_window.h" #include "lr_dao.hpp" #include "main_window_style.hpp" #include "note_dao.hpp" @@ -18,8 +25,17 @@ #include "project_dao.hpp" #include "projectitem.h" #include "projectlist.h" +#include "registration_window.h" +#include "style_manager.h" namespace Ui { + +const std::vector MainWindow::THEMES = { + Ui::main_window_light_autumn_theme, Ui::main_window_dark_autumn_theme, + Ui::main_window_dark_purple_theme, Ui::main_window_light_purple_theme, + Ui::main_window_blue_theme +}; + MainWindow::MainWindow( QWidget *parent, std::string username, @@ -28,41 +44,78 @@ MainWindow::MainWindow( : QWidget(parent), username(username), main_layout_(new QVBoxLayout(this)), - top_bar_(new BottomBar(this, username, "EFFICIO :: Таск-Трекер")), + top_bar_(new BottomBar(this, username, "EFFICIO :: Task-Tracker")), content_layout_(new QHBoxLayout(this)), project_list_(new ProjectList(this)), - note_list_(new NoteList(this)), + actual_notes_(new NoteList(this, "actual")), + overdue_notes_(new NoteList(this, "overdue")), + completed_notes_(new NoteList(this, "completed")), + deleted_notes_(new NoteList(this, "deleted")), content_widget_(new QWidget(this)), new_project_button_(new QPushButton("Новый проект", this)), new_note_button_(new QPushButton("Новая заметка", this)), - storage_(storage) { + storage_(storage), + tab_widget_(new QTabWidget(this)) { this->setObjectName("main-window"); this->setAttribute(Qt::WA_StyledBackground); - this->setMinimumSize(QSize(800, 600)); - this->setStyleSheet(main_window_style); + + tab_widget_->addTab(create_scroll_area(actual_notes_), "Актуальные"); + tab_widget_->addTab(create_scroll_area(overdue_notes_), "Просроченные"); + tab_widget_->addTab(create_scroll_area(completed_notes_), "Выполненные"); + tab_widget_->addTab(create_scroll_area(deleted_notes_), "Удаленные"); + + tab_widget_->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + actual_notes_->setSizePolicy( + QSizePolicy::Expanding, QSizePolicy::Expanding + ); + overdue_notes_->setSizePolicy( + QSizePolicy::Expanding, QSizePolicy::Expanding + ); + completed_notes_->setSizePolicy( + QSizePolicy::Expanding, QSizePolicy::Expanding + ); + deleted_notes_->setSizePolicy( + QSizePolicy::Expanding, QSizePolicy::Expanding + ); main_layout_->addWidget(top_bar_, Qt::AlignTop); main_layout_->setAlignment(Qt::AlignCenter); - main_layout_->addWidget(content_widget_); - content_widget_->setLayout(content_layout_); - auto right_layout = new QVBoxLayout(content_widget_); + + QWidget *right_panel = new QWidget(this); + QVBoxLayout *right_layout = new QVBoxLayout(right_panel); + // right_layout->setContentsMargins(0, 34, 0, 0); // Верхний отступ 10px right_layout->addWidget(project_list_); right_layout->addWidget(new_project_button_); right_layout->addWidget(new_note_button_); - QScrollArea* scrollArea = new QScrollArea(content_widget_); - scrollArea->setWidgetResizable(true); - scrollArea->setWidget(note_list_); - content_layout_->addWidget(scrollArea, Qt::AlignRight); - content_layout_->addLayout(right_layout); - main_layout_->addWidget(content_widget_); - this->setLayout(main_layout_); + right_panel->setFixedWidth(210); + tab_widget_->tabBar()->setExpanding(true); + + content_layout_->addWidget(tab_widget_); + content_layout_->addWidget(right_panel); - this->project_list_->load_projects(storage); + main_layout_->addWidget(top_bar_); + main_layout_->addLayout(content_layout_); + project_list_->load_projects(storage); + + connect( + project_list_, &QListWidget::itemClicked, actual_notes_, + &NoteList::load_project_notes + ); + connect( + project_list_, &QListWidget::itemClicked, overdue_notes_, + &NoteList::load_project_notes + ); connect( - project_list_, &QListWidget::itemClicked, note_list_, + project_list_, &QListWidget::itemClicked, completed_notes_, &NoteList::load_project_notes ); + connect( + project_list_, &QListWidget::itemClicked, deleted_notes_, + &NoteList::load_project_notes + ); + connect( new_note_button_, &QPushButton::clicked, this, &Ui::MainWindow::add_note ); @@ -70,25 +123,137 @@ MainWindow::MainWindow( new_project_button_, &QPushButton::clicked, this, &Ui::MainWindow::add_project ); + connect( + top_bar_, &Ui::BottomBar::profile_button_clicked, this, + &MainWindow::on_profile_button_click + ); + connect( + StyleManager::instance(), &StyleManager::theme_changed, this, + &MainWindow::handle_theme_changed + ); + connect( + StyleManager::instance(), &StyleManager::font_size_changed, this, + &MainWindow::handle_font_size_changed + ); + connect( + LanguageManager::instance(), &LanguageManager::language_changed, this, + &MainWindow::handle_language_changed + ); + handle_theme_changed(StyleManager::instance()->current_theme()); + handle_font_size_changed(StyleManager::instance()->current_font_size()); + handle_language_changed(LanguageManager::instance()->current_language()); +} + +QScrollArea *MainWindow::create_scroll_area(NoteList *note_list) { + QScrollArea *scrollArea = new QScrollArea(); + scrollArea->setWidgetResizable(true); + scrollArea->setWidget(note_list); + scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + scrollArea->setFrameShape(QFrame::NoFrame); + return scrollArea; +} + +void MainWindow::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + new_project_button_->setText("Новый проект"); + new_note_button_->setText("Новая заметка"); + } else if (new_language == "EN") { + new_project_button_->setText("New project"); + new_note_button_->setText("New note"); + } +} + +void MainWindow::on_delete_account_button_click() { + this->deleteLater(); + emit delete_account_requested(); +} + +void MainWindow::on_logout_button_click() { + this->deleteLater(); + emit logout_requested(); +} + +void MainWindow::handle_theme_changed(int theme) { + this->setStyleSheet(THEMES[theme]); +} + +void MainWindow::handle_font_size_changed(std::string font_size_) { + QString font_rule; + if (font_size_ == "small") { + font_rule = + "#ProjectList, #BottomBar QLabel, #BottomBar QPushButton, " + "#NoteWidget QPushButton, QPushButton { font-size: 11px; }"; + } else if (font_size_ == "medium") { + font_rule = + "#ProjectList, #BottomBar QLabel, #BottomBar QPushButton, " + "#NoteWidget QPushButton, QPushButton { font-size: 13px; }"; + } else if (font_size_ == "big") { + font_rule = + "#ProjectList, #BottomBar QLabel, #BottomBar QPushButton, " + "#NoteWidget QPushButton, QPushButton { font-size: 15px; }"; + } + + this->setStyleSheet( + THEMES[StyleManager::instance()->current_theme()] + font_rule + ); +} + +void MainWindow::on_profile_button_click() { + this->setEnabled(false); + ProfileWindow *new_profile_window = new ProfileWindow( + QString::fromStdString(this->username), this->parentWidget() + ); + new_profile_window->setAttribute(Qt::WA_DeleteOnClose); + connect( + new_profile_window, &ProfileWindow::logout_requested, this, + &MainWindow::on_logout_button_click + ); + connect( + new_profile_window, &ProfileWindow::delete_account_requested, this, + &MainWindow::on_delete_account_button_click + ); + connect(new_profile_window, &ProfileWindow::destroyed, this, [this]() { + this->setEnabled(true); + }); + new_profile_window->show(); + new_profile_window->raise(); + new_profile_window->activateWindow(); } void MainWindow::add_project() { bool ok; - QString name_of_project = QInputDialog::getText( - nullptr, "Название проекта:", "Введите название", QLineEdit::Normal, "", - &ok - ); - if (ok) { + QString name_of_project; + if (LanguageManager::instance()->current_language() == "RU") { + name_of_project = QInputDialog::getText( + nullptr, "Название проекта:", "Введите название", QLineEdit::Normal, + "", &ok + ); + } else if (LanguageManager::instance()->current_language() == "EN") { + name_of_project = QInputDialog::getText( + nullptr, "Name of project:", "Create a name", QLineEdit::Normal, "", + &ok + ); + } + if (ok && name_of_project.trimmed() == "") { + if (LanguageManager::instance()->current_language() == "RU") { + QMessageBox::warning(this, "Ошибка", "Введите название!"); + } else { + QMessageBox::warning(this, "Error", "Please enter a name!"); + } + } else if (ok) { int id = 0; - if (DB::ProjectDAO::create_project(name_of_project.toStdString(), id)) { + if (DB::ProjectDAO::create_project( + name_of_project.trimmed().toStdString(), id + )) { LRDao::add_project_to_user(username, id); auto &project = storage_->add_project( - Project(id, name_of_project.toStdString(), "") + Project(id, name_of_project.trimmed().toStdString(), "") ); project_list_->add_project(&project); } } + handle_font_size_changed(StyleManager::instance()->current_font_size()); } void MainWindow::add_note() { @@ -101,11 +266,15 @@ void MainWindow::add_note() { ); auto ¬e = project_item->project_->add_note({id, "Пустая заметка", ""}); - note_list_->add_note_widget(¬e); + actual_notes_->add_note_widget(¬e, project_list_->currentItem()); } } else { QMessageBox msg; - msg.setText("Проект не выбран!"); + if (LanguageManager::instance()->current_language() == "RU") { + msg.setText("Сперва выберите проект!"); + } else if (LanguageManager::instance()->current_language() == "EN") { + msg.setText("Choose a project first!"); + } msg.exec(); } } diff --git a/ui/main-window/src/notelist.cpp b/ui/main-window/src/notelist.cpp index 4af7558..dd9083a 100644 --- a/ui/main-window/src/notelist.cpp +++ b/ui/main-window/src/notelist.cpp @@ -5,19 +5,17 @@ #include #include #include "note.hpp" -#include "notewidget.h" -#include "projectitem.h" namespace Ui { -NoteList::NoteList(QWidget *parent) +NoteList::NoteList(QWidget *parent, const std::string type) : QWidget(parent), main_layout_(new QHBoxLayout(this)), - vertical_layouts_(std::vector()){ - + vertical_layouts_(std::vector()), + type_(type) { this->setAttribute(Qt::WA_StyledBackground); this->setObjectName("NoteList"); this->setLayout(main_layout_); - vertical_layouts_.resize(4, nullptr); + vertical_layouts_.resize(3, nullptr); for (auto &layout : vertical_layouts_) { layout = new QVBoxLayout(this); @@ -25,15 +23,21 @@ NoteList::NoteList(QWidget *parent) } } -void NoteList::add_note_widget(const project_storage_model::Note *note) { - auto current_layout = vertical_layouts_[note_counter_ % 4]; +void NoteList::add_note_widget( + const project_storage_model::Note *note, + QListWidgetItem *project +) { + auto current_layout = vertical_layouts_[note_counter_ % 3]; if (current_layout->count() > 1) { current_layout->removeItem( current_layout->itemAt(current_layout->count() - 1) ); } - vertical_layouts_[note_counter_ % 4]->addWidget( - new NoteWidget(this, note), 0, Qt::AlignTop + auto *new_note = new NoteWidget(this, note, this->type_, project); + vertical_layouts_[note_counter_ % 3]->addWidget(new_note, 0, Qt::AlignTop); + connect( + new_note, &NoteWidget::change_type_requested, this, + &NoteList::load_project_notes ); current_layout->addStretch(); note_counter_++; @@ -41,14 +45,12 @@ void NoteList::add_note_widget(const project_storage_model::Note *note) { void NoteList::load_project_notes(QListWidgetItem *project) { ProjectItem *p = dynamic_cast(project); - assert(p != nullptr); - qDebug() << "Адрес проекта" - << QString::fromStdString(p->project_->get_name()) << ":" - << p->project_; this->clear_note_list(); note_counter_ = 0; for (const auto ¬e : p->project_->get_notes()) { - this->add_note_widget(¬e); + if (note.get_type() == this->type_) { + this->add_note_widget(¬e, project); + } } } diff --git a/ui/main-window/src/notewidget.cpp b/ui/main-window/src/notewidget.cpp index 3ced750..f4a5c77 100644 --- a/ui/main-window/src/notewidget.cpp +++ b/ui/main-window/src/notewidget.cpp @@ -1,28 +1,39 @@ #include "notewidget.h" #include +#include #include #include +#include "language_manager.h" #include "note.hpp" #include "note_edit_dialog.h" +#include "style_manager.h" namespace Ui { NoteWidget::NoteWidget( QWidget *parent, - const project_storage_model::Note *model_note + const Note *model_note, + const std::string type, + QListWidgetItem *p ) : QWidget(parent), model_note_(model_note), main_layout_(new QVBoxLayout(this)), - open_button_(new QPushButton("Открыть")) { + open_button_(new QPushButton(tr("Открыть"))), + delete_button_(new QPushButton(tr("Удалить"))), + type_(type), + project_(p) { this->setObjectName("NoteWidget"); this->setMinimumWidth(100); this->setFixedHeight(100); - title_label_ = new QLabel(model_note_->get_title().c_str(), this); - text_label_ = new QLabel(model_note_->get_text().c_str(), this); - - title_label_->setStyleSheet("color: rgb(33, 44, 50);"); - text_label_->setStyleSheet("color: rgb(33, 44, 50);"); - + + title_label_ = + new QLabel(QString::fromStdString(model_note_->get_title()), this); + text_label_ = + new QLabel(QString::fromStdString(model_note_->get_text()), this); + + title_label_->setStyleSheet("color: rgb(33, 44, 50); font-size: 15px;"); + text_label_->setStyleSheet("color: rgb(33, 44, 50); font-size: 15px;"); + main_layout_->addWidget(title_label_); main_layout_->addWidget(text_label_); @@ -30,24 +41,101 @@ NoteWidget::NoteWidget( title_label_->setWordWrap(false); text_label_->setTextInteractionFlags(Qt::TextSelectableByMouse); - main_layout_->addWidget(open_button_); + QHBoxLayout *buttons_layout = new QHBoxLayout; + + buttons_layout->addWidget(open_button_); + buttons_layout->addWidget(delete_button_); + + if (type_ == "deleted") { + delete_button_->setText("Восстановить"); + } + + main_layout_->addLayout(buttons_layout); connect( open_button_, &QPushButton::clicked, this, &NoteWidget::open_note_window ); + connect( + delete_button_, &QPushButton::clicked, this, &NoteWidget::delete_note + ); + connect( + StyleManager::instance(), &StyleManager::font_size_changed, this, + &NoteWidget::handle_font_size_changed + ); this->setLayout(main_layout_); this->setAttribute(Qt::WA_StyledBackground); + connect( + LanguageManager::instance(), &LanguageManager::language_changed, this, + &NoteWidget::handle_language_changed + ); + handle_language_changed(LanguageManager::instance()->current_language()); + handle_font_size_changed(StyleManager::instance()->current_font_size()); +} + +void NoteWidget::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + open_button_->setText(tr("Открыть")); + if (title_label_->text() == "Empty note") { + title_label_->setText("Пустая заметка"); + } + if (type_ == "deleted") { + delete_button_->setText("Восстановить"); + } else { + delete_button_->setText("Удалить"); + } + } else if (new_language == "EN") { + open_button_->setText(tr("Open")); + if (title_label_->text() == "Пустая заметка") { + title_label_->setText("Empty note"); + } + if (type_ == "deleted") { + delete_button_->setText("Восстановить"); + } else { + delete_button_->setText("Удалить"); + } + } +} + +void NoteWidget::handle_font_size_changed(std::string font_size_) { + QString font_rule; + if (font_size_ == "small") { + title_label_->setStyleSheet("color: rgb(33, 44, 50); font-size: 13px;"); + } else if (font_size_ == "medium") { + title_label_->setStyleSheet("color: rgb(33, 44, 50); font-size: 15px;"); + } else if (font_size_ == "big") { + title_label_->setStyleSheet("color: rgb(33, 44, 50); font-size: 17px;"); + } } void NoteWidget::open_note_window() const { auto dialog = new ::NoteEditDialog( + dynamic_cast(project_)->project_->get_name(), const_cast(qobject_cast(this)), const_cast(model_note_) ); dialog->setAttribute(Qt::WA_DeleteOnClose); dialog->exec(); - text_label_->setText(model_note_->get_text().c_str()); - title_label_->setText(model_note_->get_title().c_str()); + title_label_->setText(QString::fromStdString(model_note_->get_title())); + main_layout_->update(); +} + +void NoteWidget::change_type(std::string new_type) { + type_ = new_type; + handle_language_changed(LanguageManager::instance()->current_language()); main_layout_->update(); + emit change_type_requested(this->project_); +} + +void NoteWidget::delete_note() { + if (type_ == "deleted") { + this->change_type("actual"); + } else { + this->change_type("deleted"); + } } + +QListWidgetItem *NoteWidget::get_project() const { + return this->project_; +} + } // namespace Ui \ No newline at end of file diff --git a/ui/note-widget/CMakeLists.txt b/ui/note-widget/CMakeLists.txt index d062724..9dcfe1d 100644 --- a/ui/note-widget/CMakeLists.txt +++ b/ui/note-widget/CMakeLists.txt @@ -37,4 +37,4 @@ target_include_directories(NoteWidget $ ) -target_link_libraries(NoteWidget PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Sql Database Scripts) \ No newline at end of file +target_link_libraries(NoteWidget PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Sql Database LanguageManager Scripts StyleManager) \ No newline at end of file diff --git a/ui/note-widget/include/note_edit_dialog.h b/ui/note-widget/include/note_edit_dialog.h index 46048a3..0dbcda5 100644 --- a/ui/note-widget/include/note_edit_dialog.h +++ b/ui/note-widget/include/note_edit_dialog.h @@ -23,10 +23,15 @@ class NoteEditDialog final : public QDialog { public: explicit NoteEditDialog( - QWidget* parent = nullptr, - Note* note = new Note(0, "NULL", "NULL") + std::string project_name = "TODO", + QWidget *parent = nullptr, + Note *note = new Note(0, "NULL", "NULL") ); ~NoteEditDialog() override; + static const std::vector THEMES; + void handle_theme_changed(int theme); + void handle_font_size_changed(std::string font_size); + void handle_language_changed(std::string new_language); private slots: void on_save_button_click(); @@ -40,19 +45,20 @@ private slots: void setup_connections(); void setup_ui(); - void add_member_avatar(const std::string& member); + void add_member_avatar(const std::string &member); void clear_member_avatars(); void update_tags_display(); - static QString create_tag_style_sheet(const QString& color); + static QString create_tag_style_sheet(const QString &color); [[nodiscard]] bool try_save_note() const; - Ui::NoteEditDialog* ui_{}; + Ui::NoteEditDialog *ui_{}; std::vector> member_avatars_; std::vector> tag_labels_; QList selected_tags_; - Note* note_; + Note *note_; + std::string project_name_; }; -#endif // NOTE_EDIT_DIALOG_H \ No newline at end of file +#endif // NOTE_EDIT_DIALOG_H \ No newline at end of file diff --git a/ui/note-widget/include/note_edit_dialog_styles.h b/ui/note-widget/include/note_edit_dialog_styles.h index 5ad1b63..898475f 100644 --- a/ui/note-widget/include/note_edit_dialog_styles.h +++ b/ui/note-widget/include/note_edit_dialog_styles.h @@ -4,7 +4,8 @@ #include namespace Ui { -QString light_theme = R"( +QString note_edit_dialog_light_autumn_theme = R"( + QDialog { background-color: #f5f5f5; } @@ -45,10 +46,6 @@ QString light_theme = R"( padding: 5px; } - QTextEdit#descriptionTextEdit::placeholder { - color: #727272; - } - /* Основные кнопки */ QHBoxLayout#buttonsLayout { @@ -79,7 +76,17 @@ QString light_theme = R"( background-color: #dadada; } - /* Боковое меню */ + QPushButton#deleteButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: white; + color: #fea36b; + padding: 5px 10px; + } + + QPushButton#deleteButton:hover { + background-color: #dadada; + } QPushButton#joinButton, QPushButton#addMembersButton, @@ -115,8 +122,6 @@ QString light_theme = R"( color: #727272; } - /* Дополнительные элементы заметки */ - QDateEdit#dateEdit { font-family: 'Arial'; border-radius: 5px; @@ -132,10 +137,9 @@ QString light_theme = R"( QDateEdit#dateEdit::drop-down { border: none; width: 20px; + border-radius: 5px; } - /* Окно с сообщением */ - QMessageBox { background-color: #ffffff; } @@ -167,6 +171,754 @@ QString light_theme = R"( background-color: #d58745; border-color: #d58745; } + + QPushButton#switch_theme { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + background-color: transparent; + border-radius: 7px; + border: 2px solid #089083; + padding: 0; + } + QPushButton::hover#switch_theme { + background-color: #089083; + } + QPushButton::pressed#switch_theme { + background-color:rgb(7, 110, 100); + } +)"; + +QString note_edit_dialog_dark_autumn_theme = R"( + QDialog { + background-color: #202020; + } + + QLineEdit#titleLineEdit { + font-family: 'Arial'; + font-size: 25px; + font-weight: bold; + color: #089083; + border: none; + padding: 0; + background: transparent; + } + + QLabel#projectNameLabel { + font-family: 'Arial'; + font-size: 13px; + color: #727272; + padding: 1px; + } + + QLabel#descriptionLabel { + font-family: 'Arial'; + font-size: 18px; + font-weight: bold; + color:rgb(202, 202, 202); + } + + QTextEdit#descriptionTextEdit { + border-radius: 10px; + border: 1px solid #000000; + background: #000000; + color: #727272; + padding: 5px; + } + + QHBoxLayout#buttonsLayout { + align: left; + } + + QPushButton#saveButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #fea36b; + color: #263238; + padding: 5px 10px; + } + + QPushButton#saveButton:hover { + background-color: #d58745; + } + + QPushButton#cancelButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #089083; + color: white; + padding: 5px 10px; + } + + QPushButton#cancelButton:hover { + background-color: #01635d; + } + + QPushButton#deleteButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #089083; + color: white; + padding: 5px 10px; + } + + QPushButton#deleteButton:hover { + background-color: #01635d; + } + + QPushButton#joinButton, + QPushButton#addMembersButton, + QPushButton#addDateButton, + QPushButton#addTagsButton { + font-family: 'Arial'; + background-color: #089083; + color: #ffffff; + padding: 5px 10px; + border-radius: 10px; + font-weight: bold; + text-align: left; + } + + QPushButton#joinButton:hover, + QPushButton#addMembersButton:hover, + QPushButton#addDateButton:hover, + QPushButton#addTagsButton:hover { + background-color: #01635d; + } + + QLabel#sidePanelLabel, + QLabel#sidePanelLabel_2 { + font-family: 'Arial'; + font-size: 14px; + font-weight: bold; + color: #727272; + } + + QLabel#membersLabel, + QLabel#tagsLabel, + QLabel#dateLabel { + color: #727272; + } + + QDateEdit#dateEdit { + font-family: 'Arial'; + border-radius: 5px; + background-color: #ffdda2; + color: #050505; + padding: 5px 5px; + border: none; + width: 70px; + height: 22px; + text-align: center; + font-weight: bold; + } + QDateEdit#dateEdit::drop-down { + border: none; + width: 20px; + } + + QMessageBox { + background-color: #263238; + } + + QMessageBox QLabel { + font-family: 'Arial'; + font-size: 14px; + color: #ffffff; + } + + QMessageBox QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + color: #263238; + background-color: #fea36b; + border-radius: 10px; + padding: 5px 15px; + min-width: 60px; + min-height: 25px; + } + + QMessageBox QPushButton:hover { + background-color: #d58745; + } + + QMessageBox QPushButton:pressed { + background-color: #d58745; + border-color: #d58745; + } + + QPushButton#switch_theme { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + background-color: transparent; + border-radius: 7px; + border: 2px solid #089083; + padding: 0; + } + QPushButton::hover#switch_theme { + background-color: #089083; + } + QPushButton::pressed#switch_theme { + background-color:rgb(7, 110, 100); + } +)"; + +QString note_edit_dialog_light_purple_theme = R"( + QDialog { + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 #9882B9, stop:0.5 rgb(176, 157, 205), stop:1 rgb(125, 109, 148)); + } + + QLineEdit#titleLineEdit { + font-family: 'Arial'; + font-size: 25px; + font-weight: bold; + color: rgb(42, 10, 25); + border: none; + padding: 0; + background: transparent; + } + + QLabel#projectNameLabel { + font-family: 'Arial'; + font-size: 13px; + color: rgb(218, 207, 235); + padding: 1px; + } + + QLabel#descriptionLabel { + font-family: 'Arial'; + font-size: 18px; + font-weight: bold; + color: rgb(42, 10, 25); + } + + QTextEdit#descriptionTextEdit { + border-radius: 10px; + border: 1px solid rgb(221, 210, 238); + background: rgb(221, 210, 238); + color: #221932; + padding: 5px; + } + + QHBoxLayout#buttonsLayout { + align: left; + } + + QPushButton#saveButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #722548; + color: rgb(206, 193, 224); + padding: 5px 10px; + } + + QPushButton#saveButton:hover { + background-color: rgb(98, 27, 59); + } + + QPushButton#cancelButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: rgb(42, 10, 25); + color: rgb(218, 207, 235); + padding: 5px 10px; + } + + QPushButton#cancelButton:hover { + background-color: rgb(27, 6, 16); + } + + QPushButton#deleteButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: rgb(42, 10, 25); + color: rgb(218, 207, 235); + padding: 5px 10px; + } + + QPushButton#deleteButton:hover { + background-color: rgb(27, 6, 16); + } + + QPushButton#joinButton, + QPushButton#addMembersButton, + QPushButton#addDateButton, + QPushButton#addTagsButton { + font-family: 'Arial'; + background-color: rgb(42, 10, 25); + color: rgb(218, 207, 235); + padding: 5px 10px; + border-radius: 10px; + font-weight: bold; + text-align: left; + } + + QPushButton#joinButton:hover, + QPushButton#addMembersButton:hover, + QPushButton#addDateButton:hover, + QPushButton#addTagsButton:hover { + background-color: rgb(27, 6, 16); + } + + QLabel#sidePanelLabel, + QLabel#sidePanelLabel_2 { + font-family: 'Arial'; + font-size: 14px; + font-weight: bold; + color: rgb(218, 207, 235); + } + + QLabel#membersLabel, + QLabel#tagsLabel, + QLabel#dateLabel { + color: rgb(218, 207, 235); + } + + QDateEdit#dateEdit { + font-family: 'Arial'; + border-radius: 5px; + background-color: #C98BB8; + color: rgb(42, 10, 25); + padding: 5px 5px; + border: none; + width: 70px; + height: 22px; + text-align: center; + font-weight: bold; + } + QDateEdit#dateEdit::drop-down { + border: none; + width: 20px; + } + + QMessageBox { + background-color: rgb(221, 210, 238); + } + + QMessageBox QLabel { + font-family: 'Arial'; + font-size: 14px; + color: #221932; + } + + QMessageBox QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + color: rgb(206, 193, 224); + background-color: #722548; + border-radius: 10px; + padding: 5px 15px; + min-width: 60px; + min-height: 25px; + } + + QMessageBox QPushButton:hover { + background-color: rgb(98, 27, 59); + } + + QMessageBox QPushButton:pressed { + background-color: rgb(98, 27, 59); + border-color: rgb(98, 27, 59); + } + + QPushButton#switch_theme { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + background-color: transparent; + border-radius: 7px; + border: 2px solid rgb(42, 10, 25); + padding: 0; + } + QPushButton::hover#switch_theme { + background-color: rgb(42, 10, 25); + } + QPushButton::pressed#switch_theme { + background-color:rgb(26, 6, 15); + } +)"; + +QString note_edit_dialog_dark_purple_theme = R"( + QDialog { + background-color:rgb(9, 6, 10); + } + + QLineEdit#titleLineEdit { + font-family: 'Arial'; + font-size: 25px; + font-weight: bold; + color: #9882B9; + border: none; + padding: 0; + background: transparent; + } + + QLabel#projectNameLabel { + font-family: 'Arial'; + font-size: 13px; + color: rgb(176, 170, 185); + padding: 1px; + } + + QLabel#descriptionLabel { + font-family: 'Arial'; + font-size: 18px; + font-weight: bold; + color: #9882B9; + } + + QTextEdit#descriptionTextEdit { + border-radius: 10px; + border: 1px solid #221932; + background: #221932; + color: rgb(176, 170, 185); + padding: 5px; + } + + QHBoxLayout#buttonsLayout { + align: left; + } + + QPushButton#saveButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #722548; + color: #060407; + padding: 5px 10px; + } + + QPushButton#saveButton:hover { + background-color: rgb(98, 27, 59); + } + + QPushButton#cancelButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: rgb(42, 10, 25); + color: #9882B9; + padding: 5px 10px; + } + + QPushButton#cancelButton:hover { + background-color: rgb(27, 6, 16); + } + + QPushButton#deleteButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: rgb(42, 10, 25); + color: #9882B9; + padding: 5px 10px; + } + + QPushButton#deleteButton:hover { + background-color: rgb(27, 6, 16); + } + + QPushButton#joinButton, + QPushButton#addMembersButton, + QPushButton#addDateButton, + QPushButton#addTagsButton { + font-family: 'Arial'; + background-color: rgb(42, 10, 25); + color: #9882B9; + padding: 5px 10px; + border-radius: 10px; + font-weight: bold; + text-align: left; + } + + QPushButton#joinButton:hover, + QPushButton#addMembersButton:hover, + QPushButton#addDateButton:hover, + QPushButton#addTagsButton:hover { + background-color: rgb(27, 6, 16); + } + + QLabel#sidePanelLabel, + QLabel#sidePanelLabel_2 { + font-family: 'Arial'; + font-size: 14px; + font-weight: bold; + color: #9882B9; + } + + QLabel#membersLabel, + QLabel#tagsLabel, + QLabel#dateLabel { + color: #9882B9; + } + + QDateEdit#dateEdit { + font-family: 'Arial'; + border-radius: 5px; + background-color: rgb(113, 97, 137); + color: #221932; + padding: 5px 5px; + border: none; + width: 70px; + height: 22px; + text-align: center; + font-weight: bold; + } + QDateEdit#dateEdit::drop-down { + border: none; + width: 20px; + } + + QMessageBox { + background-color: #221932; + } + + QMessageBox QLabel { + font-family: 'Arial'; + font-size: 14px; + color: #9882B9; + } + + QMessageBox QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + color: #060407; + background-color: #722548; + border-radius: 10px; + padding: 5px 15px; + min-width: 60px; + min-height: 25px; + } + + QMessageBox QPushButton:hover { + background-color: rgb(98, 27, 59); + } + + QMessageBox QPushButton:pressed { + background-color: rgb(98, 27, 59); + border-color: rgb(98, 27, 59); + } + + QPushButton#switch_theme { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + background-color: transparent; + border-radius: 7px; + border: 2px solid #9882B9; + padding: 0; + } + QPushButton::hover#switch_theme { + background-color: #9882B9; + } + QPushButton::pressed#switch_theme { + background-color:rgb(116, 99, 140); + } +)"; + +QString note_edit_dialog_blue_theme = R"( + QDialog { + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 #173C4C, stop:0.5 rgb(30, 66, 65), stop:1 #07142B); + } + + QLineEdit#titleLineEdit { + font-family: 'Arial'; + font-size: 25px; + font-weight: bold; + color: #BDD1BD; + border: none; + padding: 0; + background: transparent; + } + + QLabel#projectNameLabel { + font-family: 'Arial'; + font-size: 13px; + color: #BDD1BD; + padding: 1px; + } + + QLabel#descriptionLabel { + font-family: 'Arial'; + font-size: 18px; + font-weight: bold; + color: #BDD1BD; + } + + QTextEdit#descriptionTextEdit { + border-radius: 10px; + border: 1px solid #568F7C; + background: #07142B; + color: #BDD1BD; + padding: 5px; + } + + QHBoxLayout#buttonsLayout { + align: left; + } + + QPushButton#saveButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #568F7C; + color: #BDD1BD; + padding: 5px 10px; + border: none; + font-weight: bold; + } + + QPushButton#saveButton:hover { + background-color: #326D6C; + } + + QPushButton#saveButton:pressed { + background-color: #07142B; + } + + QPushButton#cancelButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #326D6C; + color: #BDD1BD; + padding: 5px 10px; + border: 1px solid #568F7C; + } + + QPushButton#cancelButton:hover { + background-color: #568F7C; + color: #07142B; + } + + QPushButton#deleteButton { + font-family: 'Arial'; + border-radius: 10px; + background-color: #326D6C; + color: #BDD1BD; + padding: 5px 10px; + border: 1px solid #568F7C; + } + + QPushButton#deleteButton:hover { + background-color: #568F7C; + color: #07142B; + } + + QPushButton#joinButton, + QPushButton#addMembersButton, + QPushButton#addDateButton, + QPushButton#addTagsButton { + font-family: 'Arial'; + background-color: #326D6C; + color: #BDD1BD; + padding: 5px 10px; + border-radius: 10px; + font-weight: bold; + text-align: left; + } + + QPushButton#joinButton:hover, + QPushButton#addMembersButton:hover, + QPushButton#addDateButton:hover, + QPushButton#addTagsButton:hover { + background-color: #568F7C; + color: #07142B; + } + + QLabel#sidePanelLabel, + QLabel#sidePanelLabel_2 { + font-family: 'Arial'; + font-size: 14px; + font-weight: bold; + color: #BDD1BD; + } + + QLabel#membersLabel, + QLabel#tagsLabel, + QLabel#dateLabel { + color: #BDD1BD; + } + + QDateEdit#dateEdit { + font-family: 'Arial'; + border-radius: 5px; + background-color: rgb(61, 104, 122); + color: #BDD1BD; + padding: 5px 5px; + border: none; + width: 70px; + height: 22px; + text-align: center; + font-weight: bold; + } + QDateEdit#dateEdit::drop-down { + border: none; + width: 20px; + } + + QMessageBox { + background-color: #07142B; + } + + QMessageBox QLabel { + font-family: 'Arial'; + font-size: 14px; + color: #BDD1BD; + } + + QMessageBox QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + color: #BDD1BD; + background-color: #568F7C; + border-radius: 10px; + padding: 5px 15px; + min-width: 60px; + min-height: 25px; + } + + QMessageBox QPushButton:hover { + background-color: #326D6C; + } + + QMessageBox QPushButton:pressed { + background-color: #07142B; + border-color: #07142B; + } + + QPushButton#switch_theme { + width: 20px; + height: 20px; + min-width: 20px; + min-height: 20px; + max-width: 20px; + max-height: 20px; + background-color: transparent; + border-radius: 7px; + border: 2px solid #326D6C; + padding: 0; + } + QPushButton::hover#switch_theme { + background-color: #326D6C; + } + QPushButton::pressed#switch_theme { + background-color:rgb(33, 74, 74); + } )"; } // namespace Ui diff --git a/ui/note-widget/include/tags_dialog.h b/ui/note-widget/include/tags_dialog.h index f8496c0..b4dcea1 100644 --- a/ui/note-widget/include/tags_dialog.h +++ b/ui/note-widget/include/tags_dialog.h @@ -6,12 +6,17 @@ #include #include #include +#include #include +#include class TagsDialog final : public QDialog { Q_OBJECT public: + const static std::vector THEMES; + void handle_theme_changed(int theme); + void handle_language_changed(std::string new_language); const int MAX_TAGS_COUNT = 5; const std::pair DIALOG_SIZE = std::make_pair(300, 250); diff --git a/ui/note-widget/include/tags_dialog_styles.h b/ui/note-widget/include/tags_dialog_styles.h index 15fd320..dd9f013 100644 --- a/ui/note-widget/include/tags_dialog_styles.h +++ b/ui/note-widget/include/tags_dialog_styles.h @@ -4,7 +4,7 @@ #include "tags_dialog.h" namespace Ui { -QString tags_dialog_light_theme = R"( +QString tags_dialog_light_autumn_theme = R"( QDialog { background-color: #f5f5f5; } @@ -14,6 +14,7 @@ QString tags_dialog_light_theme = R"( font-family: 'Arial'; color: #727272; spacing: 5px; + background-color: transparent; } QCheckBox::indicator { @@ -21,17 +22,15 @@ QString tags_dialog_light_theme = R"( height: 16px; border-radius: 3px; border: 1px solid #727272; - background-color: #ffffff; + background-color: transparent; } QCheckBox::indicator:checked { - background-color: #fea36b; - border: 1px solid #fea36b; - image: url(:/images/check.png); + background-color: #727272; } QCheckBox::indicator:hover { - border: 1px solid #fea36b; + background-color: rgb(33, 44, 50); } /* Выпадающие списки цветов */ @@ -108,16 +107,445 @@ QString tags_dialog_light_theme = R"( background-color: white; color: #fea36b; padding: 5px 10px; - font-weight: bold; + } + + QPushButton#cancel_button:hover { + background-color: #dadada; + } +)"; + +QString tags_dialog_dark_autumn_theme = R"( + QDialog { + background-color: #202020; + } + + /* Чекбоксы */ + QCheckBox { + font-family: 'Arial'; + color: #727272; + spacing: 5px; + background-color: transparent; + } + QCheckBox::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid #727272; + background-color: transparent; + } + QCheckBox::indicator:hover { + background-color: #727272; + } + QCheckBox::indicator:checked { + background-color:rgb(0, 0, 0); + } + + /* Выпадающие списки цветов */ + QComboBox { + font-family: 'Arial'; + border-radius: 10px; + background-color: #363636; + color: #BDD1BD; + padding: 5px 10px; + border: 1px solid #505050; + } + + QComboBox:hover { + border: 1px solid #fea36b; + } + + QComboBox::drop-down { + width: 20px; + border: none; + } + + QComboBox::down-arrow { + image: url(:/images/down_arrow_light.png); + } + + QComboBox QAbstractItemView { + background-color: #363636; + color: #BDD1BD; + selection-background-color: #089083; + selection-color: white; + border: 1px solid #505050; + border-radius: 5px; + } + + /* Поля ввода имени тега */ + QLineEdit { + font-family: 'Arial'; + border-radius: 10px; + background-color: #363636; + color: #BDD1BD; + padding: 5px 10px; + border: 1px solid #505050; + } + + QLineEdit:hover, + QLineEdit:focus { border: 1px solid #fea36b; + } + + QLineEdit::placeholder { + color: #727272; + } + + /* Кнопка OK */ + QPushButton#ok_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: #fea36b; + color: #263238; + padding: 5px 10px; + font-weight: bold; width: 30px; height: 25px; } + QPushButton#ok_button:hover { + background-color: #d58745; + } + + /* Кнопка Отмена */ + QPushButton#cancel_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: #089083; + color: white; + padding: 5px 10px; + } + QPushButton#cancel_button:hover { - background-color: #dadada; + background-color: #01635d; + } + +)"; + +QString tags_dialog_light_purple_theme = R"( + QDialog { + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 #9882B9, stop:0.5 rgb(176, 157, 205), stop:1 rgb(125, 109, 148)); + } + + /* Чекбоксы */ + QCheckBox { + font-family: 'Arial'; + color: rgb(42, 10, 25); + spacing: 5px; + background-color: transparent; + } + QCheckBox::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid rgb(42, 10, 25); + background-color: transparent; + } + QCheckBox::indicator:hover { + background-color: rgb(218, 207, 235); + } + QCheckBox::indicator:checked { + background-color: rgb(42, 10, 25); + } + + /* Выпадающие списки цветов */ + QComboBox { + font-family: 'Arial'; + border-radius: 10px; + background-color: #E8C9E1; + color: #221932; + padding: 5px 10px; + border: 1px solid #C98BB8; + } + + QComboBox:hover { + border: 1px solid #722548; + } + + QComboBox::drop-down { + width: 20px; + border: none; + } + + QComboBox::down-arrow { + image: url(:/images/down_arrow_purple.png); + } + + QComboBox QAbstractItemView { + background-color: #E8C9E1; + color: #221932; + selection-background-color: #722548; + selection-color: white; + border: 1px solid #C98BB8; + border-radius: 5px; + } + + /* Поля ввода имени тега */ + QLineEdit { + font-family: 'Arial'; + border-radius: 10px; + background-color: #E8C9E1; + color: #221932; + padding: 5px 10px; + border: 1px solid #C98BB8; + } + + QLineEdit:hover, + QLineEdit:focus { + border: 1px solid #722548; + } + + QLineEdit::placeholder { + color: #7A6A9A; + } + + /* Кнопка OK */ + QPushButton#ok_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: #722548; + color: #E8C9E1; + padding: 5px 10px; + font-weight: bold; + width: 30px; + height: 25px; + } + + QPushButton#ok_button:hover { + background-color: #5A1538; + } + + /* Кнопка Отмена */ + QPushButton#cancel_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: rgb(42, 10, 25); + color: rgb(218, 207, 235); + padding: 5px 10px; + } + + QPushButton#cancel_button:hover { + background-color: rgb(27, 6, 16); + } +)"; + +QString tags_dialog_dark_purple_theme = R"( + QDialog { + background-color: rgb(9, 6, 10); + } + + /* Чекбоксы */ + QCheckBox { + font-family: 'Arial'; + color: #9882B9; + spacing: 5px; + background-color: transparent; + } + QCheckBox::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid #9882B9; + background-color: transparent; + } + QCheckBox::indicator:hover { + background-color: #221932; + } + QCheckBox::indicator:checked { + background-color: #9882B9; + } + + /* Выпадающие списки цветов */ + QComboBox { + font-family: 'Arial'; + border-radius: 10px; + background-color: #322242; + color: #9882B9; + padding: 5px 10px; + border: 1px solid #775E88; + } + + QComboBox:hover { + border: 1px solid #722548; + } + + QComboBox::drop-down { + width: 20px; + border: none; + } + + QComboBox::down-arrow { + image: url(:/images/down_arrow_purple.png); + } + + QComboBox QAbstractItemView { + background-color: #322242; + color: #9882B9; + selection-background-color: #722548; + selection-color: white; + border: 1px solid #775E88; + border-radius: 5px; + } + + /* Поля ввода имени тега */ + QLineEdit { + font-family: 'Arial'; + border-radius: 10px; + background-color: #322242; + color: #9882B9; + padding: 5px 10px; + border: 1px solid #775E88; + } + + QLineEdit:hover, + QLineEdit:focus { + border: 1px solid #722548; + } + + QLineEdit::placeholder { + color: #7A6A9A; + } + + /* Кнопка OK */ + QPushButton#ok_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: #722548; + color: rgb(9, 6, 10); + padding: 5px 10px; + font-weight: bold; + width: 30px; + height: 25px; + } + + QPushButton#ok_button:hover { + background-color: #5A1538; + } + + /* Кнопка Отмена */ + QPushButton#cancel_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: rgb(42, 10, 25); + color: #9882B9; + padding: 5px 10px; + } + + QPushButton#cancel_button:hover { + background-color: rgb(27, 6, 16); + } +)"; + +QString tags_dialog_blue_theme = R"( + QDialog { + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 #173C4C, stop:0.5 rgb(30, 66, 65), stop:1 #07142B); + } + + /* Чекбоксы */ + QCheckBox { + font-family: 'Arial'; + color: #BDD1BD; + spacing: 5px; + background-color: transparent; + } + QCheckBox::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid #BDD1BD; + background-color: transparent; + } + QCheckBox::indicator:hover { + background-color: #BDD1BD; + } + QCheckBox::indicator:checked { + background-color: #07142B; + } + + /* Выпадающие списки цветов */ + QComboBox { + font-family: 'Arial'; + border-radius: 10px; + background-color: #173C4C; + color: #BDD1BD; + padding: 5px 10px; + border: 1px solid #326D6C; + } + + QComboBox:hover { + border: 1px solid #568F7C; + } + + QComboBox::drop-down { + width: 20px; + border: none; + } + + QComboBox::down-arrow { + image: url(:/images/down_arrow_blue.png); + } + + QComboBox QAbstractItemView { + background-color: #173C4C; + color: #BDD1BD; + selection-background-color: #568F7C; + selection-color: white; + border: 1px solid #326D6C; + border-radius: 5px; + } + + /* Поля ввода имени тега */ + QLineEdit { + font-family: 'Arial'; + border-radius: 10px; + background-color: #173C4C; + color: #BDD1BD; + padding: 5px 10px; + border: 1px solid #326D6C; + } + + QLineEdit:hover, + QLineEdit:focus { + border: 1px solid #568F7C; + } + + QLineEdit::placeholder { + color: #7D9CAD; + } + + /* Кнопка OK */ + QPushButton#ok_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: #568F7C; + color: #BDD1BD; + padding: 5px 10px; + font-weight: bold; + width: 30px; + height: 25px; + } + + QPushButton#ok_button:hover { + background-color: #326D6C; + } + + /* Кнопка Отмена */ + QPushButton#cancel_button { + font-family: 'Arial'; + border-radius: 10px; + background-color: #326D6C; + color: #BDD1BD; + padding: 5px 10px; + border: 1px solid #568F7C; + } + + QPushButton#cancel_button:hover { + background-color: #568F7C; + color: #07142B; } )"; -} +} // namespace Ui #endif // TAGS_DIALOG_STYLES_H \ No newline at end of file diff --git a/ui/note-widget/src/note_edit_dialog.cpp b/ui/note-widget/src/note_edit_dialog.cpp index ed18200..28d23a6 100644 --- a/ui/note-widget/src/note_edit_dialog.cpp +++ b/ui/note-widget/src/note_edit_dialog.cpp @@ -1,4 +1,5 @@ #include "note_edit_dialog.h" +#include #include #include #include @@ -6,15 +7,29 @@ #include #include #include -#include +#include #include "./ui_note_edit_dialog.h" +#include "language_manager.h" #include "note_edit_dialog_styles.h" +#include "style_manager.h" #include "tags_dialog.h" -NoteEditDialog::NoteEditDialog(QWidget* parent, Note* note) +const std::vector NoteEditDialog::THEMES = { + Ui::note_edit_dialog_light_autumn_theme, + Ui::note_edit_dialog_dark_autumn_theme, + Ui::note_edit_dialog_dark_purple_theme, + Ui::note_edit_dialog_light_purple_theme, Ui::note_edit_dialog_blue_theme +}; + +NoteEditDialog::NoteEditDialog( + std::string project_name, + QWidget *parent, + Note *note +) : QDialog(parent), ui_(new Ui::NoteEditDialog), - note_(note) { + note_(note), + project_name_(std::move(project_name)) { ui_->setupUi(this); setWindowTitle("EFFICIO"); @@ -22,20 +37,31 @@ NoteEditDialog::NoteEditDialog(QWidget* parent, Note* note) init_additional_fields(); setup_connections(); setup_ui(); + + handle_theme_changed(StyleManager::instance()->current_theme()); + handle_font_size_changed(StyleManager::instance()->current_font_size()); } -NoteEditDialog::~NoteEditDialog() { - delete ui_; +void NoteEditDialog::handle_theme_changed(int theme) { + this->setStyleSheet(THEMES[theme]); } void NoteEditDialog::init_basic_fields() { ui_->titleLineEdit->setText(QString::fromStdString(note_->get_title())); - ui_->descriptionTextEdit->setText(QString::fromStdString(note_->get_text())); + ui_->descriptionTextEdit->setText(QString::fromStdString(note_->get_text()) + ); + ui_->projectNameLabel->setTextFormat(Qt::RichText); +} + +NoteEditDialog::~NoteEditDialog() { + delete ui_; } void NoteEditDialog::init_additional_fields() { if (!note_->get_date().empty()) { - QDate date = QDate::fromString(QString::fromStdString(note_->get_date()), "yyyy-MM-dd"); + QDate date = QDate::fromString( + QString::fromStdString(note_->get_date()), "yyyy-MM-dd" + ); if (date.isValid()) { ui_->dateEdit->setDate(date); ui_->dateLabel->setVisible(true); @@ -45,7 +71,7 @@ void NoteEditDialog::init_additional_fields() { if (!note_->get_members().empty()) { ui_->membersLabel->setVisible(true); - for (const auto& member : note_->get_members()) { + for (const auto &member : note_->get_members()) { add_member_avatar(member); } ui_->joinButton->setText("Покинуть"); @@ -53,7 +79,7 @@ void NoteEditDialog::init_additional_fields() { if (!note_->get_tags().empty()) { ui_->tagsLabel->setVisible(true); - for (const auto& tag : note_->get_tags()) { + for (const auto &tag : note_->get_tags()) { TagsDialog::Tag tag_info; tag_info.is_checked = true; tag_info.color = QString::fromStdString(tag.color); @@ -69,31 +95,169 @@ void NoteEditDialog::init_additional_fields() { } void NoteEditDialog::setup_connections() { - connect(ui_->saveButton, &QPushButton::clicked, this, &NoteEditDialog::on_save_button_click); - connect(ui_->cancelButton, &QPushButton::clicked, this, &NoteEditDialog::reject); - connect(ui_->joinButton, &QPushButton::clicked, this, &NoteEditDialog::on_join_button_click); - connect(ui_->addMembersButton, &QPushButton::clicked, this, &NoteEditDialog::on_add_members_button_click); + connect( + ui_->saveButton, &QPushButton::clicked, this, + &NoteEditDialog::on_save_button_click + ); + connect( + ui_->cancelButton, &QPushButton::clicked, this, &NoteEditDialog::reject + ); + connect( + ui_->joinButton, &QPushButton::clicked, this, + &NoteEditDialog::on_join_button_click + ); + connect( + ui_->addMembersButton, &QPushButton::clicked, this, + &NoteEditDialog::on_add_members_button_click + ); connect(ui_->addDateButton, &QPushButton::clicked, this, [this]() { const bool is_visible = ui_->dateLabel->isVisible(); ui_->dateLabel->setVisible(!is_visible); ui_->dateEdit->setVisible(!is_visible); }); - connect(ui_->addTagsButton, &QPushButton::clicked, this, &NoteEditDialog::on_add_tags_button_click); + connect( + StyleManager::instance(), &StyleManager::theme_changed, this, + &NoteEditDialog::handle_theme_changed + ); + connect( + ui_->addTagsButton, &QPushButton::clicked, this, + &NoteEditDialog::on_add_tags_button_click + ); + connect( + StyleManager::instance(), &StyleManager::font_size_changed, this, + &NoteEditDialog::handle_font_size_changed + ); + connect( + LanguageManager::instance(), &LanguageManager::language_changed, this, + &NoteEditDialog::handle_language_changed + ); + handle_language_changed(LanguageManager::instance()->current_language()); +} + +void NoteEditDialog::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + setWindowTitle("EFFICIO"); + ui_->saveButton->setText("Сохранить"); + ui_->dateLabel->setText("Срок"); + ui_->cancelButton->setText("Отмена"); + ui_->joinButton->setText( + ui_->membersLabel->isVisible() ? "Покинуть" : "Присоединиться" + ); + ui_->addMembersButton->setText("Участники"); + ui_->addDateButton->setText("Дата"); + ui_->addTagsButton->setText("Теги"); + ui_->projectNameLabel->setText( + QString("в проекте: %1") + .arg(QString::fromStdString(project_name_)) + ); + ui_->descriptionLabel->setText("Описание:"); + if (note_->get_title() == "" or note_->get_title() == "Empty note") { + ui_->titleLineEdit->setText("Пустая заметка"); + } + if (note_->get_text() == "" or + note_->get_text() == "Add a detailed description of your note") { + ui_->descriptionTextEdit->setPlaceholderText( + "Добавьте подробное описание вашей заметки" + ); + } + ui_->sidePanelLabel->setText("Добавить к заметке"); + ui_->sidePanelLabel_2->setText("Предложения"); + } else if (new_language == "EN") { + setWindowTitle("EFFICIO"); + ui_->saveButton->setText("Save"); + ui_->dateLabel->setText("Deadline"); + ui_->cancelButton->setText("Cancel"); + ui_->joinButton->setText( + ui_->membersLabel->isVisible() ? "Leave" : "Join" + ); + ui_->addMembersButton->setText("Members"); + ui_->addDateButton->setText("Date"); + ui_->addTagsButton->setText("Tags"); + ui_->projectNameLabel->setText( + QString("in project: %1") + .arg(QString::fromStdString(project_name_)) + ); + ui_->descriptionLabel->setText("Description:"); + if (note_->get_title() == "" or + note_->get_title() == "Пустая заметка") { + ui_->titleLineEdit->setText("Empty note"); + } + + if (note_->get_text() == "" or + note_->get_text() == "Добавьте подробное описание вашей заметки") { + ui_->descriptionTextEdit->setPlaceholderText( + "Add a detailed description of your note" + ); + } + ui_->sidePanelLabel->setText("Add to note"); + ui_->sidePanelLabel_2->setText("Suggestions"); + } +} + +void NoteEditDialog::handle_font_size_changed(std::string font_size_) { + QString current_style = this->styleSheet(); + + QString font_rules; + if (font_size_ == "small") { + font_rules = + "QLineEdit#titleLineEdit { font-size: 20px; }" + "QLabel#projectNameLabel { font-size: 11px; }" + "QLabel#descriptionLabel { font-size: 14px; }" + "QLabel#sidePanelLabel, QLabel#sidePanelLabel_2 { font-size: 12px; " + "}" + "QMessageBox QLabel { font-size: 12px; }" + "QMessageBox QPushButton { font-size: 11px; }"; + } else if (font_size_ == "big") { + font_rules = + "QLineEdit#titleLineEdit { font-size: 30px; }" + "QLabel#projectNameLabel { font-size: 16px; }" + "QLabel#descriptionLabel { font-size: 21px; }" + "QLabel#sidePanelLabel, QLabel#sidePanelLabel_2 { font-size: 17px; " + "}" + "QMessageBox QLabel { font-size: 17px; }" + "QMessageBox QPushButton { font-size: 16px; }"; + } + + this->setStyleSheet( + THEMES[StyleManager::instance()->current_theme()] + font_rules + ); } void NoteEditDialog::setup_ui() { setFixedSize(700, 480); - setStyleSheet(Ui::light_theme); + setStyleSheet(THEMES[StyleManager::instance()->current_theme()]); ui_->buttonsLayout->setAlignment(Qt::AlignLeft); } void NoteEditDialog::on_save_button_click() { if (try_save_note()) { - QMessageBox::information(this, "Заметка сохранена", - QString("Заголовок: %1\nСодержимое: %2") - .arg(ui_->titleLineEdit->text(), ui_->descriptionTextEdit->toPlainText())); + if (LanguageManager::instance()->current_language() == "RU") { + QMessageBox::information( + this, "Заметка сохранена", + QString("Заголовок: %1\nСодержимое: %2") + .arg( + ui_->titleLineEdit->text(), + ui_->descriptionTextEdit->toPlainText() + ) + ); + } else { + QMessageBox::information( + this, "Note Saved", + QString("Title: %1\nDescription: %2") + .arg( + ui_->titleLineEdit->text(), + ui_->descriptionTextEdit->toPlainText() + ) + ); + } } else { - QMessageBox::information(this, "Ошибка", "Не удалось сохранить заметку"); + if (LanguageManager::instance()->current_language() == "RU") { + QMessageBox::information( + this, "Ошибка", "Не удалось сохранить заметку" + ); + } else { + QMessageBox::information(this, "Error", "Failed to save the note"); + } } close(); } @@ -114,7 +278,7 @@ void NoteEditDialog::on_join_button_click() { } } -void NoteEditDialog::add_member_avatar(const std::string& member) { +void NoteEditDialog::add_member_avatar(const std::string &member) { QPixmap pixmap(32, 32); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); @@ -130,14 +294,22 @@ void NoteEditDialog::add_member_avatar(const std::string& member) { } void NoteEditDialog::clear_member_avatars() { - for (auto& avatar : member_avatars_) { + for (auto &avatar : member_avatars_) { ui_->avatarsLayout->removeWidget(avatar.get()); } member_avatars_.clear(); } void NoteEditDialog::on_add_members_button_click() { - QMessageBox::information(this, "Ошибка", "Другие участники не найдены :("); + if (LanguageManager::instance()->current_language() == "RU") { + QMessageBox::information( + this, "Ошибка", "Другие участники не найдены." + ); + } else { + QMessageBox::information( + this, "Error", "No other participants were found." + ); + } } void NoteEditDialog::on_add_tags_button_click() { @@ -149,7 +321,7 @@ void NoteEditDialog::on_add_tags_button_click() { } void NoteEditDialog::update_tags_display() { - for (auto& tag_label : tag_labels_) { + for (auto &tag_label : tag_labels_) { ui_->tagsLayout->removeWidget(tag_label.get()); } tag_labels_.clear(); @@ -165,18 +337,19 @@ void NoteEditDialog::update_tags_display() { } } -QString NoteEditDialog::create_tag_style_sheet(const QString& color) { +QString NoteEditDialog::create_tag_style_sheet(const QString &color) { return QString( - "background-color: %1; " - "color: white; " - "padding: 9px 10px; " - "border-radius: 5px; " - "font-family: 'Arial'; " - "font-size: 12px; " - "font-weight: bold;" - "width: 40px;" - "height: 25px;" - ).arg(color); + "background-color: %1; " + "color: white; " + "padding: 9px 10px; " + "border-radius: 5px; " + "font-family: 'Arial'; " + "font-size: 12px; " + "font-weight: bold;" + "width: 40px;" + "height: 25px;" + ) + .arg(color); } bool NoteEditDialog::try_save_note() const { diff --git a/ui/note-widget/src/tags_dialog.cpp b/ui/note-widget/src/tags_dialog.cpp index 5a3d61e..0459371 100644 --- a/ui/note-widget/src/tags_dialog.cpp +++ b/ui/note-widget/src/tags_dialog.cpp @@ -2,8 +2,16 @@ #include #include #include +#include "language_manager.h" +#include "style_manager.h" #include "tags_dialog_styles.h" +const std::vector TagsDialog::THEMES = { + Ui::tags_dialog_light_autumn_theme, Ui::tags_dialog_dark_autumn_theme, + Ui::tags_dialog_dark_purple_theme, Ui::tags_dialog_light_purple_theme, + Ui::tags_dialog_blue_theme +}; + TagsDialog::TagsDialog(const QList &initial_tags, QWidget *parent) : QDialog(parent) { setup_ui(); @@ -23,7 +31,58 @@ TagsDialog::TagsDialog(const QList &initial_tags, QWidget *parent) setWindowTitle("Добавить теги"); setModal(true); setFixedSize(DIALOG_SIZE.first, DIALOG_SIZE.second); - setStyleSheet(Ui::tags_dialog_light_theme); + handle_theme_changed(StyleManager::instance()->current_theme()); + connect( + LanguageManager::instance(), &LanguageManager::language_changed, this, + &TagsDialog::handle_language_changed + ); + handle_language_changed(LanguageManager::instance()->current_language()); +} + +void TagsDialog::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + setWindowTitle("Добавить теги"); + ok_button_->setText(tr("OK")); + cancel_button_->setText(tr("Отмена")); + + const QStringList colors = { + "Красный", "Синий", "Розовый", "Зеленый", "Желтый" + }; + for (int i = 0; i < MAX_TAGS_COUNT; ++i) { + if (color_combo_boxes_[i]) { + color_combo_boxes_[i]->setItemText(0, colors[0]); + color_combo_boxes_[i]->setItemText(1, colors[1]); + color_combo_boxes_[i]->setItemText(2, colors[2]); + color_combo_boxes_[i]->setItemText(3, colors[3]); + color_combo_boxes_[i]->setItemText(4, colors[4]); + } + if (name_line_edits_[i]) { + name_line_edits_[i]->setPlaceholderText( + "Имя тега " + QString::number(i + 1) + ); + } + } + } else if (new_language == "EN") { + setWindowTitle("Add tags"); + ok_button_->setText(tr("OK")); + cancel_button_->setText(tr("Cancel")); + + const QStringList colors = {"Red", "Blue", "Pink", "Green", "Yellow"}; + for (int i = 0; i < MAX_TAGS_COUNT; ++i) { + if (color_combo_boxes_[i]) { + color_combo_boxes_[i]->setItemText(0, colors[0]); + color_combo_boxes_[i]->setItemText(1, colors[1]); + color_combo_boxes_[i]->setItemText(2, colors[2]); + color_combo_boxes_[i]->setItemText(3, colors[3]); + color_combo_boxes_[i]->setItemText(4, colors[4]); + } + if (name_line_edits_[i]) { + name_line_edits_[i]->setPlaceholderText( + "Tag name " + QString::number(i + 1) + ); + } + } + } } void TagsDialog::setup_ui() { @@ -69,6 +128,14 @@ void TagsDialog::setup_ui() { connect( cancel_button_.get(), &QPushButton::clicked, this, &TagsDialog::reject ); + connect( + StyleManager::instance(), &StyleManager::theme_changed, this, + &TagsDialog::handle_theme_changed + ); +} + +void TagsDialog::handle_theme_changed(int theme) { + this->setStyleSheet(THEMES[theme]); } QList TagsDialog::get_selected_tags() const { diff --git a/ui/note-widget/ui/note_edit_dialog.ui b/ui/note-widget/ui/note_edit_dialog.ui index 60eebd8..a0e0cbd 100644 --- a/ui/note-widget/ui/note_edit_dialog.ui +++ b/ui/note-widget/ui/note_edit_dialog.ui @@ -45,7 +45,6 @@ Arial 10 false - true @@ -366,4 +365,4 @@ - \ No newline at end of file + diff --git a/ui/profile-window/CMakeLists.txt b/ui/profile-window/CMakeLists.txt new file mode 100644 index 0000000..2e19e88 --- /dev/null +++ b/ui/profile-window/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.16) + +project(ProfileWindow LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 COMPONENTS Widgets Core Gui Sql REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(SOURCES + src/profile_window.cpp +) + +set(HEADERS + include/profile_window.h + include/profile_window_style_sheet.h +) + +add_library(ProfileWindow STATIC ${SOURCES} ${HEADERS} ${UI_FILES}) + +target_include_directories(ProfileWindow + PUBLIC + $ + $ +) + +target_link_libraries(ProfileWindow PRIVATE + Qt6::Widgets + Qt6::Core + Qt6::Gui + Qt6::Sql + Database + StyleManager + LanguageManager + AuthorizationWindows + SettingsWindow + AnalyticsWindow +) \ No newline at end of file diff --git a/ui/profile-window/include/profile_window.h b/ui/profile-window/include/profile_window.h new file mode 100644 index 0000000..28f1fee --- /dev/null +++ b/ui/profile-window/include/profile_window.h @@ -0,0 +1,49 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "style_manager.h" +#include + +QT_BEGIN_NAMESPACE +namespace Ui { + +class ProfileWindow : public QDialog { + Q_OBJECT + + QVBoxLayout* main_layout; + QPushButton* logout_button; + QPushButton* delete_button; + QPushButton* stats_button; + QPushButton* settings_button; + QString current_username; + + void setup_ui(QDialog* profile_window); + void switch_window(QWidget *new_window); + +public: + explicit ProfileWindow(const QString& username, QWidget* parent = nullptr); + ~ProfileWindow() = default; + + static const std::vector THEMES; + void handle_theme_changed(int theme); + void handle_font_size_changed(std::string font_size); + void handle_language_changed(std::string new_language); + friend class MainWindow; + +signals: + void logout_requested(); + void delete_account_requested(); + +private slots: + void on_logout_clicked(); + void on_delete_account_clicked(); + void on_stats_clicked(); + void on_settings_clicked(); +}; + +} // namespace Ui +QT_END_NAMESPACE \ No newline at end of file diff --git a/ui/profile-window/include/profile_window_style_sheet.h b/ui/profile-window/include/profile_window_style_sheet.h new file mode 100644 index 0000000..50df3f1 --- /dev/null +++ b/ui/profile-window/include/profile_window_style_sheet.h @@ -0,0 +1,393 @@ +#ifndef PROFILE_WINDOW_STYLE_HPP +#define PROFILE_WINDOW_STYLE_HPP + +#include + +namespace Ui { + +QString profile_window_light_autumn_theme = R"( + QDialog { + background-color: #f5f5f5; + } + + QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + padding: 5px 10px; + width: 60px; + height: 25px; + } + + QPushButton#logout_button { + background-color: #fea36b; + color: white; + } + + QPushButton#logout_button:hover { + background-color:rgb(245, 148, 89); + } + + QPushButton#logout_button:pressed { + background-color:rgb(238, 122, 50); + } + + QPushButton#delete_button { + background-color: #fea36b; + color: white; + } + + QPushButton#delete_button:hover { + background-color:rgb(245, 148, 89); + } + + QPushButton#delete_button:pressed { + background-color:rgb(238, 122, 50); + } + + QPushButton#stats_button { + background-color: #089083; + color: #f5f5f5; + border: none; + padding: 10px; + margin: 2px; + } + + QPushButton#stats_button:hover { + background-color:rgb(8, 82, 74); + } + + QPushButton#stats_button:pressed { + background-color:rgb(3, 58, 54); + } + + QPushButton#settings_button { + background-color: rgb(33, 44, 50); + color: #f5f5f5; + padding: 2px; + font-size: 35px; + border-radius: 15px; + width: 30px; + height: 30px; + } + + QPushButton#settings_button:hover { + background-color: rgb(14, 17, 19); + } + + QPushButton#settings_button:pressed { + background-color: rgb(4, 4, 5); + } +)"; + +QString profile_window_dark_autumn_theme = R"( + QDialog { + background-color:rgb(43, 43, 43); + } + + QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + padding: 5px 10px; + width: 60px; + height: 25px; + } + + QPushButton#logout_button { + background-color:rgb(211, 139, 95); + color: #263238; + } + + QPushButton#logout_button:hover { + background-color:rgb(181, 114, 59); + } + + QPushButton#logout_button:pressed { + background-color:rgb(158, 94, 45); + } + + QPushButton#delete_button { + background-color:rgb(211, 139, 95); + color: #263238; + } + + QPushButton#delete_button:hover { + background-color:rgb(181, 114, 59); + } + + QPushButton#delete_button:pressed { + background-color:rgb(158, 94, 45); + } + + QPushButton#stats_button { + background-color: #089083; + color: #f5f5f5; + border: none; + padding: 10px; + margin: 2px; + } + + QPushButton#stats_button:hover { + background-color:rgb(12, 114, 104); + } + + QPushButton#stats_button:pressed { + background-color:rgb(14, 101, 92); + } + + QPushButton#settings_button { + background-color:rgb(0, 0, 0); + color: #f5f5f5; + padding: 2px; + font-size: 35px; + border-radius: 15px; + width: 30px; + height: 30px; + } + + QPushButton#settings_button:hover { + background-color:rgb(54, 54, 54); + } + + QPushButton#settings_button:pressed { + background-color: rgb(99, 99, 99); + } +)"; + +QString profile_window_light_purple_theme = R"( + QDialog { + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 #9882B9, stop:0.5 rgb(176, 157, 205), stop:1 rgb(103, 88, 126)); + } + + QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + padding: 5px 10px; + width: 60px; + height: 25px; + } + + QPushButton#logout_button { + background-color: #722548; + color: #9882B9; + } + + QPushButton#logout_button:hover { + background-color:rgb(82, 27, 51); + } + + QPushButton#logout_button:pressed { + background-color:rgb(64, 21, 40); + } + + QPushButton#delete_button { + background-color: #722548; + color: #9882B9; + } + + QPushButton#delete_button:hover { + background-color:rgb(84, 27, 53); + } + + QPushButton#delete_button:pressed { + background-color:rgb(64, 21, 40); + } + + QPushButton#stats_button { + background-color: rgb(42, 10, 25); + color: rgb(163, 148, 184); + border: none; + padding: 10px; + margin: 2px; + } + + QPushButton#stats_button:hover { + background-color: rgb(42, 10, 25); + } + + QPushButton#stats_button:pressed { + background-color:rgb(42, 10, 25); + } + + QPushButton#settings_button { + background-color: rgb(221, 210, 238); + color: rgb(42, 10, 25); + padding: 2px; + font-size: 35px; + border-radius: 15px; + width: 30px; + height: 30px; + } + + QPushButton#settings_button:hover { + background-color: rgb(177, 166, 194); + } + + QPushButton#settings_button:pressed { + background-color: rgb(152, 140, 170); + } +)"; + +QString profile_window_dark_purple_theme = R"( + QDialog { + background-color: rgb(9, 6, 10); + } + + QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + padding: 5px 10px; + width: 60px; + height: 25px; + } + + QPushButton#logout_button { + background-color: #722548; + color: #060407; + } + + QPushButton#logout_button:hover { + background-color: rgb(79, 25, 50); + } + + QPushButton#logout_button:pressed { + background-color:rgb(59, 16, 35); + } + + QPushButton#delete_button { + background-color: #722548; + color: #060407; + } + + QPushButton#delete_button:hover { + background-color:rgb(79, 25, 50); + } + + QPushButton#delete_button:pressed { + background-color:rgb(59, 16, 35); + } + + QPushButton#stats_button { + background-color: rgb(42, 10, 25); + color: #9882B9; + border: none; + padding: 10px; + margin: 2px; + } + + QPushButton#stats_button:hover { + background-color:rgb(22, 5, 13); + } + + QPushButton#stats_button:pressed { + background-color:rgb(11, 3, 7); + } + + QPushButton#settings_button { + background-color: #221932; + color: #9882B9; + padding: 2px; + font-size: 35px; + border-radius: 15px; + width: 30px; + height: 30px; + } + + QPushButton#settings_button:hover { + background-color:rgb(21, 16, 31); + } + + QPushButton#settings_button:pressed { + background-color:rgb(4, 3, 5); + } +)"; + +QString profile_window_blue_theme = R"( + QDialog { + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 #173C4C, stop:0.5 #326D6C, stop:1 #07142B); + } + + QPushButton { + font-family: 'Arial'; + font-size: 13px; + font-weight: bold; + border-radius: 10px; + padding: 5px 10px; + width: 60px; + height: 25px; + border: none; + } + + QPushButton#logout_button { + background-color: #BDD1BD; + color: #173C4C; + } + + QPushButton#logout_button:hover { + background-color:rgb(158, 176, 158); + } + + QPushButton#logout_button:pressed { + background-color:rgb(141, 157, 141); + } + + QPushButton#delete_button { + background-color: #BDD1BD; + color: #173C4C; + } + + QPushButton#delete_button:hover { + background-color:rgb(158, 176, 158); + } + + QPushButton#delete_button:pressed { + background-color:rgb(141, 157, 141); + } + + QPushButton#stats_button { + background-color: #326D6C; + color: #BDD1BD; + border: none; + padding: 10px; + margin: 2px; + } + + QPushButton#stats_button:hover { + background-color:rgb(47, 89, 89); + } + + QPushButton#stats_button:pressed { + background-color:rgb(31, 69, 85); + } + + QPushButton#settings_button { + background-color: #07142B; + color: #BDD1BD; + padding: 2px; + font-size: 35px; + border-radius: 15px; + width: 30px; + height: 30px; + } + + QPushButton#settings_button:hover { + background-color:rgb(4, 12, 26); + } + + QPushButton#settings_button:pressed { + background-color:rgb(2, 3, 5); + } +)"; + +} // namespace Ui + +#endif // PROFILE_WINDOW_STYLE_HPP \ No newline at end of file diff --git a/ui/profile-window/src/profile_window.cpp b/ui/profile-window/src/profile_window.cpp new file mode 100644 index 0000000..20872d6 --- /dev/null +++ b/ui/profile-window/src/profile_window.cpp @@ -0,0 +1,158 @@ +#include "profile_window.h" +#include "profile_window_style_sheet.h" +#include +#include "database_manager.hpp" +#include "lr_dao.hpp" +#include "settings_window.h" +#include "analytics_window.h" +#include "language_manager.h" + +namespace Ui { + +const std::vector ProfileWindow::THEMES = { + profile_window_light_autumn_theme, + profile_window_dark_autumn_theme, + profile_window_dark_purple_theme, + profile_window_light_purple_theme, + profile_window_blue_theme +}; + +ProfileWindow::ProfileWindow(const QString& username, QWidget* parent) + : QDialog(parent), current_username(username) { + main_layout = new QVBoxLayout(this); + + logout_button = new QPushButton(tr("Выйти из аккаунта"), this); + logout_button->setObjectName("logout_button"); + main_layout->addWidget(logout_button); + + delete_button = new QPushButton(tr("Удалить аккаунт"), this); + delete_button->setObjectName("delete_button"); + main_layout->addWidget(delete_button); + + QHBoxLayout* bottom_layout = new QHBoxLayout(); + + stats_button = new QPushButton(tr("Моя статистика"), this); + stats_button->setObjectName("stats_button"); + bottom_layout->addWidget(stats_button); + + settings_button = new QPushButton("⚙", this); + settings_button->setObjectName("settings_button"); + settings_button->setFixedSize(45, 45); + bottom_layout->addWidget(settings_button); + + setWindowTitle(tr("Профиль")); + + main_layout->addLayout(bottom_layout); + setFixedSize(250, 160); + + connect( + logout_button, &QPushButton::clicked, + this, &Ui::ProfileWindow::on_logout_clicked + ); + connect( + delete_button, &QPushButton::clicked, + this, &Ui::ProfileWindow::on_delete_account_clicked + ); + connect( + stats_button, &QPushButton::clicked, + this, &Ui::ProfileWindow::on_stats_clicked + ); + connect(settings_button, &QPushButton::clicked, + this, &Ui::ProfileWindow::on_settings_clicked + ); + connect(StyleManager::instance(), &StyleManager::theme_changed, + this, &Ui::ProfileWindow::handle_theme_changed + ); + handle_theme_changed(StyleManager::instance()->current_theme()); + connect(StyleManager::instance(), &StyleManager::font_size_changed, + this, &Ui::ProfileWindow::handle_font_size_changed + ); + handle_font_size_changed(StyleManager::instance()->current_font_size()); +} + +void ProfileWindow::handle_font_size_changed(std::string font_size) { + + QString font_rule; + if(font_size == "small") { + font_rule = "QPushButton { font-size: 11px; }"; + } + else if(font_size == "medium") { + font_rule = "QPushButton { font-size: 13px; }"; + } + else if(font_size == "big") { + font_rule = "QPushButton { font-size: 15px; }"; + } + + this->setStyleSheet(THEMES[StyleManager::instance()->current_theme()] + font_rule); + connect(LanguageManager::instance(), &LanguageManager::language_changed, + this, &ProfileWindow::handle_language_changed + ); + handle_language_changed(LanguageManager::instance()->current_language()); +} + + +void ProfileWindow::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + setWindowTitle(tr("Профиль")); + logout_button->setText(tr("Выйти из аккаунта")); + delete_button->setText(tr("Удалить аккаунт")); + stats_button->setText(tr("Моя статистика")); + } + else if (new_language == "EN") { + setWindowTitle(tr("Profile")); + logout_button->setText(tr("Log out")); + delete_button->setText(tr("Delete account")); + stats_button->setText(tr("My statistics")); + } +} + + + +void ProfileWindow::handle_theme_changed(int theme) { + setStyleSheet(THEMES[theme]); +} + +void ProfileWindow::on_logout_clicked() { + emit logout_requested(); + this->deleteLater(); +} + +void ProfileWindow::on_delete_account_clicked() { + QMessageBox::StandardButton reply = QMessageBox::question( + this, + tr("Удаление аккаунта"), + tr("Вы уверены, что хотите удалить аккаунт? Все данные будут потеряны!"), + QMessageBox::Yes | QMessageBox::No + ); + + if (reply == QMessageBox::Yes && LRDao::try_delete_user(current_username)) { + QMessageBox::information(this, tr("Успех"), tr("Аккаунт успешно удалён")); + emit delete_account_requested(); + this->deleteLater(); + } else if (reply == QMessageBox::Yes) { + QMessageBox::critical(this, tr("Ошибка"), tr("Не удалось удалить аккаунт")); + } +} + +void ProfileWindow::on_stats_clicked() { + AnalyticsWindow *new_analytics_window = new AnalyticsWindow(this->parentWidget()); + this->switch_window(new_analytics_window); +} + +void ProfileWindow::on_settings_clicked() { + SettingsWindow *new_settings_window = new SettingsWindow(this->parentWidget()); + this->switch_window(new_settings_window); +} + + +void ProfileWindow::switch_window(QWidget *new_window) { + this->setEnabled(false); + new_window->setAttribute(Qt::WA_DeleteOnClose); + connect(new_window, &AnalyticsWindow::destroyed, + this, [this]() { this->setEnabled(true); }); + new_window->show(); + new_window->raise(); + new_window->activateWindow(); +} + +} // namespace Ui \ No newline at end of file diff --git a/ui/settings-window/CMakeLists.txt b/ui/settings-window/CMakeLists.txt new file mode 100644 index 0000000..ec37601 --- /dev/null +++ b/ui/settings-window/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.16) + +project(SettingsWindow LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 COMPONENTS Widgets Core Gui Sql REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + +set(SOURCES + src/settings_window.cpp +) + +set(HEADERS + include/settings_window.h + include/settings_window_style_sheet.h +) + +add_library(SettingsWindow STATIC ${SOURCES} ${HEADERS} ${UI_FILES}) + +target_include_directories(SettingsWindow + PUBLIC + $ + $ +) + +target_link_libraries(SettingsWindow PRIVATE + Qt6::Widgets + Qt6::Core + Qt6::Gui + Qt6::Sql + Database + StyleManager + LanguageManager + AuthorizationWindows +) \ No newline at end of file diff --git a/ui/settings-window/include/settings_window.h b/ui/settings-window/include/settings_window.h new file mode 100644 index 0000000..d64a358 --- /dev/null +++ b/ui/settings-window/include/settings_window.h @@ -0,0 +1,43 @@ +#ifndef SETTINGS_WINDOW_H +#define SETTINGS_WINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include + +class SettingsWindow : public QDialog { + Q_OBJECT + +public: + explicit SettingsWindow(QWidget *parent = nullptr); + void handle_theme_changed(int theme_); + void handle_font_size_changed(std::string font_size_); + void handle_language_changed(std::string new_language); + static const std::vector THEMES; + +private slots: + void toggle_language(); + void toggle_theme(); + void set_small_font(); + void set_medium_font(); + void set_big_font(); + +private: + void update_ui_text(); + + QVBoxLayout* main_layout; + QPushButton *language_button; + QPushButton *theme_button; + QLabel *title_label; + QLabel *font_size_label; + QRadioButton *small_font_radio; + QRadioButton *medium_font_radio; + QRadioButton *large_font_radio; +}; + +#endif // SETTINGS_WINDOW_H \ No newline at end of file diff --git a/ui/settings-window/include/settings_window_style_sheet.h b/ui/settings-window/include/settings_window_style_sheet.h new file mode 100644 index 0000000..be57728 --- /dev/null +++ b/ui/settings-window/include/settings_window_style_sheet.h @@ -0,0 +1,385 @@ +#pragma once + +#include + +namespace Ui { + QString settings_window_light_autumn_theme = R"( + QWidget { + background-color: white; + } + + QLabel { + font-weight: bold; + font-family: 'Arial'; + color: #089083; + background-color: transparent; + } + + QLabel#title_label { + font-size: 28px; + } + + QLabel#font_size_label { + font-size: 35px; + } + + QPushButton#theme_button { + background-color: #fea36b; + width: 50px; + height: 30px; + color: #f5f5f5; + padding: 2px; + font-size: 15px; + border-radius: 7px; + } + + QPushButton#theme_button:hover { + background-color:rgb(245, 148, 89); + } + QPushButton#theme_button:pressed { + background-color:rgb(238, 122, 50); + } + + QPushButton#language_button { + background-color: #089083; + width: 50px; + height: 30px; + color: #f5f5f5; + padding: 2px; + font-size: 20px; + border-radius: 7px; + } + QPushButton#language_button:hover { + background-color: rgb(8, 82, 74); + color: #f5f5f5; + } + + QPushButton::pressed#language_button { + background-color:rgb(3, 58, 54); + color: #f5f5f5; + } + + QRadioButton { + font-family: 'Arial'; + color: #727272; + spacing: 5px; + background-color: transparent; + } + QRadioButton::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid #727272; + background-color: transparent; + } + QRadioButton::indicator:hover { + background-color: #727272; + } + QRadioButton::indicator:checked { + background-color: rgb(33, 44, 50); + } + )"; + + QString settings_window_dark_autumn_theme = R"( + QWidget { + background-color: #202020; + } + + QLabel { + font-weight: bold; + font-family: 'Arial'; + color: #089083; + background-color: transparent; + } + + QLabel#title_label { + font-size: 28px; + } + + QLabel#font_size_label { + font-size: 35px; + } + + QPushButton#language_button { + background-color: #fea36b; + width: 50px; + height: 30px; + color: #263238; + padding: 2px; + font-size: 20px; + border-radius: 7px; + } + + QPushButton#language_button:hover { + background-color: #d58745; + } + QPushButton#language_button:pressed { + background-color: #b87338; + } + + QPushButton#theme_button { + background-color: #089083; + color: #f5f5f5; + width: 50px; + height: 30px; + padding: 2px; + font-size: 15px; + border-radius: 7px; + } + QPushButton#theme_button:hover { + background-color:rgb(8, 82, 74); + } + + QPushButton::pressed#switch_theme { + background-color: #089083; + } + + QRadioButton { + font-family: 'Arial'; + color: #727272; + spacing: 5px; + background-color: transparent; + } + QRadioButton::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid #727272; + background-color: transparent; + } + QRadioButton::indicator:hover { + background-color: #727272; + } + QRadioButton::indicator:checked { + background-color:rgb(0, 0, 0); + } + )"; + + QString settings_window_light_purple_theme = R"( + QWidget { + background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, + stop:0 #9882B9, stop:0.5 rgb(176, 157, 205), stop:1 rgb(125, 109, 148)); + } + + QLabel { + font-weight: bold; + font-family: 'Arial'; + color: rgb(42, 10, 25); + background-color: transparent; + } + + QLabel#title_label { + font-size: 28px; + } + + QLabel#font_size_label { + font-size: 35px; + } + + QPushButton#language_button { + background-color: #722548; + width: 50px; + height: 30px; + color: rgb(206, 193, 224); + padding: 2px; + font-size: 20px; + border-radius: 7px; + } + + QPushButton#language_button:hover { + background-color: rgb(98, 27, 59); + } + QPushButton#language_button:pressed { + background-color: rgb(78, 21, 47); + } + + QPushButton#theme_button { + background-color: rgb(42, 10, 25); + color: rgb(163, 148, 184); + width: 50px; + height: 30px; + padding: 2px; + font-size: 15px; + border-radius: 7px; + } + QPushButton#theme_button:hover { + background-color: rgb(21, 5, 12); + } + + QPushButton#theme_button:pressed{ + background-color: rgb(2, 0, 1); + } + + QRadioButton { + font-family: 'Arial'; + color: rgb(42, 10, 25); + spacing: 5px; + background-color: transparent; + } + QRadioButton::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid rgb(42, 10, 25); + background-color: transparent; + } + QRadioButton::indicator:hover { + background-color: rgb(42, 10, 25); + } + QRadioButton::indicator:checked { + background-color: rgb(218, 207, 235); + } + )"; + + QString settings_window_dark_purple_theme = R"( + QWidget { + background-color: rgb(9, 6, 10); + } + + QLabel { + font-weight: bold; + font-family: 'Arial'; + color: #9882B9; + background-color: transparent; + } + + QLabel#title_label { + font-size: 28px; + } + + QLabel#font_size_label { + font-size: 35px; + } + + QPushButton#language_button { + background-color: #722548; + color: #060407; + width: 50px; + height: 30px; + padding: 2px; + font-size: 20px; + border-radius: 7px; + } + + QPushButton#language_button:hover { + background-color: rgb(79, 25, 50); + } + QPushButton#language_button:pressed { + background-color:rgb(59, 16, 35); + } + + QPushButton#theme_button { + background-color: rgb(42, 10, 25); + color: #9882B9; + width: 50px; + height: 30px; + padding: 2px; + font-size: 15px; + border-radius: 7px; + } + QPushButton#theme_button:hover { + background-color:rgb(22, 5, 13); + } + + QPushButton#theme_button:pressed { + background-color:rgb(11, 3, 7); + } + + QRadioButton { + font-family: 'Arial'; + color: #9882B9; + spacing: 5px; + background-color: transparent; + } + QRadioButton::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid #9882B9; + background-color: transparent; + } + QRadioButton::indicator:hover { + background-color: #221932; + } + QRadioButton::indicator:checked { + background-color: #9882B9; + } + )"; + + QString settings_window_blue_theme = R"( + QWidget { + background: #173C4C; + } + + QLabel { + font-weight: bold; + font-family: 'Arial'; + color: #BDD1BD; + background-color: transparent; + } + + QLabel#title_label { + font-size: 28px; + } + + QLabel#font_size_label { + font-size: 35px; + } + + QPushButton#language_button { + background-color: #BDD1BD; + color: #173C4C; + width: 50px; + height: 30px; + padding: 2px; + font-size: 20px; + border-radius: 7px; + } + + QPushButton#language_button:hover { + background-color:rgb(158, 176, 158); + } + QPushButton#language_button:pressed { + background-color:rgb(141, 157, 141); + } + + QPushButton#theme_button { + background-color: #326D6C; + color: #BDD1BD; + width: 50px; + height: 30px; + color: #BDD1BD; + padding: 2px; + font-size: 15px; + border-radius: 7px; + } + QPushButton#theme_button:hover { + background-color:rgb(47, 89, 89); + } + + QPushButton#theme_button:pressed { + background-color:rgb(31, 69, 85); + } + + QRadioButton { + font-family: 'Arial'; + color: #BDD1BD; + spacing: 5px; + background-color: transparent; + } + QRadioButton::indicator { + width: 16px; + height: 16px; + border-radius: 3px; + border: 1px solid #BDD1BD; + background-color: transparent; + } + QRadioButton::indicator:hover { + background-color: #BDD1BD; + } + QRadioButton::indicator:checked { + background-color: #07142B; + } + )"; + +} // namespace Ui \ No newline at end of file diff --git a/ui/settings-window/src/settings_window.cpp b/ui/settings-window/src/settings_window.cpp new file mode 100644 index 0000000..d39c939 --- /dev/null +++ b/ui/settings-window/src/settings_window.cpp @@ -0,0 +1,162 @@ +#include "settings_window.h" +#include "settings_window_style_sheet.h" +#include "style_manager.h" +#include "language_manager.h" +#include + +const std::vector SettingsWindow::THEMES = { + Ui::settings_window_light_autumn_theme, + Ui::settings_window_dark_autumn_theme, + Ui::settings_window_dark_purple_theme, + Ui::settings_window_light_purple_theme, + Ui::settings_window_blue_theme +}; + +SettingsWindow::SettingsWindow(QWidget *parent) : QDialog(parent) { + main_layout = new QVBoxLayout(this); + + title_label = new QLabel(tr("Настройки"), this); + title_label->setObjectName("title_label"); + title_label->setAlignment(Qt::AlignCenter); + main_layout->addWidget(title_label); + + QHBoxLayout *buttons_layout = new QHBoxLayout(); + + language_button = new QPushButton(tr("RU"), this); + language_button->setObjectName("language_button"); + + theme_button = new QPushButton(tr("Тема"), this); + theme_button->setObjectName("theme_button"); + + buttons_layout->addWidget(language_button); + buttons_layout->addWidget(theme_button); + main_layout->addLayout(buttons_layout); + + font_size_label = new QLabel(tr("Размер шрифта"), this); + main_layout->addWidget(font_size_label); + + QButtonGroup *font_group = new QButtonGroup(this); + small_font_radio = new QRadioButton(tr("Мелкий"), this); + medium_font_radio = new QRadioButton(tr("Средний"), this); + large_font_radio = new QRadioButton(tr("Крупный"), this); + + font_group->addButton(small_font_radio); + font_group->addButton(medium_font_radio); + font_group->addButton(large_font_radio); + medium_font_radio->setChecked(true); + + QVBoxLayout *font_layout = new QVBoxLayout(); + font_layout->addWidget(small_font_radio); + font_layout->addWidget(medium_font_radio); + font_layout->addWidget(large_font_radio); + main_layout->addLayout(font_layout); + + connect(language_button, &QPushButton::clicked, this, &SettingsWindow::toggle_language); + connect(theme_button, &QPushButton::clicked, this, &SettingsWindow::toggle_theme); + connect(small_font_radio, &QRadioButton::clicked, this, &SettingsWindow::set_small_font); + connect(medium_font_radio, &QRadioButton::clicked, this, &SettingsWindow::set_medium_font); + connect(large_font_radio, &QRadioButton::clicked, this, &SettingsWindow::set_big_font); + connect(StyleManager::instance(), &StyleManager::theme_changed, + this, &SettingsWindow::handle_theme_changed); + connect(StyleManager::instance(), &StyleManager::font_size_changed, + this, &SettingsWindow::handle_font_size_changed + ); + title_label->setText(tr("Настройки")); + font_size_label->setText(tr("Размер шрифта")); + theme_button->setText(tr("Тема")); + small_font_radio->setText(tr("Мелкий")); + medium_font_radio->setText(tr("Средний")); + large_font_radio->setText(tr("Крупный")); + + language_button->setText(tr("RU")); + setWindowTitle(tr("Настройки")); + + setLayout(main_layout); + setFixedSize(250, 250); + handle_theme_changed(StyleManager::instance()->current_theme()); + + handle_font_size_changed(StyleManager::instance()->current_font_size()); + connect(LanguageManager::instance(), &LanguageManager::language_changed, + this, &SettingsWindow::handle_language_changed + ); + handle_language_changed(LanguageManager::instance()->current_language()); +} + +void SettingsWindow::handle_language_changed(std::string new_language) { + if (new_language == "RU") { + setWindowTitle(tr("Настройки")); + title_label->setText(tr("Настройки")); + font_size_label->setText(tr("Размер шрифта")); + theme_button->setText(tr("Тема")); + small_font_radio->setText(tr("Мелкий")); + medium_font_radio->setText(tr("Средний")); + large_font_radio->setText(tr("Крупный")); + language_button->setText("RU"); + } + else if (new_language == "EN") { + setWindowTitle(tr("Settings")); + title_label->setText(tr("Settings")); + font_size_label->setText(tr("Font size")); + theme_button->setText(tr("Theme")); + small_font_radio->setText(tr("Small")); + medium_font_radio->setText(tr("Medium")); + large_font_radio->setText(tr("Large")); + language_button->setText("EN"); + } +} + + +void SettingsWindow::handle_font_size_changed(std::string font_size) { + QString font_rule; + if(font_size == "small") { + font_rule = + "QPushButton#language_button, QPushButton#theme_button { font-size: 12px; }" + "QWidget { font-size: 12px; }" + "QLabel#title_label { font-size: 23px; }" + "QLabel#font_size_label { font-size: 30px; }"; + } + else if(font_size == "medium") { + font_rule = + "QPushButton#language_button, QPushButton#theme_button { font-size: 15px; }" + "QWidget { font-size: 15px; }" + "QLabel#title_label { font-size: 28px; }" + "QLabel#font_size_label { font-size: 35px; }"; + } + else if(font_size == "big") { + font_rule = + "QPushButton#language_button, QPushButton#theme_button { font-size: 18px; }" + "QWidget { font-size: 18px; }" + "QLabel#title_label { font-size: 32px; }" + "QLabel#font_size_label { font-size: 40px; }"; + } + this->setStyleSheet(THEMES[StyleManager::instance()->current_theme()] + font_rule); +} + +void SettingsWindow::handle_theme_changed(int theme_) { + this->setStyleSheet(THEMES[theme_]); +} + +void SettingsWindow::toggle_language() { + if (language_button->text() == tr("RU")) { + language_button->setText(tr("EN")); + LanguageManager::instance()->apply_language("EN"); + } else { + language_button->setText(tr("RU")); + LanguageManager::instance()->apply_language("RU"); + } +} + +void SettingsWindow::toggle_theme() { + int next_theme = (StyleManager::instance()->current_theme() + 1) % 5; + StyleManager::instance()->apply_theme(next_theme); +} + +void SettingsWindow::set_small_font() { + StyleManager::instance()->apply_font_size("small"); + } +void SettingsWindow::set_medium_font() { + StyleManager::instance()->apply_font_size("medium"); + } +void SettingsWindow::set_big_font() { + StyleManager::instance()->apply_font_size("big"); + } \ No newline at end of file diff --git a/ui/style-manager/CMakeLists.txt b/ui/style-manager/CMakeLists.txt new file mode 100644 index 0000000..1706ec9 --- /dev/null +++ b/ui/style-manager/CMakeLists.txt @@ -0,0 +1,32 @@ +cmake_minimum_required(VERSION 3.16) + +project(StyleManager LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +find_package(Qt6 COMPONENTS Core Gui Widgets Core Gui Sql REQUIRED) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTOUIC ON) +set(CMAKE_AUTORCC ON) + + +set(SOURCES + src/style_manager.cpp +) + +set(HEADERS + include/style_manager.h +) + +add_library(StyleManager STATIC ${SOURCES} ${HEADERS}) + +target_include_directories(StyleManager + PUBLIC + $ + $ +) + +target_link_libraries(StyleManager PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui Qt6::Sql Database Scripts) + diff --git a/ui/style-manager/include/style_manager.h b/ui/style-manager/include/style_manager.h new file mode 100644 index 0000000..a34ce77 --- /dev/null +++ b/ui/style-manager/include/style_manager.h @@ -0,0 +1,32 @@ +#ifndef STYLE_MANAGER_H +#define STYLE_MANAGER_H + +#include +#include +#include +#include +#include +#include + +class StyleManager : public QObject { + Q_OBJECT + +public: + static StyleManager* instance(); + + void apply_theme(int theme); + void apply_font_size(std::string font_size_); + int current_theme() const; + std::string current_font_size() const; +signals: + void theme_changed(int new_theme); + void font_size_changed(std::string new_font_size_); + +private: + explicit StyleManager(QObject *parent = nullptr); + static StyleManager* m_instance; + int current_theme_; + std::string current_font_size_; +}; + +#endif // style_manager_H \ No newline at end of file diff --git a/ui/style-manager/src/style_manager.cpp b/ui/style-manager/src/style_manager.cpp new file mode 100644 index 0000000..8cf6c93 --- /dev/null +++ b/ui/style-manager/src/style_manager.cpp @@ -0,0 +1,37 @@ +#include "style_manager.h" +#include +#include +#include + +StyleManager* StyleManager::m_instance = nullptr; + +StyleManager::StyleManager(QObject *parent) + : QObject(parent) { + current_theme_ = 0; + emit theme_changed(this->current_theme_); +} + +StyleManager* StyleManager::instance() { + if (!m_instance) { + m_instance = new StyleManager(); + } + return m_instance; +} + +void StyleManager::apply_theme(int theme) { + this->current_theme_ = theme; + emit theme_changed(this->current_theme_); +} + +int StyleManager::current_theme() const { + return current_theme_; +} + +void StyleManager::apply_font_size(std::string font_size_) { + current_font_size_ = font_size_; + emit font_size_changed(current_font_size_); +} + +std::string StyleManager::current_font_size() const { + return current_font_size_; +} \ No newline at end of file