From ad50383d034a9f33ade547c25773d3b2d9c0a355 Mon Sep 17 00:00:00 2001 From: osamu-kj <64986162+0xdeadbeer@users.noreply.github.com> Date: Sat, 13 May 2023 15:58:02 +0200 Subject: [PATCH] Calendar: Implement basic reading feature This commit contains a lot of different changes. Starting from some refacting of user input code, coloring, and adding a basic reading feature to the program. --- README.md | 6 +- src/calendar/calendar.cpp | 34 +++++++++ src/calendar/calendar.hpp | 11 ++- src/engine/engine.cpp | 143 +++++++++++++++++++++++++++++--------- src/engine/engine.hpp | 27 +++++-- src/main.cpp | 31 ++++++--- 6 files changed, 203 insertions(+), 49 deletions(-) diff --git a/README.md b/README.md index 76290e5..45924ca 100644 --- a/README.md +++ b/README.md @@ -30,9 +30,11 @@ For example: `vis school.cal` This will open the default view mode (month) and display the current month's calendar. From there, you can use the following commands to navigate and edit the calendar: - `h/j/k/l` - Move 1 day left/down/up/right - `u/o` - Move 1 month left/right - - `gg` - Go to the beginning of the month + - `g` - Go to the beginning of the month - `G` - Go to the end of the month - - `i` - Enter insert mode for the active day. + - `i` - Enter insert mode for selected day. + - `x` - Delete event from selected day. + - `w` - Write changes to file (i.e. save) - `q` - Quit and save the calendar # Todos diff --git a/src/calendar/calendar.cpp b/src/calendar/calendar.cpp index c462cc7..a3604c0 100644 --- a/src/calendar/calendar.cpp +++ b/src/calendar/calendar.cpp @@ -11,6 +11,13 @@ calendar_information::calendar_information() { current_month_days = Calendar::get_days_in_month(current_month, current_year); } +calendar_information::calendar_information(int cday, int cmonth, int cyear) { + current_day = cday; + current_month = cmonth; + current_year = cyear; + current_month_days = Calendar::get_days_in_month(current_month, current_year); +} + int Calendar::get_days_in_month(int month, int year) { tm date = {0}; date.tm_year = year - 1900; @@ -45,7 +52,12 @@ calendar_information Calendar::get_info() { return this->info; } +calendar_information Calendar::get_current_date() { + return this->current_date; +} + Calendar::Calendar(calendar_information *preinfo) { + this->current_date = calendar_information(); this->info = *preinfo; if (preinfo != nullptr) @@ -53,3 +65,25 @@ Calendar::Calendar(calendar_information *preinfo) { this->info = calendar_information(); } + +// https://stackoverflow.com/questions/6054016/c-program-to-find-day-of-week-given-date +int get_weekday(calendar_information *date_info) { + if (date_info == nullptr) + return 0; + + int d = date_info->current_day; + int m = date_info->current_month; + int y = date_info->current_year; + + return (d += m < 3 ? y-- : y - 2, 23*m/9 + d + 4 + y/4- y/100 + y/400)%7; + +} + +int datecmp(calendar_information *one, calendar_information *two) { + if (one->current_day != two->current_day) return 0; + if (one->current_month != two->current_month) return 0; + if (one->current_month_days != two->current_month_days) return 0; + if (one->current_year != two->current_year) return 0; + return 1; +} + diff --git a/src/calendar/calendar.hpp b/src/calendar/calendar.hpp index b397e39..6b0326d 100644 --- a/src/calendar/calendar.hpp +++ b/src/calendar/calendar.hpp @@ -10,6 +10,7 @@ struct calendar_information { int current_year; calendar_information(); + calendar_information(int cday, int cmonth, int cyear); }; const bool operator<(const calendar_information& first, const calendar_information& second) { @@ -23,11 +24,17 @@ class Calendar { void set_day(int day); void set_month(int month); void set_year(int year); - calendar_information get_info(); + calendar_information get_info(); + calendar_information get_current_date(); Calendar(calendar_information *preinfo = nullptr); private: - calendar_information info; + calendar_information info; // mutable date that can be changed + calendar_information current_date; // current date }; + +int get_weekday(calendar_information *date_info = nullptr); +int datecmp(calendar_information *one, calendar_information *two); + #endif diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 70e62f7..757f694 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1,7 +1,9 @@ #include +#include #include #include #include +#include #include "engine.hpp" Engine::Engine(int padding, calendar_view_mode view_mode) { @@ -60,12 +62,20 @@ void Engine::ui_month_draw(WINDOW *win) { if (this->events_map.count(tmp_date) > 0) wattron(win, COLOR_PAIR(2)); + calendar_information current_date = this->calendar->get_current_date(); + if (datecmp(¤t_date, &tmp_date)) + wattron(win, COLOR_PAIR(3)); + if (this->active_cell == i) wattron(win, COLOR_PAIR(1)); - mvwprintw(win, y_location, x_location, "D%d", i+1); + std::string weekday_prefix = weekday_prefixes[get_weekday(&tmp_date)]; + + // mvwprintw(win, y_location, x_location, "D%d", i+1); + mvwprintw(win, y_location, x_location, "%s[%d]", weekday_prefix.c_str(), i+1); wattroff(win, COLOR_PAIR(1)); wattroff(win, COLOR_PAIR(2)); + wattroff(win, COLOR_PAIR(3)); } } @@ -81,7 +91,6 @@ void Engine::ui_top_draw(WINDOW *win) { if (VIS_COLORING) wattron(win, COLOR_PAIR(1)); mvwprintw(win, 1, 1, "Vi Scheduler"); - mvwprintw(win, 2, 1, "@0xdeadbeer"); if (VIS_COLORING) wattroff(win, COLOR_PAIR(1)); } @@ -97,12 +106,24 @@ void Engine::ui_bottom_draw(WINDOW *win) { if (VIS_COLORING) wattroff(win, COLOR_PAIR(1)); } -void Engine::input_handle_month(WINDOW *win) { - char key = getch(); +void Engine::input_handle(WINDOW *win) { + char key = getch(); + + if (this->input_handle_universal(win, key)) + return; - calendar_information date_info = this->calendar->get_info(); + if (this->view_mode == MONTH_VIEW) + this->input_handle_month(win, key); + else if (this->view_mode == WEEK_VIEW) + this->input_handle_week(win, key); + else if (this->view_mode == MONTHS_VIEW) + this->input_handle_months(win, key); - int day, month, res; + // fuc. +} + +bool Engine::input_handle_universal(WINDOW *win, char key) { + int day; switch (key) { case 'h': if (this->calendar->get_info().current_day <= 1) break; @@ -128,32 +149,14 @@ void Engine::input_handle_month(WINDOW *win) { this->active_cell += 7; break; - case 'k': if (this->calendar->get_info().current_day-7 < 1) break; + case 'k': day = this->calendar->get_info().current_day; this->calendar->set_day(day-7); this->active_cell -= 7; break; - case 'u': - if (this->calendar->get_info().current_month <= 1) break; - - month = this->calendar->get_info().current_month; - this->calendar->set_month(--month); - this->calendar->set_day(1); - - this->active_cell = 0; - break; - case 'o': - if (this->calendar->get_info().current_month >= 12) break; - - month = this->calendar->get_info().current_month; - this->calendar->set_month(++month); - this->calendar->set_day(1); - - this->active_cell = 0; - break; case 'i': { // TODO: Break down this monstrocity of a case endwin(); int vipe_out[2], vipe_in[2]; @@ -196,10 +199,48 @@ void Engine::input_handle_month(WINDOW *win) { break; } case 'x': { - calendar_information date_info = this->calendar->get_info(); + calendar_information date_info = this->calendar->get_info(); this->events_map.erase(date_info); break; } + case 'w': + break; + case 'q': + endwin(); + exit(EXIT_SUCCESS); + break; + default: + return false; + break; + } + + return true; +} + +void Engine::input_handle_month(WINDOW *win, char key) { + + calendar_information date_info = this->calendar->get_info(); + + int month; + switch (key) { + case 'u': + if (this->calendar->get_info().current_month <= 1) break; + + month = this->calendar->get_info().current_month; + this->calendar->set_month(--month); + this->calendar->set_day(1); + + this->active_cell = 0; + break; + case 'o': + if (this->calendar->get_info().current_month >= 12) break; + + month = this->calendar->get_info().current_month; + this->calendar->set_month(++month); + this->calendar->set_day(1); + + this->active_cell = 0; + break; case 'g': this->calendar->set_day(1); this->active_cell = 0; @@ -208,17 +249,55 @@ void Engine::input_handle_month(WINDOW *win) { this->calendar->set_day(this->calendar->get_info().current_month_days); this->active_cell = this->calendar->get_info().current_month_days-1; break; - case 't': - this->view_mode = WEEK_VIEW; - wclear(win); - break; } } -void Engine::input_handle_week(WINDOW *win) { +void Engine::input_handle_week(WINDOW *win, char key) { // TODO } -void Engine::input_handle_months(WINDOW *win) { +void Engine::input_handle_months(WINDOW *win, char key) { // TODO } + +calendar_information Engine::parse_date(std::string date) { + char *token = strtok((char *) date.c_str(), "."); + std::vector tokens; + + while (token != NULL) { + tokens.push_back(std::stoi(token)); + token = strtok(NULL, "."); + } + + return calendar_information(tokens[0], tokens[1], tokens[2]); +} + +void Engine::parse_line(std::string line) { + char *token = strtok((char *) line.c_str(), " "); + std::vector tokens; + + while (token != NULL) { + tokens.push_back(token); + token = strtok(NULL, " "); + } + + if (tokens.size() != 2) + return; + + calendar_information event_date = this->parse_date(tokens[0]); + this->events_map[event_date] = tokens[1]; +} + +void Engine::open_calendar(char *filename) { + this->calendar_file.open(filename, std::ios::in | std::ios::out); + + // If the file does not exist, + // we'll create and reopen it later ('write' shortcut) + if (this->calendar_file.fail()) + return; + + std::string line; + while (std::getline(this->calendar_file, line)) { + this->parse_line(line); + } +} diff --git a/src/engine/engine.hpp b/src/engine/engine.hpp index 69b37c6..e1ff2e3 100644 --- a/src/engine/engine.hpp +++ b/src/engine/engine.hpp @@ -2,6 +2,7 @@ #define ENGINE_HPP #include +#include #include #include // #include @@ -20,6 +21,16 @@ enum calendar_view_mode { MONTHS_VIEW }; +std::string weekday_prefixes[] = { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat" +}; + std::string calendar_view_mode_str[] = { "MONTH_VIEW", "WEEK_VIEW", @@ -30,7 +41,7 @@ std::string calendar_view_mode_str[] = { // description: use for drawing the TUI and interact with the cells class Engine { public: - Engine(int padding = 10, calendar_view_mode view_mode = MONTH_VIEW); + Engine(int padding, calendar_view_mode view_mode); ~Engine(); void ui_draw(WINDOW *win); @@ -40,9 +51,15 @@ class Engine { void ui_bottom_draw(WINDOW *win); void ui_top_draw(WINDOW *win); - void input_handle_month(WINDOW *win); - void input_handle_week(WINDOW *win); - void input_handle_months(WINDOW *win); + void input_handle(WINDOW* win); + bool input_handle_universal(WINDOW *win, char key); + void input_handle_month(WINDOW *win, char key); + void input_handle_week(WINDOW *win, char key); + void input_handle_months(WINDOW *win, char key); + + calendar_information parse_date(std::string date); + void parse_line(std::string line); + void open_calendar(char *filename); Calendar *calendar; // std::unordered_map events_map; @@ -54,7 +71,7 @@ class Engine { private: std::vector cells_table; - + std::fstream calendar_file; }; #endif diff --git a/src/main.cpp b/src/main.cpp index 4442635..1f2744e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,7 +6,7 @@ #include "engine/engine.hpp" #include "global/global.hpp" -Engine engine = Engine(10, MONTH_VIEW); +Engine engine(10, MONTH_VIEW); WINDOW *main_win; void sig_winch(int sig) { @@ -31,7 +31,25 @@ void signals() { signal(SIGWINCH, sig_winch); } -int main() { +void print_help() { + +} + +bool check_args(int argc, char **argv) { + if (argc != 2) { + print_help(); + return false; + } + + engine.open_calendar(argv[1]); + + return true; +} + +int main(int argc, char **argv) { + if (!check_args(argc, argv)) + return EXIT_FAILURE; + initscr(); refresh(); @@ -49,6 +67,7 @@ int main() { init_pair(0, COLOR_WHITE, COLOR_BLACK); init_pair(1, COLOR_BLACK, COLOR_WHITE); init_pair(2, COLOR_BLACK, COLOR_RED); + init_pair(3, COLOR_BLACK, COLOR_GREEN); } // handle required signals @@ -57,14 +76,10 @@ int main() { for (;;) { engine.ui_draw(main_win); - if (engine.view_mode == MONTH_VIEW) - engine.input_handle_month(main_win); - if (engine.view_mode == WEEK_VIEW) - engine.input_handle_week(main_win); - else if (engine.view_mode == MONTHS_VIEW) - engine.input_handle_months(main_win); + engine.input_handle(main_win); } + endwin(); return 0;