forked from AuroraMiddleware/gtk
Add another example application
This new step sets the headerbar as titlebar, and enables fallback for the app menu.
This commit is contained in:
parent
07d71cf945
commit
7265d9d9ad
@ -1829,6 +1829,7 @@ examples/application6/Makefile
|
|||||||
examples/application7/Makefile
|
examples/application7/Makefile
|
||||||
examples/application8/Makefile
|
examples/application8/Makefile
|
||||||
examples/application9/Makefile
|
examples/application9/Makefile
|
||||||
|
examples/application10/Makefile
|
||||||
tests/Makefile
|
tests/Makefile
|
||||||
tests/visuals/Makefile
|
tests/visuals/Makefile
|
||||||
testsuite/Makefile
|
testsuite/Makefile
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
SUBDIRS = \
|
SUBDIRS = \
|
||||||
application1 application2 application3 \
|
application1 application2 application3 \
|
||||||
application4 application5 application6 \
|
application4 application5 application6 \
|
||||||
application7 application8 application9
|
application7 application8 application9 \
|
||||||
|
application10
|
||||||
|
|
||||||
AM_CPPFLAGS = \
|
AM_CPPFLAGS = \
|
||||||
-I$(top_srcdir) \
|
-I$(top_srcdir) \
|
||||||
|
50
examples/application10/Makefile.am
Normal file
50
examples/application10/Makefile.am
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir) \
|
||||||
|
-I$(top_srcdir)/gdk \
|
||||||
|
-I$(top_builddir)/gdk \
|
||||||
|
$(GTK_DEBUG_FLAGS) \
|
||||||
|
$(GTK_DEP_CFLAGS)
|
||||||
|
|
||||||
|
LDADD = \
|
||||||
|
$(top_builddir)/gtk/libgtk-3.la \
|
||||||
|
$(top_builddir)/gdk/libgdk-3.la \
|
||||||
|
$(GTK_DEP_LIBS)
|
||||||
|
|
||||||
|
|
||||||
|
noinst_PROGRAMS = exampleapp
|
||||||
|
|
||||||
|
exampleapp_SOURCES = \
|
||||||
|
main.c \
|
||||||
|
exampleapp.c exampleapp.h \
|
||||||
|
exampleappwin.c exampleappwin.h \
|
||||||
|
exampleappprefs.c exampleappprefs.h \
|
||||||
|
resources.c
|
||||||
|
|
||||||
|
BUILT_SOURCES = \
|
||||||
|
resources.c \
|
||||||
|
gschemas.compiled
|
||||||
|
|
||||||
|
resources.c: exampleapp.gresource.xml $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir=$(srcdir) --generate-dependencies $(srcdir)/exampleapp.gresource.xml)
|
||||||
|
$(AM_V_GEN) $(GLIB_COMPILE_RESOURCES) $(srcdir)/exampleapp.gresource.xml \
|
||||||
|
--target=$@ --sourcedir=$(srcdir) --generate-source
|
||||||
|
|
||||||
|
gsettings_SCHEMAS = \
|
||||||
|
org.gtk.exampleapp.gschema.xml
|
||||||
|
|
||||||
|
@GSETTINGS_RULES@
|
||||||
|
|
||||||
|
gschemas.compiled: org.gtk.exampleapp.gschema.xml
|
||||||
|
$(GLIB_COMPILE_SCHEMAS) .
|
||||||
|
|
||||||
|
EXTRA_DIST = \
|
||||||
|
window.ui \
|
||||||
|
app-menu.ui \
|
||||||
|
prefs.ui \
|
||||||
|
gears-menu.ui \
|
||||||
|
exampleapp.gresource.xml \
|
||||||
|
org.gtk.exampleapp.gschema.xml
|
||||||
|
|
||||||
|
CLEANFILES = \
|
||||||
|
gschemas.compiled
|
||||||
|
|
||||||
|
-include $(top_srcdir)/git.mk
|
19
examples/application10/app-menu.ui
Normal file
19
examples/application10/app-menu.ui
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<interface>
|
||||||
|
<!-- interface-requires gtk+ 3.0 -->
|
||||||
|
<menu id="appmenu">
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">_Preferences</attribute>
|
||||||
|
<attribute name="action">app.preferences</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">_Quit</attribute>
|
||||||
|
<attribute name="action">app.quit</attribute>
|
||||||
|
<attribute name="accel"><![CDATA[<Ctrl>Q]]></attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
|
</interface>
|
115
examples/application10/exampleapp.c
Normal file
115
examples/application10/exampleapp.c
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "exampleapp.h"
|
||||||
|
#include "exampleappwin.h"
|
||||||
|
#include "exampleappprefs.h"
|
||||||
|
|
||||||
|
struct _ExampleApp
|
||||||
|
{
|
||||||
|
GtkApplication parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ExampleAppClass
|
||||||
|
{
|
||||||
|
GtkApplicationClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE(ExampleApp, example_app, GTK_TYPE_APPLICATION);
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_init (ExampleApp *app)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
preferences_activated (GSimpleAction *action,
|
||||||
|
GVariant *parameter,
|
||||||
|
gpointer app)
|
||||||
|
{
|
||||||
|
ExampleAppPrefs *prefs;
|
||||||
|
GtkWindow *win;
|
||||||
|
|
||||||
|
win = gtk_application_get_active_window (GTK_APPLICATION (app));
|
||||||
|
prefs = example_app_prefs_new (EXAMPLE_APP_WINDOW (win));
|
||||||
|
gtk_window_present (GTK_WINDOW (prefs));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
quit_activated (GSimpleAction *action,
|
||||||
|
GVariant *parameter,
|
||||||
|
gpointer app)
|
||||||
|
{
|
||||||
|
g_application_quit (G_APPLICATION (app));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GActionEntry app_entries[] =
|
||||||
|
{
|
||||||
|
{ "preferences", preferences_activated, NULL, NULL, NULL },
|
||||||
|
{ "quit", quit_activated, NULL, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_startup (GApplication *app)
|
||||||
|
{
|
||||||
|
GtkBuilder *builder;
|
||||||
|
GMenuModel *app_menu;
|
||||||
|
|
||||||
|
G_APPLICATION_CLASS (example_app_parent_class)->startup (app);
|
||||||
|
|
||||||
|
g_action_map_add_action_entries (G_ACTION_MAP (app),
|
||||||
|
app_entries, G_N_ELEMENTS (app_entries),
|
||||||
|
app);
|
||||||
|
|
||||||
|
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/app-menu.ui");
|
||||||
|
app_menu = G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu"));
|
||||||
|
gtk_application_set_app_menu (GTK_APPLICATION (app), app_menu);
|
||||||
|
g_object_unref (builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_activate (GApplication *app)
|
||||||
|
{
|
||||||
|
ExampleAppWindow *win;
|
||||||
|
|
||||||
|
win = example_app_window_new (EXAMPLE_APP (app));
|
||||||
|
gtk_window_present (GTK_WINDOW (win));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_open (GApplication *app,
|
||||||
|
GFile **files,
|
||||||
|
gint n_files,
|
||||||
|
const gchar *hint)
|
||||||
|
{
|
||||||
|
GList *windows;
|
||||||
|
ExampleAppWindow *win;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
windows = gtk_application_get_windows (GTK_APPLICATION (app));
|
||||||
|
if (windows)
|
||||||
|
win = EXAMPLE_APP_WINDOW (windows->data);
|
||||||
|
else
|
||||||
|
win = example_app_window_new (EXAMPLE_APP (app));
|
||||||
|
|
||||||
|
for (i = 0; i < n_files; i++)
|
||||||
|
example_app_window_open (win, files[i]);
|
||||||
|
|
||||||
|
gtk_window_present (GTK_WINDOW (win));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_class_init (ExampleAppClass *class)
|
||||||
|
{
|
||||||
|
G_APPLICATION_CLASS (class)->startup = example_app_startup;
|
||||||
|
G_APPLICATION_CLASS (class)->activate = example_app_activate;
|
||||||
|
G_APPLICATION_CLASS (class)->open = example_app_open;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExampleApp *
|
||||||
|
example_app_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (EXAMPLE_APP_TYPE,
|
||||||
|
"application-id", "org.gtk.exampleapp",
|
||||||
|
"flags", G_APPLICATION_HANDLES_OPEN,
|
||||||
|
NULL);
|
||||||
|
}
|
9
examples/application10/exampleapp.gresource.xml
Normal file
9
examples/application10/exampleapp.gresource.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<gresources>
|
||||||
|
<gresource prefix="/org/gtk/exampleapp">
|
||||||
|
<file preprocess="xml-stripblanks">window.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">app-menu.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">gears-menu.ui</file>
|
||||||
|
<file preprocess="xml-stripblanks">prefs.ui</file>
|
||||||
|
</gresource>
|
||||||
|
</gresources>
|
19
examples/application10/exampleapp.h
Normal file
19
examples/application10/exampleapp.h
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#ifndef __EXAMPLEAPP_H
|
||||||
|
#define __EXAMPLEAPP_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define EXAMPLE_APP_TYPE (example_app_get_type ())
|
||||||
|
#define EXAMPLE_APP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_APP_TYPE, ExampleApp))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _ExampleApp ExampleApp;
|
||||||
|
typedef struct _ExampleAppClass ExampleAppClass;
|
||||||
|
|
||||||
|
|
||||||
|
GType example_app_get_type (void);
|
||||||
|
ExampleApp *example_app_new (void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __EXAMPLEAPP_H */
|
79
examples/application10/exampleappprefs.c
Normal file
79
examples/application10/exampleappprefs.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include "exampleapp.h"
|
||||||
|
#include "exampleappwin.h"
|
||||||
|
#include "exampleappprefs.h"
|
||||||
|
|
||||||
|
struct _ExampleAppPrefs
|
||||||
|
{
|
||||||
|
GtkDialog parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ExampleAppPrefsClass
|
||||||
|
{
|
||||||
|
GtkDialogClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _ExampleAppPrefsPrivate ExampleAppPrefsPrivate;
|
||||||
|
|
||||||
|
struct _ExampleAppPrefsPrivate
|
||||||
|
{
|
||||||
|
GSettings *settings;
|
||||||
|
GtkWidget *font;
|
||||||
|
GtkWidget *transition;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE(ExampleAppPrefs, example_app_prefs, GTK_TYPE_DIALOG)
|
||||||
|
|
||||||
|
static void
|
||||||
|
preferences_closed (GtkWidget *button)
|
||||||
|
{
|
||||||
|
gtk_widget_destroy (gtk_widget_get_toplevel (button));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_prefs_init (ExampleAppPrefs *prefs)
|
||||||
|
{
|
||||||
|
ExampleAppPrefsPrivate *priv;
|
||||||
|
|
||||||
|
priv = example_app_prefs_get_instance_private (prefs);
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (prefs));
|
||||||
|
priv->settings = g_settings_new ("org.gtk.exampleapp");
|
||||||
|
|
||||||
|
g_settings_bind (priv->settings, "font",
|
||||||
|
priv->font, "font",
|
||||||
|
G_SETTINGS_BIND_DEFAULT);
|
||||||
|
g_settings_bind (priv->settings, "transition",
|
||||||
|
priv->transition, "active-id",
|
||||||
|
G_SETTINGS_BIND_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_prefs_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
ExampleAppPrefsPrivate *priv;
|
||||||
|
|
||||||
|
priv = example_app_prefs_get_instance_private (EXAMPLE_APP_PREFS (object));
|
||||||
|
g_clear_object (&priv->settings);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (example_app_prefs_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_prefs_class_init (ExampleAppPrefsClass *class)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (class)->dispose = example_app_prefs_dispose;
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
||||||
|
"/org/gtk/exampleapp/prefs.ui");
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppPrefs, font);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppPrefs, transition);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), preferences_closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExampleAppPrefs *
|
||||||
|
example_app_prefs_new (ExampleAppWindow *win)
|
||||||
|
{
|
||||||
|
return g_object_new (EXAMPLE_APP_PREFS_TYPE, "transient-for", win, NULL);
|
||||||
|
}
|
20
examples/application10/exampleappprefs.h
Normal file
20
examples/application10/exampleappprefs.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#ifndef __EXAMPLEAPPPREFS_H
|
||||||
|
#define __EXAMPLEAPPPREFS_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "exampleappwin.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define EXAMPLE_APP_PREFS_TYPE (example_app_prefs_get_type ())
|
||||||
|
#define EXAMPLE_APP_PREFS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_APP_PREFS_TYPE, ExampleAppPrefs))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _ExampleAppPrefs ExampleAppPrefs;
|
||||||
|
typedef struct _ExampleAppPrefsClass ExampleAppPrefsClass;
|
||||||
|
|
||||||
|
|
||||||
|
GType example_app_prefs_get_type (void);
|
||||||
|
ExampleAppPrefs *example_app_prefs_new (ExampleAppWindow *win);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __EXAMPLEAPPPREFS_H */
|
341
examples/application10/exampleappwin.c
Normal file
341
examples/application10/exampleappwin.c
Normal file
@ -0,0 +1,341 @@
|
|||||||
|
#include "exampleapp.h"
|
||||||
|
#include "exampleappwin.h"
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
struct _ExampleAppWindow
|
||||||
|
{
|
||||||
|
GtkApplicationWindow parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _ExampleAppWindowClass
|
||||||
|
{
|
||||||
|
GtkApplicationWindowClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _ExampleAppWindowPrivate ExampleAppWindowPrivate;
|
||||||
|
|
||||||
|
struct _ExampleAppWindowPrivate
|
||||||
|
{
|
||||||
|
GSettings *settings;
|
||||||
|
GtkWidget *stack;
|
||||||
|
GtkWidget *search;
|
||||||
|
GtkWidget *searchbar;
|
||||||
|
GtkWidget *searchentry;
|
||||||
|
GtkWidget *gears;
|
||||||
|
GtkWidget *sidebar;
|
||||||
|
GtkWidget *words;
|
||||||
|
GtkWidget *lines;
|
||||||
|
GtkWidget *lines_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_PRIVATE(ExampleAppWindow, example_app_window, GTK_TYPE_APPLICATION_WINDOW);
|
||||||
|
|
||||||
|
static void
|
||||||
|
search_text_changed (GtkEntry *entry)
|
||||||
|
{
|
||||||
|
ExampleAppWindow *win;
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
const gchar *text;
|
||||||
|
GtkWidget *tab;
|
||||||
|
GtkWidget *view;
|
||||||
|
GtkTextBuffer *buffer;
|
||||||
|
GtkTextIter start, match_start, match_end;
|
||||||
|
|
||||||
|
text = gtk_entry_get_text (entry);
|
||||||
|
|
||||||
|
if (text[0] == '\0')
|
||||||
|
return;
|
||||||
|
|
||||||
|
win = EXAMPLE_APP_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (entry)));
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
|
||||||
|
tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack));
|
||||||
|
view = gtk_bin_get_child (GTK_BIN (tab));
|
||||||
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||||
|
|
||||||
|
/* Very simple-minded search implementation */
|
||||||
|
gtk_text_buffer_get_start_iter (buffer, &start);
|
||||||
|
if (gtk_text_iter_forward_search (&start, text, GTK_TEXT_SEARCH_CASE_INSENSITIVE,
|
||||||
|
&match_start, &match_end, NULL))
|
||||||
|
{
|
||||||
|
gtk_text_buffer_select_range (buffer, &match_start, &match_end);
|
||||||
|
gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (view), &match_start,
|
||||||
|
0.0, FALSE, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
find_word (GtkButton *button,
|
||||||
|
ExampleAppWindow *win)
|
||||||
|
{
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
const gchar *word;
|
||||||
|
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
|
||||||
|
word = gtk_button_get_label (button);
|
||||||
|
gtk_entry_set_text (GTK_ENTRY (priv->searchentry), word);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_words (ExampleAppWindow *win)
|
||||||
|
{
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
GHashTable *strings;
|
||||||
|
GHashTableIter iter;
|
||||||
|
GtkWidget *tab, *view, *row;
|
||||||
|
GtkTextBuffer *buffer;
|
||||||
|
GtkTextIter start, end;
|
||||||
|
GList *children, *l;
|
||||||
|
gchar *word, *key;
|
||||||
|
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
|
||||||
|
tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack));
|
||||||
|
|
||||||
|
if (tab == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
view = gtk_bin_get_child (GTK_BIN (tab));
|
||||||
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||||
|
|
||||||
|
strings = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||||
|
|
||||||
|
gtk_text_buffer_get_start_iter (buffer, &start);
|
||||||
|
while (!gtk_text_iter_is_end (&start))
|
||||||
|
{
|
||||||
|
while (!gtk_text_iter_starts_word (&start))
|
||||||
|
{
|
||||||
|
if (!gtk_text_iter_forward_char (&start))
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
end = start;
|
||||||
|
if (!gtk_text_iter_forward_word_end (&end))
|
||||||
|
goto done;
|
||||||
|
word = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
|
||||||
|
g_hash_table_add (strings, g_utf8_strdown (word, -1));
|
||||||
|
g_free (word);
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
children = gtk_container_get_children (GTK_CONTAINER (priv->words));
|
||||||
|
for (l = children; l; l = l->next)
|
||||||
|
gtk_container_remove (GTK_CONTAINER (priv->words), GTK_WIDGET (l->data));
|
||||||
|
g_list_free (children);
|
||||||
|
|
||||||
|
g_hash_table_iter_init (&iter, strings);
|
||||||
|
while (g_hash_table_iter_next (&iter, (gpointer *)&key, NULL))
|
||||||
|
{
|
||||||
|
row = gtk_button_new_with_label (key);
|
||||||
|
g_signal_connect (row, "clicked",
|
||||||
|
G_CALLBACK (find_word), win);
|
||||||
|
gtk_widget_show (row);
|
||||||
|
gtk_container_add (GTK_CONTAINER (priv->words), row);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_hash_table_unref (strings);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_lines (ExampleAppWindow *win)
|
||||||
|
{
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
GtkWidget *tab, *view;
|
||||||
|
GtkTextBuffer *buffer;
|
||||||
|
GtkTextIter iter;
|
||||||
|
int count;
|
||||||
|
gchar *lines;
|
||||||
|
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
|
||||||
|
tab = gtk_stack_get_visible_child (GTK_STACK (priv->stack));
|
||||||
|
|
||||||
|
if (tab == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
view = gtk_bin_get_child (GTK_BIN (tab));
|
||||||
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
|
||||||
|
gtk_text_buffer_get_start_iter (buffer, &iter);
|
||||||
|
while (!gtk_text_iter_is_end (&iter))
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
if (!gtk_text_iter_forward_line (&iter))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lines = g_strdup_printf ("%d", count);
|
||||||
|
gtk_label_set_text (GTK_LABEL (priv->lines), lines);
|
||||||
|
g_free (lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
visible_child_changed (GObject *stack,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
ExampleAppWindow *win;
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
|
||||||
|
if (gtk_widget_in_destruction (GTK_WIDGET (stack)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
win = EXAMPLE_APP_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (stack)));
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
gtk_search_bar_set_search_mode (GTK_SEARCH_BAR (priv->searchbar), FALSE);
|
||||||
|
update_words (win);
|
||||||
|
update_lines (win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
words_changed (GObject *sidebar,
|
||||||
|
GParamSpec *pspec,
|
||||||
|
ExampleAppWindow *win)
|
||||||
|
{
|
||||||
|
update_words (win);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_window_init (ExampleAppWindow *win)
|
||||||
|
{
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
GtkBuilder *builder;
|
||||||
|
GMenuModel *menu;
|
||||||
|
GAction *action;
|
||||||
|
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
gtk_widget_init_template (GTK_WIDGET (win));
|
||||||
|
priv->settings = g_settings_new ("org.gtk.exampleapp");
|
||||||
|
|
||||||
|
g_settings_bind (priv->settings, "transition",
|
||||||
|
priv->stack, "transition-type",
|
||||||
|
G_SETTINGS_BIND_DEFAULT);
|
||||||
|
|
||||||
|
g_settings_bind (priv->settings, "show-words",
|
||||||
|
priv->sidebar, "reveal-child",
|
||||||
|
G_SETTINGS_BIND_DEFAULT);
|
||||||
|
|
||||||
|
g_object_bind_property (priv->search, "active",
|
||||||
|
priv->searchbar, "search-mode-enabled",
|
||||||
|
G_BINDING_BIDIRECTIONAL);
|
||||||
|
|
||||||
|
g_signal_connect (priv->sidebar, "notify::reveal-child",
|
||||||
|
G_CALLBACK (words_changed), win);
|
||||||
|
|
||||||
|
builder = gtk_builder_new_from_resource ("/org/gtk/exampleapp/gears-menu.ui");
|
||||||
|
menu = G_MENU_MODEL (gtk_builder_get_object (builder, "menu"));
|
||||||
|
gtk_menu_button_set_menu_model (GTK_MENU_BUTTON (priv->gears), menu);
|
||||||
|
g_object_unref (builder);
|
||||||
|
|
||||||
|
action = g_settings_create_action (priv->settings, "show-words");
|
||||||
|
g_action_map_add_action (G_ACTION_MAP (win), action);
|
||||||
|
g_object_unref (action);
|
||||||
|
|
||||||
|
action = (GAction*) g_property_action_new ("show-lines", priv->lines, "visible");
|
||||||
|
g_action_map_add_action (G_ACTION_MAP (win), action);
|
||||||
|
g_object_unref (action);
|
||||||
|
|
||||||
|
g_object_bind_property (priv->lines, "visible",
|
||||||
|
priv->lines_label, "visible",
|
||||||
|
G_BINDING_DEFAULT);
|
||||||
|
|
||||||
|
gtk_window_set_icon_name (GTK_WINDOW (win), "sunny");
|
||||||
|
g_object_set (gtk_settings_get_default (), "gtk-shell-shows-app-menu", FALSE, NULL);
|
||||||
|
gtk_application_window_set_show_menubar (GTK_APPLICATION_WINDOW (win), TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_window_dispose (GObject *object)
|
||||||
|
{
|
||||||
|
ExampleAppWindow *win;
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
|
||||||
|
win = EXAMPLE_APP_WINDOW (object);
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
|
||||||
|
g_clear_object (&priv->settings);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (example_app_window_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
example_app_window_class_init (ExampleAppWindowClass *class)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (class)->dispose = example_app_window_dispose;
|
||||||
|
|
||||||
|
gtk_widget_class_set_template_from_resource (GTK_WIDGET_CLASS (class),
|
||||||
|
"/org/gtk/exampleapp/window.ui");
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, stack);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, search);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchbar);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, searchentry);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, gears);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, words);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, sidebar);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines);
|
||||||
|
gtk_widget_class_bind_template_child_private (GTK_WIDGET_CLASS (class), ExampleAppWindow, lines_label);
|
||||||
|
|
||||||
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), search_text_changed);
|
||||||
|
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), visible_child_changed);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExampleAppWindow *
|
||||||
|
example_app_window_new (ExampleApp *app)
|
||||||
|
{
|
||||||
|
return g_object_new (EXAMPLE_APP_WINDOW_TYPE, "application", app, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
example_app_window_open (ExampleAppWindow *win,
|
||||||
|
GFile *file)
|
||||||
|
{
|
||||||
|
ExampleAppWindowPrivate *priv;
|
||||||
|
gchar *basename;
|
||||||
|
GtkWidget *scrolled, *view;
|
||||||
|
gchar *contents;
|
||||||
|
gsize length;
|
||||||
|
GtkTextBuffer *buffer;
|
||||||
|
GtkTextTag *tag;
|
||||||
|
GtkTextIter start_iter, end_iter;
|
||||||
|
|
||||||
|
priv = example_app_window_get_instance_private (win);
|
||||||
|
basename = g_file_get_basename (file);
|
||||||
|
|
||||||
|
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||||
|
gtk_widget_show (scrolled);
|
||||||
|
gtk_widget_set_hexpand (scrolled, TRUE);
|
||||||
|
gtk_widget_set_vexpand (scrolled, TRUE);
|
||||||
|
view = gtk_text_view_new ();
|
||||||
|
gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE);
|
||||||
|
gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE);
|
||||||
|
gtk_widget_show (view);
|
||||||
|
gtk_container_add (GTK_CONTAINER (scrolled), view);
|
||||||
|
gtk_stack_add_titled (GTK_STACK (priv->stack), scrolled, basename, basename);
|
||||||
|
|
||||||
|
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
|
||||||
|
|
||||||
|
if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
|
||||||
|
{
|
||||||
|
gtk_text_buffer_set_text (buffer, contents, length);
|
||||||
|
g_free (contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
tag = gtk_text_buffer_create_tag (buffer, NULL, NULL);
|
||||||
|
g_settings_bind (priv->settings, "font",
|
||||||
|
tag, "font",
|
||||||
|
G_SETTINGS_BIND_DEFAULT);
|
||||||
|
|
||||||
|
gtk_text_buffer_get_start_iter (buffer, &start_iter);
|
||||||
|
gtk_text_buffer_get_end_iter (buffer, &end_iter);
|
||||||
|
gtk_text_buffer_apply_tag (buffer, tag, &start_iter, &end_iter);
|
||||||
|
|
||||||
|
g_free (basename);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (priv->search, TRUE);
|
||||||
|
|
||||||
|
update_words (win);
|
||||||
|
update_lines (win);
|
||||||
|
}
|
22
examples/application10/exampleappwin.h
Normal file
22
examples/application10/exampleappwin.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef __EXAMPLEAPPWIN_H
|
||||||
|
#define __EXAMPLEAPPWIN_H
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include "exampleapp.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define EXAMPLE_APP_WINDOW_TYPE (example_app_window_get_type ())
|
||||||
|
#define EXAMPLE_APP_WINDOW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EXAMPLE_APP_WINDOW_TYPE, ExampleAppWindow))
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _ExampleAppWindow ExampleAppWindow;
|
||||||
|
typedef struct _ExampleAppWindowClass ExampleAppWindowClass;
|
||||||
|
|
||||||
|
|
||||||
|
GType example_app_window_get_type (void);
|
||||||
|
ExampleAppWindow *example_app_window_new (ExampleApp *app);
|
||||||
|
void example_app_window_open (ExampleAppWindow *win,
|
||||||
|
GFile *file);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __EXAMPLEAPPWIN_H */
|
16
examples/application10/gears-menu.ui
Normal file
16
examples/application10/gears-menu.ui
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<interface>
|
||||||
|
<!-- interface-requires gtk+ 3.0 -->
|
||||||
|
<menu id="menu">
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">_Words</attribute>
|
||||||
|
<attribute name="action">win.show-words</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">_Lines</attribute>
|
||||||
|
<attribute name="action">win.show-lines</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</menu>
|
||||||
|
</interface>
|
15
examples/application10/main.c
Normal file
15
examples/application10/main.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <exampleapp.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
/* Since this example is running uninstalled,
|
||||||
|
* we have to help it find its schema. This
|
||||||
|
* is *not* necessary in properly installed
|
||||||
|
* application.
|
||||||
|
*/
|
||||||
|
g_setenv ("GSETTINGS_SCHEMA_DIR", ".", FALSE);
|
||||||
|
|
||||||
|
return g_application_run (G_APPLICATION (example_app_new ()), argc, argv);
|
||||||
|
}
|
25
examples/application10/org.gtk.exampleapp.gschema.xml
Normal file
25
examples/application10/org.gtk.exampleapp.gschema.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<schemalist>
|
||||||
|
<schema path="/org/gtk/exampleapp/" id="org.gtk.exampleapp">
|
||||||
|
<key name="font" type="s">
|
||||||
|
<default>'Monospace 12'</default>
|
||||||
|
<summary>Font</summary>
|
||||||
|
<description>The font to be used for content.</description>
|
||||||
|
</key>
|
||||||
|
<key name="transition" type="s">
|
||||||
|
<choices>
|
||||||
|
<choice value='none'/>
|
||||||
|
<choice value='crossfade'/>
|
||||||
|
<choice value='slide-left-right'/>
|
||||||
|
</choices>
|
||||||
|
<default>'none'</default>
|
||||||
|
<summary>Transition</summary>
|
||||||
|
<description>The transition to use when switching tabs.</description>
|
||||||
|
</key>
|
||||||
|
<key name="show-words" type="b">
|
||||||
|
<default>false</default>
|
||||||
|
<summary>Show words</summary>
|
||||||
|
<description>Whether to show a word list in the sidebar</description>
|
||||||
|
</key>
|
||||||
|
</schema>
|
||||||
|
</schemalist>
|
83
examples/application10/prefs.ui
Normal file
83
examples/application10/prefs.ui
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<!-- interface-requires gtk+ 3.8 -->
|
||||||
|
<template class="ExampleAppPrefs" parent="GtkDialog">
|
||||||
|
<property name="title" translatable="yes">Preferences</property>
|
||||||
|
<property name="resizable">False</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<child internal-child="vbox">
|
||||||
|
<object class="GtkBox" id="vbox">
|
||||||
|
<child>
|
||||||
|
<object class="GtkGrid" id="grid">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="margin">6</property>
|
||||||
|
<property name="row-spacing">12</property>
|
||||||
|
<property name="column-spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="fontlabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label">_Font:</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="mnemonic-widget">font</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">0</property>
|
||||||
|
<property name="top-attach">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFontButton" id="font">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="top-attach">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="transitionlabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label">_Transition:</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="mnemonic-widget">transition</property>
|
||||||
|
<property name="xalign">1</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">0</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkComboBoxText" id="transition">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<items>
|
||||||
|
<item translatable="yes" id="none">None</item>
|
||||||
|
<item translatable="yes" id="crossfade">Fade</item>
|
||||||
|
<item translatable="yes" id="slide-left-right">Slide</item>
|
||||||
|
</items>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkButtonBox" id="action_area">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="close">
|
||||||
|
<signal name="clicked" handler="preferences_closed"/>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="label">_Close</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
117
examples/application10/window.ui
Normal file
117
examples/application10/window.ui
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<interface>
|
||||||
|
<!-- interface-requires gtk+ 3.8 -->
|
||||||
|
<template class="ExampleAppWindow" parent="GtkApplicationWindow">
|
||||||
|
<property name="title" translatable="yes">Example Application</property>
|
||||||
|
<property name="default-width">600</property>
|
||||||
|
<property name="default-height">400</property>
|
||||||
|
<child type="titlebar">
|
||||||
|
<object class="GtkHeaderBar" id="header">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="show-close-button">True</property>
|
||||||
|
<property name="show-fallback-app-menu">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="lines_label">
|
||||||
|
<property name="visible">False</property>
|
||||||
|
<property name="label" translatable="yes">Lines:</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="pack-type">start</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="lines">
|
||||||
|
<property name="visible">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="pack-type">start</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child type="title">
|
||||||
|
<object class="GtkStackSwitcher" id="tabs">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="stack">stack</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkToggleButton" id="search">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="sensitive">False</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="search-icon">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="icon-name">edit-find-symbolic</property>
|
||||||
|
<property name="icon-size">1</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="pack-type">end</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkMenuButton" id="gears">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkImage" id="gears-icon">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="icon-name">emblem-system-symbolic</property>
|
||||||
|
<property name="icon-size">1</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="pack-type">end</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="content_box">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="orientation">vertical</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSearchBar" id="searchbar">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkSearchEntry" id="searchentry">
|
||||||
|
<signal name="search-changed" handler="search_text_changed"/>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox" id="hbox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkRevealer" id="sidebar">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="transition-type">slide-right</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScrolledWindow" id="sidebar-sw">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="hscrollbar-policy">never</property>
|
||||||
|
<property name="vscrollbar-policy">automatic</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkListBox" id="words">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="selection-mode">none</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStack" id="stack">
|
||||||
|
<signal name="notify::visible-child" handler="visible_child_changed"/>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</template>
|
||||||
|
</interface>
|
Loading…
Reference in New Issue
Block a user