Optimization of history save.
Formerly, each widget saved its history self in WIDGET_DESTROY stage. Thus, history file was read and written as many times as many widgets with history are in dialog. Now all widget histories are written to ${XDG_CACHE_HOME}/mc/history file at one time before dialog destruction. An ev_history_load_save_t event type is created to use new event engine to save histories. Signed-off-by: Andrew Borodin <aborodin@vmail.ru>
Этот коммит содержится в:
родитель
b473577525
Коммит
cff5925598
@ -7,16 +7,19 @@
|
|||||||
|
|
||||||
/* Event groups for main modules */
|
/* Event groups for main modules */
|
||||||
#define MCEVENT_GROUP_CORE "Core"
|
#define MCEVENT_GROUP_CORE "Core"
|
||||||
|
#define MCEVENT_GROUP_DIALOG "Dialog"
|
||||||
#define MCEVENT_GROUP_DIFFVIEWER "DiffViewer"
|
#define MCEVENT_GROUP_DIFFVIEWER "DiffViewer"
|
||||||
#define MCEVENT_GROUP_EDITOR "Editor"
|
#define MCEVENT_GROUP_EDITOR "Editor"
|
||||||
#define MCEVENT_GROUP_FILEMANAGER "FileManager"
|
#define MCEVENT_GROUP_FILEMANAGER "FileManager"
|
||||||
#define MCEVENT_GROUP_VIEWER "Viewer"
|
#define MCEVENT_GROUP_VIEWER "Viewer"
|
||||||
|
|
||||||
|
/* Events */
|
||||||
|
#define MCEVENT_HISTORY_SAVE "history_save"
|
||||||
|
|
||||||
/*** enums ***************************************************************************************/
|
/*** enums ***************************************************************************************/
|
||||||
|
|
||||||
/*** structures declarations (and typedefs of structures)*****************************************/
|
/*** structures declarations (and typedefs of structures)*****************************************/
|
||||||
|
|
||||||
|
|
||||||
/* MCEVENT_GROUP_CORE:vfs_timestamp */
|
/* MCEVENT_GROUP_CORE:vfs_timestamp */
|
||||||
struct vfs_class;
|
struct vfs_class;
|
||||||
typedef struct
|
typedef struct
|
||||||
@ -26,7 +29,6 @@ typedef struct
|
|||||||
gboolean ret;
|
gboolean ret;
|
||||||
} ev_vfs_stamp_create_t;
|
} ev_vfs_stamp_create_t;
|
||||||
|
|
||||||
|
|
||||||
/* MCEVENT_GROUP_CORE:vfs_print_message */
|
/* MCEVENT_GROUP_CORE:vfs_print_message */
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -63,6 +65,14 @@ typedef struct
|
|||||||
} ret;
|
} ret;
|
||||||
} ev_background_parent_call_t;
|
} ev_background_parent_call_t;
|
||||||
|
|
||||||
|
/* MCEVENT_GROUP_DIALOG:history_save */
|
||||||
|
struct mc_config_t;
|
||||||
|
struct Widget;
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
struct mc_config_t *cfg;
|
||||||
|
struct Widget *receiver; /* NULL means broadcast message */
|
||||||
|
} ev_history_load_save_t;
|
||||||
|
|
||||||
/*** global variables defined in .c file *********************************************************/
|
/*** global variables defined in .c file *********************************************************/
|
||||||
|
|
||||||
|
@ -24,10 +24,13 @@
|
|||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h> /* open() */
|
||||||
|
|
||||||
#include "lib/global.h"
|
#include "lib/global.h"
|
||||||
|
|
||||||
@ -37,6 +40,7 @@
|
|||||||
#include "lib/tty/key.h"
|
#include "lib/tty/key.h"
|
||||||
#include "lib/strutil.h"
|
#include "lib/strutil.h"
|
||||||
#include "lib/widget.h"
|
#include "lib/widget.h"
|
||||||
|
#include "lib/fileloc.h" /* MC_HISTORY_FILE */
|
||||||
#include "lib/event.h" /* mc_event_raise() */
|
#include "lib/event.h" /* mc_event_raise() */
|
||||||
|
|
||||||
/*** global variables ****************************************************************************/
|
/*** global variables ****************************************************************************/
|
||||||
@ -1154,6 +1158,8 @@ run_dlg (Dlg_head * h)
|
|||||||
void
|
void
|
||||||
destroy_dlg (Dlg_head * h)
|
destroy_dlg (Dlg_head * h)
|
||||||
{
|
{
|
||||||
|
/* if some widgets have history, save all history at one moment here */
|
||||||
|
dlg_save_history (h);
|
||||||
dlg_broadcast_msg (h, WIDGET_DESTROY, FALSE);
|
dlg_broadcast_msg (h, WIDGET_DESTROY, FALSE);
|
||||||
g_list_foreach (h->widgets, (GFunc) g_free, NULL);
|
g_list_foreach (h->widgets, (GFunc) g_free, NULL);
|
||||||
g_list_free (h->widgets);
|
g_list_free (h->widgets);
|
||||||
@ -1167,6 +1173,43 @@ destroy_dlg (Dlg_head * h)
|
|||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write history to the ${XDG_CACHE_HOME}/mc/history file
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
dlg_save_history (Dlg_head * h)
|
||||||
|
{
|
||||||
|
char *profile;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (num_history_items_recorded == 0) /* this is how to disable */
|
||||||
|
return;
|
||||||
|
|
||||||
|
profile = g_build_filename (mc_config_get_cache_path (), MC_HISTORY_FILE, (char *) NULL);
|
||||||
|
i = open (profile, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
|
||||||
|
if (i != -1)
|
||||||
|
close (i);
|
||||||
|
|
||||||
|
/* Make sure the history is only readable by the user */
|
||||||
|
if (chmod (profile, S_IRUSR | S_IWUSR) != -1 || errno == ENOENT)
|
||||||
|
{
|
||||||
|
ev_history_load_save_t event_data;
|
||||||
|
|
||||||
|
event_data.cfg = mc_config_init (profile);
|
||||||
|
event_data.receiver = NULL;
|
||||||
|
|
||||||
|
/* get all histories in dialog */
|
||||||
|
mc_event_raise (h->event_group, MCEVENT_HISTORY_SAVE, &event_data);
|
||||||
|
|
||||||
|
mc_config_save_file (event_data.cfg, NULL);
|
||||||
|
mc_config_deinit (event_data.cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
char *
|
char *
|
||||||
dlg_get_title (const Dlg_head * h, size_t len)
|
dlg_get_title (const Dlg_head * h, size_t len)
|
||||||
{
|
{
|
||||||
|
@ -190,6 +190,7 @@ int run_dlg (Dlg_head * d);
|
|||||||
void destroy_dlg (Dlg_head * h);
|
void destroy_dlg (Dlg_head * h);
|
||||||
|
|
||||||
void dlg_run_done (Dlg_head * h);
|
void dlg_run_done (Dlg_head * h);
|
||||||
|
void dlg_save_history (Dlg_head * h);
|
||||||
void dlg_process_event (Dlg_head * h, int key, Gpm_Event * event);
|
void dlg_process_event (Dlg_head * h, int key, Gpm_Event * event);
|
||||||
|
|
||||||
char *dlg_get_title (const Dlg_head * h, size_t len);
|
char *dlg_get_title (const Dlg_head * h, size_t len);
|
||||||
|
@ -214,6 +214,9 @@ history_save (struct mc_config_t * cfg, const char *name, GList * h)
|
|||||||
GString *buffer;
|
GString *buffer;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (name == NULL || *name == '\0' || h == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
/* go to end of list */
|
/* go to end of list */
|
||||||
h = g_list_last (h);
|
h = g_list_last (h);
|
||||||
|
|
||||||
@ -261,6 +264,7 @@ history_save (struct mc_config_t * cfg, const char *name, GList * h)
|
|||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
#if 0
|
||||||
/**
|
/**
|
||||||
* Write the history to the ${XDG_CACHE_HOME}/mc/history file.
|
* Write the history to the ${XDG_CACHE_HOME}/mc/history file.
|
||||||
*/
|
*/
|
||||||
@ -296,6 +300,7 @@ history_put (const char *input_name, GList * h)
|
|||||||
|
|
||||||
g_free (profile);
|
g_free (profile);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
@ -24,8 +24,10 @@ extern int num_history_items_recorded;
|
|||||||
GList *history_get (const char *input_name);
|
GList *history_get (const char *input_name);
|
||||||
/* save history to the mc_config, but don't save config to file */
|
/* save history to the mc_config, but don't save config to file */
|
||||||
void history_save (struct mc_config_t * cfg, const char *name, GList * h);
|
void history_save (struct mc_config_t * cfg, const char *name, GList * h);
|
||||||
|
#if 0
|
||||||
/* write history to the ${XDG_CACHE_HOME}/mc/history file */
|
/* write history to the ${XDG_CACHE_HOME}/mc/history file */
|
||||||
void history_put (const char *input_name, GList * h);
|
void history_put (const char *input_name, GList * h);
|
||||||
|
#endif
|
||||||
/* for repositioning of history dialog we should pass widget to this
|
/* for repositioning of history dialog we should pass widget to this
|
||||||
* function, as position of history dialog depends on widget's position */
|
* function, as position of history dialog depends on widget's position */
|
||||||
char *history_show (GList ** history, Widget * widget);
|
char *history_show (GList ** history, Widget * widget);
|
||||||
|
@ -758,6 +758,30 @@ input_execute_cmd (WInput * in, unsigned long command)
|
|||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* "history_save" event handler */
|
||||||
|
static gboolean
|
||||||
|
input_save_history (const gchar * event_group_name, const gchar * event_name,
|
||||||
|
gpointer init_data, gpointer data)
|
||||||
|
{
|
||||||
|
WInput *in = (WInput *) init_data;
|
||||||
|
|
||||||
|
(void) event_group_name;
|
||||||
|
(void) event_name;
|
||||||
|
|
||||||
|
if (in->history != NULL && !in->is_password && (((Widget *) in)->owner->ret_value != B_CANCEL))
|
||||||
|
{
|
||||||
|
ev_history_load_save_t *ev = (ev_history_load_save_t *) data;
|
||||||
|
|
||||||
|
if (in->need_push)
|
||||||
|
push_history (in, in->buffer);
|
||||||
|
history_save (ev->cfg, in->history_name, in->history);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
input_destroy (WInput * in)
|
input_destroy (WInput * in)
|
||||||
{
|
{
|
||||||
@ -769,11 +793,10 @@ input_destroy (WInput * in)
|
|||||||
|
|
||||||
input_clean (in);
|
input_clean (in);
|
||||||
|
|
||||||
|
/* clean history */
|
||||||
if (in->history != NULL)
|
if (in->history != NULL)
|
||||||
{
|
{
|
||||||
if (!in->is_password && (((Widget *) in)->owner->ret_value != B_CANCEL))
|
/* history is already saved before this moment */
|
||||||
history_put (in->history_name, in->history);
|
|
||||||
|
|
||||||
in->history = g_list_first (in->history);
|
in->history = g_list_first (in->history);
|
||||||
g_list_foreach (in->history, (GFunc) g_free, NULL);
|
g_list_foreach (in->history, (GFunc) g_free, NULL);
|
||||||
g_list_free (in->history);
|
g_list_free (in->history);
|
||||||
@ -903,6 +926,11 @@ input_callback (Widget * w, widget_msg_t msg, int parm)
|
|||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
|
case WIDGET_INIT:
|
||||||
|
/* subscribe to "history_save" event */
|
||||||
|
mc_event_add (w->owner->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w, NULL);
|
||||||
|
return MSG_HANDLED;
|
||||||
|
|
||||||
case WIDGET_KEY:
|
case WIDGET_KEY:
|
||||||
if (parm == XCTRL ('q'))
|
if (parm == XCTRL ('q'))
|
||||||
{
|
{
|
||||||
@ -943,6 +971,8 @@ input_callback (Widget * w, widget_msg_t msg, int parm)
|
|||||||
return MSG_HANDLED;
|
return MSG_HANDLED;
|
||||||
|
|
||||||
case WIDGET_DESTROY:
|
case WIDGET_DESTROY:
|
||||||
|
/* unsubscribe from "history_save" event */
|
||||||
|
mc_event_del (w->owner->event_group, MCEVENT_HISTORY_SAVE, input_save_history, w);
|
||||||
input_destroy (in);
|
input_destroy (in);
|
||||||
return MSG_HANDLED;
|
return MSG_HANDLED;
|
||||||
|
|
||||||
@ -1210,6 +1240,7 @@ input_disable_update (WInput * in)
|
|||||||
void
|
void
|
||||||
input_clean (WInput * in)
|
input_clean (WInput * in)
|
||||||
{
|
{
|
||||||
|
if (in->need_push)
|
||||||
push_history (in, in->buffer);
|
push_history (in, in->buffer);
|
||||||
in->need_push = TRUE;
|
in->need_push = TRUE;
|
||||||
in->buffer[0] = '\0';
|
in->buffer[0] = '\0';
|
||||||
|
@ -810,6 +810,7 @@ set_display_type (int num, panel_view_mode_t type)
|
|||||||
unsigned int the_other = 0; /* Index to the other panel */
|
unsigned int the_other = 0; /* Index to the other panel */
|
||||||
const char *file_name = NULL; /* For Quick view */
|
const char *file_name = NULL; /* For Quick view */
|
||||||
Widget *new_widget = NULL, *old_widget = NULL;
|
Widget *new_widget = NULL, *old_widget = NULL;
|
||||||
|
panel_view_mode_t old_type;
|
||||||
WPanel *the_other_panel = NULL;
|
WPanel *the_other_panel = NULL;
|
||||||
|
|
||||||
if (num >= MAX_VIEWS)
|
if (num >= MAX_VIEWS)
|
||||||
@ -837,17 +838,15 @@ set_display_type (int num, panel_view_mode_t type)
|
|||||||
cols = w->cols;
|
cols = w->cols;
|
||||||
lines = w->lines;
|
lines = w->lines;
|
||||||
old_widget = w;
|
old_widget = w;
|
||||||
|
old_type = panels[num].type;
|
||||||
|
|
||||||
if (panels[num].type == view_listing)
|
if (old_type == view_listing && panel->frame_size == frame_full && type != view_listing)
|
||||||
{
|
|
||||||
if (panel->frame_size == frame_full && type != view_listing)
|
|
||||||
{
|
{
|
||||||
cols = COLS - first_panel_size;
|
cols = COLS - first_panel_size;
|
||||||
if (num == 1)
|
if (num == 1)
|
||||||
x = first_panel_size;
|
x = first_panel_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* Restoring saved path from panels.ini for nonlist panel */
|
/* Restoring saved path from panels.ini for nonlist panel */
|
||||||
/* when it's first creation (for example view_info) */
|
/* when it's first creation (for example view_info) */
|
||||||
@ -897,7 +896,16 @@ set_display_type (int num, panel_view_mode_t type)
|
|||||||
/* We use replace to keep the circular list of the dialog in the */
|
/* We use replace to keep the circular list of the dialog in the */
|
||||||
/* same state. Maybe we could just kill it and then replace it */
|
/* same state. Maybe we could just kill it and then replace it */
|
||||||
if ((midnight_dlg != NULL) && (old_widget != NULL))
|
if ((midnight_dlg != NULL) && (old_widget != NULL))
|
||||||
|
{
|
||||||
|
if (old_widget == view_listing)
|
||||||
|
{
|
||||||
|
/* save and write directory history of panel
|
||||||
|
* ... and other histories of midnight_dlg */
|
||||||
|
dlg_save_history (midnight_dlg);
|
||||||
|
}
|
||||||
|
|
||||||
dlg_replace_widget (old_widget, new_widget);
|
dlg_replace_widget (old_widget, new_widget);
|
||||||
|
}
|
||||||
|
|
||||||
if (type == view_listing)
|
if (type == view_listing)
|
||||||
{
|
{
|
||||||
|
@ -1187,6 +1187,28 @@ panel_save_name (WPanel * panel)
|
|||||||
|
|
||||||
/* --------------------------------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/* "history_save" event handler */
|
||||||
|
static gboolean
|
||||||
|
panel_save_history (const gchar * event_group_name, const gchar * event_name,
|
||||||
|
gpointer init_data, gpointer data)
|
||||||
|
{
|
||||||
|
WPanel *p = (WPanel *) init_data;
|
||||||
|
|
||||||
|
(void) event_group_name;
|
||||||
|
(void) event_name;
|
||||||
|
|
||||||
|
if (p->dir_history != NULL)
|
||||||
|
{
|
||||||
|
ev_history_load_save_t *ev = (ev_history_load_save_t *) data;
|
||||||
|
|
||||||
|
history_save (ev->cfg, p->hist_name, p->dir_history);
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
panel_destroy (WPanel * p)
|
panel_destroy (WPanel * p)
|
||||||
{
|
{
|
||||||
@ -1203,11 +1225,10 @@ panel_destroy (WPanel * p)
|
|||||||
|
|
||||||
panel_clean_dir (p);
|
panel_clean_dir (p);
|
||||||
|
|
||||||
/* save and clean history */
|
/* clean history */
|
||||||
if (p->dir_history != NULL)
|
if (p->dir_history != NULL)
|
||||||
{
|
{
|
||||||
history_put (p->hist_name, p->dir_history);
|
/* directory history is already saved before this moment */
|
||||||
|
|
||||||
p->dir_history = g_list_first (p->dir_history);
|
p->dir_history = g_list_first (p->dir_history);
|
||||||
g_list_foreach (p->dir_history, (GFunc) g_free, NULL);
|
g_list_foreach (p->dir_history, (GFunc) g_free, NULL);
|
||||||
g_list_free (p->dir_history);
|
g_list_free (p->dir_history);
|
||||||
@ -2908,6 +2929,11 @@ panel_callback (Widget * w, widget_msg_t msg, int parm)
|
|||||||
|
|
||||||
switch (msg)
|
switch (msg)
|
||||||
{
|
{
|
||||||
|
case WIDGET_INIT:
|
||||||
|
/* subscribe to "history_save" event */
|
||||||
|
mc_event_add (w->owner->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w, NULL);
|
||||||
|
return MSG_HANDLED;
|
||||||
|
|
||||||
case WIDGET_DRAW:
|
case WIDGET_DRAW:
|
||||||
/* Repaint everything, including frame and separator */
|
/* Repaint everything, including frame and separator */
|
||||||
paint_frame (panel); /* including show_dir */
|
paint_frame (panel); /* including show_dir */
|
||||||
@ -2956,6 +2982,8 @@ panel_callback (Widget * w, widget_msg_t msg, int parm)
|
|||||||
return panel_execute_cmd (panel, parm);
|
return panel_execute_cmd (panel, parm);
|
||||||
|
|
||||||
case WIDGET_DESTROY:
|
case WIDGET_DESTROY:
|
||||||
|
/* unsubscribe from "history_save" event */
|
||||||
|
mc_event_del (w->owner->event_group, MCEVENT_HISTORY_SAVE, panel_save_history, w);
|
||||||
panel_destroy (panel);
|
panel_destroy (panel);
|
||||||
free_my_statfs ();
|
free_my_statfs ();
|
||||||
return MSG_HANDLED;
|
return MSG_HANDLED;
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user