Move user information after save/reload to the command level
Moving user information to calcurse.c makes it easier to perform the actual save/reload operatons in io.c, e.g. it is possible to load instead of reload after a merge in conflict resolving. The save/reload operations are of such importance that the user should always be informed of the result (it's a bit disquieting when there is no reaction to a save or reload command). Hence, the save/reload status messages are no longer conditioned by show_dialogs(). No confirmation is asked for, so a message stays until the status bar is updated by another action. Care is taken to inform about save/reload actions that result in no change. Texts are kept concise because of the limited message area. When conflicts are present, whether saving or reloading, the "continue/merge/cancel" pattern seems easier to grasp. Signed-off-by: Lars Henriksen <LarsHenriksen@get2net.dk> Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
This commit is contained in:
parent
d7777ed44e
commit
8b39637a62
@ -271,7 +271,12 @@ static inline void key_generic_help(void)
|
|||||||
|
|
||||||
static inline void key_generic_save(void)
|
static inline void key_generic_save(void)
|
||||||
{
|
{
|
||||||
if (io_save_cal(IO_SAVE_DISPLAY_BAR) == IO_SAVE_RELOAD) {
|
char *msg = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = io_save_cal(IO_SAVE_DISPLAY_BAR);
|
||||||
|
|
||||||
|
if (ret == IO_SAVE_RELOAD) {
|
||||||
ui_todo_load_items();
|
ui_todo_load_items();
|
||||||
ui_todo_sel_reset();
|
ui_todo_sel_reset();
|
||||||
do_storage(0);
|
do_storage(0);
|
||||||
@ -279,11 +284,30 @@ static inline void key_generic_save(void)
|
|||||||
ui_calendar_monthly_view_cache_set_invalid();
|
ui_calendar_monthly_view_cache_set_invalid();
|
||||||
}
|
}
|
||||||
wins_update(FLAG_ALL);
|
wins_update(FLAG_ALL);
|
||||||
|
switch (ret) {
|
||||||
|
case IO_SAVE_CTINUE:
|
||||||
|
msg = _("Data were saved successfully");
|
||||||
|
break;
|
||||||
|
case IO_SAVE_RELOAD:
|
||||||
|
msg = _("Data were saved/reloaded successfully");
|
||||||
|
break;
|
||||||
|
case IO_SAVE_CANCEL:
|
||||||
|
msg = _("Save cancelled");
|
||||||
|
break;
|
||||||
|
case IO_SAVE_NOOP:
|
||||||
|
msg = _("Data were already saved");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
status_mesg(msg, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void key_generic_reload(void)
|
static inline void key_generic_reload(void)
|
||||||
{
|
{
|
||||||
if (io_reload_data()) {
|
char *msg = NULL;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = io_reload_data();
|
||||||
|
if (ret != IO_RELOAD_CANCEL && ret != IO_RELOAD_NOOP) {
|
||||||
ui_todo_load_items();
|
ui_todo_load_items();
|
||||||
ui_todo_sel_reset();
|
ui_todo_sel_reset();
|
||||||
do_storage(0);
|
do_storage(0);
|
||||||
@ -291,6 +315,22 @@ static inline void key_generic_reload(void)
|
|||||||
ui_calendar_monthly_view_cache_set_invalid();
|
ui_calendar_monthly_view_cache_set_invalid();
|
||||||
}
|
}
|
||||||
wins_update(FLAG_ALL);
|
wins_update(FLAG_ALL);
|
||||||
|
switch (ret) {
|
||||||
|
case IO_RELOAD_LOAD:
|
||||||
|
case IO_RELOAD_CTINUE:
|
||||||
|
msg = _("Data were reloaded successfully");
|
||||||
|
break;
|
||||||
|
case IO_RELOAD_MERGE:
|
||||||
|
msg = _("Date were merged/reloaded successfully");
|
||||||
|
break;
|
||||||
|
case IO_RELOAD_CANCEL:
|
||||||
|
msg = _("Reload cancelled");
|
||||||
|
break;
|
||||||
|
case IO_RELOAD_NOOP:
|
||||||
|
msg = _("Data were already loaded");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
status_mesg(msg, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void key_generic_import(void)
|
static inline void key_generic_import(void)
|
||||||
|
@ -658,7 +658,17 @@ enum getstr {
|
|||||||
enum {
|
enum {
|
||||||
IO_SAVE_CTINUE,
|
IO_SAVE_CTINUE,
|
||||||
IO_SAVE_RELOAD,
|
IO_SAVE_RELOAD,
|
||||||
IO_SAVE_CANCEL
|
IO_SAVE_CANCEL,
|
||||||
|
IO_SAVE_NOOP
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Return codes for the io_reload_data() function. */
|
||||||
|
enum {
|
||||||
|
IO_RELOAD_LOAD,
|
||||||
|
IO_RELOAD_CTINUE,
|
||||||
|
IO_RELOAD_MERGE,
|
||||||
|
IO_RELOAD_CANCEL,
|
||||||
|
IO_RELOAD_NOOP
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Week days. */
|
/* Week days. */
|
||||||
@ -860,7 +870,7 @@ unsigned io_save_keys(void);
|
|||||||
int io_save_cal(enum save_display);
|
int io_save_cal(enum save_display);
|
||||||
void io_load_app(struct item_filter *);
|
void io_load_app(struct item_filter *);
|
||||||
void io_load_todo(struct item_filter *);
|
void io_load_todo(struct item_filter *);
|
||||||
void io_load_data(struct item_filter *, int);
|
int io_load_data(struct item_filter *, int);
|
||||||
int io_reload_data(void);
|
int io_reload_data(void);
|
||||||
void io_load_keys(const char *);
|
void io_load_keys(const char *);
|
||||||
int io_check_dir(const char *);
|
int io_check_dir(const char *);
|
||||||
|
60
src/io.c
60
src/io.c
@ -503,12 +503,12 @@ static int resolve_save_conflict(void)
|
|||||||
{
|
{
|
||||||
char *msg_um_asktype = NULL;
|
char *msg_um_asktype = NULL;
|
||||||
const char *msg_um_prefix =
|
const char *msg_um_prefix =
|
||||||
_("Data have changed since loaded:");
|
_("Data files have changed and will be overwritten:");
|
||||||
const char *msg_um_overwrite = _("(o)verwrite");
|
const char *msg_um_overwrite = _("(c)ontinue");
|
||||||
const char *msg_um_merge = _("(m)erge");
|
const char *msg_um_merge = _("(m)erge");
|
||||||
const char *msg_um_keep = _("(c)ancel");
|
const char *msg_um_keep = _("c(a)ncel");
|
||||||
const char *msg_um_choice = _("[omc]");
|
const char *msg_um_choice = _("[cma]");
|
||||||
int ret;
|
int ret = IO_SAVE_CANCEL;
|
||||||
|
|
||||||
asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
|
asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
|
||||||
msg_um_overwrite, msg_um_merge, msg_um_keep);
|
msg_um_overwrite, msg_um_merge, msg_um_keep);
|
||||||
@ -519,7 +519,7 @@ static int resolve_save_conflict(void)
|
|||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
io_merge_data();
|
io_merge_data();
|
||||||
io_reload_data();
|
io_load_data(NULL, FORCE);
|
||||||
ret = IO_SAVE_RELOAD;
|
ret = IO_SAVE_RELOAD;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
@ -573,14 +573,12 @@ cleanup:
|
|||||||
* The return value tells how a possible save conflict should be/was resolved:
|
* The return value tells how a possible save conflict should be/was resolved:
|
||||||
* IO_SAVE_CTINUE: continue save operation and overwrite the data files
|
* IO_SAVE_CTINUE: continue save operation and overwrite the data files
|
||||||
* IO_SAVE_RELOAD: cancel save operation (data files changed and reloaded)
|
* IO_SAVE_RELOAD: cancel save operation (data files changed and reloaded)
|
||||||
* IO_SAVE_CANCEL: cancel save operation (keep data files, no reload)
|
* IO_SAVE_CANCEL: cancel save operation (user's decision, keep data files, no reload)
|
||||||
|
* IO_SAVE_NOOP: cancel save operation (nothing has changed)
|
||||||
*/
|
*/
|
||||||
int io_save_cal(enum save_display display)
|
int io_save_cal(enum save_display display)
|
||||||
{
|
{
|
||||||
const char *access_pb = _("Problems accessing data file ...");
|
const char *access_pb = _("Problems accessing data file ...");
|
||||||
const char *save_success =
|
|
||||||
_("The data files were successfully saved");
|
|
||||||
const char *enter = _("Press [ENTER] to continue");
|
|
||||||
int show_bar, ret = IO_SAVE_CTINUE;
|
int show_bar, ret = IO_SAVE_CTINUE;
|
||||||
|
|
||||||
if (read_only)
|
if (read_only)
|
||||||
@ -591,7 +589,7 @@ int io_save_cal(enum save_display display)
|
|||||||
return ret;
|
return ret;
|
||||||
} else
|
} else
|
||||||
if (!io_get_modified())
|
if (!io_get_modified())
|
||||||
return IO_SAVE_CANCEL;
|
return IO_SAVE_NOOP;
|
||||||
|
|
||||||
run_hook("pre-save");
|
run_hook("pre-save");
|
||||||
io_mutex_lock();
|
io_mutex_lock();
|
||||||
@ -623,13 +621,6 @@ int io_save_cal(enum save_display display)
|
|||||||
|
|
||||||
io_unset_modified();
|
io_unset_modified();
|
||||||
|
|
||||||
/* Print a message telling data were saved */
|
|
||||||
if (ui_mode == UI_CURSES && display == IO_SAVE_DISPLAY_BAR &&
|
|
||||||
show_dialogs()) {
|
|
||||||
status_mesg(save_success, enter);
|
|
||||||
keys_wait_for_any_key(win[KEY].p);
|
|
||||||
}
|
|
||||||
|
|
||||||
io_compute_hash(path_apts, apts_sha1);
|
io_compute_hash(path_apts, apts_sha1);
|
||||||
io_compute_hash(path_todo, todo_sha1);
|
io_compute_hash(path_todo, todo_sha1);
|
||||||
|
|
||||||
@ -925,8 +916,9 @@ void io_load_todo(struct item_filter *filter)
|
|||||||
* Load appointments and todo items.
|
* Load appointments and todo items.
|
||||||
* Unless told otherwise, the function will only load a file that has changed
|
* Unless told otherwise, the function will only load a file that has changed
|
||||||
* since last saved or loaded, see new_data() return codes.
|
* since last saved or loaded, see new_data() return codes.
|
||||||
|
* Return codes are for use in io_reload_data() only.
|
||||||
*/
|
*/
|
||||||
void io_load_data(struct item_filter *filter, int force)
|
int io_load_data(struct item_filter *filter, int force)
|
||||||
{
|
{
|
||||||
run_hook("pre-load");
|
run_hook("pre-load");
|
||||||
if (force)
|
if (force)
|
||||||
@ -957,24 +949,25 @@ void io_load_data(struct item_filter *filter, int force)
|
|||||||
|
|
||||||
io_mutex_unlock();
|
io_mutex_unlock();
|
||||||
run_hook("post-load");
|
run_hook("post-load");
|
||||||
|
return force;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The return codes reflect the user choice in case of unsaved in-memory changes.
|
||||||
|
*/
|
||||||
int io_reload_data(void)
|
int io_reload_data(void)
|
||||||
{
|
{
|
||||||
char *msg_um_asktype = NULL;
|
char *msg_um_asktype = NULL;
|
||||||
const char *reload_success =
|
|
||||||
_("The data files were reloaded successfully");
|
|
||||||
const char *enter = _("Press [ENTER] to continue");
|
|
||||||
int ret = 0;
|
|
||||||
int load = NOFORCE;
|
int load = NOFORCE;
|
||||||
|
int ret = IO_RELOAD_LOAD;
|
||||||
|
|
||||||
if (io_get_modified()) {
|
if (io_get_modified()) {
|
||||||
const char *msg_um_prefix =
|
const char *msg_um_prefix =
|
||||||
_("There are unsaved modifications:");
|
_("Screen data have changed and will be lost:");
|
||||||
const char *msg_um_discard = _("(d)iscard");
|
const char *msg_um_discard = _("(c)ontinue");
|
||||||
const char *msg_um_merge = _("(m)erge");
|
const char *msg_um_merge = _("(m)erge");
|
||||||
const char *msg_um_keep = _("(c)ancel");
|
const char *msg_um_keep = _("c(a)ncel");
|
||||||
const char *msg_um_choice = _("[dmc]");
|
const char *msg_um_choice = _("[cma]");
|
||||||
|
|
||||||
asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
|
asprintf(&msg_um_asktype, "%s %s, %s, %s", msg_um_prefix,
|
||||||
msg_um_discard, msg_um_merge, msg_um_keep);
|
msg_um_discard, msg_um_merge, msg_um_keep);
|
||||||
@ -982,26 +975,25 @@ int io_reload_data(void)
|
|||||||
switch (status_ask_choice(msg_um_asktype, msg_um_choice, 3)) {
|
switch (status_ask_choice(msg_um_asktype, msg_um_choice, 3)) {
|
||||||
case 1:
|
case 1:
|
||||||
load = FORCE;
|
load = FORCE;
|
||||||
|
ret = IO_RELOAD_CTINUE;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
io_merge_data();
|
io_merge_data();
|
||||||
load = FORCE;
|
load = FORCE;
|
||||||
|
ret = IO_RELOAD_MERGE;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
|
ret = IO_RELOAD_CANCEL;
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
default:
|
default:
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
io_load_data(NULL, load);
|
load = io_load_data(NULL, load);
|
||||||
|
if (load == NONEW)
|
||||||
|
ret = IO_RELOAD_NOOP;
|
||||||
|
|
||||||
if (show_dialogs()) {
|
|
||||||
status_mesg(reload_success, enter);
|
|
||||||
keys_wait_for_any_key(win[KEY].p);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = 1;
|
|
||||||
cleanup:
|
cleanup:
|
||||||
mem_free(msg_um_asktype);
|
mem_free(msg_um_asktype);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user