为了获得上下文,我正在制作一个 GUI 应用程序,它基于通过 GtkEntry 的输入命令,就像ls
它会弹出一个窗口,其中包含该目录中的相应文件。所以 GTK4 演示有一个文件浏览器的示例,它可以完美地满足我的需求,但我就是无法让它工作!
这是我的项目结构:
main.c
#include <gtk/gtk.h>
#include "../headers/mainApp.h"
int main(int argc, char* argv[]){
g_setenv("GSETTINGS_SCHEMA_DIR", ".", FALSE);
return g_application_run(G_APPLICATION(main_app_new()), argc, argv);
}
mainApp.c
#include <gtk/gtk.h>
#include "../headers/mainApp.h"
#include "../headers/mainAppWindow.h"
#include "../headers/mainAppPreferences.h"
static void main_app_init(MainApp* app);
static void main_app_class_init(MainAppClass* class);
static void main_app_open(GApplication* app, GFile** files, int n_files, const char* hint);
static void preferences_activated(GSimpleAction* action, GVariant* parameter, gpointer app);
static void quit_activated(GSimpleAction* action, GVariant* parameter, gpointer app);
static void main_app_startup(GApplication* app);
static void main_app_activate(GApplication* app);
struct _MainApp {
GtkApplication parent;
};
G_DEFINE_TYPE(MainApp, main_app, GTK_TYPE_APPLICATION)
MainApp* main_app_new(void) {
return g_object_new(MAIN_APP_TYPE, "application-id", "org.gtk.mainapp", "flags", G_APPLICATION_HANDLES_OPEN, NULL);
}
static void main_app_init(MainApp* app){}
static void main_app_open(GApplication* app, GFile** files, int n_files, const char* hint){
GList* windows;
MainAppWindow* window;
int i;
windows = gtk_application_get_windows(GTK_APPLICATION(app));
if(windows)
window = MAIN_APP_WINDOW(MAIN_APP(app));
else
window = main_app_window_new(MAIN_APP(app));
/*for(i = 0; i < n_files; i++)
main_app_window_open(window, files[i]);*/
gtk_window_present(GTK_WINDOW(window));
}
static void main_app_class_init(MainAppClass* class){
G_APPLICATION_CLASS (class)->startup = main_app_startup;
G_APPLICATION_CLASS (class)->activate = main_app_activate;
G_APPLICATION_CLASS (class)->open = main_app_open;
}
static void preferences_activated(GSimpleAction* action, GVariant* parameter, gpointer app){
MainAppPreferences *preferences;
GtkWindow *window;
window = gtk_application_get_active_window (GTK_APPLICATION (app));
preferences = main_app_preferences_new(MAIN_APP_WINDOW(window));
gtk_window_present (GTK_WINDOW (preferences));
}
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 main_app_startup(GApplication* app){
const char* quit_accels[2] = {"<Ctrl>Q", NULL};
G_APPLICATION_CLASS(main_app_parent_class)->startup (app);
g_action_map_add_action_entries (G_ACTION_MAP (app), app_entries, G_N_ELEMENTS (app_entries), app);
gtk_application_set_accels_for_action (GTK_APPLICATION (app), "app.quit", quit_accels);
}
static void main_app_activate(GApplication* app){
MainAppWindow* window;
window = main_app_window_new(MAIN_APP(app));
gtk_window_present(GTK_WINDOW(window));
}
mainAppWindow.c
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include <stdio.h>
#include "../headers/mainApp.h"
#include "../headers/mainAppWindow.h"
#include "../headers/fileBrowserView.h"
static void main_app_window_class_init(MainAppWindowClass* class);
static void main_app_window_dispose(GObject* object);
static void main_app_window_init(MainAppWindow* window);
static void command_changed(GtkEntry* entry, MainAppWindow* window);
static void command_submit_pressed(GtkButton *button, gpointer user_data);
static GtkTreeModel* create_completion_model(void);
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
struct _MainAppWindow {
GtkApplicationWindow parent;
GSettings* settings;
GtkWidget* gears;
GtkWidget* commandEntry;
GtkWidget* btnCommandSubmit;
GtkWidget* stack;
};
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
G_DEFINE_TYPE (MainAppWindow, main_app_window, GTK_TYPE_APPLICATION_WINDOW)
MainAppWindow* main_app_window_new(MainApp* app){
return g_object_new(MAIN_APP_WINDOW_TYPE, "application", app, NULL);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void main_app_window_class_init(MainAppWindowClass* class){
GObjectClass* gobject_class = G_OBJECT_CLASS(class);
gobject_class->dispose = main_app_window_dispose;
gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS(class), "/org/gtk/mainapp/ui/window.ui");
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), MainAppWindow, gears);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), MainAppWindow, commandEntry);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), MainAppWindow, btnCommandSubmit);
gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class), MainAppWindow, stack);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), command_changed);
gtk_widget_class_bind_template_callback (GTK_WIDGET_CLASS (class), command_submit_pressed);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void main_app_window_init(MainAppWindow* window){
GtkBuilder* builder;
GMenuModel* menu;
GAction* action;
GtkEntryCompletion* completion;
GtkTreeModel *completion_model;
GtkBox* box;
gtk_widget_init_template(GTK_WIDGET(window));
builder = gtk_builder_new_from_resource("/org/gtk/mainapp/ui/gears-menu.ui");
menu = G_MENU_MODEL(gtk_builder_get_object(builder, "menu"));
gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(window->gears), menu);
window->stack = GTK_WIDGET(gtk_builder_get_object(builder, "stack"));
g_object_unref(builder);
window->settings = g_settings_new("org.gtk.mainapp");
//Create completion object.
completion = gtk_entry_completion_new();
//Asign the completion to the entry.
gtk_entry_set_completion(GTK_ENTRY(window->commandEntry), completion);
g_object_unref(completion);
//Create a tree model and use it as the completion model.
completion_model = create_completion_model();
gtk_entry_completion_set_model(completion, completion_model);
g_object_unref(completion_model);
/* Use model column 0 as the text column */
gtk_entry_completion_set_text_column (completion, 0);
gtk_entry_completion_set_inline_completion (completion, TRUE);
gtk_entry_completion_set_inline_selection (completion, TRUE);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
void main_app_window_open(MainAppWindow* window, GFile* file){
char *basename;
GtkWidget *scrolled, *view;
char *contents;
gsize length;
GtkTextBuffer *buffer;
GtkTextTag *tag;
GtkTextIter start_iter, end_iter;
basename = g_file_get_basename (file);
scrolled = gtk_scrolled_window_new ();
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_scrolled_window_set_child (GTK_SCROLLED_WINDOW (scrolled), view);
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 (window->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);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void main_app_window_dispose(GObject* object){
MainAppWindow* window;
window = MAIN_APP_WINDOW(object);
g_clear_object(&window->settings);
G_OBJECT_CLASS(main_app_window_parent_class)->dispose(object);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void command_changed(GtkEntry* entry, MainAppWindow* window){
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void command_submit_pressed(GtkButton *button, gpointer user_data){
GtkWidget* window;
window = do_listview_filebrowser(NULL);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static GtkTreeModel* create_completion_model(void){
const char* commands[] = {
"ls [dir]",
"ls -l [dir]",
"cat [file_path]",
"pwd",
"adduser [user_name]",
"deluser [user_name]",
NULL
};
int i;
GtkListStore *store;
GtkTreeIter iter;
store = gtk_list_store_new (1, G_TYPE_STRING);
for (i = 0; commands[i]; i++)
{
/* Append one word */
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter, 0, commands[i], -1);
}
return GTK_TREE_MODEL (store);
}
///////////////////////////////////////////////////////////////////////////////////////
/* Layout:
+-------------------------------------+
| +-----------++-------++-----------+ |
| | CmdEntry || Space || Submit | |
| +-----------++-------++-----------+ |
+-------------------------------------+
Constraints:
super.start = cmdEntry.start - 8
cmdEntry.end = space.start
space.end = Submit.start
submit.end = super.end - 8
*/
///////////////////////////////////////////////////////////////////////////////////////
fileBrowserView.c
#include <gtk/gtk.h>
#include <glib/gi18n.h>
#include "../headers/mainAppWindow.h"
#include "../headers/fileBrowserView.h"
static void file_browser_view_set_property (GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec);
static void file_browser_view_get_property (GObject* object, guint property_id, GValue* value, GParamSpec* pspec);
static void file_browser_view_finalize (GObject *object);
char* filebrowser_get_display_name (GObject* object, GFileInfo* info);
char* filebrowser_get_content_type (GObject* object, GFileInfo* info);
char* filebrowser_get_size (GObject* object, GFileInfo* info);
GIcon* filebrowser_get_icon (GObject* object, GFileInfo* info);
void filebrowser_up_clicked_cb (GtkButton* button, GtkDirectoryList* list);
void filebrowser_view_activated_cb (GtkGridView* view, guint pos, GtkDirectoryList* list);
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
struct _FileBrowserView {
GObject parent_instance;
GtkListItemFactory *factory;
char *icon_name;
char *title;
GtkOrientation orientation;
};
enum {
PROP_0,
PROP_FACTORY,
PROP_ICON_NAME,
PROP_TITLE,
PROP_ORIENTATION,
N_PROPS
};
static GParamSpec* properties[N_PROPS] = { NULL, };
static GtkWidget *window = NULL;
G_DEFINE_TYPE (FileBrowserView, file_browser_view, G_TYPE_OBJECT)
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
FileBrowserView* file_browser_view_new(GtkWindow* window){
return g_object_new(FILE_BROWSER_TYPE, NULL, window, NULL);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void file_browser_view_class_init(FileBrowserViewClass* view){
GObjectClass* gobject_class = G_OBJECT_CLASS(view);
gobject_class->get_property = file_browser_view_get_property;
gobject_class->set_property = file_browser_view_set_property;
gobject_class->finalize = file_browser_view_finalize;
properties[PROP_FACTORY] =
g_param_spec_object ("factory",
"factory",
"factory to use in the main view",
GTK_TYPE_LIST_ITEM_FACTORY,
G_PARAM_READWRITE);
properties[PROP_ICON_NAME] =
g_param_spec_string ("icon-name",
"icon name",
"icon to display for selecting this view",
NULL,
G_PARAM_READWRITE);
properties[PROP_TITLE] =
g_param_spec_string ("title",
"title",
"title to display for selecting this view",
NULL,
G_PARAM_READWRITE);
properties[PROP_ORIENTATION] =
g_param_spec_enum ("orientation",
"orientation",
"orientation of the view",
GTK_TYPE_ORIENTATION,
GTK_ORIENTATION_VERTICAL,
G_PARAM_READWRITE);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void file_browser_view_init(FileBrowserView* view) {}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void file_browser_view_get_property (GObject* object, guint property_id, GValue* value, GParamSpec* pspec) {
FileBrowserView *self = FILE_BROWSER_VIEW (object);
switch (property_id) {
case PROP_FACTORY:
g_value_set_object (value, self->factory);
break;
case PROP_ICON_NAME:
g_value_set_string (value, self->icon_name);
break;
case PROP_TITLE:
g_value_set_string (value, self->title);
break;
case PROP_ORIENTATION:
g_value_set_enum (value, self->orientation);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void file_browser_view_set_property (GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec) {
FileBrowserView *self = FILE_BROWSER_VIEW (object);
switch (prop_id) {
case PROP_FACTORY:
g_set_object (&self->factory, g_value_get_object (value));
break;
case PROP_ICON_NAME:
g_free (self->icon_name);
self->icon_name = g_value_dup_string (value);
break;
case PROP_TITLE:
g_free (self->title);
self->title = g_value_dup_string (value);
break;
case PROP_ORIENTATION:
self->orientation = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
static void file_browser_view_finalize (GObject *object) {
FileBrowserView *self = FILE_BROWSER_VIEW (object);
g_object_unref (self->factory);
g_free (self->icon_name);
g_free (self->title);
G_OBJECT_CLASS (file_browser_view_parent_class)->dispose (object);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
char* filebrowser_get_display_name (GObject* object, GFileInfo* info) {
if (!info)
return NULL;
return g_strdup (g_file_info_get_attribute_string (info, "standard::display-name"));
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
char* filebrowser_get_content_type (GObject* object, GFileInfo* info) {
if (!info)
return NULL;
return g_strdup (g_file_info_get_attribute_string (info, "standard::content-type"));
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
char* filebrowser_get_size (GObject* object, GFileInfo* info) {
if (!info)
return NULL;
return g_format_size (g_file_info_get_attribute_uint64 (info, "standard::size"));
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
GIcon* filebrowser_get_icon (GObject* object, GFileInfo* info) {
GIcon *icon;
if (info)
icon = G_ICON (g_file_info_get_attribute_object (info, "standard::icon"));
else
icon = NULL;
if (icon)
g_object_ref (icon);
return icon;
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
void filebrowser_up_clicked_cb (GtkButton* button, GtkDirectoryList* list) {
GFile *file;
file = g_file_get_parent (gtk_directory_list_get_file (list));
if (file == NULL)
return;
gtk_directory_list_set_file (list, file);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
void filebrowser_view_activated_cb (GtkGridView* view, guint pos, GtkDirectoryList* list) {
GFileInfo *info;
info = g_list_model_get_item (G_LIST_MODEL (gtk_grid_view_get_model (view)), pos);
if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY)
gtk_directory_list_set_file (list, G_FILE (g_file_info_get_attribute_object (info, "standard::file")));
g_object_unref (info);
}
///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////
GtkWidget* do_listview_filebrowser (GtkWidget *do_widget) {
if (!window)
{
GtkWidget *view;
GtkBuilder *builder;
GtkDirectoryList *dirlist;
GFile *file;
char *cwd;
GtkCssProvider *provider;
provider = gtk_css_provider_new ();
gtk_css_provider_load_from_resource (provider, "/org/gtk/mainapp/css/fileBrowser.css");
gtk_style_context_add_provider_for_display (gdk_display_get_default (),
GTK_STYLE_PROVIDER (provider),
800);
g_object_unref (provider);
builder = gtk_builder_new_from_resource ("/org/gtk/mainapp/ui/file-browser.ui");
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
g_signal_connect(window, "clicked", G_CALLBACK(filebrowser_up_clicked_cb), NULL);
g_signal_connect(window, "activate", G_CALLBACK(filebrowser_view_activated_cb), NULL);
gtk_window_set_display (GTK_WINDOW (window),
gtk_widget_get_display (do_widget));
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *) &window);
/* Create the model and fill it with the contents of the current directory */
cwd = g_get_current_dir ();
file = g_file_new_for_path (cwd);
g_free (cwd);
dirlist = GTK_DIRECTORY_LIST (gtk_builder_get_object (builder, "dirlist"));
gtk_directory_list_set_file (dirlist, file);
g_object_unref (file);
/* grab focus in the view */
view = GTK_WIDGET (gtk_builder_get_object (builder, "view"));
gtk_widget_grab_focus (view);
g_object_unref (builder);
}
if (!gtk_widget_get_visible (window))
gtk_widget_show (window);
else
gtk_window_destroy (GTK_WINDOW (window));
return window;
}
file-browser.ui
https://github.com/panchis7u7/Encryption_Algorithms/blob/master/GUI_User_Resource_Manager/ui/file-browser.ui
如果我尝试运行代码,我会得到一个failed to add UI from resource /org/gtk/mainapp/ui/file-browser.ui: .:66:1 Invalid type 'FileBrowserView'
作为一种解决方案,我只是调用该方法以通过该file_browser_view_new()
方法创建一个新的 FileBrowserView,并且可以正常工作,但是随后信号file-browser.ui
不在的位置:failed to add UI from resource /org/gtk/mainapp/ui/file-browser.ui: No function named filebrowser_up_clicked_cb.
有关详细信息,这里是 github 中的项目:https ://github.com/panchis7u7/Encryption_Algorithms/tree/master/GUI_User_Resource_Manager