Compare commits

..

11 Commits

12 changed files with 140 additions and 65 deletions

1
.gitignore vendored
View File

@ -1,6 +1,7 @@
takl.sqlite3 takl.sqlite3
takl takl
takl-daemon takl-daemon
takl.sock
out out
.vscode .vscode

View File

@ -1,5 +1,6 @@
FLAGS = -g -Wall -Wextra -DLOG_USE_COLOR `pkg-config --cflags --libs libnotify` FLAGS = -g -Wall -Wextra -DLOG_USE_COLOR
LD_FLAGS = -lsqlite3 -lpthread LD_FLAGS = -lsqlite3 -lpthread
NOTIF_FLAGS = `pkg-config --cflags --libs libnotify`
$(shell mkdir -p out) $(shell mkdir -p out)
@ -11,6 +12,9 @@ all: takl takl-daemon
out/%.o: src/%.c out/%.o: src/%.c
$(CC) -c $(FLAGS) $^ -o $@ $(CC) -c $(FLAGS) $^ -o $@
out/notification.o: src/main/notification.c
$(CC) -c $(FLAGS) $(NOTIF_FLAGS) $^ -o $@
out/%.o: src/main/%.c out/%.o: src/main/%.c
$(CC) -c $(FLAGS) $^ -o $@ $(CC) -c $(FLAGS) $^ -o $@
@ -20,8 +24,8 @@ out/%.o: src/log/%.c
takl: out/main.o out/db.o out/tasks.o out/utils.o takl: out/main.o out/db.o out/tasks.o out/utils.o
$(CC) $(FLAGS) $(LD_FLAGS) $^ -o $@ $(CC) $(FLAGS) $(LD_FLAGS) $^ -o $@
takl-daemon: out/daemon.o out/db.o out/tasks.o out/utils.o out/log.o takl-daemon: out/daemon.o out/db.o out/tasks.o out/utils.o out/log.o out/notification.o
$(CC) $(FLAGS) $(LD_FLAGS) $^ -o $@ $(CC) $(FLAGS) $(LD_FLAGS) $(NOTIF_FLAGS) $^ -o $@
install: takl takl-daemon install: takl takl-daemon

View File

@ -5,7 +5,7 @@ facile d'utilisation et donnant rapidement les choses demandées
### Installation ### Installation
Les seules dépendances nécessaires sont `gcc` et `g++`. Les seules dépendances nécessaires sont `gcc` et `libnotify`.
(Peut-être que des bibliothèques comme sqlite3 sont à installer sur certaines distributions/ OS) (Peut-être que des bibliothèques comme sqlite3 sont à installer sur certaines distributions/ OS)
```bash ```bash
@ -24,14 +24,17 @@ Pour gnome, `make gnome-install` lancera le programme à tous les prochains red
### Utilisation ### Utilisation
``` ```
Utilisation: takl ( list | add | info | rm | done ) Utilisation: takl ( list | add | reschedule | info | rm | done )
list [-a:voir les tâches complétées] list [category] [-a:voir les tâches complétées]
add <task> [date] add [category:]<task> [date]
Format de la date: reschedule <id> [date]
Relatif: min+%d, h+%d, j+%d
Absolu: dd/mm (pas de changement d'année pour l'instant)
info <id1> <id2> ... info <id1> <id2> ...
done <id1> <id2> ... done <id1> <id2> ...
rm <id1> <id2> ... rm <id1> <id2> ...
Format des dates:
Relatif: min+%d, h+%d, j+%d
Absolu: dd/mm (pas de changement d'année pour l'instant)
``` ```
Appeler l'exécutable sans arguments vous renverra cette petite liste de commandes que vous pouvez utiliser. Appeler l'exécutable sans arguments vous renverra cette petite liste de commandes que vous pouvez utiliser.

View File

@ -22,6 +22,7 @@
#include "main/include/utils.h" #include "main/include/utils.h"
#include "main/include/colors.h" #include "main/include/colors.h"
#include "main/include/config.h" #include "main/include/config.h"
#include "main/include/notification.h"
#define EVENT_SIZE ( sizeof (struct inotify_event) ) #define EVENT_SIZE ( sizeof (struct inotify_event) )
@ -35,10 +36,9 @@ pthread_mutex_t tasks_lock = PTHREAD_MUTEX_INITIALIZER; // locks tasks and has_c
void* inotify_check_changes(void* arg) { void* inotify_check_changes(void* sk_path) {
(void)arg; char* socket_path = (char*)sk_path;
char buffer[EVENT_BUF_LEN]; char buffer[EVENT_BUF_LEN];
char* socket_path = get_socket_path();
while (1) { // Regarde si /tmp/takl.$USER a changé (donc si la BDD a changé et doit être rechargée) while (1) { // Regarde si /tmp/takl.$USER a changé (donc si la BDD a changé et doit être rechargée)
int fd = inotify_init(); int fd = inotify_init();
@ -60,21 +60,18 @@ void* inotify_check_changes(void* arg) {
log_debug("Base de données changée"); log_debug("Base de données changée");
pthread_mutex_lock(&tasks_lock); pthread_mutex_lock(&tasks_lock);
free_task_list(tasks); free_task_list(tasks);
tasks = get_task_list(false); tasks = get_task_list(false, false);
has_changed = true; has_changed = true;
pthread_mutex_unlock(&tasks_lock); pthread_mutex_unlock(&tasks_lock);
inotify_rm_watch(fd, wd); inotify_rm_watch(fd, wd);
close(fd); close(fd);
} }
free(socket_path);
return NULL; return NULL;
} }
int existing_takl_daemon() { int existing_takl_daemon(char* socket_path) {
char* socket_path = get_socket_path();
if (!access(socket_path, F_OK)) { // tmp file exists if (!access(socket_path, F_OK)) { // tmp file exists
FILE* fp = fopen(socket_path, "r+"); FILE* fp = fopen(socket_path, "r+");
int daemon_pid; int daemon_pid;
@ -90,25 +87,26 @@ int existing_takl_daemon() {
fprintf(fp, "%d", getpid()); fprintf(fp, "%d", getpid());
fclose(fp); fclose(fp);
free(socket_path);
return false; return false;
} }
int main() { int main() {
bool notified_no_change = false; bool notified_no_change = false;
char* socket_path = get_socket_path();
log_debug("Socket path:%s", socket_path);
if (!existing_takl_daemon()) { if (!existing_takl_daemon(socket_path)) {
log_info("TaKl " VERSION " -- Daemon started"); log_info("TaKl " VERSION " -- Daemon started");
} else { } else {
log_info("TaKl Daemon déjà en cours d'exécution. Arrêt"); log_info("TaKl Daemon déjà en cours d'exécution. Arrêt");
return 1; return 1;
} }
tasks = get_task_list(false); tasks = get_task_list(false, false);
pthread_t inotify_id = 0; // Lancement d'inotify dans un autre fil pthread_t inotify_id = 0; // Lancement d'inotify dans un autre fil
pthread_create(&inotify_id, NULL, inotify_check_changes, NULL); pthread_create(&inotify_id, NULL, inotify_check_changes, (void*)socket_path);
while (1) { while (1) {
pthread_mutex_lock(&tasks_lock); pthread_mutex_lock(&tasks_lock);
@ -169,5 +167,6 @@ int main() {
pthread_join(inotify_id, NULL); pthread_join(inotify_id, NULL);
free_task_list(tasks); free_task_list(tasks);
free(socket_path);
return 0; return 0;
} }

View File

@ -25,8 +25,17 @@ void sqlAssert(int ret, sqlite3* db, char* file, int line) {
char* get_db_path() { char* get_db_path() {
#ifndef DB_FILE /*
//! We should check that $HOME/.config already exists even if it should be the case Checks if $TAKL_DB env variable is set
else, the DB is located at $HOME/.config/takl.sqlite3
*/
char* env_db_path = getenv("TAKL_DB");
if (env_db_path) {
char* db_path = malloc(sizeof(char)*(strlen(env_db_path)+1));
strcpy(db_path, env_db_path);
return db_path;
} else {
char* base_path = ".config/takl.sqlite3"; char* base_path = ".config/takl.sqlite3";
char* home_dir = getenv("HOME"); char* home_dir = getenv("HOME");
@ -36,12 +45,7 @@ char* get_db_path() {
sprintf(db_path, "%s/%s", home_dir, base_path); sprintf(db_path, "%s/%s", home_dir, base_path);
return db_path; return db_path;
#else }
char* db_path = malloc(sizeof(char)*(strlen(DB_FILE)+1));
memcpy(db_path, DB_FILE, sizeof(char)*(strlen(DB_FILE)+1));
return db_path;
#endif
} }
@ -59,7 +63,7 @@ sqlite3* get_db() {
"CREATE TABLE tasks ( \ "CREATE TABLE tasks ( \
id INTEGER PRIMARY KEY,\ id INTEGER PRIMARY KEY,\
text TEXT NOT NULL,\ text TEXT NOT NULL,\
category TEXT DEFAULT '', \ category TEXT DEFAULT NULL, \
done INTEGER, \ done INTEGER, \
due_to INTEGER \ due_to INTEGER \
);", );",
@ -153,6 +157,8 @@ int update_task(task_t t) {
sprintf(str_due_to, "%ld", t.due_to); sprintf(str_due_to, "%ld", t.due_to);
sqlCheck( sqlite3_bind_text(stmt, 4, str_due_to, -1, SQLITE_STATIC) ); sqlCheck( sqlite3_bind_text(stmt, 4, str_due_to, -1, SQLITE_STATIC) );
sqlite3_step(stmt);
sqlCheck( sqlite3_finalize(stmt) ); sqlCheck( sqlite3_finalize(stmt) );
sqlCheck( sqlite3_close(db) ); sqlCheck( sqlite3_close(db) );
notify_change(); notify_change();
@ -202,8 +208,12 @@ void get_task(int id, task_t* t) {
strcpy(t->text, text); strcpy(t->text, text);
char* category = (char*)sqlite3_column_text(stmt, 4); char* category = (char*)sqlite3_column_text(stmt, 4);
t->category = malloc(sizeof(char)*(strlen(category)+1)); if (category) {
strcpy(t->category, category); t->category = malloc(sizeof(char)*(strlen(category)+1));
strcpy(t->category, category);
} else {
t->category = NULL;
}
} }
sqlCheck( sqlite3_finalize(stmt) ); sqlCheck( sqlite3_finalize(stmt) );
@ -238,8 +248,13 @@ task_list_t* get_task_list(char* input_category, bool include_completed) {
strcpy(t.text, text); strcpy(t.text, text);
char* category = (char*)sqlite3_column_text(stmt, 4); char* category = (char*)sqlite3_column_text(stmt, 4);
t.category = malloc(sizeof(char)*(strlen(category)+1)); if (category) {
strcpy(t.category, category); t.category = malloc(sizeof(char)*(strlen(category)+1));
strcpy(t.category, category);
} else {
t.category = NULL;
}
task_list_t* cur = malloc(sizeof(task_list_t)); // Add the parsed task to the beginning of the list task_list_t* cur = malloc(sizeof(task_list_t)); // Add the parsed task to the beginning of the list
cur->task = t; cur->task = t;

View File

@ -1,15 +1,11 @@
#ifndef DEF_CONFIG_H #ifndef DEF_CONFIG_H
#define DEF_CONFIG_H #define DEF_CONFIG_H
#define VERSION "1.2.0" #define VERSION "1.3.5"
// By default, $HOME/.config/takl.sqlite3 is used. You can change this behaviour here
//#define DB_FILE "takl.sqlite3"
// By default, /tmp/takl.$USER is used. You can change this behaviour here
//#define SOCKET_FILE "takl.sock"
#define MAX_TASK_ID 10000 // max is set to MAX_TASK_ID-1 #define MAX_TASK_ID 10000 // max is set to MAX_TASK_ID-1
#define NEW_TASK_ID_MAX_RETRIES 10000 // number of retries before giving up #define NEW_TASK_ID_MAX_RETRIES 10000 // number of retries before giving up
#define TMPDIR "/tmp" // Some Unix systems don't use /tmp as tmp dir (eg Android)
#endif #endif

View File

@ -0,0 +1,10 @@
#ifndef DEF_NOTIFICATION_H
#define DEF_NOTIFICATION_H
#include "tasks.h"
/*
Envoyer une notification avec t
*/
void desktop_notification(task_t t);
#endif

View File

@ -29,9 +29,4 @@ Libère la mémoire allouée à une liste de tâches
*/ */
void free_task_list(task_list_t* list); void free_task_list(task_list_t* list);
/*
Envoyer une notification avec t
*/
void desktop_notification(task_t t);
#endif #endif

11
src/main/notification.c Normal file
View File

@ -0,0 +1,11 @@
#include <libnotify/notify.h>
#include "include/notification.h"
void desktop_notification(task_t t) {
notify_init ("TaKl");
NotifyNotification * Notif = notify_notification_new ("TaKl Daemon", t.text, "dialog-information");
notify_notification_show (Notif, NULL);
g_object_unref(G_OBJECT(Notif));
notify_uninit();
}

View File

@ -5,7 +5,6 @@ Fonctions utilitaires concernant les tâches
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <libnotify/notify.h>
#include "include/db.h" #include "include/db.h"
#include "include/struct.h" #include "include/struct.h"
@ -131,12 +130,4 @@ void free_task_list(task_list_t* list) {
free(list); free(list);
list = next; list = next;
} }
}
void desktop_notification(task_t t) {
notify_init ("TaKl");
NotifyNotification * Notif = notify_notification_new ("TaKl Daemon", t.text, "dialog-information");
notify_notification_show (Notif, NULL);
g_object_unref(G_OBJECT(Notif));
notify_uninit();
} }

View File

@ -8,22 +8,30 @@
#include "include/struct.h" #include "include/struct.h"
char* get_socket_path() { char* get_socket_path() {
#ifndef SOCKET_FILE /*
char* base_path = "/tmp/takl"; Checks if $TAKL_SOCKET env variable is set
else, the socket is located at /tmp/takl
*/
char* env_socket_path = getenv("TAKL_SOCKET");
if (env_socket_path) {
char* socket_path = malloc(sizeof(char)*(strlen(env_socket_path)+1));
strcpy(socket_path, env_socket_path);
return socket_path;
} else {
char* base_path = TMPDIR "/takl";
char* username = getenv("USER"); char* username = getenv("USER");
if (!username)
username = getenv("USERNAME");
assert(username != NULL); assert(username != NULL);
char* socket_path = malloc(sizeof(char)*(strlen(base_path)+strlen(username)+1)); char* socket_path = malloc(sizeof(char)*(strlen(base_path)+strlen(username)+1));
sprintf(socket_path, "%s.%s", base_path, username); sprintf(socket_path, "%s.%s", base_path, username);
return socket_path; return socket_path;
#else }
char* socket_path = malloc(sizeof(char)*(strlen(SOCKET_FILE)+1));
memcpy(socket_path, SOCKET_FILE, sizeof(char)*(strlen(SOCKET_FILE)+1));
return socket_path;
#endif
} }

42
tests/main.sh Executable file
View File

@ -0,0 +1,42 @@
#!/bin/bash
TMPDIR=$(mktemp -d)
#! On ne teste pas que l'on peut bien récupérer ces chemins automatiquement,
#! ce qui peut-être une source d'erreurs
export TAKL_DB="$TMPDIR/takl.sqlite3"
export TAKL_SOCKET="$TMPDIR/takl.socket"
echo "Using $TMPDIR"
make -j
# Catégories
./takl add "nocategory"
./takl add "category1:test1"
# Dates
./takl add "date:avec date" min+5
./takl add "date:avec date2" h+5
./takl add "date:avec date3" j+5
./takl add "date:avec date4" "31/12"
TASK_ID=$(./takl add "done soon" | sed 's/\x1B\[[0-9;]\{1,\}[A-Za-z]//g' | awk '-F[' '{ print $2 }' | awk '-F]' '{ print $1 }')
# List
./takl list
./takl list date
# Reschedule
./takl reschedule $TASK_ID "22/11"
# Get info
./takl info $TASK_ID
# Mark as done
./takl done $TASK_ID
./takl list -a
./takl rm $TASK_ID
#* À rajouter: tests sur le fait que les changements ont bien eu lieu
rm $TMPDIR -r