aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c433
1 files changed, 189 insertions, 244 deletions
diff --git a/main.c b/main.c
index aa076f8..8549ec2 100644
--- a/main.c
+++ b/main.c
@@ -44,8 +44,6 @@ const char *DB_FILE_SIGN = "TTT:B:01";
const size_t SIZEOF_DB_FILE_SIGN = sizeof(DB_FILE_SIGN);
const size_t SIZEOF_TASK_T = sizeof(task_t);
const size_t SIZEOF_DATABASE_T = sizeof(database_t);
-const char *DAYS_OF_WEEK[] = { "sun", "mon", "tue", "wed", "thu", "fri", "sat" };
-const uint8_t DAYS_ON_WEEK = sizeof(DAYS_OF_WEEK)/sizeof(char*);
database_t database;
database_t archive; // TODO To be implemented in the future.
@@ -92,17 +90,23 @@ void print_task(const task_t *task) {
printf("t[6]: '%" PRIu32 "'\n", task->times[6]);
}
-char* get_time_task(uint32_t time, char* string) {
+char* format_time(uint32_t time, char* string) {
const time_t seconds_per_day = 25*60*60;
if (time > 24*60*60) {
// ---.-- d
// │ 3│
// │ │
- sprintf(string, "%5.2f d", (double)time / (double)seconds_per_day);
+ sprintf(string, "%5.2fd", (double)time / (double)seconds_per_day);
}
- double hours = (double)time / 3600.0;
- double minutes = (time - (time_t)hours) / 60.0;
- sprinf(string, "%3.0f:%02f", hours, minutes);
+ else if (time > 60) {
+ double hours = (double)time / 3600.0;
+ double minutes = (time - (time_t)hours) / 60.0;
+ sprintf(string, "%02.0f:%02.0f", hours, minutes);
+ }
+ else {
+ sprintf(string, "%2dsec", time);
+ }
+ return string;
}
@@ -266,13 +270,13 @@ bool export_to_csv(const database_t *db, const char *path_name) {
fprintf(file, "%s,%s,%s,%s,%s,%s,%s,%s\n",
"task",
- DAYS_OF_WEEK[0],
- DAYS_OF_WEEK[1],
- DAYS_OF_WEEK[2],
- DAYS_OF_WEEK[3],
- DAYS_OF_WEEK[4],
- DAYS_OF_WEEK[5],
- DAYS_OF_WEEK[6]
+ "sunday",
+ "monday",
+ "tuesday",
+ "wednesday",
+ "thursday",
+ "friday",
+ "saturday"
);
char name[MAX_TASK_NAME];
@@ -525,14 +529,10 @@ void update_timers(database_t *db) {
active_task->times[start_week_day] += next_start - start_time;
-
-// fprintf(stderr, "Added '%zu' on %s\n", next_start - start_time, DAYS_OF_WEEK[start_week_day]);
-
start_time = next_start;
}
db->modified_on = stop_time;
-// fprintf(stderr, "> done\n");
}
@@ -541,53 +541,71 @@ char *line_buffer;
int size_x, size_y, pos_x, pos_y;
uint8_t selected_layout = 0;
-#define TABLE_HEADERS_SIZE 9
+#define NUM_OF_COLUMNS 9
typedef struct {
- int table_size;
- int table_headers_size;
- char *table_headers[TABLE_HEADERS_SIZE];
+ int columns_size;
+ char *table_headers[NUM_OF_COLUMNS];
+ int column_widths[NUM_OF_COLUMNS];
+ char alignments[NUM_OF_COLUMNS];
} layout_t;
layout_t *layouts = NULL;
-void initialize_layouts() {
- layout_t *layout = NULL;
+void initialize_tui() {
layouts = calloc(2, sizeof(layout_t));
// Layout : 0 : normal.
- layout = &layouts[0];
- layout->table_size = 8;
- layout->table_headers_size = TABLE_HEADERS_SIZE;
// TODO Headers must be dynamic according to FIRST_DAY_OF_WEEK
- layout->table_headers[0] = " Task Time Tracker v1 ";
- layout->table_headers[1] = " Sun ";
- layout->table_headers[2] = " Mon ";
- layout->table_headers[3] = " Tue ";
- layout->table_headers[4] = " Wed ";
- layout->table_headers[5] = " Thu ";
- layout->table_headers[6] = " Fri ";
- layout->table_headers[7] = " Sat ";
- layout->table_headers[8] = " Total ";
-// layout->table_headers = { " Task ", " Mon ", " Tue ", " Wed ", " Thu ", " Fri ", " Sat ", " Sun ", " Total " };
-
+ layouts[0] = (layout_t) {
+ .columns_size = 8,
+
+ .column_widths = { -1, 7, 7, 7, 7, 7, 7, 7, 9 },
+ .alignments = { 'L', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C' },
+ .table_headers = {
+ " Task Time Tracker v1 ",
+ " Sun ",
+ " Mon ",
+ " Tue ",
+ " Wed ",
+ " Thu ",
+ " Fri ",
+ " Sat ",
+ " Total ",
+ },
+ };
+
// Layout : 1 : compact.
- layout = &layouts[1];
- layout->table_size = 6;
- layout->table_headers_size = TABLE_HEADERS_SIZE;
// TODO Headers must be dynamic according to FIRST_DAY_OF_WEEK
- layout->table_headers[0] = " TTT ";
- layout->table_headers[1] = " S ";
- layout->table_headers[2] = " M ";
- layout->table_headers[3] = " T ";
- layout->table_headers[4] = " W ";
- layout->table_headers[5] = " T ";
- layout->table_headers[6] = " F ";
- layout->table_headers[7] = " S ";
- layout->table_headers[8] = " # ";
-// layout->table_headers = { " T ", " M ", " T ", " W ", " T ", " F ", " S ", " S ", " # " };
+ layouts[1] = (layout_t){
+ .columns_size = 6,
+
+ .column_widths = { -1, 5, 5, 5, 5, 5, 5, 5, 5 },
+ .alignments = { 'L', 'C', 'C', 'C', 'C', 'C', 'C', 'C', 'C' },
+ .table_headers = {
+ " TTT v1 ",
+ " S ",
+ " M ",
+ " T ",
+ " W ",
+ " T ",
+ " F ",
+ " S ",
+ " # ",
+ },
+ };
+
+ initscr(); // Start curses mode.
+ cbreak(); // Line buffering disabled, Pass on everty thing to me.
+ keypad(stdscr, TRUE); // I need that nifty F1
+ curs_set(0); // Set cursor invisible.
+
+ start_color();
+ init_pair(1, COLOR_BLUE, COLOR_BLACK);
+ init_pair(2, COLOR_BLACK, COLOR_CYAN);
+ init_pair(3, COLOR_WHITE, COLOR_BLUE);
}
void initialization() {
@@ -606,41 +624,94 @@ void free_memory() {
layouts = NULL;
}
-void draw_header() {
-
+
+void draw_tui() {
layout_t *layout = &layouts[selected_layout];
- int table_size = layout->table_size;
+ int columns_size = layout->columns_size;
char **table_headers = layout->table_headers;
- mvaddch(0, 0, ACS_ULCORNER);
- for (int idx = 1; idx < size_x-1; idx++) {
- addch(ACS_HLINE);
+ time_t now_utc = time(NULL);
+ uint8_t today = localtime(&now_utc)->tm_wday;
+ int color_pair = 0;
+
+ // The first column expands to fill the remaining space (is dynamic).
+ layout->column_widths[0] = size_x - (NUM_OF_COLUMNS - 1) - 2;
+ for (int idx = 1; idx < NUM_OF_COLUMNS; idx++) {
+ layout->column_widths[0] -= layout->column_widths[idx];
}
- addch(ACS_URCORNER);
- int start_columns = size_x - 1 - 8*table_size - 2;
- int columns[] = {
- 0,
- start_columns+(table_size*0),
- start_columns+(table_size*1),
- start_columns+(table_size*2),
- start_columns+(table_size*3),
- start_columns+(table_size*4),
- start_columns+(table_size*5),
- start_columns+(table_size*6),
- start_columns+(table_size*7),
- };
- time_t now = time(NULL);
- uint8_t today = localtime(&now)->tm_wday + 1;
+ clear();
- start_color();
- init_pair(1, COLOR_BLUE, COLOR_BLACK);
- init_pair(2, COLOR_BLACK, COLOR_CYAN);
- init_pair(3, COLOR_WHITE, COLOR_BLUE);
- int color_pair = 1;
+ // Draw outer border.
+ box(stdscr, 0, 0);
+
+ // Draw column grids.
+ int x = 0;
+ for (int idx = 0; idx < NUM_OF_COLUMNS - 1; idx++) {
+
+ x += 1 + layout->column_widths[idx];
+ mvaddch(0, x, ACS_TTEE);
+ for (int y = 1; y < size_y - 1; y++) {
+ mvaddch(y, x, ACS_VLINE);
+ }
+ mvaddch(size_y - 1, x, ACS_BTEE);
+ }
+
+ // Draw headers.
+ // TODO Missing some spacing on the initial column.
+ x = 0;
+ for (int idx = 0; idx < NUM_OF_COLUMNS; idx++) {
+ x += 1;
+ int header_position = x;
+ switch(layout->alignments[idx]) {
+ case 'L':
+ break;
+
+ case 'C':
+ header_position += ((layout->column_widths[idx] - strlen(layout->table_headers[idx])) / 2);
+ break;
+
+ case 'R':
+ header_position += (layout->column_widths[idx] - strlen(layout->table_headers[idx]));
+ break;
+ }
+
+ mvaddstr(0, header_position, layout->table_headers[idx]);
+ x += layout->column_widths[idx];
+ }
+
+
+ // Draw tasks.
+ int y = 0;
+ for (task_t *task = database.tasks; task < database.tasks + database.count; task++) {
+ y++;
+ int x = 0;
+ x++;
+ mvaddstr(y, x, task->name);
+// x += 1 + layouts->column_widths[0];
+// mvaddstr(y, x,
+ }
+
+ // WIP TODO TASK BUG TEST HACK WARNING
+
+ return;
+
+ int start_columns = size_x - 1 - 8*columns_size;
+ int columns[] = {
+ 0,
+ start_columns+(columns_size*0),
+ start_columns+(columns_size*1),
+ start_columns+(columns_size*2),
+ start_columns+(columns_size*3),
+ start_columns+(columns_size*4),
+ start_columns+(columns_size*5),
+ start_columns+(columns_size*6),
+ start_columns+(columns_size*7),
+ };
+
mvaddstr(0, columns[0]+2, table_headers[0]);
for (int idx = 1; idx < 9; idx++) { // TODO When does the week start?
@@ -650,67 +721,44 @@ void draw_header() {
attron(COLOR_PAIR(color_pair));
}
+// mvaddch(0, columns[idx]+1, ACS_RTEE);
mvaddstr(0, columns[idx]+2, table_headers[idx]);
+// mvaddch(0, columns[idx+1]-1, ACS_LTEE);
if (idx == today) {
attroff(COLOR_PAIR(color_pair));
}
}
-}
-
-void draw_table() {
- task_t *task;
- task_t *active_task;
- task_t *selected_task;
-
- layout_t *layout = &layouts[selected_layout];
- int table_size = layout->table_size;
-// char **table_headers = layout->table_headers;
-
- // TODO Maybe move this to side function?
- start_color();
- init_pair(1, COLOR_BLUE, COLOR_BLACK);
- init_pair(2, COLOR_BLACK, COLOR_CYAN);
- init_pair(3, COLOR_WHITE, COLOR_BLUE);
- int color_pair;
+ ///////////////////////////////////////////////////////////////////////////
+ // Table
- int start_columns = size_x - 1 - 8*table_size - 2;
- int columns[] = {
- 0,
- start_columns+(table_size*0),
- start_columns+(table_size*1),
- start_columns+(table_size*2),
- start_columns+(table_size*3),
- start_columns+(table_size*4),
- start_columns+(table_size*5),
- start_columns+(table_size*6),
- start_columns+(table_size*7),
- size_x-1,
- };
+ task_t *x_task;
+ task_t *active_task;
+ task_t *selected_task;
+
// Draw rows with tasks.
move(1, 0);
active_task = database.tasks + database.active_task;
selected_task = database.tasks + database.selected_task;
-
uint64_t total = 0;
uint64_t totals[8] = {0, 0, 0, 0, 0, 0, 0, 0};
- for (uint32_t idx = 0; idx < database.count; idx++){
+ for (size_t idx = 0; idx < database.count; idx++){
- task = &database.tasks[idx];
+ x_task = &database.tasks[idx];
// Enable highlight color on selected entry.
color_pair = 0;
- if (task == active_task) {
+ if (x_task == active_task) {
color_pair = 1;
}
- if (task == selected_task) {
+ if (x_task == selected_task) {
color_pair = 2;
}
- if (task == active_task && task == selected_task) {
+ if (x_task == active_task && x_task == selected_task) {
color_pair = 3;
}
if (color_pair == 1 || color_pair == 3) {
@@ -723,28 +771,36 @@ void draw_table() {
line_buffer[size_x-1] = '\0';
// Check maximum available space for task name and print it accordingly.
- size_t task_name_length = strlen(task->name)*sizeof(char);
+ size_t task_name_length = strlen(x_task->name)*sizeof(char);
size_t max_column_length = start_columns - 2;
size_t copy_length = task_name_length < max_column_length ? task_name_length : max_column_length;
- memcpy(line_buffer+2, task->name, copy_length);
+ memcpy(line_buffer+2, x_task->name, copy_length);
- uint32_t *time = task->times;
- sprintf(line_buffer + columns[1], "%8d", time[0]);
- sprintf(line_buffer + columns[2], "%8d", time[1]);
- sprintf(line_buffer + columns[3], "%8d", time[2]);
- sprintf(line_buffer + columns[4], "%8d", time[3]);
- sprintf(line_buffer + columns[5], "%8d", time[4]);
- sprintf(line_buffer + columns[6], "%8d", time[5]);
- sprintf(line_buffer + columns[7], "%8d", time[6]);
+ uint32_t *times = x_task->times;
+ sprintf(line_buffer + columns[1], "%8d", times[0]);
+ sprintf(line_buffer + columns[2], "%8d", times[1]);
+ sprintf(line_buffer + columns[3], "%8d", times[2]);
+ sprintf(line_buffer + columns[4], "%8d", times[3]);
+ sprintf(line_buffer + columns[5], "%8d", times[4]);
+ sprintf(line_buffer + columns[6], "%8d", times[5]);
+ sprintf(line_buffer + columns[7], "%8d", times[6]);
+// char time_str[7];
+// sprintf(line_buffer + columns[1], "%s", format_time(times[0], time_str));
+// sprintf(line_buffer + columns[2], "%s", format_time(times[1], time_str));
+// sprintf(line_buffer + columns[3], "%s", format_time(times[2], time_str));
+// sprintf(line_buffer + columns[4], "%s", format_time(times[3], time_str));
+// sprintf(line_buffer + columns[5], "%s", format_time(times[4], time_str));
+// sprintf(line_buffer + columns[6], "%s", format_time(times[5], time_str));
+// sprintf(line_buffer + columns[7], "%s", format_time(times[6], time_str));
// Update totals.
total = 0;
- for(int idx = DAYS_ON_WEEK-1; idx >= 0; idx--) {
- total += time[idx];
- totals[idx] += time[idx];
+ for(int idx = 7-1; idx >= 0; idx--) {
+ total += times[idx];
+ totals[idx] += times[idx];
}
- totals[DAYS_ON_WEEK] += total;
- sprintf(line_buffer + columns[8], "%10" PRIu64, total); // BUG This causes "corrupted size vs. prev_size because it is writing beyond line_buffer size.
+ totals[7] += total;
+ sprintf(line_buffer + columns[8], "%6" PRIu64, total); // BUG This causes "corrupted size vs. prev_size because it is writing beyond line_buffer size.
addstr(line_buffer);
@@ -774,73 +830,9 @@ void draw_table() {
sprintf(line_buffer + columns[6], "%8" PRIu64, totals[5]);
sprintf(line_buffer + columns[7], "%8" PRIu64, totals[6]);
mvaddstr(pos_y, 0, line_buffer);
- pos_y++;
-
- // Draw empty rows.
- // TODO Do this properly.
- int dummy = 100;
- while (dummy > 0) {
-
- // Clear current line.
- move(pos_y, 0);
- clrtoeol();
-
- // Print columns separators.
- pos_y = getcury(stdscr);
- for (int c_idx = 0; c_idx < sizeof(columns)/sizeof(int); c_idx++) {
- mvaddch(pos_y, columns[c_idx], ACS_VLINE);
- }
-
- pos_y++;
- move(pos_y, 0);
- dummy--;
- }
-
}
-void draw_footer() {
- const char *app_name_version = "TTT v1";
-
- int row, col; // To store the number of rows and the number of colums of the screen.
- initscr(); // Start the curses mode.
- getmaxyx(stdscr,row,col); // Get the number of rows and columns.
-
- mvaddch(row-1, 0, ACS_LLCORNER);
- addch(' ');
- printw(app_name_version);
- addch(' ');
- for (int idx = strlen(app_name_version) + 3; idx < col - 1; idx ++) {
- addch(ACS_HLINE);
- }
- addch(ACS_LRCORNER);
-
-
- // TODO This code is now repeated accross the header, table and footer. Clean this up.
- layout_t *layout = &layouts[selected_layout];
- int table_size = layout->table_size;
-// char **table_headers = layout->table_headers;
-
- int start_columns = size_x - 1 - 8*table_size - 2;
- int columns[] = {
- 0,
- start_columns+(table_size*0),
- start_columns+(table_size*1),
- start_columns+(table_size*2),
- start_columns+(table_size*3),
- start_columns+(table_size*4),
- start_columns+(table_size*5),
- start_columns+(table_size*6),
- start_columns+(table_size*7),
- };
-
-// mvaddstr(row-1, columns[0]+2, table_headers[0]);
- for (int idx = 1; idx < 9; idx++) {
- mvaddch(row-1, columns[idx], ACS_BTEE);
- }
-}
-WINDOW *create_newwin(int height, int width, int starty, int startx);
-void destroy_win(WINDOW *local_win);
int main(int argc, char *argv[]) {
@@ -930,26 +922,14 @@ int main(int argc, char *argv[]) {
initialization();
- initialize_layouts();
+ initialize_tui();
- WINDOW *my_win;
- int startx, starty, width, height;
int ch;
+
- initscr(); // Start curses mode.
- cbreak(); // Line buffering disabled, Pass on everty thing to me.
- keypad(stdscr, TRUE); // I need that nifty F1
- curs_set(0); // Set cursor invisible.
- timeout(1000); // Make getch() timeout after timeout(...) miliseconds.
-
- height = 3;
- width = 10;
- starty = (LINES - height) / 2; // Calculating for a center placement of the window.
- startx = (COLS - width) / 2; //
- refresh();
- my_win = create_newwin(height, width, starty, startx);
-
+ // TODO When this is active, it cancels selecting text with the mouse, and breaks the creation of a new task.
+ timeout(10000); // Make getch() timeout after timeout(...) miliseconds.
ch = KEY_RESIZE;
do {
@@ -1045,13 +1025,9 @@ int main(int argc, char *argv[]) {
break;
case KEY_LEFT:
- destroy_win(my_win);
- my_win = create_newwin(height, width, starty,--startx);
break;
case KEY_RIGHT:
- destroy_win(my_win);
- my_win = create_newwin(height, width, starty,++startx);
break;
case KEY_UP:
@@ -1069,9 +1045,7 @@ int main(int argc, char *argv[]) {
if (size_x >= 60 && size_y > 2) {
selected_layout = size_x > 100 ? 0 : 1;
- draw_header();
- draw_table();
- draw_footer();
+ draw_tui();
}
else {
const char *INVALID_WINDOW_MESSAGE = "Please expand window.";
@@ -1091,32 +1065,3 @@ int main(int argc, char *argv[]) {
endwin();
return EXIT_SUCCESS;
}
-
-WINDOW *create_newwin(int height, int width, int starty, int startx) {
- WINDOW *local_win;
-
- local_win = newwin(height, width, starty, startx);
- box(local_win, 0 , 0); // 0, 0 gives default characters for the vertical and horizontal lines.
- wrefresh(local_win); // Show that box.
-
- return local_win;
-}
-
-void destroy_win(WINDOW *local_win) {
- // box(local_win, ' ', ' '); : This won't produce the desired
- // result of erasing the window. It will leave it's four corners
- // and so an ugly remnant of window.
- wborder(local_win, ' ', ' ', ' ',' ',' ',' ',' ',' ');
- // The parameters taken are
- // 1. win: the window on which to operate
- // 2. ls: character to be used for the left side of the window
- // 3. rs: character to be used for the right side of the window
- // 4. ts: character to be used for the top side of the window
- // 5. bs: character to be used for the bottom side of the window
- // 6. tl: character to be used for the top left corner of the window
- // 7. tr: character to be used for the top right corner of the window
- // 8. bl: character to be used for the bottom left corner of the window
- // 9. br: character to be used for the bottom right corner of the window
- wrefresh(local_win);
- delwin(local_win);
-}