mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-17 11:10:18 +00:00
refactor: coord prefs/theme saves in one staged path; drop broken manager wrappers
This commit is contained in:
@@ -1009,15 +1009,51 @@ load_config (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
save_config (void)
|
||||
static int
|
||||
save_config_write_to_fd (int fh)
|
||||
{
|
||||
int fh, i;
|
||||
char *config, *new_config;
|
||||
int i;
|
||||
|
||||
if (!cfg_put_str (fh, "version", PACKAGE_VERSION))
|
||||
return 0;
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
switch (vars[i].type)
|
||||
{
|
||||
case TYPE_STR:
|
||||
if (!cfg_put_str (fh, vars[i].name, (char *) &prefs + vars[i].offset))
|
||||
return 0;
|
||||
break;
|
||||
case TYPE_INT:
|
||||
case TYPE_BOOL:
|
||||
if (!cfg_put_int (fh, *((int *) &prefs + vars[i].offset), vars[i].name))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (vars[i].after_update != NULL)
|
||||
vars[i].after_update();
|
||||
i++;
|
||||
}
|
||||
while (vars[i].name);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
save_config_prepare (char **temp_path)
|
||||
{
|
||||
int fh;
|
||||
char *config;
|
||||
char *new_config;
|
||||
|
||||
if (check_config_dir () != 0)
|
||||
make_config_dirs ();
|
||||
|
||||
if (!temp_path)
|
||||
return 0;
|
||||
|
||||
config = default_file ();
|
||||
new_config = g_strconcat (config, ".new", NULL);
|
||||
|
||||
@@ -1028,63 +1064,67 @@ save_config (void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!cfg_put_str (fh, "version", PACKAGE_VERSION))
|
||||
if (!save_config_write_to_fd (fh))
|
||||
{
|
||||
close (fh);
|
||||
g_free (new_config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
switch (vars[i].type)
|
||||
{
|
||||
case TYPE_STR:
|
||||
if (!cfg_put_str (fh, vars[i].name, (char *) &prefs + vars[i].offset))
|
||||
{
|
||||
close (fh);
|
||||
g_free (new_config);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case TYPE_INT:
|
||||
case TYPE_BOOL:
|
||||
if (!cfg_put_int (fh, *((int *) &prefs + vars[i].offset), vars[i].name))
|
||||
{
|
||||
close (fh);
|
||||
g_free (new_config);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (vars[i].after_update != NULL)
|
||||
{
|
||||
vars[i].after_update();
|
||||
}
|
||||
i++;
|
||||
}
|
||||
while (vars[i].name);
|
||||
|
||||
if (close (fh) == -1)
|
||||
{
|
||||
g_free (new_config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
g_unlink (config); /* win32 can't rename to an existing file */
|
||||
#endif
|
||||
if (g_rename (new_config, config) == -1)
|
||||
{
|
||||
g_free (new_config);
|
||||
*temp_path = new_config;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
save_config_finalize (const char *temp_path)
|
||||
{
|
||||
char *config;
|
||||
|
||||
if (!temp_path)
|
||||
return 0;
|
||||
|
||||
config = default_file ();
|
||||
#ifdef WIN32
|
||||
g_unlink (config);
|
||||
#endif
|
||||
if (g_rename (temp_path, config) == -1)
|
||||
return 0;
|
||||
}
|
||||
g_free (new_config);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
save_config_discard (const char *temp_path)
|
||||
{
|
||||
if (!temp_path)
|
||||
return;
|
||||
|
||||
g_unlink (temp_path);
|
||||
}
|
||||
|
||||
int
|
||||
save_config (void)
|
||||
{
|
||||
char *temp_path = NULL;
|
||||
int result;
|
||||
|
||||
if (!save_config_prepare (&temp_path))
|
||||
return 0;
|
||||
|
||||
result = save_config_finalize (temp_path);
|
||||
if (!result)
|
||||
save_config_discard (temp_path);
|
||||
g_free (temp_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
set_showval (session *sess, const struct prefs *var, char *tbuf)
|
||||
{
|
||||
|
||||
@@ -43,6 +43,9 @@ int make_config_dirs (void);
|
||||
int make_dcc_dirs (void);
|
||||
int load_config (void);
|
||||
int save_config (void);
|
||||
int save_config_prepare (char **temp_path);
|
||||
int save_config_finalize (const char *temp_path);
|
||||
void save_config_discard (const char *temp_path);
|
||||
void list_free (GSList ** list);
|
||||
void list_loadconf (char *file, GSList ** list, char *defaultconf);
|
||||
int list_delentry (GSList ** list, char *name);
|
||||
|
||||
@@ -61,6 +61,7 @@ powershell "Get-Content -Encoding UTF8 '$(ZoiteChatLib)zoitechat.rc.utf8' | Out-
|
||||
<ClInclude Include="icon-resolver.h" />
|
||||
<ClInclude Include="joind.h" />
|
||||
<ClInclude Include="maingui.h" />
|
||||
<ClInclude Include="preferences-persistence.h" />
|
||||
<ClInclude Include="menu.h" />
|
||||
<ClInclude Include="notifications\notification-backend.h" />
|
||||
<ClInclude Include="notifygui.h" />
|
||||
@@ -107,6 +108,7 @@ powershell "Get-Content -Encoding UTF8 '$(ZoiteChatLib)zoitechat.rc.utf8' | Out-
|
||||
<ClCompile Include="notifications\notification-windows.c" />
|
||||
<ClCompile Include="notifygui.c" />
|
||||
<ClCompile Include="pixmaps.c" />
|
||||
<ClCompile Include="preferences-persistence.c" />
|
||||
<ClCompile Include="plugin-notification.c" />
|
||||
<ClCompile Include="plugin-tray.c" />
|
||||
<ClCompile Include="plugingui.c" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
@@ -51,6 +51,9 @@
|
||||
<ClInclude Include="maingui.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="preferences-persistence.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="menu.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@@ -182,6 +185,9 @@
|
||||
<ClCompile Include="pixmaps.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="preferences-persistence.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="plugingui.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "theme/theme-palette.h"
|
||||
#include "maingui.h"
|
||||
#include "menu.h"
|
||||
#include "preferences-persistence.h"
|
||||
#include "fkeys.h"
|
||||
#include "userlistgui.h"
|
||||
#include "chanview.h"
|
||||
@@ -178,15 +179,37 @@ static void mg_apply_emoji_fallback_widget (GtkWidget *widget);
|
||||
static guint mg_config_save_source_id = 0;
|
||||
static gboolean mg_config_prefs_dirty = FALSE;
|
||||
|
||||
static void
|
||||
mg_show_save_failure (const PreferencesPersistenceResult *save_result)
|
||||
{
|
||||
char buffer[192];
|
||||
|
||||
if (!save_result || save_result->success)
|
||||
return;
|
||||
|
||||
if (save_result->partial_failure)
|
||||
{
|
||||
fe_message (_("Could not fully save preferences. zoitechat.conf was written, but colors.conf failed. Retry is possible."), FE_MSG_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
g_snprintf (buffer, sizeof (buffer), _("Could not save preferences (%s). Retry is possible."), save_result->failed_file ? save_result->failed_file : _("unknown file"));
|
||||
fe_message (buffer, FE_MSG_ERROR);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
mg_config_save_timeout_cb (gpointer userdata)
|
||||
{
|
||||
PreferencesPersistenceResult save_result;
|
||||
|
||||
mg_config_save_source_id = 0;
|
||||
|
||||
if (!mg_config_prefs_dirty)
|
||||
return G_SOURCE_REMOVE;
|
||||
|
||||
save_config ();
|
||||
save_result = preferences_persistence_save_all ();
|
||||
if (!save_result.success)
|
||||
mg_show_save_failure (&save_result);
|
||||
mg_config_prefs_dirty = FALSE;
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
@@ -209,6 +232,8 @@ mg_schedule_config_save (void)
|
||||
static void
|
||||
mg_flush_config_save (void)
|
||||
{
|
||||
PreferencesPersistenceResult save_result;
|
||||
|
||||
if (mg_config_save_source_id != 0)
|
||||
{
|
||||
g_source_remove (mg_config_save_source_id);
|
||||
@@ -217,7 +242,9 @@ mg_flush_config_save (void)
|
||||
|
||||
if (mg_config_prefs_dirty)
|
||||
{
|
||||
save_config ();
|
||||
save_result = preferences_persistence_save_all ();
|
||||
if (!save_result.success)
|
||||
mg_show_save_failure (&save_result);
|
||||
mg_config_prefs_dirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ zoitechat_gtk_sources = [
|
||||
'maingui.c',
|
||||
'notifygui.c',
|
||||
'pixmaps.c',
|
||||
'preferences-persistence.c',
|
||||
'plugin-tray.c',
|
||||
'plugin-notification.c',
|
||||
'rawlog.c',
|
||||
|
||||
66
src/fe-gtk/preferences-persistence.c
Normal file
66
src/fe-gtk/preferences-persistence.c
Normal file
@@ -0,0 +1,66 @@
|
||||
#include "preferences-persistence.h"
|
||||
|
||||
#include "../common/cfgfiles.h"
|
||||
#include "theme/theme-runtime.h"
|
||||
|
||||
PreferencesPersistenceResult
|
||||
preferences_persistence_save_all (void)
|
||||
{
|
||||
PreferencesPersistenceResult result;
|
||||
char *config_temp;
|
||||
char *theme_temp;
|
||||
|
||||
result.success = FALSE;
|
||||
result.retry_possible = TRUE;
|
||||
result.partial_failure = FALSE;
|
||||
result.config_failed = FALSE;
|
||||
result.theme_failed = FALSE;
|
||||
result.failed_file = NULL;
|
||||
config_temp = NULL;
|
||||
theme_temp = NULL;
|
||||
|
||||
if (!save_config_prepare (&config_temp))
|
||||
{
|
||||
result.config_failed = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!theme_runtime_save_prepare (&theme_temp))
|
||||
{
|
||||
result.theme_failed = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!save_config_finalize (config_temp))
|
||||
{
|
||||
result.config_failed = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!theme_runtime_save_finalize (theme_temp))
|
||||
{
|
||||
result.theme_failed = TRUE;
|
||||
result.partial_failure = TRUE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
result.success = TRUE;
|
||||
|
||||
done:
|
||||
if (!result.success)
|
||||
{
|
||||
if (result.config_failed && result.theme_failed)
|
||||
result.failed_file = "zoitechat.conf and colors.conf";
|
||||
else if (result.config_failed)
|
||||
result.failed_file = "zoitechat.conf";
|
||||
else if (result.theme_failed)
|
||||
result.failed_file = "colors.conf";
|
||||
}
|
||||
|
||||
save_config_discard (config_temp);
|
||||
theme_runtime_save_discard (theme_temp);
|
||||
g_free (config_temp);
|
||||
g_free (theme_temp);
|
||||
|
||||
return result;
|
||||
}
|
||||
18
src/fe-gtk/preferences-persistence.h
Normal file
18
src/fe-gtk/preferences-persistence.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef ZOITECHAT_PREFERENCES_PERSISTENCE_H
|
||||
#define ZOITECHAT_PREFERENCES_PERSISTENCE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean success;
|
||||
gboolean retry_possible;
|
||||
gboolean partial_failure;
|
||||
gboolean config_failed;
|
||||
gboolean theme_failed;
|
||||
const char *failed_file;
|
||||
} PreferencesPersistenceResult;
|
||||
|
||||
PreferencesPersistenceResult preferences_persistence_save_all (void);
|
||||
|
||||
#endif
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "maingui.h"
|
||||
#include "pixmaps.h"
|
||||
#include "menu.h"
|
||||
#include "preferences-persistence.h"
|
||||
#include "plugin-tray.h"
|
||||
#include "notifications/notification-backend.h"
|
||||
|
||||
@@ -2191,12 +2192,23 @@ setup_apply (struct zoitechatprefs *pr)
|
||||
static void
|
||||
setup_ok_cb (GtkWidget *but, GtkWidget *win)
|
||||
{
|
||||
PreferencesPersistenceResult save_result;
|
||||
char buffer[192];
|
||||
|
||||
gtk_widget_destroy (win);
|
||||
setup_apply (&setup_prefs);
|
||||
if (!save_config ())
|
||||
fe_message (_("Could not save zoitechat.conf."), FE_MSG_ERROR);
|
||||
if (!theme_manager_save_preferences ())
|
||||
fe_message (_("Could not save colors.conf."), FE_MSG_ERROR);
|
||||
save_result = preferences_persistence_save_all ();
|
||||
if (save_result.success)
|
||||
return;
|
||||
|
||||
if (save_result.partial_failure)
|
||||
{
|
||||
fe_message (_("Preferences were partially saved. zoitechat.conf succeeded, colors.conf failed. Retry is possible."), FE_MSG_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
g_snprintf (buffer, sizeof (buffer), _("Could not save preferences (%s). Retry is possible."), save_result.failed_file ? save_result.failed_file : _("unknown file"));
|
||||
fe_message (buffer, FE_MSG_ERROR);
|
||||
}
|
||||
|
||||
static GtkWidget *
|
||||
|
||||
@@ -449,12 +449,11 @@ theme_runtime_load (void)
|
||||
user_colors_valid = TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
theme_runtime_save (void)
|
||||
static gboolean
|
||||
theme_runtime_save_to_fd (int fh)
|
||||
{
|
||||
size_t i;
|
||||
size_t j;
|
||||
int fh;
|
||||
ThemePalettePersistenceMode modes[] = {
|
||||
{ "light", "color", &light_palette, &user_colors_valid },
|
||||
{ "dark", "dark_color", &dark_palette, &dark_user_colors_valid },
|
||||
@@ -485,15 +484,8 @@ theme_runtime_save (void)
|
||||
else
|
||||
modes[1].palette = &dark_palette;
|
||||
|
||||
fh = zoitechat_open_file ("colors.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
|
||||
if (fh == -1)
|
||||
return FALSE;
|
||||
|
||||
if (!cfg_put_int (fh, THEME_PALETTE_MIGRATION_MARKER_VALUE, (char *) THEME_PALETTE_MIGRATION_MARKER_KEY))
|
||||
{
|
||||
close (fh);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (i = 0; i < mode_count; i++)
|
||||
{
|
||||
@@ -512,19 +504,131 @@ theme_runtime_save (void)
|
||||
continue;
|
||||
g_assert (theme_palette_get_color (modes[i].palette, def->token, &color));
|
||||
if (!palette_write_token_color (fh, modes[i].mode_name, def, &color))
|
||||
{
|
||||
close (fh);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
theme_runtime_save_prepare (char **temp_path)
|
||||
{
|
||||
int fh;
|
||||
const char *temp_name;
|
||||
|
||||
if (!temp_path)
|
||||
return FALSE;
|
||||
|
||||
temp_name = "colors.conf.new";
|
||||
fh = zoitechat_open_file (temp_name, O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
|
||||
if (fh == -1)
|
||||
return FALSE;
|
||||
|
||||
if (!theme_runtime_save_to_fd (fh))
|
||||
{
|
||||
close (fh);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (close (fh) == -1)
|
||||
return FALSE;
|
||||
|
||||
*temp_path = g_strdup (temp_name);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
theme_runtime_save_finalize (const char *temp_path)
|
||||
{
|
||||
int src_fh;
|
||||
int dst_fh;
|
||||
char buffer[4096];
|
||||
ssize_t read_len;
|
||||
|
||||
if (!temp_path)
|
||||
return FALSE;
|
||||
|
||||
src_fh = zoitechat_open_file (temp_path, O_RDONLY, 0, XOF_DOMODE);
|
||||
if (src_fh == -1)
|
||||
return FALSE;
|
||||
|
||||
dst_fh = zoitechat_open_file ("colors.conf", O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
|
||||
if (dst_fh == -1)
|
||||
{
|
||||
close (src_fh);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while ((read_len = read (src_fh, buffer, sizeof (buffer))) > 0)
|
||||
{
|
||||
ssize_t offset;
|
||||
|
||||
offset = 0;
|
||||
while (offset < read_len)
|
||||
{
|
||||
ssize_t written;
|
||||
|
||||
written = write (dst_fh, buffer + offset, (size_t) (read_len - offset));
|
||||
if (written <= 0)
|
||||
{
|
||||
close (src_fh);
|
||||
close (dst_fh);
|
||||
return FALSE;
|
||||
}
|
||||
offset += written;
|
||||
}
|
||||
}
|
||||
|
||||
if (read_len < 0)
|
||||
{
|
||||
close (src_fh);
|
||||
close (dst_fh);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (close (src_fh) == -1)
|
||||
{
|
||||
close (dst_fh);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (close (dst_fh) == -1)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
theme_runtime_save_discard (const char *temp_path)
|
||||
{
|
||||
int fh;
|
||||
|
||||
if (!temp_path)
|
||||
return;
|
||||
|
||||
fh = zoitechat_open_file (temp_path, O_TRUNC | O_WRONLY | O_CREAT, 0600, XOF_DOMODE);
|
||||
if (fh != -1)
|
||||
close (fh);
|
||||
}
|
||||
|
||||
gboolean
|
||||
theme_runtime_save (void)
|
||||
{
|
||||
char *temp_path = NULL;
|
||||
gboolean result;
|
||||
|
||||
if (!theme_runtime_save_prepare (&temp_path))
|
||||
return FALSE;
|
||||
|
||||
result = theme_runtime_save_finalize (temp_path);
|
||||
if (!result)
|
||||
theme_runtime_save_discard (temp_path);
|
||||
g_free (temp_path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
palette_color_eq (const GdkRGBA *a, const GdkRGBA *b)
|
||||
{
|
||||
|
||||
@@ -19,6 +19,9 @@ typedef struct
|
||||
|
||||
void theme_runtime_load (void);
|
||||
gboolean theme_runtime_save (void);
|
||||
gboolean theme_runtime_save_prepare (char **temp_path);
|
||||
gboolean theme_runtime_save_finalize (const char *temp_path);
|
||||
void theme_runtime_save_discard (const char *temp_path);
|
||||
gboolean theme_runtime_apply_mode (unsigned int mode, gboolean *palette_changed);
|
||||
gboolean theme_runtime_apply_dark_mode (gboolean enable);
|
||||
void theme_runtime_user_set_color (ThemeSemanticToken token, const GdkRGBA *col);
|
||||
|
||||
Reference in New Issue
Block a user