如何加载 GTK4 演示示例? 专门的文件浏览器

问题描述

为了了解上下文,我正在制作一个 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,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,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,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,gpointer app){
  g_application_quit (G_APPLICATION (app));
}

static GActionEntry app_entries[] = {
  { "preferences",preferences_activated,NULL,NULL },{ "quit",quit_activated,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),commandEntry);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class),btnCommandSubmit);
  gtk_widget_class_bind_template_child (GTK_WIDGET_CLASS (class),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,&contents,&length,NULL))
    {
      gtk_text_buffer_set_text (buffer,contents,length);
      g_free (contents);
    }

  tag = gtk_text_buffer_create_tag (buffer,NULL);
  g_settings_bind (window->settings,"font",tag,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,&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,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,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",G_ParaM_READWRITE);
  properties[PROP_TITLE] =
    g_param_spec_string ("title","title","title to display for selecting this view",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,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,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,"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,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;
}

window.ui https://github.com/panchis7u7/Encryption_Algorithms/blob/master/GUI_User_Resource_Manager/ui/window.ui

file-browser.ui https://github.com/panchis7u7/Encryption_Algorithms/blob/master/GUI_User_Resource_Manager/ui/file-browser.ui

window.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.

Signals not found and new file browser

更多细节,这里是github中的项目:https://github.com/panchis7u7/Encryption_Algorithms/tree/master/GUI_User_Resource_Manager

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)