diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 5ab7ea9..42a9577 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -33,7 +33,7 @@ jobs:
- name: qmake and nmake
run: |
- echo $(git rev-parse --short "$GITHUB_SHA") > text\\REVISION.txt
+ echo $(git rev-parse --short "${{github.sha}}") > text\\REVISION.txt
type text\\REVISION.txt
qmake theoreticaldiary.pro CONFIG+=release
set CL=/MP
diff --git a/images/readme/editor.png b/images/readme/editor.png
index 791e0f3..0ec5176 100644
Binary files a/images/readme/editor.png and b/images/readme/editor.png differ
diff --git a/images/readme/entry_list.png b/images/readme/entry_list.png
index 0b692e9..4a77981 100644
Binary files a/images/readme/entry_list.png and b/images/readme/entry_list.png differ
diff --git a/images/readme/main_menu.png b/images/readme/main_menu.png
index da51507..1f59495 100644
Binary files a/images/readme/main_menu.png and b/images/readme/main_menu.png differ
diff --git a/images/readme/pixels.png b/images/readme/pixels.png
index e0863c6..db7636b 100644
Binary files a/images/readme/pixels.png and b/images/readme/pixels.png differ
diff --git a/images/readme/settings.png b/images/readme/settings.png
index 220f391..4cb8af7 100644
Binary files a/images/readme/settings.png and b/images/readme/settings.png differ
diff --git a/images/readme/statistics.png b/images/readme/statistics.png
index 19fe523..5f65456 100644
Binary files a/images/readme/statistics.png and b/images/readme/statistics.png differ
diff --git a/images/themes/dark/eye_off.svg b/images/themes/dark/eye_off.svg
index 74f33ec..396cb2a 100644
--- a/images/themes/dark/eye_off.svg
+++ b/images/themes/dark/eye_off.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/images/themes/dark/eye_on.svg b/images/themes/dark/eye_on.svg
index eaf9346..ca40f72 100644
--- a/images/themes/dark/eye_on.svg
+++ b/images/themes/dark/eye_on.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/images/themes/dark/star.svg b/images/themes/dark/star.svg
index 4e6ed3a..ee43c24 100644
--- a/images/themes/dark/star.svg
+++ b/images/themes/dark/star.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/images/themes/light/eye_off.svg b/images/themes/light/eye_off.svg
index 396cb2a..74f33ec 100644
--- a/images/themes/light/eye_off.svg
+++ b/images/themes/light/eye_off.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/images/themes/light/eye_on.svg b/images/themes/light/eye_on.svg
index ca40f72..eaf9346 100644
--- a/images/themes/light/eye_on.svg
+++ b/images/themes/light/eye_on.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/images/themes/light/star.svg b/images/themes/light/star.svg
index ee43c24..4e6ed3a 100644
--- a/images/themes/light/star.svg
+++ b/images/themes/light/star.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/src/core/googlewrapper.cpp b/src/core/googlewrapper.cpp
index a0378a8..1cc8e90 100644
--- a/src/core/googlewrapper.cpp
+++ b/src/core/googlewrapper.cpp
@@ -25,7 +25,8 @@
char const *CLIENT_ID = "71530390003-2fr89p1c0unpd1n169munqajeepnhdco.apps.googleusercontent.com";
char const *CLIENT_SECRET = "zuyjH1Cd_8pL4Q-OFNLjNCJ7";
-char const *SCOPE = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/drive.appdata";
+char const *SCOPE = "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/drive.appdata "
+ "https://www.googleapis.com/auth/drive.file";
char const *REPLY_CONTENT =
"
Authorization flow completed. Feel free to close "
"this window. ";
@@ -303,7 +304,7 @@ std::pair GoogleWrapper::get_file_ids(QByteArray const &data)
}
for (auto const &file : json["files"]) {
- if ("drive#file" == file["kind"] && "application/octet-stream" == file["mimeType"]) {
+ if ("drive#file" == file["kind"]) {
if ("diary.dat" == file["name"]) {
primary_backup_id = QString::fromStdString(file["id"]);
}
diff --git a/src/core/internalmanager.cpp b/src/core/internalmanager.cpp
index b7a4027..8698371 100644
--- a/src/core/internalmanager.cpp
+++ b/src/core/internalmanager.cpp
@@ -61,14 +61,25 @@ void InternalManager::init_settings(const bool force_reset)
settings->setValue("lock_timeout", static_cast(300000 /* 5 minutes */));
}
-td::Theme InternalManager::get_theme()
+td::Theme InternalManager::get_theme(bool const opposite)
{
- return static_cast(settings->value("theme").toInt());
+ if (opposite) {
+ return static_cast(settings->value("theme").toInt()) == td::Theme::Dark ? td::Theme::Light
+ : td::Theme::Dark;
+ }
+ else {
+ return static_cast(settings->value("theme").toInt());
+ }
}
-QString InternalManager::get_theme_str()
+QString InternalManager::get_theme_str(bool const opposite)
{
- return QString(td::Theme::Light == get_theme() ? "light" : "dark");
+ if (opposite) {
+ return td::Theme::Light == get_theme() ? "dark" : "light";
+ }
+ else {
+ return td::Theme::Light == get_theme() ? "light" : "dark";
+ }
}
QString InternalManager::data_location()
@@ -104,16 +115,15 @@ void InternalManager::end_busy_mode(int const line, std::string const &func, std
void InternalManager::start_update_theme()
{
QPixmapCache::clear();
- state_color_palette = StateColorPalette();
if (get_theme() == td::Theme::Dark) {
- state_color_palette.initDefaultPaletteDark();
+ set_dark_palette();
auto s = new DarkStyle;
QApplication::setPalette(s->standardPalette());
QApplication::setStyle(s);
}
else {
- state_color_palette.initDefaultPaletteLight();
+ set_light_palette();
auto s = new LightStyle;
QApplication::setPalette(s->standardPalette());
QApplication::setStyle(s);
@@ -121,3 +131,25 @@ void InternalManager::start_update_theme()
emit update_theme();
}
+
+void InternalManager::set_light_palette()
+{
+ set_colour(td::ColourRole::Unknown, QStringLiteral("#C9C9CF"));
+ set_colour(td::ColourRole::VeryBad, QStringLiteral("#7b1fa2"));
+ set_colour(td::ColourRole::Bad, QStringLiteral("#5e35b1"));
+ set_colour(td::ColourRole::Ok, QStringLiteral("#1976d2"));
+ set_colour(td::ColourRole::Good, QStringLiteral("#0097a7"));
+ set_colour(td::ColourRole::VeryGood, QStringLiteral("#4caf50"));
+ set_colour(td::ColourRole::Text, QStringLiteral("#1D1D20"));
+}
+
+void InternalManager::set_dark_palette()
+{
+ set_colour(td::ColourRole::Unknown, QStringLiteral("#2F2F32"));
+ set_colour(td::ColourRole::VeryBad, QStringLiteral("#7b1fa2"));
+ set_colour(td::ColourRole::Bad, QStringLiteral("#5e35b1"));
+ set_colour(td::ColourRole::Ok, QStringLiteral("#1976d2"));
+ set_colour(td::ColourRole::Good, QStringLiteral("#0097a7"));
+ set_colour(td::ColourRole::VeryGood, QStringLiteral("#4caf50"));
+ set_colour(td::ColourRole::Text, QStringLiteral("#CACBCE"));
+}
diff --git a/src/core/internalmanager.h b/src/core/internalmanager.h
index 19fd440..5452cd0 100644
--- a/src/core/internalmanager.h
+++ b/src/core/internalmanager.h
@@ -24,7 +24,6 @@
#include
#include
-#include "../gui/styles/statecolorpalette.h"
#include "../util/eventfilters.h"
#include "asyncfuture.h"
#include "json.hpp"
@@ -127,6 +126,22 @@ enum class Window { Main, Editor, Options };
enum class LinkingResponse { Fail, ScopeMismatch, OK };
using NRO = AsyncFuture::Observable;
+
+struct CalendarButtonData {
+ std::optional day;
+ std::optional important;
+ std::optional rating;
+ std::optional selected;
+ std::optional current_day;
+};
+
+struct DiaryEntryIconData {
+ std::optional day;
+ std::optional rating;
+ std::optional important;
+};
+
+enum class ColourRole { Text, Unknown, VeryBad, Bad, Ok, Good, VeryGood };
} // namespace td
// The reason why this class exists is to redirect #include statements away from theoreticaldiary.h
@@ -149,18 +164,30 @@ class InternalManager : public QObject {
~InternalManager();
static InternalManager *instance();
- QString get_theme_str();
- td::Theme get_theme();
+ QString get_theme_str(bool const opposite = false);
+ td::Theme get_theme(bool const opposite = false);
QString data_location();
void start_busy_mode(int const line, std::string const &func, std::string const &file);
void end_busy_mode(int const line, std::string const &func, std::string const &file);
void init_settings(bool const force_reset);
void start_update_theme();
+ void set_dark_palette();
+ void set_light_palette();
+
+ inline void set_colour(td::ColourRole role, const QColor &colour)
+ {
+ colourmap[static_cast(role)] = colour;
+ }
+
+ inline QColor colour(td::ColourRole role) const
+ {
+ return colourmap.value(static_cast(role));
+ }
+ QHash colourmap;
QSettings *settings;
InactiveFilter *inactive_filter;
BusyFilter busy_filter;
- StateColorPalette state_color_palette;
bool app_busy;
bool internal_diary_changed;
bool diary_file_changed;
diff --git a/src/gui/calendarbutton.cpp b/src/gui/calendarbutton.cpp
deleted file mode 100644
index 30a2205..0000000
--- a/src/gui/calendarbutton.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * This file is part of Theoretical Diary.
- * Copyright (C) 2022 someretical
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "calendarbutton.h"
-#include "diaryeditor.h"
-
-CalendarButton::CalendarButton(td::CalendarButtonData const &d) : QPushButton(qobject_cast(*d.parent))
-{
- data = d;
-
- setAutoDefault(true);
- setCursor(QCursor(Qt::PointingHandCursor));
- setText(QString::number(*d.day));
-
- QFont f = font();
- f.setPointSize(16);
- setFont(f);
-
- update();
-
- // Apply new themes if requested
- connect(*d.parent, &DiaryEditor::sig_re_render_buttons, this, &CalendarButton::re_render, Qt::QueuedConnection);
-
- // Link click event through here to pass day variable through.
- connect(this, &CalendarButton::clicked, this, &CalendarButton::clicked_on, Qt::QueuedConnection);
- connect(this, &CalendarButton::sig_clicked, *d.parent, &DiaryEditor::date_clicked, Qt::QueuedConnection);
-
- re_render(d);
-}
-
-CalendarButton::~CalendarButton() {}
-
-// Update the the following properties of the button:
-// - Background colour
-// - Icon
-// - Whether it is selected or not
-void CalendarButton::re_render(td::CalendarButtonData const &d)
-{
- // // Set stylesheet (determines colours).
- // QString stylesheet((*data.parent)->base_stylesheet);
-
- // // Set background star if necessary.
- // // If the provided 'd' object does not have the 'important' property set, use the 'important' property from
- // 'data'
- // // instead. If the provided 'd' object DOES contain an 'important' property, update the 'important' property
- // of
- // // 'data'.
- // data.important = std::optional(d.important.value_or(*data.important));
- // data.rating = std::optional(d.rating.value_or(*data.rating));
-
- // if (*data.important) {
- // switch (*data.rating) {
- // case td::Rating::Unknown:
- // // Fall through
- // case td::Rating::VeryBad:
- // // Fall through
- // case td::Rating::Bad:
- // // Fall through
- // case td::Rating::Ok:
- // stylesheet.append((*data.parent)->white_star);
- // break;
- // case td::Rating::Good:
- // // Fall through
- // case td::Rating::VeryGood:
- // stylesheet.append((*data.parent)->black_star);
- // break;
- // }
- // }
-
- // // Set colour scheme.
- // auto const r = d.rating.value_or(*data.rating);
- // data.rating = std::optional(r);
- // stylesheet.append(*(((*data.parent)->rating_stylesheets)[static_cast(r)]));
-
- // // Give border if selected.
- // data.selected = std::optional(d.selected.value_or(*data.selected));
- // if (*data.selected) {
- // stylesheet.append((*data.parent)->selected_stylesheet);
- // }
-
- // setStylesheet\(stylesheet);
-}
-
-void CalendarButton::clicked_on()
-{
- emit sig_clicked(*data.day);
-}
diff --git a/src/gui/calendarbutton.h b/src/gui/calendarbutton.h
deleted file mode 100644
index b9cf11a..0000000
--- a/src/gui/calendarbutton.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file is part of Theoretical Diary.
- * Copyright (C) 2022 someretical
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef CALENDARBUTTON_H
-#define CALENDARBUTTON_H
-
-class DiaryEditor;
-
-#include
-#include
-
-#include "../core/internalmanager.h"
-
-namespace td {
-struct CalendarButtonData {
- std::optional day;
- std::optional parent;
- std::optional important;
- std::optional rating;
- std::optional selected;
-};
-} // namespace td
-
-class CalendarButton : public QPushButton {
- Q_OBJECT
-
-signals:
- void sig_clicked(int const day);
-
-public:
- explicit CalendarButton(td::CalendarButtonData const &d);
- ~CalendarButton();
-
- td::CalendarButtonData data;
-
-public slots:
- void clicked_on();
- void re_render(td::CalendarButtonData const &d);
-};
-
-#endif // CALENDARBUTTON_H
diff --git a/src/gui/diaryeditor.cpp b/src/gui/diaryeditor.cpp
index e73decb..22bd995 100644
--- a/src/gui/diaryeditor.cpp
+++ b/src/gui/diaryeditor.cpp
@@ -28,13 +28,6 @@ DiaryEditor::DiaryEditor(QDate const &date, QWidget *parent) : QWidget(parent),
ui->alert_text->setText("");
ui->alert_text->update();
- // These will be filled when update_theme is called.
- base_stylesheet = QString();
- selected_stylesheet = QString();
- white_star = QString();
- black_star = QString();
- rating_stylesheets = std::vector>();
-
current_month_offset = 0;
last_selected_day = 0;
@@ -85,48 +78,19 @@ DiaryEditor::~DiaryEditor()
void DiaryEditor::update_theme()
{
- // auto const &theme = InternalManager::instance()->get_theme_str();
-
- // QFile file(QString(":/%1/diaryeditor.qss").arg(theme));
- // file.open(QIODevice::ReadOnly);
- // // setStylesheet\(file.readAll());
- // file.close();
-
- // file.setFileName(QString(":/%1/theoretical_calendar/base.qss").arg(theme));
- // file.open(QIODevice::ReadOnly);
- // base_stylesheet = file.readAll();
- // file.close();
-
- // file.setFileName(QString(":/%1/theoretical_calendar/selected.qss").arg(theme));
- // file.open(QIODevice::ReadOnly);
- // selected_stylesheet = file.readAll();
- // file.close();
-
- // file.setFileName(":/global/white_star.qss");
- // file.open(QIODevice::ReadOnly);
- // white_star = file.readAll();
- // file.close();
-
- // file.setFileName(":/global/black_star.qss");
- // file.open(QIODevice::ReadOnly);
- // black_star = file.readAll();
- // file.close();
-
- // for (auto &ss_ptr : rating_stylesheets)
- // ss_ptr.reset();
-
- // rating_stylesheets.clear();
-
- // for (int i = 0; i < 6; ++i) {
- // file.setFileName(QString(":/%1/theoretical_calendar/%2.qss").arg(theme, QString::number(i)));
- // file.open(QIODevice::ReadOnly);
- // rating_stylesheets.push_back(std::make_unique(file.readAll()));
- // file.close();
- // }
-
- // // When this function is run in the constructor, no buttons should exist yet.
- // emit sig_re_render_buttons(
- // td::CalendarButtonData{std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt});
+ // When this function is run in the constructor, no buttons should exist yet.
+ emit sig_re_render_buttons(
+ td::CalendarButtonData{std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt});
+}
+
+DiaryCalendarButton *DiaryEditor::create_button(const td::CalendarButtonData &&d)
+{
+ auto ptr = new DiaryCalendarButton(d);
+
+ connect(this, &DiaryEditor::sig_re_render_buttons, ptr, &DiaryCalendarButton::re_render, Qt::QueuedConnection);
+ connect(ptr, &DiaryCalendarButton::sig_clicked, this, &DiaryEditor::date_clicked, Qt::QueuedConnection);
+
+ return ptr;
}
// Note for future me and any other readers:
@@ -135,6 +99,7 @@ void DiaryEditor::update_theme()
void DiaryEditor::render_month(QDate const &date, std::optional const &opt)
{
// Note that the YearMap iterator actually contains a month map which holds all the days of the month.
+ auto irl_current_day = QDate::currentDate();
// Render spacers for first row padding.
for (int i = 0; i < current_month_offset; ++i)
@@ -150,6 +115,9 @@ void DiaryEditor::render_month(QDate const &date, std::optionalsecond;
auto const &entry_iter = monthmap.find(i - current_month_offset + 1);
@@ -157,18 +125,16 @@ void DiaryEditor::render_month(QDate const &date, std::optionalsecond;
- td::CalendarButtonData const d{std::optional(i - current_month_offset + 1), std::optional(this),
- std::optional(important), std::optional(rating), std::optional(false)};
-
- ui->dates->addWidget(new CalendarButton(d), 0, i, 1, 1, Qt::AlignCenter);
+ auto ptr = create_button(td::CalendarButtonData{std::optional(i - current_month_offset + 1),
+ std::optional(important), std::optional(rating), std::optional(false), std::optional(current)});
+ ui->dates->addWidget(ptr, 0, i, 1, 1, Qt::AlignCenter);
continue;
}
}
- td::CalendarButtonData const d{std::optional(i - current_month_offset + 1), std::optional(this),
- std::optional(false), std::optional(td::Rating::Unknown), std::optional(false)};
-
- ui->dates->addWidget(new CalendarButton(d), 0, i, 1, 1, Qt::AlignCenter);
+ auto ptr = create_button(td::CalendarButtonData{std::optional(i - current_month_offset + 1),
+ std::optional(false), std::optional(td::Rating::Unknown), std::optional(false), std::optional(current)});
+ ui->dates->addWidget(ptr, 0, i, 1, 1, Qt::AlignCenter);
}
// Render rest of month.
@@ -179,6 +145,9 @@ void DiaryEditor::render_month(QDate const &date, std::optionalsecond;
auto const &entry_iter = monthmap.find(i + 1);
@@ -186,18 +155,16 @@ void DiaryEditor::render_month(QDate const &date, std::optionalsecond;
- td::CalendarButtonData const d{std::optional(i + 1), std::optional(this), std::optional(important),
- std::optional(rating), std::optional(false)};
-
- ui->dates->addWidget(new CalendarButton(d), row, current_row_length, 1, 1, Qt::AlignCenter);
+ auto ptr = create_button(td::CalendarButtonData{std::optional(i + 1), std::optional(important),
+ std::optional(rating), std::optional(false), std::optional(current)});
+ ui->dates->addWidget(ptr, row, current_row_length, 1, 1, Qt::AlignCenter);
continue;
}
}
- td::CalendarButtonData const d{std::optional(i + 1), std::optional(this), std::optional(false),
- std::optional(td::Rating::Unknown), std::optional(false)};
-
- ui->dates->addWidget(new CalendarButton(d), row, current_row_length, 1, 1, Qt::AlignCenter);
+ auto ptr = create_button(td::CalendarButtonData{std::optional(i + 1), std::optional(false),
+ std::optional(td::Rating::Unknown), std::optional(false), std::optional(current)});
+ ui->dates->addWidget(ptr, row, current_row_length, 1, 1, Qt::AlignCenter);
}
// Fill in last row with spacers if necessary. There is a vertical spacer beneath the whole grid of buttons to push
@@ -247,7 +214,7 @@ void DiaryEditor::change_month(QDate const &date, bool const suppress_confirm)
// Render current day.
td::CalendarButtonData const d{
- std::optional(date.day()), std::nullopt, std::nullopt, std::nullopt, std::optional(true)};
+ std::optional(date.day()), std::nullopt, std::nullopt, std::optional(true), std::nullopt};
render_day(d, true);
emit InternalManager::instance()->update_data(date);
@@ -266,7 +233,7 @@ void DiaryEditor::render_day(td::CalendarButtonData const &d, bool const set_inf
int const x = (*d.day + current_month_offset - 1) % 7;
int const y = static_cast((*d.day + current_month_offset - 1) / 7);
- auto const &button = qobject_cast(ui->dates->itemAtPosition(y, x)->widget());
+ auto const &button = qobject_cast(ui->dates->itemAtPosition(y, x)->widget());
button->re_render(d);
if (set_info_pane) {
@@ -322,9 +289,9 @@ void DiaryEditor::date_clicked(int const day)
update_day(true); // Suppress entry saved message so it doesn't appear on new date.
td::CalendarButtonData const old{
- std::optional(last_selected_day), std::nullopt, std::nullopt, std::nullopt, std::optional(false)};
+ std::optional(last_selected_day), std::nullopt, std::nullopt, std::optional(false), std::nullopt};
td::CalendarButtonData const n{
- std::optional(day), std::nullopt, std::nullopt, std::nullopt, std::optional(true)};
+ std::optional(day), std::nullopt, std::nullopt, std::optional(true), std::nullopt};
// Remove selected border from old calendar button.
render_day(old, false);
// Add selected border to new calendar button.
@@ -391,9 +358,8 @@ void DiaryEditor::update_day(bool const suppress_error)
if (!DiaryHolder::instance()->save() && suppress_error)
return cmb::save_error(this, []() {});
- td::CalendarButtonData const d{std::optional(last_selected_day), std::nullopt,
- std::optional(ui->special_box->isChecked()),
- std::optional(static_cast(ui->rating_dropdown->currentIndex())), std::nullopt};
+ td::CalendarButtonData const d{std::optional(last_selected_day), std::optional(ui->special_box->isChecked()),
+ std::optional(static_cast(ui->rating_dropdown->currentIndex())), std::nullopt, std::nullopt};
// This updates the day button in the calendar widget.
render_day(d, false);
@@ -403,6 +369,8 @@ void DiaryEditor::update_day(bool const suppress_error)
// Thanks stackoverflow ;)
ui->last_edited->setText("Last edited " + last_edited.toString("dd MMM ''yy 'at' h:mm ap"));
ui->last_edited->update();
+ ui->alert_text->setText("Updated entry.");
+ ui->alert_text->update();
// This updates the information in the other tabs.
// The pixels tab should call end_busy_mode when it is done re rendering.
@@ -432,8 +400,8 @@ void DiaryEditor::delete_day()
update_info_pane(new_date, td::Entry{false, td::Rating::Unknown, "", 0});
- td::CalendarButtonData const d{std::optional(last_selected_day), std::nullopt, std::optional(false),
- std::optional(static_cast(td::Rating::Unknown)), std::nullopt};
+ td::CalendarButtonData const d{std::optional(last_selected_day), std::optional(false),
+ std::optional(static_cast(td::Rating::Unknown)), std::nullopt, std::nullopt};
render_day(d, false);
// This updates the information in the other tabs.
diff --git a/src/gui/diaryeditor.h b/src/gui/diaryeditor.h
index 6ee8869..b3ee124 100644
--- a/src/gui/diaryeditor.h
+++ b/src/gui/diaryeditor.h
@@ -23,7 +23,8 @@
#include
#include
-#include "calendarbutton.h"
+#include "../core/internalmanager.h"
+#include "../util/diarycalendarbutton.h"
namespace Ui {
class DiaryEditor;
@@ -45,13 +46,6 @@ class DiaryEditor : public QWidget {
QShortcut *save_shortcut;
- // This is an array of 6 stylesheets.
- std::vector> rating_stylesheets;
- QString base_stylesheet;
- QString selected_stylesheet;
- QString white_star;
- QString black_star;
-
public slots:
void update_theme();
@@ -73,6 +67,8 @@ public slots:
private:
Ui::DiaryEditor *ui;
+
+ DiaryCalendarButton *create_button(td::CalendarButtonData const &&d);
};
#endif // DIARYEDITOR_H
diff --git a/src/gui/diaryeditor.ui b/src/gui/diaryeditor.ui
index cc0755f..7477a59 100644
--- a/src/gui/diaryeditor.ui
+++ b/src/gui/diaryeditor.ui
@@ -101,7 +101,7 @@
-
- 7
+ 0
diff --git a/src/gui/diaryentryviewer.cpp b/src/gui/diaryentryviewer.cpp
index 86d4e00..a1ebfd2 100644
--- a/src/gui/diaryentryviewer.cpp
+++ b/src/gui/diaryentryviewer.cpp
@@ -23,6 +23,29 @@
int const MAX_LINE_LEN = 110;
int const DAY_LABEL_SIZE = 50;
+int const SIZE = 50;
+
+const char *PLACEHOLDER_TEXT = R"(
+It seems there are no entries yet for this month...
+)";
+
+char const *TABLE_START = "";
+
+char const *SINGLE_ROW = R"(
+
+
+%2
+
+)";
+
+const QString HR_ROW(R"(
+
+
+
+
+)");
+
+char const *TABLE_END = "
";
DiaryEntryViewer::DiaryEntryViewer(QWidget *parent) : QWidget(parent), ui(new Ui::DiaryEntryViewer)
{
@@ -45,13 +68,6 @@ DiaryEntryViewer::DiaryEntryViewer(QWidget *parent) : QWidget(parent), ui(new Ui
Qt::QueuedConnection);
update_theme();
- // Make scroll bar hit the bottom.
- QTimer::singleShot(0, this, [&]() {
- ui->scrollArea->widget()->adjustSize();
- ui->scrollArea->widget()->update();
- ui->scrollArea->verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMaximum);
- });
-
// current_date is initialised by &InternalManager::change_month signal.
}
@@ -62,52 +78,11 @@ DiaryEntryViewer::~DiaryEntryViewer()
void DiaryEntryViewer::update_theme()
{
- // auto const &theme = InternalManager::instance()->get_theme_str();
-
- // QFile file(QString(":/%1/diary_entry_list/base.qss").arg(theme));
- // file.open(QIODevice::ReadOnly);
- // // ui->scrollArea->setStyleSheet(file.readAll());
- // file.close();
-
- // file.setFileName(QString(":/%1/diaryentryviewer.qss").arg(theme));
- // file.open(QIODevice::ReadOnly);
- // // setStylesheet\(file.readAll());
- // file.close();
-
- // file.setFileName(":/global/white_star.qss");
- // file.open(QIODevice::ReadOnly);
- // white_star = file.readAll();
- // file.close();
-
- // file.setFileName(":/global/black_star.qss");
- // file.open(QIODevice::ReadOnly);
- // black_star = file.readAll();
- // file.close();
-
- // for (auto &ss_ptr : rating_stylesheets)
- // ss_ptr.reset();
-
- // rating_stylesheets.clear();
-
- // for (int i = 0; i < 6; ++i) {
- // file.setFileName(QString(":/%1/diary_entry_list/%2.qss").arg(theme, QString::number(i)));
- // file.open(QIODevice::ReadOnly);
- // rating_stylesheets.push_back(std::make_unique(file.readAll()));
- // file.close();
- // }
-
- // emit sig_update_labels();
+ change_month(QDate::currentDate());
}
void DiaryEntryViewer::change_month(QDate const &date)
{
- // Remove everything from current grid.
- QLayoutItem *child;
- while ((child = ui->entry_grid->takeAt(0)) != 0) {
- delete child->widget();
- delete child;
- }
-
// Update the selector UI.
ui->month_dropdown->blockSignals(true);
ui->year_edit->blockSignals(true);
@@ -125,18 +100,12 @@ void DiaryEntryViewer::change_month(QDate const &date)
ui->year_edit->blockSignals(false);
auto const &opt = DiaryHolder::instance()->get_monthmap(date.isValid() ? date : current_date);
- if (!opt) {
- auto label = new QLabel("It seems there are no entries yet for this month...", this);
- label->setAlignment(Qt::AlignCenter);
- auto f = label->font();
- f.setPointSize(11);
- label->setFont(f);
-
- current_date = date;
- return ui->entry_grid->addWidget(label);
- }
+ if (!opt)
+ return ui->entry_edit->setText(PLACEHOLDER_TEXT);
- int row_counter = 0;
+ QString html(TABLE_START);
+
+ auto row_counter = 0;
for (auto const &i : (*opt)->second) {
auto const &[important, rating, message, dummy] = i.second;
@@ -144,26 +113,23 @@ void DiaryEntryViewer::change_month(QDate const &date)
if (message.empty())
continue;
- // Ideally, the message should have been trimmed when the entry itself was saved. However, that was not always
- // the case so the message has to be trimmed here for backwards compatability.
- auto msg_copy = message;
- auto day = new DiaryEntryDayLabel(td::LabelData{this, i.first, rating, important}, this);
- auto formatted_msg = new DiaryEntryDayMessage(misc::trim(msg_copy), this);
- auto spacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
+ auto copy = message;
+
+ // This is just about the most janky thing in this entire app.
+ html.append(QString(SINGLE_ROW)
+ .arg(generate_base64_icon(i.first, rating, important), misc::sanitise_html(misc::trim(copy))));
+ html.append(HR_ROW);
- ui->entry_grid->addWidget(day, row_counter, 0, 1, 1, Qt::AlignTop | Qt::AlignLeft);
- ui->entry_grid->addWidget(formatted_msg, row_counter, 1, 1, 1, Qt::AlignVCenter | Qt::AlignLeft);
- ui->entry_grid->addItem(spacer, row_counter++, 2);
+ ++row_counter;
}
if (0 == row_counter) {
- auto label = new QLabel("It seems there are no entries yet for this month...", this);
- label->setAlignment(Qt::AlignCenter);
- auto f = label->font();
- f.setPointSize(11);
- label->setFont(f);
-
- ui->entry_grid->addWidget(label);
+ return ui->entry_edit->setText(PLACEHOLDER_TEXT);
+ }
+ else {
+ html.chop(HR_ROW.size());
+ html.append(TABLE_END);
+ ui->entry_edit->setText(html);
}
current_date = date;
@@ -174,31 +140,15 @@ void DiaryEntryViewer::change_month(QDate const &date)
void DiaryEntryViewer::next_month()
{
QDate const next = ui->year_edit->date().addMonths(1);
- if (next.isValid()) {
+ if (next.isValid())
change_month(next);
-
- // Make scroll bar hit top.
- QTimer::singleShot(0, this, [&]() {
- ui->scrollArea->widget()->adjustSize();
- ui->scrollArea->widget()->update();
- ui->scrollArea->verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMinimum);
- });
- }
}
void DiaryEntryViewer::prev_month()
{
QDate const prev = ui->year_edit->date().addMonths(-1);
- if (prev.isValid()) {
+ if (prev.isValid())
change_month(prev);
-
- // Make scroll bar hit bottom.
- QTimer::singleShot(0, this, [&]() {
- ui->scrollArea->widget()->adjustSize();
- ui->scrollArea->widget()->update();
- ui->scrollArea->verticalScrollBar()->triggerAction(QAbstractSlider::SliderToMaximum);
- });
- }
}
void DiaryEntryViewer::month_changed(int)
@@ -212,102 +162,110 @@ void DiaryEntryViewer::year_changed(QDate const &date)
change_month(QDate(ui->year_edit->date().year(), ui->month_dropdown->currentIndex() + 1, 1));
}
-/*
- * DiaryEntryDayLabel class
- */
-DiaryEntryDayLabel::DiaryEntryDayLabel(td::LabelData const &d, QWidget *parent) : QLabel(parent)
+QByteArray DiaryEntryViewer::generate_base64_icon(int const day, td::Rating const rating, bool const important)
{
- data = d;
- setText(QString::number(d.day));
- setFixedHeight(DAY_LABEL_SIZE);
- setFixedWidth(DAY_LABEL_SIZE);
- setAlignment(Qt::AlignCenter);
+ QPixmap pixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.drawPixmap(0, 0, generate_background(rating));
- QFont f = font();
- f.setPointSize(14);
- f.setBold(true);
- setFont(f);
+ if (important)
+ p.drawPixmap(0, 0, generate_star(rating));
- update();
+ p.drawPixmap(0, 0, generate_text(day, rating));
- connect(InternalManager::instance(), &InternalManager::update_theme, this, &DiaryEntryDayLabel::update_theme,
- Qt::QueuedConnection);
- connect(
- d.parent, &DiaryEntryViewer::sig_update_labels, this, &DiaryEntryDayLabel::update_theme, Qt::QueuedConnection);
- update_theme();
-}
+ QByteArray barray;
+ QBuffer buf(&barray);
+ buf.open(QIODevice::WriteOnly);
-DiaryEntryDayLabel::~DiaryEntryDayLabel() {}
+ pixmap.toImage().save(&buf, "PNG");
+ return barray.toBase64();
+}
-void DiaryEntryDayLabel::update_theme()
+QPixmap DiaryEntryViewer::generate_background(td::Rating const rating)
{
- // // Set colour theme.
- // QString stylesheet(*(data.parent->rating_stylesheets)[static_cast(data.rating)]);
-
- // // Set background star if necessary.
- // if (data.special) {
- // switch (data.rating) {
- // case td::Rating::Unknown:
- // // Fall through
- // case td::Rating::VeryBad:
- // // Fall through
- // case td::Rating::Bad:
- // // Fall through
- // case td::Rating::Ok:
- // stylesheet.append(data.parent->white_star);
- // break;
- // case td::Rating::Good:
- // // Fall through
- // case td::Rating::VeryGood:
- // stylesheet.append(data.parent->black_star);
- // break;
- // }
- // }
-
- // setStylesheet\(stylesheet);
+ QString key = QString("diaryentryicon:bkg:%1:%2")
+ .arg(QString::number(static_cast(rating)),
+ QString::number(static_cast(InternalManager::instance()->get_theme())));
+ QPixmap pixmap;
+
+ if (!QPixmapCache::find(key, pixmap)) {
+ pixmap = QPixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
+
+ QColor colour = misc::rating_to_colour(rating);
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
+
+ if (InternalManager::instance()->get_theme() == td::Theme::Light)
+ p.setOpacity(0.8);
+
+ p.setPen(Qt::transparent);
+ p.setBrush(QBrush(colour));
+ p.drawEllipse(0, 0, SIZE, SIZE);
+
+ QPixmapCache::insert(key, pixmap);
+ }
+
+ return pixmap;
}
-/*
- * DiaryEntryDayMessage class
- */
-DiaryEntryDayMessage::DiaryEntryDayMessage(std::string const &m, QWidget *parent) : QLabel(parent)
+QPixmap DiaryEntryViewer::generate_star(td::Rating const rating)
{
- message = std::string(m);
- expanded = false;
+ auto theme_str = misc::rating_to_theme(rating) == td::Theme::Dark ? "dark" : "light";
+ QString key = QString("diaryentryicon:star:%1").arg(theme_str);
+ QPixmap pixmap;
- // Set text.
- setText(misc::get_trunc_first_line(m, MAX_LINE_LEN).data());
- setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
- setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
+ if (!QPixmapCache::find(key, pixmap)) {
+ pixmap = QPixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
- QFont f = font();
- f.setPointSize(14);
- setFont(f);
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.setOpacity(0.3);
- update();
+ auto overlay = QIcon(QString(":/themes/%1/star.svg").arg(theme_str)).pixmap(SIZE * 0.8, SIZE * 0.8);
- setCursor(QCursor(Qt::PointingHandCursor));
+ // Draw overlay on the centre of the pixmap.
+ auto x = ((rect().bottomRight().x() - overlay.rect().bottomRight().x()) / 2);
+ // y is the same as x since it's a square.
- connect(InternalManager::instance(), &InternalManager::update_theme, this, &DiaryEntryDayMessage::update_theme,
- Qt::QueuedConnection);
- update_theme();
-}
+ p.drawPixmap(x, x, overlay);
-DiaryEntryDayMessage::~DiaryEntryDayMessage() {}
+ QPixmapCache::insert(key, pixmap);
+ }
-void DiaryEntryDayMessage::update_theme() {}
+ return pixmap;
+}
-void DiaryEntryDayMessage::mouseDoubleClickEvent(QMouseEvent *event)
+QPixmap DiaryEntryViewer::generate_text(int const day_, td::Rating const rating)
{
- if (event->button() != Qt::LeftButton)
- return;
+ QString day = QString::number(day_);
+ auto theme = QString::number(static_cast(misc::rating_to_theme(rating)));
+ QString key = QString("diaryentryicon:text:%1:%2").arg(day, theme);
+ QPixmap pixmap;
+
+ if (!QPixmapCache::find(key, pixmap)) {
+ pixmap = QPixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
+
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
- if (expanded)
- setText(misc::get_trunc_first_line(message, MAX_LINE_LEN).data());
- else
- setText(message.data());
+ auto bold_font = QApplication::font();
+ bold_font.setBold(true);
+ bold_font.setPointSize(16);
+ p.setFont(bold_font);
- update();
+ QRectF rect;
+ rect = p.boundingRect(pixmap.rect(), Qt::AlignCenter, day);
+
+ p.setPen(misc::theme_to_text(misc::rating_to_theme(rating)));
+ p.drawText(rect, Qt::AlignCenter, day);
+
+ QPixmapCache::insert(key, pixmap);
+ }
- expanded = !expanded;
+ return pixmap;
}
diff --git a/src/gui/diaryentryviewer.h b/src/gui/diaryentryviewer.h
index 41ae40e..3db0f86 100644
--- a/src/gui/diaryentryviewer.h
+++ b/src/gui/diaryentryviewer.h
@@ -28,16 +28,6 @@ namespace Ui {
class DiaryEntryViewer;
}
-class DiaryEntryViewer;
-namespace td {
-struct LabelData {
- DiaryEntryViewer *parent;
- int day;
- td::Rating rating;
- bool special;
-};
-} // namespace td
-
class DiaryEntryViewer : public QWidget {
Q_OBJECT
@@ -63,36 +53,11 @@ public slots:
private:
Ui::DiaryEntryViewer *ui;
-};
-
-class DiaryEntryDayLabel : public QLabel {
- Q_OBJECT
-
-public:
- explicit DiaryEntryDayLabel(td::LabelData const &d, QWidget *parent = nullptr);
- ~DiaryEntryDayLabel();
-
- td::LabelData data;
-
-public slots:
- void update_theme();
-};
-
-class DiaryEntryDayMessage : public QLabel {
- Q_OBJECT
-
-public:
- explicit DiaryEntryDayMessage(std::string const &m, QWidget *parent = nullptr);
- ~DiaryEntryDayMessage();
-
- std::string message;
- bool expanded;
-
-public slots:
- void update_theme();
-protected:
- void mouseDoubleClickEvent(QMouseEvent *event);
+ QByteArray generate_base64_icon(int const day, td::Rating const rating, bool const important);
+ QPixmap generate_background(td::Rating const rating);
+ QPixmap generate_star(td::Rating const rating);
+ QPixmap generate_text(int const day_, td::Rating const rating);
};
#endif // DIARYENTRYVIEWER_H
diff --git a/src/gui/diaryentryviewer.ui b/src/gui/diaryentryviewer.ui
index 560b239..068cd41 100644
--- a/src/gui/diaryentryviewer.ui
+++ b/src/gui/diaryentryviewer.ui
@@ -80,87 +80,6 @@
30
- -
-
-
-
- 0
- 0
-
-
-
- true
-
-
- Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
-
-
-
- 0
- 0
- 1218
- 545
-
-
-
-
- 0
- 0
-
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 0
-
-
-
-
- -
-
-
- 15
-
-
- 15
-
-
- 15
-
-
- 15
-
-
- 30
-
-
-
-
-
-
-
-
@@ -364,13 +283,19 @@
+ -
+
+
+ Qt::TextSelectableByMouse
+
+
+
- scrollArea
prev_month
month_dropdown
year_edit
diff --git a/src/gui/diarypixels.cpp b/src/gui/diarypixels.cpp
index c0e9f89..332d3a6 100644
--- a/src/gui/diarypixels.cpp
+++ b/src/gui/diarypixels.cpp
@@ -21,7 +21,6 @@
#include "../util/custommessageboxes.h"
#include "../util/diarypixellabel.h"
#include "../util/misc.h"
-#include "styles/statecolorpalette.h"
#include "ui_diarypixels.h"
char const *MONTH_LETTERS = "JFMAMJJASOND";
diff --git a/src/gui/diarystats.cpp b/src/gui/diarystats.cpp
index 8954b11..743693e 100644
--- a/src/gui/diarystats.cpp
+++ b/src/gui/diarystats.cpp
@@ -18,13 +18,12 @@
#include "diarystats.h"
#include "../core/diaryholder.h"
+#include "../util/misc.h"
#include "ui_diarystats.h"
using namespace QtCharts;
char const *ratings[] = {"Unknown", "Very bad", "Bad", "OK", "Good", "Very good"};
-QColor const rating_colours[] = {QColor(84, 110, 122, 51), QColor(123, 31, 162, 255), QColor(94, 53, 177, 255),
- QColor(25, 118, 210, 255), QColor(0, 151, 167, 255), QColor(76, 175, 80, 255)};
qreal const angular_min = 1;
// qreal const angular_max = 31;
@@ -36,9 +35,6 @@ auto const light_background = QColor(230, 230, 230, 170);
auto const dark_white = light_background.darker();
auto const light_black = dark_background.lighter();
-auto const almost_white = QColor(202, 203, 206);
-auto const almost_black = QColor(29, 29, 32);
-
DiaryStats::DiaryStats(QWidget *parent) : QWidget(parent), ui(new Ui::DiaryStats)
{
ui->setupUi(this);
@@ -188,8 +184,8 @@ void DiaryStats::render_pie_chart(std::vector const &rating_counts)
// If there is no data for the current month, display an empty pie chart.
pie_series->append(ratings[0], current_date.daysInMonth());
auto slice = pie_series->slices().at(0);
- slice->setBrush(rating_colours[0]);
- slice->setLabelColor(td::Theme::Dark == theme ? almost_white : almost_black);
+ slice->setBrush(InternalManager::instance()->colour(td::ColourRole::Unknown));
+ slice->setLabelColor(InternalManager::instance()->colour(td::ColourRole::Text));
slice->setLabelVisible();
slice->setBorderWidth(4);
slice->setBorderColor(td::Theme::Dark == theme ? light_black : dark_white);
@@ -212,9 +208,9 @@ void DiaryStats::render_pie_chart(std::vector const &rating_counts)
auto slice = pie_series->slices().at(pie_series->slices().size() - 1);
slice->setBorderWidth(4);
slice->setBorderColor(td::Theme::Dark == theme ? light_black : dark_white);
- slice->setLabelColor(td::Theme::Dark == theme ? almost_white : almost_black);
+ slice->setLabelColor(InternalManager::instance()->colour(td::ColourRole::Text));
slice->setLabelVisible();
- slice->setBrush(rating_colours[static_cast(rating)]);
+ slice->setBrush(misc::rating_to_colour(rating));
}
}
@@ -236,7 +232,7 @@ void DiaryStats::render_polar_chart(std::optional const &
auto angular_axis = new QValueAxis();
angular_axis->setTickCount(angular_max + 1);
angular_axis->setLabelFormat("%d");
- angular_axis->setLabelsColor(td::Theme::Dark == theme ? almost_white : almost_black);
+ angular_axis->setLabelsColor(InternalManager::instance()->colour(td::ColourRole::Text));
angular_axis->setRange(angular_min, angular_max + 1);
angular_axis->setGridLineColor(td::Theme::Dark == theme ? light_black : dark_white);
chart->addAxis(angular_axis, QPolarChart::PolarOrientationAngular);
@@ -266,7 +262,7 @@ void DiaryStats::render_polar_chart(std::optional const &
area->setLowerSeries(lower);
area->setUpperSeries(upper);
area->setOpacity(0.75);
- area->setColor(rating_colours[static_cast(rating)]);
+ area->setColor(misc::rating_to_colour(rating));
area->setBorderColor(QColor(Qt::transparent));
area->attachAxis(angular_axis);
area->attachAxis(radial_axis);
@@ -328,10 +324,10 @@ void DiaryStats::render_spline_chart(std::optional const
x_axis->setGridLineColor(td::Theme::Dark == theme ? light_black : dark_white);
x_axis->setLabelFormat("%d");
- x_axis->setLabelsColor(td::Theme::Dark == theme ? almost_white : almost_black);
+ x_axis->setLabelsColor(InternalManager::instance()->colour(td::ColourRole::Text));
x_axis->setLabelsVisible();
x_axis->setTitleText("Day");
- x_axis->setTitleBrush(QBrush(td::Theme::Dark == theme ? almost_white : almost_black));
+ x_axis->setTitleBrush(QBrush(InternalManager::instance()->colour(td::ColourRole::Text)));
auto y_axis = new QValueAxis();
chart->addAxis(y_axis, Qt::AlignLeft);
@@ -339,17 +335,17 @@ void DiaryStats::render_spline_chart(std::optional const
y_axis->setTickCount(5);
y_axis->setGridLineColor(td::Theme::Dark == theme ? light_black : dark_white);
y_axis->setLabelFormat("%d");
- y_axis->setLabelsColor(td::Theme::Dark == theme ? almost_white : almost_black);
+ y_axis->setLabelsColor(InternalManager::instance()->colour(td::ColourRole::Text));
y_axis->setLabelsVisible();
y_axis->setTitleText("Rating");
- y_axis->setTitleBrush(QBrush(td::Theme::Dark == theme ? almost_white : almost_black));
+ y_axis->setTitleBrush(QBrush(InternalManager::instance()->colour(td::ColourRole::Text)));
auto scatter_series = new QScatterSeries();
chart->addSeries(scatter_series);
scatter_series->attachAxis(x_axis);
scatter_series->attachAxis(y_axis);
scatter_series->setMarkerSize(8);
- scatter_series->setColor(td::Theme::Dark == theme ? almost_white : almost_black);
+ scatter_series->setColor(InternalManager::instance()->colour(td::ColourRole::Text));
scatter_series->setBorderColor(QColor(Qt::transparent));
if (opt) {
@@ -358,7 +354,7 @@ void DiaryStats::render_spline_chart(std::optional const
chart->addSeries(current_spline_series);
current_spline_series->attachAxis(x_axis);
current_spline_series->attachAxis(y_axis);
- current_spline_series->setColor(rating_colours[3]);
+ current_spline_series->setColor(InternalManager::instance()->colour(td::ColourRole::Text));
for (auto const &[day, data] : (*opt)->second) {
auto const &[important, rating, dummy, d2] = data;
@@ -376,7 +372,7 @@ void DiaryStats::render_spline_chart(std::optional const
chart->addSeries(current_spline_series);
current_spline_series->attachAxis(x_axis);
current_spline_series->attachAxis(y_axis);
- current_spline_series->setColor(rating_colours[3]);
+ current_spline_series->setColor(InternalManager::instance()->colour(td::ColourRole::Text));
}
else {
++prev_day;
diff --git a/src/gui/styles/statecolorpalette.cpp b/src/gui/styles/statecolorpalette.cpp
deleted file mode 100644
index 0cefc3c..0000000
--- a/src/gui/styles/statecolorpalette.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2021 KeePassXC Team
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 or (at your option)
- * version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "statecolorpalette.h"
-
-StateColorPalette::StateColorPalette() {}
-
-void StateColorPalette::initDefaultPaletteLight()
-{
- setColor(ColorRole::Error, QStringLiteral("#FF7D7D"));
- setColor(ColorRole::Warning, QStringLiteral("#FFD30F"));
- setColor(ColorRole::Info, QStringLiteral("#84D0E1"));
- setColor(ColorRole::Incomplete, QStringLiteral("#FFD30F"));
-
- setColor(ColorRole::Unknown, QStringLiteral("#C9C9CF"));
- setColor(ColorRole::VeryBad, QStringLiteral("#7b1fa2"));
- setColor(ColorRole::Bad, QStringLiteral("#5e35b1"));
- setColor(ColorRole::Ok, QStringLiteral("#1976d2"));
- setColor(ColorRole::Good, QStringLiteral("#0097a7"));
- setColor(ColorRole::VeryGood, QStringLiteral("#4caf50"));
-
- setColor(ColorRole::True, QStringLiteral("#5EA10E"));
- setColor(ColorRole::False, QStringLiteral("#C43F31"));
-}
-
-void StateColorPalette::initDefaultPaletteDark()
-{
- setColor(ColorRole::Error, QStringLiteral("#802D2D"));
- setColor(ColorRole::Warning, QStringLiteral("#73682E"));
- setColor(ColorRole::Info, QStringLiteral("#207183"));
- setColor(ColorRole::Incomplete, QStringLiteral("#665124"));
-
- setColor(ColorRole::Unknown, QStringLiteral("#2F2F32"));
- setColor(ColorRole::VeryBad, QStringLiteral("#7b1fa2"));
- setColor(ColorRole::Bad, QStringLiteral("#5e35b1"));
- setColor(ColorRole::Ok, QStringLiteral("#1976d2"));
- setColor(ColorRole::Good, QStringLiteral("#0097a7"));
- setColor(ColorRole::VeryGood, QStringLiteral("#4caf50"));
-
- setColor(ColorRole::True, QStringLiteral("#608A22"));
- setColor(ColorRole::False, QStringLiteral("#C43F31"));
-}
diff --git a/src/gui/styles/statecolorpalette.h b/src/gui/styles/statecolorpalette.h
deleted file mode 100644
index 681c952..0000000
--- a/src/gui/styles/statecolorpalette.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2021 KeePassXC Team
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 or (at your option)
- * version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef KEEPASSXC_STATECOLORPALETTE_H
-#define KEEPASSXC_STATECOLORPALETTE_H
-
-#include
-#include
-#include
-
-// TODO fix the really janky workaround keeping this class separate.
-// Probably merge it into the internal manager class some time.
-
-/**
- * Extended color palette for indicating custom widget states.
- */
-class StateColorPalette {
- Q_GADGET
-
-public:
- StateColorPalette();
-
- enum ColorRole { Error, Warning, Info, Incomplete, True, False, Unknown, VeryBad, Bad, Ok, Good, VeryGood };
-
- inline void setColor(ColorRole role, const QColor &color)
- {
- m_colorMap[role] = color;
- }
-
- inline QColor color(ColorRole role) const
- {
- return m_colorMap.value(role);
- }
-
- void initDefaultPaletteLight();
- void initDefaultPaletteDark();
-
-private:
- QHash m_colorMap;
-};
-
-#endif // KEEPASSXC_STATECOLORPALETTE_H
diff --git a/src/main.cpp b/src/main.cpp
index 5008124..6706b43 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -21,7 +21,6 @@
#include "core/internalmanager.h"
#include "core/theoreticaldiary.h"
-#include "gui/calendarbutton.h"
#include "gui/mainwindow.h"
#include "o2requestor.h"
#include "util/runguard.h"
diff --git a/src/util/diarycalendarbutton.h b/src/util/diarycalendarbutton.h
new file mode 100644
index 0000000..64b8e59
--- /dev/null
+++ b/src/util/diarycalendarbutton.h
@@ -0,0 +1,278 @@
+/*
+ * This file is part of Theoretical Diary.
+ * Copyright (C) 2022 someretical
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef DIARYCALENDARBUTTON_H
+#define DIARYCALENDARBUTTON_H
+
+class DiaryEditor;
+
+#include
+#include
+
+#include "../core/internalmanager.h"
+#include "misc.h"
+
+static int const SIZE = 86; // Should be even.
+static int const BORDER_WIDTH = 4; // Should be even.
+static int const ROUNDNESS = 8;
+
+class DiaryCalendarButton : public QAbstractButton {
+ Q_OBJECT
+
+signals:
+ void sig_clicked(int const day);
+
+public:
+ DiaryCalendarButton(td::CalendarButtonData const &d, QWidget *p = nullptr) : QAbstractButton(p)
+ {
+ setText(QString::number(*d.day));
+ setFixedSize(QSize(SIZE, SIZE));
+ data = d;
+ mouse_down = false;
+
+ repaint();
+ }
+
+ ~DiaryCalendarButton() {}
+
+ td::CalendarButtonData data;
+ bool mouse_down;
+
+public slots:
+ void re_render(td::CalendarButtonData const &d)
+ {
+ if (d.important)
+ data.important = d.important;
+
+ if (d.rating)
+ data.rating = d.rating;
+
+ if (d.selected)
+ data.selected = d.selected;
+
+ repaint();
+ }
+
+protected:
+ void enterEvent(QEvent *)
+ {
+ repaint();
+ }
+
+ void leaveEvent(QEvent *)
+ {
+ repaint();
+ }
+
+ void mousePressEvent(QMouseEvent *)
+ {
+ mouse_down = true;
+ repaint();
+ }
+
+ void mouseReleaseEvent(QMouseEvent *e)
+ {
+ mouse_down = false;
+
+ // Mouse move events are not broadcast when the mouse is held down.
+ if (rect().contains(e->pos()))
+ emit sig_clicked(*data.day);
+
+ repaint();
+ }
+
+ void paintEvent(QPaintEvent *)
+ {
+ QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing);
+ p.drawPixmap(0, 0, generate_background());
+
+ if (*data.important)
+ p.drawPixmap(0, 0, generate_star());
+
+ p.drawPixmap(0, 0, generate_text());
+ }
+
+private:
+ QPixmap generate_background()
+ {
+ QString key = QString("calendarbutton:bkg:%1:%2:%3")
+ .arg(QString::number(static_cast(*data.rating)),
+ QString::number(static_cast(InternalManager::instance()->get_theme())),
+ QString::number(get_state()));
+ QPixmap pixmap;
+
+ if (!QPixmapCache::find(key, pixmap)) {
+ pixmap = QPixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
+
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
+
+ QPainterPath path;
+ auto topleft_offset = BORDER_WIDTH / 2;
+ auto adjusted_size = SIZE - BORDER_WIDTH;
+ path.addRoundedRect(
+ QRect(topleft_offset, topleft_offset, adjusted_size, adjusted_size), ROUNDNESS, ROUNDNESS);
+
+ if (InternalManager::instance()->get_theme() == td::Theme::Light)
+ p.setOpacity(0.8);
+
+ // Set background color.
+ QColor color = misc::rating_to_colour(*data.rating);
+ if (mouse_down) {
+ p.fillPath(path, QBrush(color.darker(120)));
+ }
+ // else if (underMouse()) {
+ // p.fillPath(path, QBrush(color.lighter(110)));
+ // }
+ else {
+ p.fillPath(path, QBrush(color));
+ }
+
+ // Set border color.
+ if (mouse_down || underMouse() || *data.selected) {
+ if (InternalManager::instance()->get_theme() == td::Theme::Light) {
+ p.strokePath(path, QPen(QBrush(color.lighter(110)), BORDER_WIDTH));
+ }
+ else {
+ p.strokePath(path, QPen(QBrush(color.darker(130)), BORDER_WIDTH));
+ }
+ }
+ else {
+ p.setCompositionMode(QPainter::CompositionMode_Clear); // This will actually erase.
+ p.strokePath(path, QPen(QBrush(Qt::transparent), BORDER_WIDTH));
+ }
+
+ QPixmapCache::insert(key, pixmap);
+ }
+
+ return pixmap;
+ }
+
+ QPixmap generate_text()
+ {
+ QString day = QString::number(*data.day);
+ QPixmap pixmap;
+
+ if (*data.current_day) {
+
+ pixmap = QPixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
+
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
+
+ auto bold_font = QApplication::font();
+ bold_font.setBold(true);
+ bold_font.setItalic(true);
+ bold_font.setPointSize(16);
+ p.setFont(bold_font);
+
+ QRectF rect;
+ rect = p.boundingRect(pixmap.rect(), Qt::AlignTop | Qt::AlignRight, day);
+ rect.translate(-12, 8);
+
+ p.setPen(misc::theme_to_text(misc::rating_to_theme(*data.rating)));
+ p.drawText(rect, Qt::AlignTop | Qt::AlignRight, day);
+
+ return pixmap;
+ }
+
+ auto theme = QString::number(static_cast(misc::rating_to_theme(*data.rating)));
+ QString key = QString("calendarbutton:text:%1:%2").arg(day, theme);
+
+ if (!QPixmapCache::find(key, pixmap)) {
+ pixmap = QPixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
+
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
+
+ auto bold_font = QApplication::font();
+ bold_font.setBold(true);
+ bold_font.setPointSize(16);
+ QRectF rect;
+
+ p.setFont(bold_font);
+ rect = p.boundingRect(pixmap.rect(), Qt::AlignTop | Qt::AlignRight, day);
+ rect.translate(-10, 8);
+
+ p.setPen(misc::theme_to_text(misc::rating_to_theme(*data.rating)));
+ p.drawText(rect, Qt::AlignTop | Qt::AlignRight, day);
+
+ QPixmapCache::insert(key, pixmap);
+ }
+
+ return pixmap;
+ }
+
+ QPixmap generate_star()
+ {
+ auto theme_str = misc::rating_to_theme(*data.rating) == td::Theme::Dark ? "dark" : "light";
+ QString key = QString("calendarbutton:star:%1:%2").arg(theme_str, QString::number(get_state()));
+ QPixmap pixmap;
+
+ if (!QPixmapCache::find(key, pixmap)) {
+ pixmap = QPixmap(SIZE, SIZE);
+ pixmap.fill(Qt::transparent);
+
+ QPainter p(&pixmap);
+ p.setRenderHint(QPainter::Antialiasing);
+
+ if (mouse_down) {
+ p.setOpacity(0.4);
+ }
+ else if (underMouse()) {
+ p.setOpacity(0.4);
+ }
+ else {
+ p.setOpacity(0.5);
+ }
+
+ auto overlay = QIcon(QString(":/themes/%1/star.svg").arg(theme_str)).pixmap(SIZE * 0.8, SIZE * 0.8);
+
+ // Draw overlay on the centre of the pixmap.
+ auto x = ((rect().bottomRight().x() - overlay.rect().bottomRight().x()) / 2);
+ // y is the same as x since it's a square.
+
+ p.drawPixmap(x, x, overlay);
+
+ QPixmapCache::insert(key, pixmap);
+ }
+
+ return pixmap;
+ }
+
+ int get_state()
+ {
+ // If the mouse is NOT hovering over and NOT clicking, state is 0.
+ // If the mouse IS hovering over but not clicking, state is 1.
+ // If the mouse IS hovering over AND clicking, state is 2.
+
+ if (mouse_down)
+ return 2;
+
+ if (underMouse() || *data.selected)
+ return 1;
+
+ return 0;
+ }
+};
+
+#endif // DIARYCALENDARBUTTON_H
diff --git a/src/util/diarycomparisonlabel.h b/src/util/diarycomparisonlabel.h
index 32062a7..f590fc9 100644
--- a/src/util/diarycomparisonlabel.h
+++ b/src/util/diarycomparisonlabel.h
@@ -47,12 +47,13 @@ class DiaryComparisonLabel : public QLabel {
QPixmap generate_pixmap()
{
if (special) {
- auto theme_str = InternalManager::instance()->get_theme() == td::Theme::Light ? "light" : "dark";
+ auto theme_str = InternalManager::instance()->get_theme_str(true);
auto svg = QIcon(QString(":/themes/%1/star.svg").arg(theme_str)).pixmap(size());
QPixmap bkg(SIZE, SIZE);
bkg.fill(Qt::transparent);
QPainter p(&bkg);
+ p.setRenderHint(QPainter::Antialiasing);
p.setOpacity(0.5);
p.drawPixmap(0, 0, svg);
return bkg;
@@ -61,8 +62,9 @@ class DiaryComparisonLabel : public QLabel {
QPixmap bkg(SIZE, SIZE);
bkg.fill(Qt::transparent);
- QColor bkg_color = misc::rating_to_color(rating);
+ QColor bkg_color = misc::rating_to_colour(rating);
QPainter p(&bkg);
+ p.setRenderHint(QPainter::Antialiasing);
if (InternalManager::instance()->get_theme() == td::Theme::Light)
p.setOpacity(0.8);
@@ -90,6 +92,7 @@ class DiaryComparisonLabel : public QLabel {
}
QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing);
p.drawPixmap(0, 0, pixmap);
}
};
diff --git a/src/util/diarypixellabel.h b/src/util/diarypixellabel.h
index 22f9423..c9ffc88 100644
--- a/src/util/diarypixellabel.h
+++ b/src/util/diarypixellabel.h
@@ -70,11 +70,12 @@ public slots:
}
QPainter p(this);
+ p.setRenderHint(QPainter::Antialiasing);
p.drawPixmap(0, 0, pixmap);
// Since starred days are supposed to be a lot less common, caching isn't done for them.
if (special) {
- auto theme_str = misc::rating_to_theme(rating) == td::Theme::Light ? "light" : "dark";
+ auto theme_str = misc::rating_to_theme(rating) == td::Theme::Dark ? "dark" : "light";
QPixmap svg_overlay = QIcon(QString(":/themes/%1/star.svg").arg(theme_str)).pixmap(size_);
p.setOpacity(0.5);
@@ -87,14 +88,15 @@ public slots:
{
QPixmap bkg(size_.width(), size_.width());
bkg.fill(Qt::transparent);
- QColor bkg_color = misc::rating_to_color(rating);
+ QColor bkg_colour = misc::rating_to_colour(rating);
QPainter p(&bkg);
+ p.setRenderHint(QPainter::Antialiasing);
if (InternalManager::instance()->get_theme() == td::Theme::Light)
p.setOpacity(0.8);
- p.setPen(bkg_color);
- p.setBrush(QBrush(bkg_color));
+ p.setPen(bkg_colour);
+ p.setBrush(QBrush(bkg_colour));
p.drawRoundedRect(0, 0, size_.width(), size_.width(), 5, 5);
return bkg;
diff --git a/src/util/misc.cpp b/src/util/misc.cpp
index dfff3b1..fc92d84 100644
--- a/src/util/misc.cpp
+++ b/src/util/misc.cpp
@@ -18,7 +18,7 @@
#include
-#include "../gui/styles/statecolorpalette.h"
+#include "../core/internalmanager.h"
#include "misc.h"
namespace misc {
@@ -80,13 +80,6 @@ void extend_top_line(std::string &top, long unsigned int const max_line_len)
top.append(max_line_len - top.size(), ' ');
}
-QString get_danger_stylesheet()
-{
- QFile file(QString(":/%1/dangerbutton.qss").arg(InternalManager::instance()->get_theme_str()));
- file.open(QIODevice::ReadOnly);
- return QString(file.readAll());
-}
-
void clear_message_boxes()
{
QWidget *w;
@@ -103,33 +96,38 @@ void clear_message_boxes()
}
}
-QColor rating_to_color(const td::Rating rating)
+QColor rating_to_colour(const td::Rating rating)
{
- auto const &c = InternalManager::instance()->state_color_palette;
+ auto intman = InternalManager::instance();
switch (rating) {
case td::Rating::Unknown:
- return c.color(StateColorPalette::ColorRole::Unknown);
+ return intman->colour(td::ColourRole::Unknown);
case td::Rating::VeryBad:
- return c.color(StateColorPalette::ColorRole::VeryBad);
+ return intman->colour(td::ColourRole::VeryBad);
case td::Rating::Bad:
- return c.color(StateColorPalette::ColorRole::Bad);
+ return intman->colour(td::ColourRole::Bad);
case td::Rating::Ok:
- return c.color(StateColorPalette::ColorRole::Ok);
+ return intman->colour(td::ColourRole::Ok);
case td::Rating::Good:
- return c.color(StateColorPalette::ColorRole::Good);
+ return intman->colour(td::ColourRole::Good);
case td::Rating::VeryGood:
- return c.color(StateColorPalette::ColorRole::VeryGood);
+ return intman->colour(td::ColourRole::VeryGood);
}
// This can never happen, it's only here to shut down the compiler warning.
- return c.color(StateColorPalette::ColorRole::Unknown);
+ return intman->colour(td::ColourRole::Unknown);
}
td::Theme rating_to_theme(const td::Rating rating)
{
switch (rating) {
case td::Rating::Unknown:
+ if (InternalManager::instance()->get_theme() == td::Theme::Light)
+ return td::Theme::Dark;
+ else
+ return td::Theme::Light;
+
case td::Rating::VeryBad:
case td::Rating::Bad:
case td::Rating::Ok:
@@ -142,4 +140,27 @@ td::Theme rating_to_theme(const td::Rating rating)
// This can never happen, it's only here to shut down the compiler warning.
return td::Theme::Dark;
}
+
+static const auto light_text = QColor("#CACBCE");
+static const auto dark_text = QColor("#1D1D20");
+
+QColor theme_to_text(const td::Theme theme)
+{
+ if (td::Theme::Light == theme) {
+ return light_text;
+ }
+ else {
+ return dark_text;
+ }
+}
+
+QString sanitise_html(std::string const &str)
+{
+ return QString::fromStdString(str)
+ .replace("&", "&")
+ .replace("<", "<")
+ .replace(">", ">")
+ .replace("\n", " ");
+}
+
} // namespace misc
diff --git a/src/util/misc.h b/src/util/misc.h
index a77af72..2c09975 100644
--- a/src/util/misc.h
+++ b/src/util/misc.h
@@ -49,10 +49,11 @@ inline std::string &trim(std::string &s)
}
void extend_top_line(std::string &top, long unsigned int const max_line_len);
-QString get_danger_stylesheet();
void clear_message_boxes();
-QColor rating_to_color(td::Rating const rating);
+QColor rating_to_colour(td::Rating const rating);
td::Theme rating_to_theme(const td::Rating rating);
+QColor theme_to_text(const td::Theme theme);
+QString sanitise_html(std::string const &str);
} // namespace misc
#endif // MISC_H
diff --git a/src/util/passwordlineedit.cpp b/src/util/passwordlineedit.cpp
deleted file mode 100644
index 36ccbc3..0000000
--- a/src/util/passwordlineedit.cpp
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * This file is part of Theoretical Diary.
- * Copyright (C) 2022 someretical
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-// The code in this file was adapted from https://stackoverflow.com/a/51194796.
-
-#include "passwordlineedit.h"
-#include "../core/internalmanager.h"
-
-PasswordLineEdit::PasswordLineEdit(QWidget *parent) : QLineEdit(parent)
-{
- setEchoMode(QLineEdit::Password);
-
- auto monospaced = QFontDatabase::systemFont(QFontDatabase::FixedFont);
- monospaced.setLetterSpacing(QFont::PercentageSpacing, 110);
- setFont(monospaced);
-
- QAction *action = addAction(QIcon(get_eye_icon(false)), QLineEdit::TrailingPosition);
- button = qobject_cast(action->associatedWidgets().last());
- button->setCursor(QCursor(Qt::PointingHandCursor));
- connect(button, &QToolButton::pressed, this, &PasswordLineEdit::on_pressed, Qt::QueuedConnection);
- connect(button, &QToolButton::released, this, &PasswordLineEdit::on_released, Qt::QueuedConnection);
-}
-
-void PasswordLineEdit::on_pressed()
-{
- QToolButton *button = qobject_cast(sender());
- button->setIcon(QIcon(get_eye_icon(true)));
- setEchoMode(QLineEdit::Normal);
-}
-
-void PasswordLineEdit::on_released()
-{
- QToolButton *button = qobject_cast(sender());
- button->setIcon(QIcon(get_eye_icon(false)));
- setEchoMode(QLineEdit::Password);
-}
-
-QString PasswordLineEdit::get_eye_icon(bool const on)
-{
- return QString(":/themes/%1/%2.svg").arg(InternalManager::instance()->get_theme_str(), on ? "eye_on" : "eye_off");
-}
diff --git a/src/util/passwordlineedit.h b/src/util/passwordlineedit.h
index bc6e1ad..dd5cb9d 100644
--- a/src/util/passwordlineedit.h
+++ b/src/util/passwordlineedit.h
@@ -23,18 +23,59 @@
#include
+#include "../core/internalmanager.h"
+
+// The code in this file was adapted from https://stackoverflow.com/a/51194796.
+
class PasswordLineEdit : public QLineEdit {
public:
- PasswordLineEdit(QWidget *parent = nullptr);
+ PasswordLineEdit(QWidget *parent = nullptr) : QLineEdit(parent)
+ {
+ setEchoMode(QLineEdit::Password);
+
+ auto monospaced = QFontDatabase::systemFont(QFontDatabase::FixedFont);
+ monospaced.setLetterSpacing(QFont::PercentageSpacing, 110);
+ setFont(monospaced);
+
+ QAction *action = addAction(QIcon(get_eye_icon(false)), QLineEdit::TrailingPosition);
+ button = qobject_cast(action->associatedWidgets().last());
+ button->setCursor(QCursor(Qt::PointingHandCursor));
+ connect(button, &QToolButton::pressed, this, &PasswordLineEdit::on_pressed, Qt::QueuedConnection);
+ connect(button, &QToolButton::released, this, &PasswordLineEdit::on_released, Qt::QueuedConnection);
+
+ connect(InternalManager::instance(), &InternalManager::update_theme, this, &PasswordLineEdit::update_theme,
+ Qt::QueuedConnection);
+ }
+
+public slots:
+ void update_theme()
+ {
+ button->setIcon(QIcon(get_eye_icon(true)));
+ }
private slots:
- void on_pressed();
- void on_released();
+ void on_pressed()
+ {
+ QToolButton *button = qobject_cast(sender());
+ button->setIcon(QIcon(get_eye_icon(true)));
+ setEchoMode(QLineEdit::Normal);
+ }
+
+ void on_released()
+ {
+ QToolButton *button = qobject_cast(sender());
+ button->setIcon(QIcon(get_eye_icon(false)));
+ setEchoMode(QLineEdit::Password);
+ }
private:
QToolButton *button;
- QString get_eye_icon(bool const on);
+ QString get_eye_icon(bool const on)
+ {
+ return QString(":/themes/%1/%2.svg")
+ .arg(InternalManager::instance()->get_theme_str(true), on ? "eye_on" : "eye_off");
+ }
};
#endif // PASSWORDLINEEDIT_H
diff --git a/styles/dark/darkstyle.qss b/styles/dark/darkstyle.qss
index a9aef28..ee7502c 100644
--- a/styles/dark/darkstyle.qss
+++ b/styles/dark/darkstyle.qss
@@ -1,10 +1,8 @@
-DatabaseWidget:!active, GroupView:!active,
-EntryPreviewWidget QLineEdit:!active, EntryPreviewWidget QTextEdit:!active {
+GroupView:!active,QLineEdit:!active, QTextEdit:!active {
background-color: #404042;
}
-DatabaseWidget:disabled, GroupView:disabled,
-EntryPreviewWidget QLineEdit:disabled, EntryPreviewWidget QTextEdit:disabled {
+GroupView:disabled, QLineEdit:disabled, QTextEdit:disabled {
background-color: #424242;
}
@@ -26,3 +24,7 @@ QToolTip {
QGroupBox {
background-color: palette(light);
}
+
+QTextEdit#entry_edit {
+ background-color: #39393C;
+}
diff --git a/styles/light/lightstyle.qss b/styles/light/lightstyle.qss
index 5a8fe64..3818824 100644
--- a/styles/light/lightstyle.qss
+++ b/styles/light/lightstyle.qss
@@ -1,10 +1,8 @@
-DatabaseWidget:!active, GroupView:!active,
-EntryPreviewWidget QLineEdit:!active, EntryPreviewWidget QTextEdit:!active {
+GroupView:!active, QLineEdit:!active, QTextEdit:!active {
background-color: #FCFCFC;
}
-DatabaseWidget:disabled, GroupView:disabled,
-EntryPreviewWidget QLineEdit:disabled, EntryPreviewWidget QTextEdit:disabled {
+GroupView:disabled, QLineEdit:disabled, QTextEdit:disabled {
background-color: #EDEDED;
}
diff --git a/text/VERSION.txt b/text/VERSION.txt
index 276cbf9..2bf1c1c 100644
--- a/text/VERSION.txt
+++ b/text/VERSION.txt
@@ -1 +1 @@
-2.3.0
+2.3.1
diff --git a/theoreticaldiary.pro b/theoreticaldiary.pro
index 60e5c39..f2d9eb2 100644
--- a/theoreticaldiary.pro
+++ b/theoreticaldiary.pro
@@ -34,7 +34,6 @@ SOURCES += \
src/core/theoreticaldiary.cpp \
src/gui/aboutdialog.cpp \
src/gui/apiresponse.cpp \
- src/gui/calendarbutton.cpp \
src/gui/diaryeditor.cpp \
src/gui/diaryentryviewer.cpp \
src/gui/diarymenu.cpp \
@@ -48,13 +47,11 @@ SOURCES += \
src/gui/styles/base/phantomcolor.cpp \
src/gui/styles/dark/darkstyle.cpp \
src/gui/styles/light/lightstyle.cpp \
- src/gui/styles/statecolorpalette.cpp \
src/main.cpp \
src/util/alertlabel.cpp \
src/util/encryptor.cpp \
src/util/eventfilters.cpp \
src/util/misc.cpp \
- src/util/passwordlineedit.cpp \
src/util/runguard.cpp \
src/util/zipper.cpp
@@ -65,7 +62,6 @@ HEADERS += \
src/core/theoreticaldiary.h \
src/gui/aboutdialog.h \
src/gui/apiresponse.h \
- src/gui/calendarbutton.h \
src/gui/diaryeditor.h \
src/gui/diaryentryviewer.h \
src/gui/diarymenu.h \
@@ -79,9 +75,9 @@ HEADERS += \
src/gui/styles/base/phantomcolor.h \
src/gui/styles/dark/darkstyle.h \
src/gui/styles/light/lightstyle.h \
- src/gui/styles/statecolorpalette.h \
src/util/alertlabel.h \
src/util/custommessageboxes.h \
+ src/util/diarycalendarbutton.h \
src/util/diarycomparisonlabel.h \
src/util/diarypixellabel.h \
src/util/encryptor.h \