Compare commits

..
23 Commits
Author SHA1 Message Date
ssri_sunshine_sequence b977901bc4 bump manifest tag 2026-03-06 16:19:11 +03:00
ssri_sunshine_sequence c00b561d03 feat: add record/category management, imports and exports 2026-03-06 16:13:31 +03:00
ssri_sunshine_sequence 4f95b6b274 Update README.md 2026-03-01 23:29:40 +03:00
ssri_sunshine_sequence 44ef968105 bump manifest tag 2026-03-01 23:17:22 +03:00
ssri_sunshine_sequence 79d87ca7b3 fix: force white text, just realized light mode is broken 2026-03-01 23:16:01 +03:00
ssri_sunshine_sequence eafff31a99 add distribution info 2026-03-01 20:27:50 +03:00
ssri_sunshine_sequence 8c9488cfef bump manifest tag 2026-03-01 20:21:09 +03:00
ssri_sunshine_sequence c8af2ce2d0 ref: proper desktop icon 2026-03-01 20:19:50 +03:00
ssri_sunshine_sequence 263591704d Update README.md 2026-03-01 15:15:03 +03:00
ssri_sunshine_sequence f620287051 update release tag 2026-03-01 04:04:17 +03:00
ssri_sunshine_sequence c8c147901e fix: adapt app for gnome environments that have no tray 2026-03-01 04:02:14 +03:00
ssri_sunshine_sequence a566b78721 use tarball instead of commit hash 2026-03-01 02:02:46 +03:00
ssri_sunshine_sequence 05ca273c38 bump manifest tag 2026-03-01 00:37:43 +03:00
ssri_sunshine_sequence 3db57eb3fc ref: use gnome C style conventions 2026-03-01 00:35:36 +03:00
ssri_sunshine_sequence 5a2fe1756c ref: update version and tag hash 2026-02-28 22:28:49 +03:00
ssri_sunshine_sequence 9106ecc1ae ref: pin manifest to latest commit 2026-02-28 22:25:07 +03:00
ssri_sunshine_sequence 17678d789a ref: update branding colors 2026-02-28 22:23:57 +03:00
ssri_sunshine_sequence 7a9d850363 ref: formatting 2026-02-28 22:14:59 +03:00
ssri_sunshine_sequence 20f5b01327 ref: pin manifest sources to commit hash 2026-02-28 22:12:15 +03:00
ssri_sunshine_sequence 14cd08e28e fix: pin image commit hash instead of raw repo uri 2026-02-28 21:39:38 +03:00
ssri_sunshine_sequence 62eacf7e04 fix: flathub-specific preview without padding; aarch64 is unsupported 2026-02-28 21:37:11 +03:00
ssri_sunshine_sequence 2c1d656982 ref: change confusing app summary 2026-02-28 21:24:37 +03:00
ssri_sunshine_sequence 730c56d944 fix: install LICENSE file via meson as required by Flathub 2026-02-28 21:22:41 +03:00
23 changed files with 1741 additions and 339 deletions
+12 -1
View File
@@ -4,7 +4,7 @@ Kaomoji picker. Browse a library of Japanese emoticons, click to copy, add your
![preview](preview.png)
## Install
1. Download .flatpak file from Releases: https://gitea.angeltech.jp/Angel-Technologies/MoeMoji/releases/tag/konater
1. Download .flatpak file from Releases: https://gitea.angeltech.jp/Angel-Technologies/MoeMoji/releases/
2. Install with `flatpak install ./moemoji.flatpak`
## Global shortcut
@@ -53,3 +53,14 @@ Run dev build: `GSETTINGS_SCHEMA_DIR=./builddir/data ./builddir/src/moemoji`
`flatpak-builder --force-clean --user --install .flatpak-build jp.angeltech.MoeMoji.json`
`flatpak run jp.angeltech.MoeMoji`
# Creating a distributable package
`flatpak-builder build/ jp.angeltech.MoeMoji.json`
`flatpak build-export export build`
`flatpak build-bundle export moemoji.flatpak jp.angeltech.MoeMoji.json`
## Local manifest
If you want to test local changes to the source code, you should build with `dev.jp.angeltech.MoeMoji.json` manifest instead, as main manifest pulls a tarball from the remote source.
Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="83px" height="83px" viewBox="0 0 83 83" version="1.1">
<g id="surface1" transform="translate(0,25.5)">
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 60.59375 18.59375 C 57.492188 18.070312 54.054688 14.488281 52.515625 10.171875 C 51.640625 7.714844 51.308594 4.003906 51.828125 2.492188 C 52.292969 1.15625 53.476562 0.71875 53.992188 1.695312 C 54.074219 1.84375 54.1875 2.914062 54.246094 4.066406 C 54.445312 8 55.3125 10.605469 57.1875 12.925781 C 60.078125 16.496094 63.039062 16.558594 65.648438 13.105469 C 67.75 10.328125 68.503906 7.429688 68.171875 3.375 C 68.089844 2.332031 68.0625 1.3125 68.113281 1.105469 C 68.164062 0.898438 68.378906 0.554688 68.59375 0.339844 C 68.921875 0.0078125 69.050781 -0.0390625 69.441406 0.0234375 C 69.695312 0.0664062 70.023438 0.207031 70.164062 0.332031 C 71.117188 1.183594 71.554688 4.667969 71.097656 7.726562 C 70.832031 9.507812 70.578125 10.394531 69.933594 11.789062 C 68.1875 15.578125 65.566406 18.050781 62.773438 18.554688 C 61.675781 18.75 61.554688 18.753906 60.59375 18.59375 Z M 60.59375 18.59375 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 21.109375 19.128906 C 19.484375 18.882812 18.238281 18.300781 16.761719 17.101562 C 14.632812 15.375 12.847656 11.914062 12.398438 8.652344 C 12.117188 6.625 12.355469 3.445312 12.929688 1.511719 C 13.199219 0.605469 14.046875 0.222656 14.585938 0.761719 C 14.890625 1.070312 14.914062 1.65625 14.695312 3.128906 C 14.375 5.230469 14.984375 8.875 15.984375 10.878906 C 17.722656 14.367188 20.324219 16.226562 22.78125 15.742188 C 24.078125 15.484375 24.875 15.015625 26.082031 13.792969 C 26.957031 12.90625 27.285156 12.457031 27.710938 11.574219 C 28.722656 9.476562 29.195312 7.75 29.558594 4.820312 C 29.761719 3.183594 30.425781 2.359375 31.398438 2.546875 C 31.828125 2.628906 32.460938 3.296875 32.652344 3.875 C 33.320312 5.902344 31.867188 11.515625 29.902344 14.496094 C 28.652344 16.386719 26.777344 17.949219 24.894531 18.664062 C 24.171875 18.9375 22.351562 19.289062 21.90625 19.242188 C 21.820312 19.234375 21.464844 19.183594 21.109375 19.128906 Z M 21.109375 19.128906 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(0%,0%,0%);fill-opacity:1;" d="M 37.5 25.976562 C 35.785156 25.4375 34.304688 23.425781 33.828125 20.988281 C 33.742188 20.539062 33.695312 19.609375 33.722656 18.882812 C 33.769531 17.726562 33.8125 17.539062 34.085938 17.246094 C 34.589844 16.703125 35.246094 16.859375 35.496094 17.582031 C 35.574219 17.808594 35.640625 18.328125 35.640625 18.730469 C 35.640625 20.203125 36.375 22.082031 37.320312 23.039062 C 38.269531 23.992188 38.84375 23.84375 39.617188 22.4375 C 39.847656 22.015625 40.242188 21.480469 40.484375 21.246094 C 40.871094 20.878906 41.023438 20.824219 41.609375 20.824219 L 42.285156 20.824219 L 43.277344 21.863281 C 43.890625 22.507812 44.371094 22.90625 44.535156 22.90625 C 44.929688 22.90625 45.695312 22.066406 46.113281 21.167969 C 46.488281 20.371094 46.632812 19.789062 46.867188 18.171875 C 47.019531 17.097656 47.242188 16.726562 47.839844 16.527344 C 48.414062 16.335938 48.878906 16.539062 49.296875 17.160156 C 49.675781 17.726562 49.6875 18.777344 49.339844 20.25 C 48.90625 22.070312 48.246094 23.320312 47.121094 24.449219 C 46.257812 25.3125 45.683594 25.570312 44.617188 25.570312 C 43.578125 25.570312 42.957031 25.300781 42.234375 24.546875 C 41.992188 24.289062 41.730469 24.082031 41.652344 24.082031 C 41.578125 24.085938 41.363281 24.3125 41.175781 24.589844 C 40.289062 25.882812 38.882812 26.414062 37.5 25.976562 Z M 37.5 25.976562 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,38.039216%,52.941179%);fill-opacity:1;" d="M 71.503906 31.695312 C 69.191406 31.105469 67.3125 29.238281 66.457031 26.679688 C 66.144531 25.746094 66.085938 25.363281 66.082031 24.210938 C 66.074219 21.390625 67.128906 19.191406 69.300781 17.488281 C 70.269531 16.726562 71.15625 16.277344 72.851562 15.679688 C 75.933594 14.59375 78.132812 15.03125 80.371094 17.171875 C 81.609375 18.351562 82.273438 19.402344 82.746094 20.921875 C 83.050781 21.902344 83.074219 22.136719 83.015625 23.589844 C 82.945312 25.414062 82.722656 26.1875 81.859375 27.660156 C 80.738281 29.574219 78.976562 30.90625 76.785156 31.503906 C 75.417969 31.875 72.609375 31.980469 71.503906 31.695312 Z M 71.503906 31.695312 "/>
<path style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,38.039216%,52.941179%);fill-opacity:1;" d="M 5.992188 31.839844 C 2.863281 31.117188 0.972656 29.347656 0.242188 26.476562 C -0.0585938 25.292969 -0.078125 24.339844 0.175781 23.144531 C 0.859375 19.882812 2.957031 17.40625 5.855469 16.429688 C 6.820312 16.105469 7.0625 16.078125 9.09375 16.074219 C 11.550781 16.066406 11.707031 16.109375 12.730469 17.054688 C 13.027344 17.324219 13.519531 17.675781 13.828125 17.835938 C 14.667969 18.265625 16.15625 19.835938 16.632812 20.789062 C 18.109375 23.734375 17.503906 26.886719 14.984375 29.429688 C 13.183594 31.242188 11.554688 31.890625 8.578125 31.96875 C 7.339844 32.003906 6.523438 31.960938 5.992188 31.839844 Z M 5.992188 31.839844 "/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

+8 -4
View File
@@ -1,10 +1,14 @@
application_id = 'jp.angeltech.MoeMoji'
scalable_dir = join_paths('hicolor', 'scalable', 'apps')
install_data(
join_paths(scalable_dir, ('@0@.svg').format(application_id)),
install_dir: join_paths(get_option('datadir'), 'icons', scalable_dir)
)
foreach size : ['48x48', '64x64', '128x128', '256x256']
size_dir = join_paths('hicolor', size, 'apps')
install_data(
join_paths(size_dir, ('@0@.png').format(application_id)),
install_dir: join_paths(get_option('datadir'), 'icons', size_dir)
)
endforeach
symbolic_dir = join_paths('hicolor', 'symbolic', 'apps')
install_data(
+9 -4
View File
@@ -3,14 +3,14 @@
<id>jp.angeltech.MoeMoji</id>
<name>MoeMoji</name>
<summary>Moe picker!</summary>
<summary>Kaomoji picker! Japanese emoticons library</summary>
<developer id="jp.angeltech">
<name>angeltech.jp</name>
</developer>
<description>
<p>Kaomoji picker. Browse a library of Japanese emoticons, click to copy, add your own!</p>
<p>Kaomoji picker! Browse a library of Japanese emoticons, click to copy, add your own!</p>
</description>
<metadata_license>CC0-1.0</metadata_license>
@@ -22,15 +22,20 @@
<project_license>WTFPL</project_license>
<content_rating type="oars-1.1" />
<branding>
<color type="primary" scheme_preference="light">#a1bedd</color>
<color type="primary" scheme_preference="dark">#363e4f</color>
</branding>
<screenshots>
<screenshot type="default">
<image>https://gitea.angeltech.jp/Angel-Technologies/MoeMoji/media/branch/main/preview.png</image>
<image>https://gitea.angeltech.jp/Angel-Technologies/MoeMoji/raw/commit/62eacf7e0446c95c9e075145f3a6ce42ca39d55f/flathub-preview.png</image>
<caption>Kaomoji picker</caption>
</screenshot>
</screenshots>
<releases>
<release version="0.1.0" date="2026-02-28">
<release version="0.1.0" date="2026-03-01">
<description>
<p>Initial release.</p>
</description>
+25
View File
@@ -0,0 +1,25 @@
{
"app-id": "jp.angeltech.MoeMoji",
"runtime": "org.gnome.Platform",
"runtime-version": "49",
"sdk": "org.gnome.Sdk",
"command": "moemoji",
"finish-args": [
"--share=ipc",
"--socket=fallback-x11",
"--socket=wayland",
"--talk-name=org.kde.StatusNotifierWatcher"
],
"modules": [
{
"name": "moemoji",
"buildsystem": "meson",
"sources": [
{
"type": "dir",
"path": "."
}
]
}
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

+3
View File
@@ -0,0 +1,3 @@
{
"only-arches": ["x86_64"]
}
+3 -2
View File
@@ -16,8 +16,9 @@
"buildsystem": "meson",
"sources": [
{
"type": "dir",
"path": "."
"type": "archive",
"url": "https://gitea.angeltech.jp/Angel-Technologies/MoeMoji/archive/v0.2.0.tar.gz",
"sha256": "16dc80365b04aa76e8d1a39fce46707556fc791d95d53624a9a3e284681cdcf6"
}
]
}
+3
View File
@@ -29,6 +29,9 @@ subdir('data')
subdir('src')
subdir('tests')
install_data('LICENSE',
install_dir: join_paths(get_option('datadir'), 'licenses', 'jp.angeltech.MoeMoji')
)
gnome.post_install(
glib_compile_schemas: true,
+3 -3
View File
@@ -9,7 +9,7 @@ static void register_with_portal (void) {
GDBusConnection *bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
if (bus == NULL) {
g_warning ("portal register: can't get session bus: %s", error->message);
g_error_free (error);
g_clear_error (&error);
return;
}
GVariantBuilder options;
@@ -27,8 +27,8 @@ static void register_with_portal (void) {
G_DBUS_CALL_FLAGS_NONE,
-1, NULL, &error);
if (result == NULL) {
g_info ("portal register: %s", error->message);
g_error_free (error);
g_warning ("portal register: %s", error->message);
g_clear_error (&error);
} else {
g_variant_unref (result);
}
+44 -17
View File
@@ -94,9 +94,12 @@ static void toggle_window(MoeMojiApplication *self) {
}
static gboolean on_close_request(GtkWindow *window, gpointer user_data) {
(void)user_data;
MoeMojiApplication *self = MOEMOJI_APPLICATION(user_data);
if (self->has_tray) {
gtk_widget_set_visible(GTK_WIDGET(window), FALSE);
return TRUE;
}
return FALSE;
}
static void dbusmenu_method_call(G_GNUC_UNUSED GDBusConnection *connection,
@@ -291,13 +294,38 @@ static void setup_sni(MoeMojiApplication *self) {
if (self->dbus_conn == NULL) {
g_warning("session bus: %s", error->message);
g_clear_error(&error);
self->has_tray = FALSE;
return;
}
GVariant *result = g_dbus_connection_call_sync(
self->dbus_conn, "org.freedesktop.DBus", "/org/freedesktop/DBus",
"org.freedesktop.DBus", "NameHasOwner",
g_variant_new("(s)", "org.kde.StatusNotifierWatcher"),
G_VARIANT_TYPE("(b)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
if (result == NULL) {
g_warning("NameHasOwner check failed: %s", error->message);
g_clear_error(&error);
self->has_tray = FALSE;
return;
}
gboolean watcher_exists = FALSE;
g_variant_get(result, "(b)", &watcher_exists);
g_variant_unref(result);
if (!watcher_exists) {
g_info("No StatusNotifierWatcher found, skipping tray setup");
self->has_tray = FALSE;
return;
}
self->has_tray = TRUE;
GDBusNodeInfo *sni_node =
g_dbus_node_info_new_for_xml(sni_introspection_xml, &error);
if (sni_node == NULL) {
g_warning("Failed to parse SNI introspection XML: %s", error->message);
g_error_free(error);
g_clear_error(&error);
return;
}
self->sni_registration_id = g_dbus_connection_register_object(
@@ -306,14 +334,14 @@ static void setup_sni(MoeMojiApplication *self) {
g_dbus_node_info_unref(sni_node);
if (self->sni_registration_id == 0) {
g_warning("Failed to register SNI object: %s", error->message);
g_error_free(error);
g_clear_error(&error);
return;
}
GDBusNodeInfo *menu_node =
g_dbus_node_info_new_for_xml(dbusmenu_introspection_xml, &error);
if (menu_node == NULL) {
g_warning("Failed to parse dbusmenu introspection XML: %s", error->message);
g_error_free(error);
g_clear_error(&error);
return;
}
self->menu_registration_id = g_dbus_connection_register_object(
@@ -322,21 +350,20 @@ static void setup_sni(MoeMojiApplication *self) {
g_dbus_node_info_unref(menu_node);
if (self->menu_registration_id == 0) {
g_warning("dbusmenu register: %s", error->message);
g_error_free(error);
g_clear_error(&error);
}
const gchar *unique_name = g_dbus_connection_get_unique_name(self->dbus_conn);
g_dbus_connection_call(
self->dbus_conn, "org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher",
"org.kde.StatusNotifierWatcher", "RegisterStatusNotifierItem",
g_variant_new("(s)", unique_name), NULL, G_DBUS_CALL_FLAGS_NONE, -1,
NULL, NULL, NULL);
self->dbus_conn, "org.kde.StatusNotifierWatcher",
"/StatusNotifierWatcher", "org.kde.StatusNotifierWatcher",
"RegisterStatusNotifierItem", g_variant_new("(s)", unique_name), NULL,
G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
}
static void on_shortcuts_activated(GDBusProxy *proxy, const gchar *sender_name,
static void on_shortcuts_activated(G_GNUC_UNUSED GDBusProxy *proxy,
G_GNUC_UNUSED const gchar *sender_name,
const gchar *signal_name,
GVariant *parameters, gpointer user_data) {
(void)proxy;
(void)sender_name;
if (g_strcmp0(signal_name, "Activated") != 0)
return;
MoeMojiApplication *self = MOEMOJI_APPLICATION(user_data);
@@ -481,7 +508,7 @@ static void setup_global_shortcuts(MoeMojiApplication *self) {
"org.freedesktop.portal.GlobalShortcuts", NULL, &error);
if (self->shortcuts_proxy == NULL) {
g_warning("GlobalShortcuts: Failed to create proxy: %s", error->message);
g_error_free(error);
g_clear_error(&error);
return;
}
g_timeout_add(500, (GSourceFunc)begin_create_session, self);
@@ -499,7 +526,7 @@ static void moemoji_application_startup(GApplication *app) {
gtk_icon_theme_add_resource_path(
gtk_icon_theme_get_for_display(gdk_display_get_default()),
"/jp/angeltech/MoeMoji/icons");
gtk_window_set_default_icon_name("jp.angeltech.MoeMoji-symbolic");
gtk_window_set_default_icon_name("jp.angeltech.MoeMoji");
gboolean in_flatpak = g_file_test("/.flatpak-info", G_FILE_TEST_EXISTS);
if (in_flatpak) {
self->icon_theme_path = NULL;
@@ -533,7 +560,7 @@ static void moemoji_application_activate(GApplication *app) {
self->window = g_object_new(MOEMOJI_TYPE_WINDOW, "application",
GTK_APPLICATION(self), NULL);
g_signal_connect(self->window, "close-request",
G_CALLBACK(on_close_request), NULL);
G_CALLBACK(on_close_request), self);
self->window_created = TRUE;
} else {
toggle_window(self);
@@ -566,8 +593,8 @@ static void moemoji_application_show_about(G_GNUC_UNUSED GSimpleAction *action,
GtkWindow *window = NULL;
g_return_if_fail(MOEMOJI_IS_APPLICATION(self));
window = gtk_application_get_active_window(GTK_APPLICATION(self));
gtk_show_about_dialog(window, "program-name", "MoeMoji", "version", "0.1.0",
NULL);
gtk_show_about_dialog(window, "program-name", "MoeMoji", "version",
PACKAGE_VERSION, NULL);
}
static void moemoji_application_class_init(MoeMojiApplicationClass *klass) {
+1
View File
@@ -16,6 +16,7 @@ struct _MoeMojiApplication {
const gchar *tray_icon_name;
GDBusProxy *shortcuts_proxy;
gchar *shortcuts_session_path;
gboolean has_tray;
};
G_BEGIN_DECLS
+967 -47
View File
File diff suppressed because it is too large Load Diff
+10
View File
@@ -20,6 +20,16 @@ struct _MoeMojiWindow {
GPtrArray *category_widgets;
GtkWidget *bottom_spacer;
int active_chip_index;
GtkStack *view_stack;
GtkWidget *add_button;
GtkWidget *back_button;
GtkWidget *menu_button;
GtkEntry *category_name_entry;
GtkWidget *entry_text_view;
GtkWidget *category_save_button;
char *selected_category_dir;
gulong scroll_handler_id;
gulong page_size_handler_id;
};
G_BEGIN_DECLS
+47
View File
@@ -10,10 +10,34 @@
<child type="titlebar">
<object class="AdwHeaderBar" id="header_bar">
<property name="show-end-title-buttons">True</property>
<child type="start">
<object class="GtkButton" id="add_button">
<property name="icon-name">list-add-symbolic</property>
</object>
</child>
<child type="start">
<object class="GtkButton" id="back_button">
<property name="icon-name">go-previous-symbolic</property>
<property name="visible">False</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton" id="menu_button">
<property name="icon-name">open-menu-symbolic</property>
<property name="menu-model">primary_menu</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkStack" id="view_stack">
<property name="transition-type">slide-left</property>
<property name="transition-duration">200</property>
<child>
<object class="GtkStackPage">
<property name="name">main</property>
<property name="child">
<object class="GtkBox" id="outer_box">
<property name="orientation">vertical</property>
<child>
@@ -41,6 +65,29 @@
</object>
</child>
</object>
</property>
</object>
</child>
</object>
</child>
</template>
<menu id="primary_menu">
<section>
<item>
<attribute name="label" translatable="yes">Manage…</attribute>
<attribute name="action">win.manage</attribute>
</item>
</section>
<section>
<item>
<attribute name="label" translatable="yes">Export…</attribute>
<attribute name="action">win.export</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Import…</attribute>
<attribute name="action">win.import</attribute>
</item>
</section>
</menu>
</interface>
+1 -1
View File
@@ -4,7 +4,7 @@
<file>moemoji-window.ui</file>
<file>style.css</file>
<file>wp.png</file>
<file alias="icons/scalable/apps/jp.angeltech.MoeMoji.svg">../data/icons/hicolor/scalable/apps/jp.angeltech.MoeMoji.svg</file>
<file alias="icons/scalable/apps/jp.angeltech.MoeMoji.png">../data/icons/hicolor/scalable/apps/jp.angeltech.MoeMoji.png</file>
<file alias="icons/scalable/apps/jp.angeltech.MoeMoji-symbolic.svg">../data/icons/hicolor/symbolic/apps/jp.angeltech.MoeMoji-symbolic.svg</file>
</gresource>
</gresources>
+49 -1
View File
@@ -34,9 +34,10 @@
background-image: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0.5)), url("/jp/angeltech/MoeMoji/wp.png");
background-size: cover;
background-color: transparent;
color: white;
}
wallpaper-bg > * {
.wallpaper-bg > * {
background-color: transparent;
}
@@ -58,3 +59,50 @@ wallpaper-bg > * {
background-color: rgba(255, 255, 255, 0.25);
border-radius: 8px;
}
.add-choice-button {
min-width: 200px;
min-height: 48px;
font-size: 16px;
}
.add-form {
padding: 24px;
margin: 12px;
}
.entry-editor-frame {
background-color: rgba(0, 0, 0, 0.5);
border-radius: 12px;
overflow: hidden;
}
.entry-text-view, .entry-text-view text {
background-color: transparent;
color: white;
caret-color: white;
}
.manage-emote {
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 8px;
padding: 6px 10px;
}
.manage-delete {
min-width: 20px;
min-height: 20px;
padding: 2px;
font-size: 10px;
background-color: @destructive_bg_color;
color: @destructive_fg_color;
}
.manage-cat-delete {
min-width: 24px;
min-height: 24px;
padding: 2px;
background-color: @destructive_bg_color;
color: @destructive_fg_color;
}
+509 -202
View File
@@ -1,294 +1,601 @@
#include "moemoji-internal.h"
#include "moemoji-window.h"
#include <glib.h>
#include <glib/gstdio.h>
#include <gtk/gtk.h>
#include "moemoji-internal.h"
#include "moemoji-window.h"
static void
test_display_name_underscores (void)
{
char *name = make_display_name ("happy_faces");
g_assert_cmpstr (name, ==, "Happy faces");
g_free (name);
static void test_display_name_underscores(void) {
char *name = make_display_name("happy_faces");
g_assert_cmpstr(name, ==, "Happy faces");
g_free(name);
}
static void
test_display_name_no_underscores (void)
{
char *name = make_display_name ("animals");
g_assert_cmpstr (name, ==, "Animals");
g_free (name);
static void test_display_name_no_underscores(void) {
char *name = make_display_name("animals");
g_assert_cmpstr(name, ==, "Animals");
g_free(name);
}
static void
test_display_name_already_upper (void)
{
char *name = make_display_name ("Animals");
g_assert_cmpstr (name, ==, "Animals");
g_free (name);
static void test_display_name_already_upper(void) {
char *name = make_display_name("Animals");
g_assert_cmpstr(name, ==, "Animals");
g_free(name);
}
static void
test_display_name_single_char (void)
{
char *name = make_display_name ("x");
g_assert_cmpstr (name, ==, "X");
g_free (name);
static void test_display_name_single_char(void) {
char *name = make_display_name("x");
g_assert_cmpstr(name, ==, "X");
g_free(name);
}
static void
test_display_name_empty (void)
{
char *name = make_display_name ("");
g_assert_cmpstr (name, ==, "");
g_free (name);
static void test_display_name_empty(void) {
char *name = make_display_name("");
g_assert_cmpstr(name, ==, "");
g_free(name);
}
static void
test_find_kaomoji_with_env (void)
{
char *dir = find_kaomoji_dir ();
g_assert_nonnull (dir);
g_assert_true (g_file_test (dir, G_FILE_TEST_IS_DIR));
g_free (dir);
static void test_find_kaomoji_with_env(void) {
char *dir = find_kaomoji_dir();
g_assert_nonnull(dir);
g_assert_true(g_file_test(dir, G_FILE_TEST_IS_DIR));
g_free(dir);
}
static gboolean find_kaomoji_bogus_passed = FALSE;
static void
run_find_kaomoji_bogus (void)
{
g_setenv ("MESON_SOURCE_ROOT", "/nonexistent", TRUE);
char *saved = g_get_current_dir ();
g_assert_true (g_chdir ("/tmp") == 0);
static void run_find_kaomoji_bogus(void) {
g_setenv("MESON_SOURCE_ROOT", "/nonexistent", TRUE);
char *saved = g_get_current_dir();
g_assert_true(g_chdir("/tmp") == 0);
char *dir = find_kaomoji_dir ();
g_free (dir);
char *dir = find_kaomoji_dir();
g_free(dir);
g_assert_true (g_chdir (saved) == 0);
g_free (saved);
g_setenv ("MESON_SOURCE_ROOT", SRCDIR, TRUE);
g_assert_true(g_chdir(saved) == 0);
g_free(saved);
g_setenv("MESON_SOURCE_ROOT", SRCDIR, TRUE);
find_kaomoji_bogus_passed = TRUE;
}
static void
test_find_kaomoji_bogus (void)
{
g_assert_true (find_kaomoji_bogus_passed);
static void test_find_kaomoji_bogus(void) {
g_assert_true(find_kaomoji_bogus_passed);
}
static void
test_sni_category (void)
{
GVariant *v = sni_get_property (NULL, NULL, NULL, NULL, "Category", NULL, NULL);
g_assert_nonnull (v);
g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "ApplicationStatus");
g_variant_unref (v);
static void test_sni_category(void) {
GVariant *v =
sni_get_property(NULL, NULL, NULL, NULL, "Category", NULL, NULL);
g_assert_nonnull(v);
g_assert_cmpstr(g_variant_get_string(v, NULL), ==, "ApplicationStatus");
g_variant_unref(v);
}
static void
test_sni_id (void)
{
GVariant *v = sni_get_property (NULL, NULL, NULL, NULL, "Id", NULL, NULL);
g_assert_nonnull (v);
g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "moemoji");
g_variant_unref (v);
static void test_sni_id(void) {
GVariant *v = sni_get_property(NULL, NULL, NULL, NULL, "Id", NULL, NULL);
g_assert_nonnull(v);
g_assert_cmpstr(g_variant_get_string(v, NULL), ==, "moemoji");
g_variant_unref(v);
}
static void
test_sni_item_is_menu (void)
{
GVariant *v = sni_get_property (NULL, NULL, NULL, NULL, "ItemIsMenu", NULL, NULL);
g_assert_nonnull (v);
g_assert_false (g_variant_get_boolean (v));
g_variant_unref (v);
static void test_sni_item_is_menu(void) {
GVariant *v =
sni_get_property(NULL, NULL, NULL, NULL, "ItemIsMenu", NULL, NULL);
g_assert_nonnull(v);
g_assert_false(g_variant_get_boolean(v));
g_variant_unref(v);
}
static void
test_sni_menu (void)
{
GVariant *v = sni_get_property (NULL, NULL, NULL, NULL, "Menu", NULL, NULL);
g_assert_nonnull (v);
g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "/MenuBar");
g_variant_unref (v);
static void test_sni_menu(void) {
GVariant *v = sni_get_property(NULL, NULL, NULL, NULL, "Menu", NULL, NULL);
g_assert_nonnull(v);
g_assert_cmpstr(g_variant_get_string(v, NULL), ==, "/MenuBar");
g_variant_unref(v);
}
static void
test_sni_unknown (void)
{
GVariant *v = sni_get_property (NULL, NULL, NULL, NULL, "Nonexistent", NULL, NULL);
g_assert_null (v);
static void test_sni_unknown(void) {
GVariant *v =
sni_get_property(NULL, NULL, NULL, NULL, "Nonexistent", NULL, NULL);
g_assert_null(v);
}
static void
test_dbusmenu_version (void)
{
GVariant *v = dbusmenu_get_property (NULL, NULL, NULL, NULL, "Version", NULL, NULL);
g_assert_nonnull (v);
g_assert_cmpuint (g_variant_get_uint32 (v), ==, 3);
g_variant_unref (v);
static void test_dbusmenu_version(void) {
GVariant *v =
dbusmenu_get_property(NULL, NULL, NULL, NULL, "Version", NULL, NULL);
g_assert_nonnull(v);
g_assert_cmpuint(g_variant_get_uint32(v), ==, 3);
g_variant_unref(v);
}
static void
test_dbusmenu_status (void)
{
GVariant *v = dbusmenu_get_property (NULL, NULL, NULL, NULL, "Status", NULL, NULL);
g_assert_nonnull (v);
g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "normal");
g_variant_unref (v);
static void test_dbusmenu_status(void) {
GVariant *v =
dbusmenu_get_property(NULL, NULL, NULL, NULL, "Status", NULL, NULL);
g_assert_nonnull(v);
g_assert_cmpstr(g_variant_get_string(v, NULL), ==, "normal");
g_variant_unref(v);
}
static void
test_dbusmenu_text_direction (void)
{
GVariant *v = dbusmenu_get_property (NULL, NULL, NULL, NULL, "TextDirection", NULL, NULL);
g_assert_nonnull (v);
g_assert_cmpstr (g_variant_get_string (v, NULL), ==, "ltr");
g_variant_unref (v);
static void test_dbusmenu_text_direction(void) {
GVariant *v = dbusmenu_get_property(NULL, NULL, NULL, NULL, "TextDirection",
NULL, NULL);
g_assert_nonnull(v);
g_assert_cmpstr(g_variant_get_string(v, NULL), ==, "ltr");
g_variant_unref(v);
}
static void
test_dbusmenu_unknown (void)
{
GVariant *v = dbusmenu_get_property (NULL, NULL, NULL, NULL, "Bogus", NULL, NULL);
g_assert_null (v);
static void test_dbusmenu_unknown(void) {
GVariant *v =
dbusmenu_get_property(NULL, NULL, NULL, NULL, "Bogus", NULL, NULL);
g_assert_null(v);
}
static void
test_category_widgets_chip_init (void)
{
CategoryWidgets *cw = g_new0 (CategoryWidgets, 1);
g_assert_null (cw->chip);
g_assert_null (cw->header);
g_assert_null (cw->flow);
g_assert_null (cw->name);
g_free (cw);
static void test_category_widgets_chip_init(void) {
CategoryWidgets *cw = g_new0(CategoryWidgets, 1);
g_assert_null(cw->chip);
g_assert_null(cw->header);
g_assert_null(cw->flow);
g_assert_null(cw->name);
g_free(cw);
}
G_GNUC_INTERNAL GResource *moemoji_get_resource (void);
G_GNUC_INTERNAL GResource *moemoji_get_resource(void);
static GResource *test_res = NULL;
static GtkWidget *test_win = NULL;
static MoeMojiWindow *test_self = NULL;
static void
window_test_setup (void)
{
static void window_test_setup(void) {
if (!test_res) {
test_res = moemoji_get_resource ();
g_resources_register (test_res);
test_res = moemoji_get_resource();
g_resources_register(test_res);
}
test_win = g_object_new (MOEMOJI_TYPE_WINDOW, NULL);
test_self = MOEMOJI_WINDOW (test_win);
test_win = g_object_new(MOEMOJI_TYPE_WINDOW, NULL);
test_self = MOEMOJI_WINDOW(test_win);
}
static void
window_test_teardown (void)
{
gtk_window_destroy (GTK_WINDOW (test_win));
static void window_test_teardown(void) {
gtk_window_destroy(GTK_WINDOW(test_win));
test_win = NULL;
test_self = NULL;
}
static void
test_window_chip_setup (void)
{
window_test_setup ();
static void test_window_chip_setup(void) {
window_test_setup();
g_assert_cmpuint (test_self->category_widgets->len, >, 0);
g_assert_cmpuint(test_self->category_widgets->len, >, 0);
for (guint i = 0; i < test_self->category_widgets->len; i++) {
CategoryWidgets *cw = g_ptr_array_index (test_self->category_widgets, i);
g_assert_nonnull (cw->chip);
CategoryWidgets *cw = g_ptr_array_index(test_self->category_widgets, i);
g_assert_nonnull(cw->chip);
}
window_test_teardown ();
window_test_teardown();
}
static void
test_window_chip_labels_match (void)
{
window_test_setup ();
static void test_window_chip_labels_match(void) {
window_test_setup();
for (guint i = 0; i < test_self->category_widgets->len; i++) {
CategoryWidgets *cw = g_ptr_array_index (test_self->category_widgets, i);
const char *chip_label = gtk_button_get_label (GTK_BUTTON (cw->chip));
g_assert_cmpstr (chip_label, ==, cw->name);
CategoryWidgets *cw = g_ptr_array_index(test_self->category_widgets, i);
const char *chip_label = gtk_button_get_label(GTK_BUTTON(cw->chip));
g_assert_cmpstr(chip_label, ==, cw->name);
}
window_test_teardown ();
window_test_teardown();
}
static void
test_window_initial_active_chip (void)
{
window_test_setup ();
static void test_window_initial_active_chip(void) {
window_test_setup();
g_assert_cmpint (test_self->active_chip_index, ==, -1);
g_assert_cmpint(test_self->active_chip_index, ==, -1);
window_test_teardown ();
window_test_teardown();
}
static void
test_window_all_categories_visible (void)
{
window_test_setup ();
static void test_window_all_categories_visible(void) {
window_test_setup();
for (guint i = 0; i < test_self->category_widgets->len; i++) {
CategoryWidgets *cw = g_ptr_array_index (test_self->category_widgets, i);
g_assert_true (gtk_widget_get_visible (cw->header));
g_assert_true (gtk_widget_get_visible (cw->flow));
CategoryWidgets *cw = g_ptr_array_index(test_self->category_widgets, i);
g_assert_true(gtk_widget_get_visible(cw->header));
g_assert_true(gtk_widget_get_visible(cw->flow));
}
window_test_teardown ();
window_test_teardown();
}
static void
test_window_bottom_spacer (void)
{
window_test_setup ();
static void test_window_bottom_spacer(void) {
window_test_setup();
g_assert_nonnull (test_self->bottom_spacer);
GtkWidget *last = gtk_widget_get_last_child (GTK_WIDGET (test_self->content_box));
g_assert_true (last == test_self->bottom_spacer);
g_assert_nonnull(test_self->bottom_spacer);
GtkWidget *last =
gtk_widget_get_last_child(GTK_WIDGET(test_self->content_box));
g_assert_true(last == test_self->bottom_spacer);
window_test_teardown ();
window_test_teardown();
}
int
main (int argc, char *argv[])
{
g_setenv ("MESON_SOURCE_ROOT", SRCDIR, TRUE);
g_test_init (&argc, &argv, NULL);
static void test_window_view_stack_exists(void) {
window_test_setup();
g_assert_nonnull(test_self->view_stack);
g_assert_true(GTK_IS_STACK(test_self->view_stack));
const char *name = gtk_stack_get_visible_child_name(test_self->view_stack);
g_assert_cmpstr(name, ==, "main");
run_find_kaomoji_bogus ();
window_test_teardown();
}
gboolean have_display = gtk_init_check ();
static void test_window_add_button_navigates(void) {
window_test_setup();
g_assert_nonnull(test_self->add_button);
g_assert_nonnull(test_self->back_button);
g_assert_true(gtk_widget_get_visible(test_self->add_button));
g_assert_false(gtk_widget_get_visible(test_self->back_button));
g_signal_emit_by_name(test_self->add_button, "clicked");
const char *name = gtk_stack_get_visible_child_name(test_self->view_stack);
g_assert_cmpstr(name, ==, "add-choice");
g_assert_false(gtk_widget_get_visible(test_self->add_button));
g_assert_true(gtk_widget_get_visible(test_self->back_button));
g_signal_emit_by_name(test_self->back_button, "clicked");
name = gtk_stack_get_visible_child_name(test_self->view_stack);
g_assert_cmpstr(name, ==, "main");
g_assert_true(gtk_widget_get_visible(test_self->add_button));
g_assert_false(gtk_widget_get_visible(test_self->back_button));
g_test_add_func ("/display-name/underscores", test_display_name_underscores);
g_test_add_func ("/display-name/no-underscores", test_display_name_no_underscores);
g_test_add_func ("/display-name/already-upper", test_display_name_already_upper);
g_test_add_func ("/display-name/single-char", test_display_name_single_char);
g_test_add_func ("/display-name/empty", test_display_name_empty);
g_test_add_func ("/find-kaomoji/with-env", test_find_kaomoji_with_env);
g_test_add_func ("/find-kaomoji/bogus", test_find_kaomoji_bogus);
g_test_add_func ("/sni/category", test_sni_category);
g_test_add_func ("/sni/id", test_sni_id);
g_test_add_func ("/sni/item-is-menu", test_sni_item_is_menu);
g_test_add_func ("/sni/menu", test_sni_menu);
g_test_add_func ("/sni/unknown", test_sni_unknown);
g_test_add_func ("/dbusmenu/version", test_dbusmenu_version);
g_test_add_func ("/dbusmenu/status", test_dbusmenu_status);
g_test_add_func ("/dbusmenu/text-direction", test_dbusmenu_text_direction);
g_test_add_func ("/dbusmenu/unknown", test_dbusmenu_unknown);
g_test_add_func ("/category-widgets/chip-init", test_category_widgets_chip_init);
window_test_teardown();
}
static void test_window_stack_pages_exist(void) {
window_test_setup();
g_assert_nonnull(gtk_stack_get_child_by_name(test_self->view_stack, "main"));
g_assert_nonnull(
gtk_stack_get_child_by_name(test_self->view_stack, "add-choice"));
g_assert_nonnull(
gtk_stack_get_child_by_name(test_self->view_stack, "add-category"));
g_assert_nonnull(
gtk_stack_get_child_by_name(test_self->view_stack, "pick-category"));
g_assert_nonnull(
gtk_stack_get_child_by_name(test_self->view_stack, "add-entry"));
g_assert_nonnull(
gtk_stack_get_child_by_name(test_self->view_stack, "manage"));
window_test_teardown();
}
static void test_add_category_creates_dir(void) {
char *cat_dir = g_build_filename(g_get_user_data_dir(), "moemoji", "kaomoji",
"ZZZ_test_category", NULL);
g_mkdir_with_parents(cat_dir, 0755);
window_test_setup();
gboolean found = FALSE;
for (guint i = 0; i < test_self->category_widgets->len; i++) {
CategoryWidgets *cw = g_ptr_array_index(test_self->category_widgets, i);
if (g_strcmp0(cw->name, "ZZZ test category") == 0) {
found = TRUE;
break;
}
}
g_assert_true(found);
window_test_teardown();
g_rmdir(cat_dir);
char *kaomoji_parent =
g_build_filename(g_get_user_data_dir(), "moemoji", "kaomoji", NULL);
g_rmdir(kaomoji_parent);
g_free(kaomoji_parent);
char *moemoji_parent =
g_build_filename(g_get_user_data_dir(), "moemoji", NULL);
g_rmdir(moemoji_parent);
g_free(moemoji_parent);
g_free(cat_dir);
}
static void test_add_entry_creates_file(void) {
char *cat_dir = g_build_filename(g_get_user_data_dir(), "moemoji", "kaomoji",
"ZZZ_test_entry_cat", NULL);
g_mkdir_with_parents(cat_dir, 0755);
char *fpath = g_build_filename(cat_dir, "1.txt", NULL);
g_file_set_contents(fpath, "(╯°□°)╯︵ ┻━┻\n", -1, NULL);
window_test_setup();
gboolean found = FALSE;
for (guint i = 0; i < test_self->category_widgets->len; i++) {
CategoryWidgets *cw = g_ptr_array_index(test_self->category_widgets, i);
if (g_strcmp0(cw->name, "ZZZ test entry cat") == 0) {
GtkWidget *first = gtk_widget_get_first_child(cw->flow);
g_assert_nonnull(first);
found = TRUE;
break;
}
}
g_assert_true(found);
g_free(test_self->selected_category_dir);
test_self->selected_category_dir = g_strdup(cat_dir);
GtkTextBuffer *buf =
gtk_text_view_get_buffer(GTK_TEXT_VIEW(test_self->entry_text_view));
gtk_text_buffer_set_text(buf, "( ˘ω˘ )", -1);
GtkWidget *entry_page =
gtk_stack_get_child_by_name(test_self->view_stack, "add-entry");
GtkWidget *save_btn = gtk_widget_get_last_child(entry_page);
g_assert_nonnull(save_btn);
g_signal_emit_by_name(save_btn, "clicked");
char *fpath2 = g_build_filename(cat_dir, "2.txt", NULL);
g_assert_true(g_file_test(fpath2, G_FILE_TEST_EXISTS));
char *contents = NULL;
g_file_get_contents(fpath2, &contents, NULL, NULL);
g_assert_nonnull(contents);
g_strchomp(contents);
g_assert_cmpstr(contents, ==, "( ˘ω˘ )");
g_free(contents);
const char *name = gtk_stack_get_visible_child_name(test_self->view_stack);
g_assert_cmpstr(name, ==, "main");
window_test_teardown();
g_unlink(fpath);
g_unlink(fpath2);
g_rmdir(cat_dir);
char *kaomoji_parent =
g_build_filename(g_get_user_data_dir(), "moemoji", "kaomoji", NULL);
g_rmdir(kaomoji_parent);
g_free(kaomoji_parent);
char *moemoji_parent =
g_build_filename(g_get_user_data_dir(), "moemoji", NULL);
g_rmdir(moemoji_parent);
g_free(moemoji_parent);
g_free(cat_dir);
g_free(fpath);
g_free(fpath2);
}
static void test_export_creates_archive(void) {
char *user_dir =
g_build_filename(g_get_user_data_dir(), "moemoji", "kaomoji", NULL);
char *cat_dir = g_build_filename(user_dir, "ZZZ_export_test", NULL);
g_mkdir_with_parents(cat_dir, 0755);
char *fpath = g_build_filename(cat_dir, "1.txt", NULL);
g_file_set_contents(fpath, "(ノ◕ヮ◕)ノ*:・゚✧\n", -1, NULL);
char *tmpdir = g_dir_make_tmp("moemoji-test-XXXXXX", NULL);
g_assert_nonnull(tmpdir);
char *archive_path = g_build_filename(tmpdir, "test-export.tar.gz", NULL);
GSubprocess *tar =
g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, NULL, "tar", "czf",
archive_path, "-C", user_dir, ".", NULL);
g_assert_nonnull(tar);
g_assert_true(g_subprocess_wait_check(tar, NULL, NULL));
g_object_unref(tar);
g_assert_true(g_file_test(archive_path, G_FILE_TEST_EXISTS));
char *extract_dir = g_build_filename(tmpdir, "extracted", NULL);
g_mkdir_with_parents(extract_dir, 0755);
GSubprocess *untar =
g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, NULL, "tar", "xzf",
archive_path, "-C", extract_dir, NULL);
g_assert_nonnull(untar);
g_assert_true(g_subprocess_wait_check(untar, NULL, NULL));
g_object_unref(untar);
char *extracted_file =
g_build_filename(extract_dir, "ZZZ_export_test", "1.txt", NULL);
g_assert_true(g_file_test(extracted_file, G_FILE_TEST_EXISTS));
char *contents = NULL;
g_file_get_contents(extracted_file, &contents, NULL, NULL);
g_assert_nonnull(contents);
g_strchomp(contents);
g_assert_cmpstr(contents, ==, "(ノ◕ヮ◕)ノ*:・゚✧");
g_free(contents);
g_unlink(extracted_file);
g_free(extracted_file);
char *extracted_cat = g_build_filename(extract_dir, "ZZZ_export_test", NULL);
g_rmdir(extracted_cat);
g_free(extracted_cat);
g_rmdir(extract_dir);
g_free(extract_dir);
g_unlink(archive_path);
g_free(archive_path);
g_rmdir(tmpdir);
g_free(tmpdir);
g_unlink(fpath);
g_free(fpath);
g_rmdir(cat_dir);
g_free(cat_dir);
char *kaomoji_parent =
g_build_filename(g_get_user_data_dir(), "moemoji", "kaomoji", NULL);
g_rmdir(kaomoji_parent);
g_free(kaomoji_parent);
char *moemoji_parent =
g_build_filename(g_get_user_data_dir(), "moemoji", NULL);
g_rmdir(moemoji_parent);
g_free(moemoji_parent);
g_free(user_dir);
}
static void test_import_extracts_and_loads(void) {
char *src_dir = g_dir_make_tmp("moemoji-import-src-XXXXXX", NULL);
g_assert_nonnull(src_dir);
char *cat_dir = g_build_filename(src_dir, "ZZZ_import_test", NULL);
g_mkdir_with_parents(cat_dir, 0755);
char *fpath = g_build_filename(cat_dir, "1.txt", NULL);
g_file_set_contents(fpath, "ヽ(>∀<☆)\n", -1, NULL);
char *archive_path = g_build_filename(src_dir, "import-test.tar.gz", NULL);
GSubprocess *tar =
g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, NULL, "tar", "czf",
archive_path, "-C", src_dir, "ZZZ_import_test", NULL);
g_assert_nonnull(tar);
g_assert_true(g_subprocess_wait_check(tar, NULL, NULL));
g_object_unref(tar);
char *user_dir =
g_build_filename(g_get_user_data_dir(), "moemoji", "kaomoji", NULL);
g_mkdir_with_parents(user_dir, 0755);
GSubprocess *untar =
g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, NULL, "tar", "xzf",
archive_path, "-C", user_dir, NULL);
g_assert_nonnull(untar);
g_assert_true(g_subprocess_wait_check(untar, NULL, NULL));
g_object_unref(untar);
char *imported_file =
g_build_filename(user_dir, "ZZZ_import_test", "1.txt", NULL);
g_assert_true(g_file_test(imported_file, G_FILE_TEST_EXISTS));
char *contents = NULL;
g_file_get_contents(imported_file, &contents, NULL, NULL);
g_assert_nonnull(contents);
g_strchomp(contents);
g_assert_cmpstr(contents, ==, "ヽ(>∀<☆)");
g_free(contents);
window_test_setup();
gboolean found = FALSE;
for (guint i = 0; i < test_self->category_widgets->len; i++) {
CategoryWidgets *cw = g_ptr_array_index(test_self->category_widgets, i);
if (g_strcmp0(cw->name, "ZZZ import test") == 0) {
found = TRUE;
break;
}
}
g_assert_true(found);
window_test_teardown();
g_unlink(imported_file);
g_free(imported_file);
char *imported_cat = g_build_filename(user_dir, "ZZZ_import_test", NULL);
g_rmdir(imported_cat);
g_free(imported_cat);
g_rmdir(user_dir);
char *moemoji_parent =
g_build_filename(g_get_user_data_dir(), "moemoji", NULL);
g_rmdir(moemoji_parent);
g_free(moemoji_parent);
g_free(user_dir);
g_unlink(fpath);
g_free(fpath);
g_rmdir(cat_dir);
g_free(cat_dir);
g_unlink(archive_path);
g_free(archive_path);
GSubprocess *rm = g_subprocess_new(G_SUBPROCESS_FLAGS_NONE, NULL, "rm", "-rf",
src_dir, NULL);
if (rm) {
g_subprocess_wait(rm, NULL, NULL);
g_object_unref(rm);
}
g_free(src_dir);
}
static void test_category_name_validation(void) {
window_test_setup();
gtk_editable_set_text(GTK_EDITABLE(test_self->category_name_entry), "");
g_assert_false(gtk_widget_get_sensitive(test_self->category_save_button));
gtk_editable_set_text(GTK_EDITABLE(test_self->category_name_entry), " ");
g_assert_false(gtk_widget_get_sensitive(test_self->category_save_button));
gtk_editable_set_text(GTK_EDITABLE(test_self->category_name_entry),
"Happy Faces");
g_assert_true(gtk_widget_get_sensitive(test_self->category_save_button));
gtk_editable_set_text(GTK_EDITABLE(test_self->category_name_entry),
"my-cool_category");
g_assert_true(gtk_widget_get_sensitive(test_self->category_save_button));
gtk_editable_set_text(GTK_EDITABLE(test_self->category_name_entry),
"bad/name");
g_assert_false(gtk_widget_get_sensitive(test_self->category_save_button));
gtk_editable_set_text(GTK_EDITABLE(test_self->category_name_entry),
"bad.name");
g_assert_false(gtk_widget_get_sensitive(test_self->category_save_button));
window_test_teardown();
}
static void test_manage_search_entry(void) {
window_test_setup();
GtkWidget *page =
gtk_stack_get_child_by_name(test_self->view_stack, "manage");
g_assert_nonnull(page);
GtkWidget *search = g_object_get_data(G_OBJECT(page), "manage-search");
g_assert_nonnull(search);
g_assert_true(GTK_IS_SEARCH_ENTRY(search));
window_test_teardown();
}
static void test_manage_populated(void) {
window_test_setup();
g_action_group_activate_action(G_ACTION_GROUP(test_self), "manage", NULL);
GtkWidget *page =
gtk_stack_get_child_by_name(test_self->view_stack, "manage");
GtkWidget *content = g_object_get_data(G_OBJECT(page), "manage-content");
g_assert_nonnull(content);
g_assert_nonnull(gtk_widget_get_first_child(content));
window_test_teardown();
}
static void test_manage_dupe_name_blocked(void) {
window_test_setup();
g_assert_cmpuint(test_self->category_widgets->len, >, 0);
CategoryWidgets *cw = g_ptr_array_index(test_self->category_widgets, 0);
gtk_editable_set_text(GTK_EDITABLE(test_self->category_name_entry), cw->name);
g_assert_false(gtk_widget_get_sensitive(test_self->category_save_button));
window_test_teardown();
}
int main(int argc, char *argv[]) {
g_setenv("MESON_SOURCE_ROOT", SRCDIR, TRUE);
g_test_init(&argc, &argv, NULL);
run_find_kaomoji_bogus();
gboolean have_display = gtk_init_check();
g_test_add_func("/display-name/underscores", test_display_name_underscores);
g_test_add_func("/display-name/no-underscores",
test_display_name_no_underscores);
g_test_add_func("/display-name/already-upper",
test_display_name_already_upper);
g_test_add_func("/display-name/single-char", test_display_name_single_char);
g_test_add_func("/display-name/empty", test_display_name_empty);
g_test_add_func("/find-kaomoji/with-env", test_find_kaomoji_with_env);
g_test_add_func("/find-kaomoji/bogus", test_find_kaomoji_bogus);
g_test_add_func("/sni/category", test_sni_category);
g_test_add_func("/sni/id", test_sni_id);
g_test_add_func("/sni/item-is-menu", test_sni_item_is_menu);
g_test_add_func("/sni/menu", test_sni_menu);
g_test_add_func("/sni/unknown", test_sni_unknown);
g_test_add_func("/dbusmenu/version", test_dbusmenu_version);
g_test_add_func("/dbusmenu/status", test_dbusmenu_status);
g_test_add_func("/dbusmenu/text-direction", test_dbusmenu_text_direction);
g_test_add_func("/dbusmenu/unknown", test_dbusmenu_unknown);
g_test_add_func("/category-widgets/chip-init",
test_category_widgets_chip_init);
if (have_display) {
g_test_add_func ("/window/chip-setup", test_window_chip_setup);
g_test_add_func ("/window/chip-labels-match", test_window_chip_labels_match);
g_test_add_func ("/window/initial-active-chip", test_window_initial_active_chip);
g_test_add_func ("/window/all-categories-visible", test_window_all_categories_visible);
g_test_add_func ("/window/bottom-spacer", test_window_bottom_spacer);
g_test_add_func("/window/chip-setup", test_window_chip_setup);
g_test_add_func("/window/chip-labels-match", test_window_chip_labels_match);
g_test_add_func("/window/initial-active-chip",
test_window_initial_active_chip);
g_test_add_func("/window/all-categories-visible",
test_window_all_categories_visible);
g_test_add_func("/window/bottom-spacer", test_window_bottom_spacer);
g_test_add_func("/window/view-stack-exists", test_window_view_stack_exists);
g_test_add_func("/window/add-button-navigates",
test_window_add_button_navigates);
g_test_add_func("/window/stack-pages-exist", test_window_stack_pages_exist);
g_test_add_func("/window/category-name-validation",
test_category_name_validation);
g_test_add_func("/window/add-category-creates-dir",
test_add_category_creates_dir);
g_test_add_func("/window/add-entry-creates-file",
test_add_entry_creates_file);
g_test_add_func("/window/export-creates-archive",
test_export_creates_archive);
g_test_add_func("/window/import-extracts-and-loads",
test_import_extracts_and_loads);
g_test_add_func("/window/manage-search-entry", test_manage_search_entry);
g_test_add_func("/window/manage-populated", test_manage_populated);
g_test_add_func("/window/manage-dupe-name-blocked",
test_manage_dupe_name_blocked);
}
return g_test_run ();
return g_test_run();
}