0

为了获得上下文,我正在制作一个 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;
}

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

窗口.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

4

0 回答 0