mirror of
https://github.com/ZoiteChat/zoitechat.git
synced 2026-03-14 01:30:19 +00:00
feat: GTK3-only theming overhaul—new theme service (discover/import/inherits), layered CSS+settings.ini apply w/ safe rollback + caching; widget/xtext palette mapping + all-colors editor; lots of win32/CI libarchive plumbing + installer assets;
This commit is contained in:
@@ -439,6 +439,7 @@ const struct prefs vars[] =
|
||||
{"gui_tab_dots", P_OFFINT (hex_gui_tab_dots), TYPE_BOOL},
|
||||
{"gui_tab_icons", P_OFFINT (hex_gui_tab_icons), TYPE_BOOL},
|
||||
{"gui_dark_mode", P_OFFINT (hex_gui_dark_mode), TYPE_INT},
|
||||
{"gui_gtk3_variant", P_OFFINT (hex_gui_gtk3_variant), TYPE_INT},
|
||||
{"gui_tab_layout", P_OFFINT (hex_gui_tab_layout), TYPE_INT},
|
||||
{"gui_tab_middleclose", P_OFFINT (hex_gui_tab_middleclose), TYPE_BOOL},
|
||||
{"gui_tab_newtofront", P_OFFINT (hex_gui_tab_newtofront), TYPE_INT},
|
||||
@@ -568,6 +569,7 @@ const struct prefs vars[] =
|
||||
{"text_font", P_OFFSET (hex_text_font), TYPE_STR},
|
||||
{"text_font_main", P_OFFSET (hex_text_font_main), TYPE_STR},
|
||||
{"text_font_alternative", P_OFFSET (hex_text_font_alternative), TYPE_STR},
|
||||
{"gui_gtk3_theme", P_OFFSET (hex_gui_gtk3_theme), TYPE_STR},
|
||||
{"text_indent", P_OFFINT (hex_text_indent), TYPE_BOOL},
|
||||
{"text_max_indent", P_OFFINT (hex_text_max_indent), TYPE_INT},
|
||||
{"text_max_lines", P_OFFINT (hex_text_max_lines), TYPE_INT},
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
<ClInclude Include="zoitechat.h" />
|
||||
<ClInclude Include="zoitechatc.h" />
|
||||
<ClInclude Include="theme-service.h" />
|
||||
<ClInclude Include="gtk3-theme-service.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="cfgfiles.c" />
|
||||
@@ -77,6 +78,7 @@
|
||||
<ClCompile Include="util.c" />
|
||||
<ClCompile Include="zoitechat.c" />
|
||||
<ClCompile Include="theme-service.c" />
|
||||
<ClCompile Include="gtk3-theme-service.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\win32\config.h.tt" />
|
||||
@@ -97,7 +99,7 @@
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WIN64;_AMD64_;NDEBUG;_LIB;$(OwnFlags);%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>$(ZoiteChatLib);$(DepsRoot)\include;$(OpenSslInclude);$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>$(ZoiteChatLib);$(DepsRoot)\include;$(ArchiveInclude);$(OpenSslInclude);$(Glib);$(Gtk);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
|
||||
@@ -122,6 +122,9 @@
|
||||
<ClInclude Include="theme-service.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="gtk3-theme-service.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="cfgfiles.c">
|
||||
@@ -208,6 +211,9 @@
|
||||
<ClCompile Include="theme-service.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="gtk3-theme-service.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\win32\config.h.tt" />
|
||||
|
||||
1152
src/common/gtk3-theme-service.c
Normal file
1152
src/common/gtk3-theme-service.c
Normal file
File diff suppressed because it is too large
Load Diff
32
src/common/gtk3-theme-service.h
Normal file
32
src/common/gtk3-theme-service.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef ZOITECHAT_GTK3_THEME_SERVICE_H
|
||||
#define ZOITECHAT_GTK3_THEME_SERVICE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ZOITECHAT_GTK3_THEME_SOURCE_SYSTEM = 0,
|
||||
ZOITECHAT_GTK3_THEME_SOURCE_USER = 1
|
||||
} ZoitechatGtk3ThemeSource;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *id;
|
||||
char *display_name;
|
||||
char *path;
|
||||
gboolean has_dark_variant;
|
||||
char *thumbnail_path;
|
||||
ZoitechatGtk3ThemeSource source;
|
||||
} ZoitechatGtk3Theme;
|
||||
|
||||
char *zoitechat_gtk3_theme_service_get_user_themes_dir (void);
|
||||
GPtrArray *zoitechat_gtk3_theme_service_discover (void);
|
||||
void zoitechat_gtk3_theme_free (ZoitechatGtk3Theme *theme);
|
||||
ZoitechatGtk3Theme *zoitechat_gtk3_theme_find_by_id (const char *theme_id);
|
||||
gboolean zoitechat_gtk3_theme_service_import (const char *source_path, char **imported_id, GError **error);
|
||||
gboolean zoitechat_gtk3_theme_service_remove_user_theme (const char *theme_id, GError **error);
|
||||
char *zoitechat_gtk3_theme_pick_css_dir_for_minor (const char *theme_root, int preferred_minor);
|
||||
char *zoitechat_gtk3_theme_pick_css_dir (const char *theme_root);
|
||||
GPtrArray *zoitechat_gtk3_theme_build_inheritance_chain (const char *theme_root);
|
||||
|
||||
#endif
|
||||
@@ -3,7 +3,7 @@ common_sources = [
|
||||
'chanopt.c',
|
||||
'ctcp.c',
|
||||
'dcc.c',
|
||||
'theme-service.c',
|
||||
'gtk3-theme-service.c',
|
||||
'zoitechat.c',
|
||||
'history.c',
|
||||
'ignore.c',
|
||||
@@ -28,12 +28,17 @@ common_sources = [
|
||||
]
|
||||
|
||||
common_sysinfo_deps = []
|
||||
libarchive_dep = dependency('libarchive', required: host_machine.system() != 'windows')
|
||||
|
||||
common_deps = [
|
||||
libgio_dep,
|
||||
libcanberra_dep,
|
||||
] + global_deps
|
||||
|
||||
if libarchive_dep.found()
|
||||
common_deps += libarchive_dep
|
||||
endif
|
||||
|
||||
common_includes = [
|
||||
config_h_include,
|
||||
include_directories('.')
|
||||
@@ -134,3 +139,18 @@ zoitechat_plugin_dep = declare_dependency(
|
||||
compile_args: common_cflags,
|
||||
dependencies: global_deps,
|
||||
)
|
||||
|
||||
|
||||
gtk3_theme_service_tests = executable('gtk3_theme_service_tests',
|
||||
[
|
||||
'tests/test-gtk3-theme-service.c',
|
||||
'gtk3-theme-service.c',
|
||||
],
|
||||
include_directories: [config_h_include, include_directories('.')],
|
||||
dependencies: [libgio_dep] + (libarchive_dep.found() ? [libarchive_dep] : []),
|
||||
)
|
||||
|
||||
test('GTK3 Theme Service Tests', gtk3_theme_service_tests,
|
||||
protocol: 'tap',
|
||||
timeout: 120,
|
||||
)
|
||||
|
||||
@@ -3770,45 +3770,6 @@ cmd_url (struct session *sess, char *tbuf, char *word[], char *word_eol[])
|
||||
{
|
||||
if (word[2][0])
|
||||
{
|
||||
char *theme_path = NULL;
|
||||
if (zoitechat_theme_path_from_arg (word[2], &theme_path))
|
||||
{
|
||||
GError *error = NULL;
|
||||
char *basename = g_path_get_basename (theme_path);
|
||||
char *dot = strrchr (basename, '.');
|
||||
char *message;
|
||||
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
if (zoitechat_import_theme (theme_path, &error))
|
||||
{
|
||||
if (zoitechat_apply_theme (basename, &error))
|
||||
{
|
||||
message = g_strdup_printf (_("Theme \"%s\" imported and applied."), basename);
|
||||
fe_message (message, FE_MSG_INFO);
|
||||
handle_command (sess, "gui apply", FALSE);
|
||||
g_free (message);
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message (error ? error->message : _("Theme imported, but failed to apply."),
|
||||
FE_MSG_ERROR);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message (error ? error->message : _("Failed to import theme."),
|
||||
FE_MSG_ERROR);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_free (basename);
|
||||
g_free (theme_path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
char *server_name = NULL;
|
||||
char *port = NULL;
|
||||
char *channel = NULL;
|
||||
|
||||
684
src/common/tests/test-gtk3-theme-service.c
Normal file
684
src/common/tests/test-gtk3-theme-service.c
Normal file
@@ -0,0 +1,684 @@
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
#include "../gtk3-theme-service.h"
|
||||
#include "../cfgfiles.h"
|
||||
|
||||
char *xdir = NULL;
|
||||
|
||||
char *
|
||||
get_xdir (void)
|
||||
{
|
||||
return xdir;
|
||||
}
|
||||
|
||||
static void
|
||||
write_text_file (const char *path, const char *contents)
|
||||
{
|
||||
g_file_set_contents (path, contents, -1, NULL);
|
||||
}
|
||||
|
||||
static char *
|
||||
make_theme_dir (const char *base, const char *name, gboolean dark, gboolean with_index)
|
||||
{
|
||||
char *root = g_build_filename (base, name, NULL);
|
||||
char *gtk_dir = g_build_filename (root, "gtk-3.0", NULL);
|
||||
char *css = g_build_filename (gtk_dir, "gtk.css", NULL);
|
||||
|
||||
g_mkdir_with_parents (gtk_dir, 0700);
|
||||
write_text_file (css, "button { background-image: url(\"../assets/a.png\"); }");
|
||||
if (dark)
|
||||
{
|
||||
char *dark_css = g_build_filename (gtk_dir, "gtk-dark.css", NULL);
|
||||
write_text_file (dark_css, "button { color: #eee; }");
|
||||
g_free (dark_css);
|
||||
}
|
||||
if (with_index)
|
||||
{
|
||||
char *index = g_build_filename (root, "index.theme", NULL);
|
||||
write_text_file (index, "[Desktop Entry]\nName=Indexed Theme\n");
|
||||
g_free (index);
|
||||
}
|
||||
g_free (css);
|
||||
g_free (gtk_dir);
|
||||
return root;
|
||||
}
|
||||
|
||||
static void
|
||||
setup_test_xdir (char **tmp_root)
|
||||
{
|
||||
char *root = g_dir_make_tmp ("zoitechat-gtk3-service-test-XXXXXX", NULL);
|
||||
xdir = g_build_filename (root, "config", NULL);
|
||||
g_mkdir_with_parents (xdir, 0700);
|
||||
*tmp_root = root;
|
||||
}
|
||||
|
||||
static void
|
||||
teardown_test_xdir (char *tmp_root)
|
||||
{
|
||||
char *cmd;
|
||||
cmd = g_strdup_printf ("rm -rf %s", tmp_root);
|
||||
g_spawn_command_line_sync (cmd, NULL, NULL, NULL, NULL);
|
||||
g_free (cmd);
|
||||
g_free (xdir);
|
||||
xdir = NULL;
|
||||
g_free (tmp_root);
|
||||
}
|
||||
|
||||
|
||||
static guint
|
||||
count_extract_temp_dirs (void)
|
||||
{
|
||||
GDir *dir;
|
||||
const char *name;
|
||||
guint count = 0;
|
||||
const char *tmp_dir = g_get_tmp_dir ();
|
||||
|
||||
dir = g_dir_open (tmp_dir, 0, NULL);
|
||||
if (!dir)
|
||||
return 0;
|
||||
|
||||
while ((name = g_dir_read_name (dir)) != NULL)
|
||||
{
|
||||
if (g_str_has_prefix (name, "zoitechat-gtk3-theme-"))
|
||||
count++;
|
||||
}
|
||||
|
||||
g_dir_close (dir);
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
static char *
|
||||
make_theme_dir_with_inherits (const char *base, const char *name, const char *inherits)
|
||||
{
|
||||
char *root = make_theme_dir (base, name, FALSE, FALSE);
|
||||
char *index = g_build_filename (root, "index.theme", NULL);
|
||||
char *contents;
|
||||
|
||||
if (inherits && inherits[0])
|
||||
contents = g_strdup_printf ("[Desktop Entry]\nName=%s\nInherits=%s\n", name, inherits);
|
||||
else
|
||||
contents = g_strdup_printf ("[Desktop Entry]\nName=%s\n", name);
|
||||
write_text_file (index, contents);
|
||||
g_free (contents);
|
||||
g_free (index);
|
||||
return root;
|
||||
}
|
||||
|
||||
static void
|
||||
test_inheritance_chain_single_parent (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *themes_root;
|
||||
char *adwaita;
|
||||
char *child;
|
||||
GPtrArray *chain;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
themes_root = g_build_filename (tmp_root, "themes", NULL);
|
||||
g_mkdir_with_parents (themes_root, 0700);
|
||||
adwaita = make_theme_dir_with_inherits (themes_root, "Adwaita", NULL);
|
||||
child = make_theme_dir_with_inherits (themes_root, "Child", "Adwaita");
|
||||
|
||||
chain = zoitechat_gtk3_theme_build_inheritance_chain (child);
|
||||
g_assert_nonnull (chain);
|
||||
g_assert_cmpuint (chain->len, ==, 2);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 0), ==, adwaita);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 1), ==, child);
|
||||
|
||||
g_ptr_array_unref (chain);
|
||||
g_free (child);
|
||||
g_free (adwaita);
|
||||
g_free (themes_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_inheritance_chain_multi_level (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *themes_root;
|
||||
char *base;
|
||||
char *middle;
|
||||
char *child;
|
||||
GPtrArray *chain;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
themes_root = g_build_filename (tmp_root, "themes", NULL);
|
||||
g_mkdir_with_parents (themes_root, 0700);
|
||||
base = make_theme_dir_with_inherits (themes_root, "Base", NULL);
|
||||
middle = make_theme_dir_with_inherits (themes_root, "Middle", "Base");
|
||||
child = make_theme_dir_with_inherits (themes_root, "Child", "Middle");
|
||||
|
||||
chain = zoitechat_gtk3_theme_build_inheritance_chain (child);
|
||||
g_assert_nonnull (chain);
|
||||
g_assert_cmpuint (chain->len, ==, 3);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 0), ==, base);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 1), ==, middle);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 2), ==, child);
|
||||
|
||||
g_ptr_array_unref (chain);
|
||||
g_free (child);
|
||||
g_free (middle);
|
||||
g_free (base);
|
||||
g_free (themes_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_inheritance_chain_missing_parent (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *themes_root;
|
||||
char *child;
|
||||
GPtrArray *chain;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
themes_root = g_build_filename (tmp_root, "themes", NULL);
|
||||
g_mkdir_with_parents (themes_root, 0700);
|
||||
child = make_theme_dir_with_inherits (themes_root, "Child", "MissingParent");
|
||||
|
||||
chain = zoitechat_gtk3_theme_build_inheritance_chain (child);
|
||||
g_assert_nonnull (chain);
|
||||
g_assert_cmpuint (chain->len, ==, 1);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 0), ==, child);
|
||||
|
||||
g_ptr_array_unref (chain);
|
||||
g_free (child);
|
||||
g_free (themes_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
static void
|
||||
test_inheritance_chain_parent_from_xdg_data_home (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *child_root;
|
||||
char *home_dir;
|
||||
char *user_data_dir;
|
||||
char *saved_home;
|
||||
char *saved_xdg_data_home;
|
||||
char *parent;
|
||||
char *child;
|
||||
GPtrArray *chain;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
child_root = g_build_filename (tmp_root, "themes", NULL);
|
||||
home_dir = g_build_filename (tmp_root, "home", NULL);
|
||||
user_data_dir = g_build_filename (tmp_root, "xdg-data-home", NULL);
|
||||
g_mkdir_with_parents (child_root, 0700);
|
||||
g_mkdir_with_parents (home_dir, 0700);
|
||||
g_mkdir_with_parents (user_data_dir, 0700);
|
||||
|
||||
saved_home = g_strdup (g_getenv ("HOME"));
|
||||
saved_xdg_data_home = g_strdup (g_getenv ("XDG_DATA_HOME"));
|
||||
|
||||
g_setenv ("HOME", home_dir, TRUE);
|
||||
g_setenv ("XDG_DATA_HOME", user_data_dir, TRUE);
|
||||
|
||||
{
|
||||
char *user_themes = g_build_filename (user_data_dir, "themes", NULL);
|
||||
g_mkdir_with_parents (user_themes, 0700);
|
||||
parent = make_theme_dir_with_inherits (user_themes, "ParentFromDataHome", NULL);
|
||||
g_free (user_themes);
|
||||
}
|
||||
child = make_theme_dir_with_inherits (child_root, "Child", "ParentFromDataHome");
|
||||
|
||||
chain = zoitechat_gtk3_theme_build_inheritance_chain (child);
|
||||
g_assert_nonnull (chain);
|
||||
g_assert_cmpuint (chain->len, ==, 2);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 0), ==, parent);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 1), ==, child);
|
||||
g_ptr_array_unref (chain);
|
||||
|
||||
if (saved_home)
|
||||
g_setenv ("HOME", saved_home, TRUE);
|
||||
else
|
||||
g_unsetenv ("HOME");
|
||||
if (saved_xdg_data_home)
|
||||
g_setenv ("XDG_DATA_HOME", saved_xdg_data_home, TRUE);
|
||||
else
|
||||
g_unsetenv ("XDG_DATA_HOME");
|
||||
|
||||
g_free (child);
|
||||
g_free (parent);
|
||||
g_free (saved_xdg_data_home);
|
||||
g_free (saved_home);
|
||||
g_free (user_data_dir);
|
||||
g_free (home_dir);
|
||||
g_free (child_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_inheritance_chain_parent_from_xdg_data_dirs (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *child_root;
|
||||
char *home_dir;
|
||||
char *system_data_dir;
|
||||
char *system_data_dirs;
|
||||
char *saved_home;
|
||||
char *saved_xdg_data_dirs;
|
||||
char *parent;
|
||||
char *child;
|
||||
GPtrArray *chain;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
child_root = g_build_filename (tmp_root, "themes", NULL);
|
||||
home_dir = g_build_filename (tmp_root, "home", NULL);
|
||||
system_data_dir = g_build_filename (tmp_root, "xdg-data-system", NULL);
|
||||
system_data_dirs = g_strdup_printf ("%s:/usr/share", system_data_dir);
|
||||
g_mkdir_with_parents (child_root, 0700);
|
||||
g_mkdir_with_parents (home_dir, 0700);
|
||||
g_mkdir_with_parents (system_data_dir, 0700);
|
||||
|
||||
saved_home = g_strdup (g_getenv ("HOME"));
|
||||
saved_xdg_data_dirs = g_strdup (g_getenv ("XDG_DATA_DIRS"));
|
||||
|
||||
g_setenv ("HOME", home_dir, TRUE);
|
||||
g_setenv ("XDG_DATA_DIRS", system_data_dirs, TRUE);
|
||||
|
||||
{
|
||||
char *system_themes = g_build_filename (system_data_dir, "themes", NULL);
|
||||
g_mkdir_with_parents (system_themes, 0700);
|
||||
parent = make_theme_dir_with_inherits (system_themes, "ParentFromDataDirs", NULL);
|
||||
g_free (system_themes);
|
||||
}
|
||||
child = make_theme_dir_with_inherits (child_root, "Child", "ParentFromDataDirs");
|
||||
|
||||
chain = zoitechat_gtk3_theme_build_inheritance_chain (child);
|
||||
g_assert_nonnull (chain);
|
||||
g_assert_cmpuint (chain->len, ==, 2);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 0), ==, parent);
|
||||
g_assert_cmpstr (g_ptr_array_index (chain, 1), ==, child);
|
||||
g_ptr_array_unref (chain);
|
||||
|
||||
if (saved_home)
|
||||
g_setenv ("HOME", saved_home, TRUE);
|
||||
else
|
||||
g_unsetenv ("HOME");
|
||||
if (saved_xdg_data_dirs)
|
||||
g_setenv ("XDG_DATA_DIRS", saved_xdg_data_dirs, TRUE);
|
||||
else
|
||||
g_unsetenv ("XDG_DATA_DIRS");
|
||||
|
||||
g_free (child);
|
||||
g_free (parent);
|
||||
g_free (saved_xdg_data_dirs);
|
||||
g_free (saved_home);
|
||||
g_free (system_data_dirs);
|
||||
g_free (system_data_dir);
|
||||
g_free (home_dir);
|
||||
g_free (child_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_invalid_archive_reports_extract_error (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *bad_archive;
|
||||
char *imported_id = NULL;
|
||||
GError *error = NULL;
|
||||
guint before_count;
|
||||
guint after_count;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
bad_archive = g_build_filename (tmp_root, "bad-theme.tar.xz", NULL);
|
||||
write_text_file (bad_archive, "this is not a real archive");
|
||||
before_count = count_extract_temp_dirs ();
|
||||
|
||||
g_assert_false (zoitechat_gtk3_theme_service_import (bad_archive, &imported_id, &error));
|
||||
g_assert_null (imported_id);
|
||||
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED);
|
||||
g_assert_cmpstr (error->message, ==, "Failed to extract theme archive.");
|
||||
g_error_free (error);
|
||||
after_count = count_extract_temp_dirs ();
|
||||
g_assert_cmpuint (after_count, ==, before_count);
|
||||
|
||||
g_free (bad_archive);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_archive_without_theme_reports_css_error (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *archive_root;
|
||||
char *archive_path;
|
||||
char *command;
|
||||
char *imported_id = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
archive_root = g_build_filename (tmp_root, "invalid-theme-root", NULL);
|
||||
g_mkdir_with_parents (archive_root, 0700);
|
||||
{
|
||||
char *readme = g_build_filename (archive_root, "README.txt", NULL);
|
||||
write_text_file (readme, "not a gtk theme");
|
||||
g_free (readme);
|
||||
}
|
||||
archive_path = g_build_filename (tmp_root, "invalid-theme.zip", NULL);
|
||||
|
||||
command = g_strdup_printf ("cd %s && zip -qr %s .", archive_root, archive_path);
|
||||
g_assert_true (g_spawn_command_line_sync (command, NULL, NULL, NULL, NULL));
|
||||
g_free (command);
|
||||
|
||||
g_assert_false (zoitechat_gtk3_theme_service_import (archive_path, &imported_id, &error));
|
||||
g_assert_null (imported_id);
|
||||
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
|
||||
g_assert_cmpstr (error->message, ==, "No GTK3 gtk.css file found in the selected theme.");
|
||||
g_error_free (error);
|
||||
|
||||
g_free (archive_path);
|
||||
g_free (archive_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_import_rejects_theme_missing_index_theme (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *src_root;
|
||||
char *theme_root;
|
||||
char *imported_id = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
src_root = g_build_filename (tmp_root, "src", NULL);
|
||||
g_mkdir_with_parents (src_root, 0700);
|
||||
theme_root = make_theme_dir (src_root, "NoIndex", FALSE, FALSE);
|
||||
|
||||
g_assert_false (zoitechat_gtk3_theme_service_import (theme_root, &imported_id, &error));
|
||||
g_assert_null (imported_id);
|
||||
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
|
||||
g_assert_nonnull (g_strstr_len (error->message, -1, "missing required index.theme"));
|
||||
g_assert_nonnull (g_strstr_len (error->message, -1, "NoIndex"));
|
||||
g_error_free (error);
|
||||
|
||||
g_free (theme_root);
|
||||
g_free (src_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_import_rejects_index_without_desktop_entry (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *src_root;
|
||||
char *theme_root;
|
||||
char *index_path;
|
||||
char *imported_id = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
src_root = g_build_filename (tmp_root, "src", NULL);
|
||||
g_mkdir_with_parents (src_root, 0700);
|
||||
theme_root = make_theme_dir (src_root, "NoDesktopEntry", FALSE, FALSE);
|
||||
index_path = g_build_filename (theme_root, "index.theme", NULL);
|
||||
write_text_file (index_path, "[X-GNOME-Metatheme]\nName=Broken\n");
|
||||
|
||||
g_assert_false (zoitechat_gtk3_theme_service_import (theme_root, &imported_id, &error));
|
||||
g_assert_null (imported_id);
|
||||
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
|
||||
g_assert_nonnull (g_strstr_len (error->message, -1, "missing the [Desktop Entry] section"));
|
||||
g_assert_nonnull (g_strstr_len (error->message, -1, "index.theme"));
|
||||
g_error_free (error);
|
||||
|
||||
g_free (index_path);
|
||||
g_free (theme_root);
|
||||
g_free (src_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_import_rejects_unresolved_inherits (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *src_root;
|
||||
char *theme_root;
|
||||
char *imported_id = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
src_root = g_build_filename (tmp_root, "src", NULL);
|
||||
g_mkdir_with_parents (src_root, 0700);
|
||||
theme_root = make_theme_dir_with_inherits (src_root, "ChildTheme", "MissingParent");
|
||||
|
||||
g_assert_false (zoitechat_gtk3_theme_service_import (theme_root, &imported_id, &error));
|
||||
g_assert_null (imported_id);
|
||||
g_assert_error (error, G_FILE_ERROR, G_FILE_ERROR_INVAL);
|
||||
g_assert_nonnull (g_strstr_len (error->message, -1, "MissingParent"));
|
||||
g_assert_nonnull (g_strstr_len (error->message, -1, "could not be resolved"));
|
||||
g_error_free (error);
|
||||
|
||||
g_free (theme_root);
|
||||
g_free (src_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_import_collision_and_dark_detection (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *src_root;
|
||||
char *theme_one;
|
||||
char *id_one = NULL;
|
||||
char *id_two = NULL;
|
||||
ZoitechatGtk3Theme *found;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
src_root = g_build_filename (tmp_root, "src", NULL);
|
||||
g_mkdir_with_parents (src_root, 0700);
|
||||
theme_one = make_theme_dir (src_root, "Ocean", TRUE, FALSE);
|
||||
|
||||
g_assert_true (zoitechat_gtk3_theme_service_import (theme_one, &id_one, NULL));
|
||||
g_assert_true (zoitechat_gtk3_theme_service_import (theme_one, &id_two, NULL));
|
||||
g_assert_nonnull (id_one);
|
||||
g_assert_nonnull (id_two);
|
||||
g_assert_cmpstr (id_one, !=, id_two);
|
||||
|
||||
found = zoitechat_gtk3_theme_find_by_id (id_two);
|
||||
g_assert_nonnull (found);
|
||||
g_assert_true (found->has_dark_variant);
|
||||
g_assert_true (g_str_has_suffix (found->path, "Ocean-1"));
|
||||
|
||||
zoitechat_gtk3_theme_free (found);
|
||||
g_free (id_one);
|
||||
g_free (id_two);
|
||||
g_free (theme_one);
|
||||
g_free (src_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_discover_includes_user_and_system_data_dirs (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *home_dir;
|
||||
char *user_data_dir;
|
||||
char *system_data_dir;
|
||||
char *system_data_dirs;
|
||||
char *saved_home;
|
||||
char *saved_xdg_data_home;
|
||||
char *saved_xdg_data_dirs;
|
||||
char *user_themes_dir;
|
||||
char *system_themes_dir;
|
||||
char *user_theme;
|
||||
char *system_theme;
|
||||
GPtrArray *themes;
|
||||
guint i;
|
||||
gboolean found_user = FALSE;
|
||||
gboolean found_system = FALSE;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
home_dir = g_build_filename (tmp_root, "home", NULL);
|
||||
user_data_dir = g_build_filename (tmp_root, "xdg-data-home", NULL);
|
||||
system_data_dir = g_build_filename (tmp_root, "xdg-data-system", NULL);
|
||||
system_data_dirs = g_strdup_printf ("%s:/usr/share", system_data_dir);
|
||||
user_themes_dir = g_build_filename (user_data_dir, "themes", NULL);
|
||||
system_themes_dir = g_build_filename (system_data_dir, "themes", NULL);
|
||||
|
||||
g_mkdir_with_parents (home_dir, 0700);
|
||||
g_mkdir_with_parents (user_themes_dir, 0700);
|
||||
g_mkdir_with_parents (system_themes_dir, 0700);
|
||||
user_theme = make_theme_dir (user_themes_dir, "UserDataTheme", FALSE, FALSE);
|
||||
system_theme = make_theme_dir (system_themes_dir, "SystemDataTheme", FALSE, FALSE);
|
||||
|
||||
saved_home = g_strdup (g_getenv ("HOME"));
|
||||
saved_xdg_data_home = g_strdup (g_getenv ("XDG_DATA_HOME"));
|
||||
saved_xdg_data_dirs = g_strdup (g_getenv ("XDG_DATA_DIRS"));
|
||||
|
||||
g_setenv ("HOME", home_dir, TRUE);
|
||||
g_setenv ("XDG_DATA_HOME", user_data_dir, TRUE);
|
||||
g_setenv ("XDG_DATA_DIRS", system_data_dirs, TRUE);
|
||||
|
||||
themes = zoitechat_gtk3_theme_service_discover ();
|
||||
g_assert_nonnull (themes);
|
||||
|
||||
for (i = 0; i < themes->len; i++)
|
||||
{
|
||||
ZoitechatGtk3Theme *theme = g_ptr_array_index (themes, i);
|
||||
if (g_strcmp0 (theme->path, user_theme) == 0)
|
||||
{
|
||||
found_user = TRUE;
|
||||
g_assert_cmpint (theme->source, ==, ZOITECHAT_GTK3_THEME_SOURCE_USER);
|
||||
}
|
||||
if (g_strcmp0 (theme->path, system_theme) == 0)
|
||||
{
|
||||
found_system = TRUE;
|
||||
g_assert_cmpint (theme->source, ==, ZOITECHAT_GTK3_THEME_SOURCE_SYSTEM);
|
||||
}
|
||||
}
|
||||
|
||||
g_assert_true (found_user);
|
||||
g_assert_true (found_system);
|
||||
g_ptr_array_unref (themes);
|
||||
|
||||
if (saved_home)
|
||||
g_setenv ("HOME", saved_home, TRUE);
|
||||
else
|
||||
g_unsetenv ("HOME");
|
||||
if (saved_xdg_data_home)
|
||||
g_setenv ("XDG_DATA_HOME", saved_xdg_data_home, TRUE);
|
||||
else
|
||||
g_unsetenv ("XDG_DATA_HOME");
|
||||
if (saved_xdg_data_dirs)
|
||||
g_setenv ("XDG_DATA_DIRS", saved_xdg_data_dirs, TRUE);
|
||||
else
|
||||
g_unsetenv ("XDG_DATA_DIRS");
|
||||
|
||||
g_free (saved_xdg_data_dirs);
|
||||
g_free (saved_xdg_data_home);
|
||||
g_free (saved_home);
|
||||
g_free (system_theme);
|
||||
g_free (user_theme);
|
||||
g_free (system_themes_dir);
|
||||
g_free (user_themes_dir);
|
||||
g_free (system_data_dirs);
|
||||
g_free (system_data_dir);
|
||||
g_free (user_data_dir);
|
||||
g_free (home_dir);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_archive_root_detection_prefers_index (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *archive_root;
|
||||
char *theme_a;
|
||||
char *theme_b_parent;
|
||||
char *theme_b;
|
||||
char *archive_path;
|
||||
char *command;
|
||||
char *imported_id = NULL;
|
||||
ZoitechatGtk3Theme *found;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
archive_root = g_build_filename (tmp_root, "archive-root", NULL);
|
||||
g_mkdir_with_parents (archive_root, 0700);
|
||||
theme_a = make_theme_dir (archive_root, "Flat", FALSE, FALSE);
|
||||
theme_b_parent = g_build_filename (archive_root, "nested", NULL);
|
||||
g_mkdir_with_parents (theme_b_parent, 0700);
|
||||
theme_b = make_theme_dir (theme_b_parent, "Indexed", FALSE, TRUE);
|
||||
archive_path = g_build_filename (tmp_root, "themes.tar.xz", NULL);
|
||||
|
||||
command = g_strdup_printf ("tar -cJf %s -C %s .", archive_path, archive_root);
|
||||
g_assert_true (g_spawn_command_line_sync (command, NULL, NULL, NULL, NULL));
|
||||
g_free (command);
|
||||
|
||||
g_assert_true (zoitechat_gtk3_theme_service_import (archive_path, &imported_id, NULL));
|
||||
found = zoitechat_gtk3_theme_find_by_id (imported_id);
|
||||
g_assert_nonnull (found);
|
||||
g_assert_true (g_str_has_suffix (found->path, "Indexed"));
|
||||
|
||||
zoitechat_gtk3_theme_free (found);
|
||||
g_free (imported_id);
|
||||
g_free (archive_path);
|
||||
g_free (theme_b);
|
||||
g_free (theme_b_parent);
|
||||
g_free (theme_a);
|
||||
g_free (archive_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
static void
|
||||
test_zip_import_nested_root (void)
|
||||
{
|
||||
char *tmp_root;
|
||||
char *zip_root;
|
||||
char *nested;
|
||||
char *theme;
|
||||
char *archive_path;
|
||||
char *command;
|
||||
char *imported_id = NULL;
|
||||
ZoitechatGtk3Theme *found;
|
||||
|
||||
setup_test_xdir (&tmp_root);
|
||||
zip_root = g_build_filename (tmp_root, "zip-root", NULL);
|
||||
nested = g_build_filename (zip_root, "bundle", "themes", NULL);
|
||||
g_mkdir_with_parents (nested, 0700);
|
||||
theme = make_theme_dir (nested, "Juno-ocean", TRUE, FALSE);
|
||||
archive_path = g_build_filename (tmp_root, "themes.zip", NULL);
|
||||
|
||||
command = g_strdup_printf ("cd %s && zip -qr %s .", zip_root, archive_path);
|
||||
g_assert_true (g_spawn_command_line_sync (command, NULL, NULL, NULL, NULL));
|
||||
g_free (command);
|
||||
|
||||
g_assert_true (zoitechat_gtk3_theme_service_import (archive_path, &imported_id, NULL));
|
||||
found = zoitechat_gtk3_theme_find_by_id (imported_id);
|
||||
g_assert_nonnull (found);
|
||||
g_assert_true (found->has_dark_variant);
|
||||
g_assert_true (g_str_has_suffix (found->path, "Juno-ocean"));
|
||||
|
||||
zoitechat_gtk3_theme_free (found);
|
||||
g_free (imported_id);
|
||||
g_free (archive_path);
|
||||
g_free (theme);
|
||||
g_free (nested);
|
||||
g_free (zip_root);
|
||||
teardown_test_xdir (tmp_root);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_add_func ("/gtk3-theme-service/inheritance-single-parent", test_inheritance_chain_single_parent);
|
||||
g_test_add_func ("/gtk3-theme-service/inheritance-multi-level", test_inheritance_chain_multi_level);
|
||||
g_test_add_func ("/gtk3-theme-service/inheritance-missing-parent", test_inheritance_chain_missing_parent);
|
||||
g_test_add_func ("/gtk3-theme-service/inheritance-parent-from-xdg-data-home", test_inheritance_chain_parent_from_xdg_data_home);
|
||||
g_test_add_func ("/gtk3-theme-service/inheritance-parent-from-xdg-data-dirs", test_inheritance_chain_parent_from_xdg_data_dirs);
|
||||
g_test_add_func ("/gtk3-theme-service/import-collision-dark", test_import_collision_and_dark_detection);
|
||||
g_test_add_func ("/gtk3-theme-service/discover-user-and-system-data-dirs", test_discover_includes_user_and_system_data_dirs);
|
||||
g_test_add_func ("/gtk3-theme-service/archive-root-detection", test_archive_root_detection_prefers_index);
|
||||
g_test_add_func ("/gtk3-theme-service/zip-import-nested-root", test_zip_import_nested_root);
|
||||
g_test_add_func ("/gtk3-theme-service/invalid-archive-extract-error", test_invalid_archive_reports_extract_error);
|
||||
g_test_add_func ("/gtk3-theme-service/archive-without-theme-css-error", test_archive_without_theme_reports_css_error);
|
||||
g_test_add_func ("/gtk3-theme-service/import-missing-index-theme", test_import_rejects_theme_missing_index_theme);
|
||||
g_test_add_func ("/gtk3-theme-service/import-missing-desktop-entry", test_import_rejects_index_without_desktop_entry);
|
||||
g_test_add_func ("/gtk3-theme-service/import-unresolved-inherits", test_import_rejects_unresolved_inherits);
|
||||
return g_test_run ();
|
||||
}
|
||||
@@ -54,7 +54,6 @@
|
||||
#include "text.h"
|
||||
#include "url.h"
|
||||
#include "zoitechatc.h"
|
||||
#include "theme-service.h"
|
||||
|
||||
#if ! GLIB_CHECK_VERSION (2, 36, 0)
|
||||
#include <glib-object.h> /* for g_type_init() */
|
||||
@@ -113,36 +112,9 @@ struct zoitechatprefs prefs;
|
||||
gboolean
|
||||
zoitechat_theme_path_from_arg (const char *arg, char **path_out)
|
||||
{
|
||||
char *path = NULL;
|
||||
const char *ext;
|
||||
|
||||
if (!arg)
|
||||
return FALSE;
|
||||
|
||||
if (g_str_has_prefix (arg, "file://"))
|
||||
path = g_filename_from_uri (arg, NULL, NULL);
|
||||
else
|
||||
path = g_strdup (arg);
|
||||
|
||||
if (!path)
|
||||
return FALSE;
|
||||
|
||||
ext = strrchr (path, '.');
|
||||
if (!g_file_test (path, G_FILE_TEST_IS_REGULAR) ||
|
||||
!ext ||
|
||||
(g_ascii_strcasecmp (ext, ".zct") != 0 &&
|
||||
g_ascii_strcasecmp (ext, ".hct") != 0))
|
||||
{
|
||||
g_free (path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (path_out)
|
||||
*path_out = path;
|
||||
else
|
||||
g_free (path);
|
||||
|
||||
return TRUE;
|
||||
(void) arg;
|
||||
(void) path_out;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
@@ -252,176 +224,19 @@ zoitechat_remote_win32 (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
static zoitechat_theme_post_apply_callback zoitechat_theme_post_apply_cb;
|
||||
|
||||
void
|
||||
zoitechat_set_theme_post_apply_callback (zoitechat_theme_post_apply_callback callback)
|
||||
{
|
||||
zoitechat_theme_service_set_post_apply_callback (callback);
|
||||
zoitechat_theme_post_apply_cb = callback;
|
||||
}
|
||||
|
||||
void
|
||||
zoitechat_run_theme_post_apply_callback (void)
|
||||
{
|
||||
zoitechat_theme_service_run_post_apply_callback ();
|
||||
}
|
||||
|
||||
gboolean
|
||||
zoitechat_apply_theme (const char *theme_name, GError **error)
|
||||
{
|
||||
return zoitechat_theme_service_apply (theme_name, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
zoitechat_import_theme (const char *path, GError **error)
|
||||
{
|
||||
char *themes_dir;
|
||||
char *basename;
|
||||
char *dot;
|
||||
char *theme_dir;
|
||||
char *argv[] = {"unzip", "-o", (char *)path, "-d", NULL, NULL};
|
||||
int status = 0;
|
||||
gboolean ok;
|
||||
#ifdef WIN32
|
||||
char *command = NULL;
|
||||
char *powershell = NULL;
|
||||
#endif
|
||||
|
||||
if (!path)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
||||
_("No theme file specified."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
themes_dir = zoitechat_theme_service_get_themes_dir ();
|
||||
basename = g_path_get_basename (path);
|
||||
if (!basename || basename[0] == '\0')
|
||||
{
|
||||
g_free (themes_dir);
|
||||
g_free (basename);
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
|
||||
_("Failed to determine theme name."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
dot = strrchr (basename, '.');
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
theme_dir = g_build_filename (themes_dir, basename, NULL);
|
||||
if (g_mkdir_with_parents (theme_dir, 0700) != 0)
|
||||
{
|
||||
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
||||
_("Failed to create theme directory."));
|
||||
g_free (theme_dir);
|
||||
g_free (basename);
|
||||
g_free (themes_dir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
powershell = g_find_program_in_path ("powershell.exe");
|
||||
if (!powershell)
|
||||
powershell = g_find_program_in_path ("powershell");
|
||||
|
||||
if (!powershell)
|
||||
{
|
||||
g_set_error (error, G_SPAWN_ERROR, G_SPAWN_ERROR_NOENT,
|
||||
_("No archive extractor was found."));
|
||||
ok = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GString *escaped_path = g_string_new ("'");
|
||||
GString *escaped_dir = g_string_new ("'");
|
||||
const char *cursor;
|
||||
|
||||
for (cursor = path; *cursor != '\0'; cursor++)
|
||||
{
|
||||
if (*cursor == '\'')
|
||||
g_string_append (escaped_path, "''");
|
||||
else
|
||||
g_string_append_c (escaped_path, *cursor);
|
||||
}
|
||||
g_string_append_c (escaped_path, '\'');
|
||||
|
||||
for (cursor = theme_dir; *cursor != '\0'; cursor++)
|
||||
{
|
||||
if (*cursor == '\'')
|
||||
g_string_append (escaped_dir, "''");
|
||||
else
|
||||
g_string_append_c (escaped_dir, *cursor);
|
||||
}
|
||||
g_string_append_c (escaped_dir, '\'');
|
||||
|
||||
command = g_strdup_printf (
|
||||
"Add-Type -AssemblyName WindowsBase; "
|
||||
"$ErrorActionPreference='Stop'; "
|
||||
"$package=[System.IO.Packaging.Package]::Open(%s); "
|
||||
"try { "
|
||||
"foreach ($part in $package.GetParts()) { "
|
||||
"$relative=$part.Uri.OriginalString.TrimStart('/'); "
|
||||
"if ([string]::IsNullOrEmpty($relative)) { continue }; "
|
||||
"$destPath=[System.IO.Path]::Combine(%s, $relative); "
|
||||
"$destDir=[System.IO.Path]::GetDirectoryName($destPath); "
|
||||
"if ($destDir -and -not (Test-Path -LiteralPath $destDir)) { "
|
||||
"[System.IO.Directory]::CreateDirectory($destDir) | Out-Null "
|
||||
"}; "
|
||||
"$partStream=$part.GetStream(); "
|
||||
"$fileStream=[System.IO.File]::Open($destPath,[System.IO.FileMode]::Create,[System.IO.FileAccess]::Write); "
|
||||
"$partStream.CopyTo($fileStream); "
|
||||
"$fileStream.Dispose(); "
|
||||
"$partStream.Dispose(); "
|
||||
"} "
|
||||
"} finally { $package.Close(); }",
|
||||
escaped_path->str,
|
||||
escaped_dir->str);
|
||||
g_string_free (escaped_path, TRUE);
|
||||
g_string_free (escaped_dir, TRUE);
|
||||
|
||||
{
|
||||
char *ps_argv[] = {powershell, "-NoProfile", "-NonInteractive", "-Command", command, NULL};
|
||||
ok = g_spawn_sync (NULL, ps_argv, NULL, 0, NULL, NULL,
|
||||
NULL, NULL, &status, error);
|
||||
}
|
||||
}
|
||||
#else
|
||||
argv[4] = theme_dir;
|
||||
ok = g_spawn_sync (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
|
||||
NULL, NULL, &status, error);
|
||||
#endif
|
||||
if (!ok)
|
||||
{
|
||||
#ifdef WIN32
|
||||
g_free (command);
|
||||
g_free (powershell);
|
||||
#endif
|
||||
g_free (theme_dir);
|
||||
g_free (basename);
|
||||
g_free (themes_dir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!g_spawn_check_exit_status (status, error))
|
||||
{
|
||||
#ifdef WIN32
|
||||
g_free (command);
|
||||
g_free (powershell);
|
||||
#endif
|
||||
g_free (theme_dir);
|
||||
g_free (basename);
|
||||
g_free (themes_dir);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
g_free (command);
|
||||
g_free (powershell);
|
||||
#endif
|
||||
|
||||
g_free (theme_dir);
|
||||
g_free (basename);
|
||||
g_free (themes_dir);
|
||||
return TRUE;
|
||||
if (zoitechat_theme_post_apply_cb)
|
||||
zoitechat_theme_post_apply_cb ();
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -725,7 +540,6 @@ irc_init (session *sess)
|
||||
{
|
||||
static int done_init = FALSE;
|
||||
char *buf;
|
||||
char *theme_path;
|
||||
|
||||
if (done_init)
|
||||
return;
|
||||
@@ -748,50 +562,10 @@ irc_init (session *sess)
|
||||
|
||||
if (arg_url != NULL)
|
||||
{
|
||||
theme_path = NULL;
|
||||
if (zoitechat_theme_path_from_arg (arg_url, &theme_path))
|
||||
{
|
||||
GError *error = NULL;
|
||||
char *basename = g_path_get_basename (theme_path);
|
||||
char *dot = strrchr (basename, '.');
|
||||
char *message;
|
||||
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
if (zoitechat_import_theme (theme_path, &error))
|
||||
{
|
||||
if (zoitechat_apply_theme (basename, &error))
|
||||
{
|
||||
message = g_strdup_printf (_("Theme \"%s\" imported and applied."), basename);
|
||||
fe_message (message, FE_MSG_INFO);
|
||||
g_free (message);
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message (error ? error->message : _("Theme imported, but failed to apply."),
|
||||
FE_MSG_ERROR);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message (error ? error->message : _("Failed to import theme."),
|
||||
FE_MSG_ERROR);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_free (basename);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = g_strdup_printf ("server %s", arg_url);
|
||||
handle_command (sess, buf, FALSE);
|
||||
g_free (buf);
|
||||
}
|
||||
|
||||
g_free (theme_path);
|
||||
g_free (arg_url); /* from GOption */
|
||||
buf = g_strdup_printf ("server %s", arg_url);
|
||||
handle_command (sess, buf, FALSE);
|
||||
g_free (buf);
|
||||
g_free (arg_url);
|
||||
}
|
||||
|
||||
if (arg_urls != NULL)
|
||||
@@ -799,49 +573,9 @@ irc_init (session *sess)
|
||||
guint i;
|
||||
for (i = 0; i < g_strv_length (arg_urls); i++)
|
||||
{
|
||||
theme_path = NULL;
|
||||
if (zoitechat_theme_path_from_arg (arg_urls[i], &theme_path))
|
||||
{
|
||||
GError *error = NULL;
|
||||
char *basename = g_path_get_basename (theme_path);
|
||||
char *dot = strrchr (basename, '.');
|
||||
char *message;
|
||||
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
if (zoitechat_import_theme (theme_path, &error))
|
||||
{
|
||||
if (zoitechat_apply_theme (basename, &error))
|
||||
{
|
||||
message = g_strdup_printf (_("Theme \"%s\" imported and applied."), basename);
|
||||
fe_message (message, FE_MSG_INFO);
|
||||
g_free (message);
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message (error ? error->message : _("Theme imported, but failed to apply."),
|
||||
FE_MSG_ERROR);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fe_message (error ? error->message : _("Failed to import theme."),
|
||||
FE_MSG_ERROR);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
|
||||
g_free (basename);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf = g_strdup_printf ("%s %s", i==0? "server" : "newserver", arg_urls[i]);
|
||||
handle_command (sess, buf, FALSE);
|
||||
g_free (buf);
|
||||
}
|
||||
|
||||
g_free (theme_path);
|
||||
buf = g_strdup_printf ("%s %s", i == 0 ? "server" : "newserver", arg_urls[i]);
|
||||
handle_command (sess, buf, FALSE);
|
||||
g_free (buf);
|
||||
}
|
||||
g_strfreev (arg_urls);
|
||||
}
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
#define ZOITECHAT_H
|
||||
|
||||
gboolean zoitechat_theme_path_from_arg (const char *arg, char **path_out);
|
||||
gboolean zoitechat_import_theme (const char *path, GError **error);
|
||||
gboolean zoitechat_apply_theme (const char *theme_name, GError **error);
|
||||
typedef void (*zoitechat_theme_post_apply_callback) (void);
|
||||
void zoitechat_set_theme_post_apply_callback (zoitechat_theme_post_apply_callback callback);
|
||||
void zoitechat_run_theme_post_apply_callback (void);
|
||||
@@ -143,6 +141,7 @@ struct zoitechatprefs
|
||||
unsigned int hex_gui_tab_dots;
|
||||
unsigned int hex_gui_tab_icons;
|
||||
unsigned int hex_gui_dark_mode;
|
||||
unsigned int hex_gui_gtk3_variant;
|
||||
unsigned int hex_gui_tab_scrollchans;
|
||||
unsigned int hex_gui_tab_server;
|
||||
unsigned int hex_gui_tab_sort;
|
||||
@@ -323,6 +322,7 @@ struct zoitechatprefs
|
||||
char hex_text_font[4 * FONTNAMELEN + 1];
|
||||
char hex_text_font_main[FONTNAMELEN + 1];
|
||||
char hex_text_font_alternative[3 * FONTNAMELEN + 1];
|
||||
char hex_gui_gtk3_theme[256];
|
||||
char hex_text_spell_langs[64];
|
||||
|
||||
/* these are the private variables */
|
||||
|
||||
Reference in New Issue
Block a user