GTK_RS: Processing command line arguments

Hi everyone!

I am new to rust and GTK. I am playing around with GTK-RS and wanna pass command line arguments into my app. If I would use any application in the example and will run app like “cargo run arg1 arg2” I will get an error:

GLib-GIO-CRITICAL **: 20:50:32.701: This application can not open files.

If I would run the app with “HANDLES_COMMAND_LINE” like so:

let app = gtk::Application::new(
Some(“com.github.gtk-rs.examples.basic”),
ApplicationFlags::HANDLES_COMMAND_LINE
);

And hear I would get another error:

Your application claims to support custom command line handling but does not implement g_application_command_line() and has no handlers connected to the ‘command-line’ signal.

At this point, I am stuck, because all examples I found are leading C examples which I am struggling to transform into runnable rust code.

Can anyone help with some code snippet?

Thanks!

I am not good at all in Rust, but I can show you a way in C:

#include <gtk/gtk.h>

static void startup_clbk ( GApplication *application )
{
    g_return_if_fail ( G_IS_APPLICATION ( application ) );

    /// ***
    g_print ( "Start_Up function Called.\n" );
}

static gint command_line_clbk ( GApplication *application,
                                GApplicationCommandLine *cmdline )
{
    g_return_val_if_fail ( G_IS_APPLICATION ( application ), 0 );

    /// ***
    GVariantDict *options;
    const gchar *app_activate = NULL;
    const gchar *const opt = "start";

    /// ***
    options = g_application_command_line_get_options_dict ( cmdline );

    /// ***
    g_variant_dict_lookup ( options, "activate", "&s", &app_activate );

    /// ***
    if ( app_activate && g_ascii_strcasecmp ( app_activate, opt ) == 0  )
    {
        g_print ( "Command_Line function Called.\n" );
        g_application_hold ( application );

        /// ***
        return 0;
    }

    /// ***
    g_print ( "\n\tType ./%s -h for more\n", g_get_prgname() );

    return 1;
}

static int local_options_clbk ( GApplication *application,
                                GVariantDict *options )
{
    g_return_val_if_fail ( G_IS_APPLICATION ( application ), 0 );
    gboolean version = FALSE;

    g_variant_dict_lookup ( options, "version", "b", &version );

    if ( version )
    {
        const gchar *const app_version = "1.0.0";
        const guint major_version = gtk_get_major_version ();
        const guint minor_version = gtk_get_minor_version ();
        const guint micro_version = gtk_get_micro_version ();

        /// ***
        g_print ( "\n\tLocal_Options function Called:\n" );

        /// ***
        g_print ( "APP-Version: %s\n", app_version );
        g_print ( "GTK-Version: %d.%d.%d\n", major_version, minor_version, micro_version );
        g_print ( "GCC-Version: %d.%d\n\n", __GNUC__, __GNUC_MINOR__ );
        return 0;
    }

    return -1;
}

static const GOptionEntry options[] =
{
    /// *** Version
    {
        "version", 'v',
        G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE,
        NULL, "The program version", NULL
    },

    /// *** Activate
    {
        "activate", 'a',
        G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING,
        NULL, "Activate should take place", "START"
    },

    { NULL }
};

gint main ( int argc, char **argv )
{
    GApplication *application;
    gint status;

    /// ***
    application = g_application_new ( "my.gtk.app", G_APPLICATION_HANDLES_COMMAND_LINE );

    /// ***
    g_application_register ( application, NULL, NULL );

    /// ***
    ///g_application_add_main_option ( G_APPLICATION ( application ), "version",  0, G_OPTION_FLAG_NONE, G_OPTION_FLAG_NONE,   "The program version",            NULL );

    /// ***
    ///g_application_add_main_option ( G_APPLICATION ( application ), "activate", 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, "Activate should not take place", "START" );

    /// ***
    g_application_add_main_option_entries ( application, options );

    /// ***
    g_signal_connect_swapped ( application, "startup",  G_CALLBACK ( startup_clbk ),  application );

    /// ***
    g_signal_connect_swapped ( application, "command-line",         G_CALLBACK ( command_line_clbk ),  application );
    g_signal_connect_swapped ( application, "handle-local-options", G_CALLBACK ( local_options_clbk ), application );

    /// ***
    status = g_application_run ( application, argc, argv );

    /// ***
    g_object_unref ( application );

    /// ***
    return status;
}

Thanks, @MichiB ! I will try to project it into Rust. Not good with it as well, but will become a great exercise :slight_smile:

1 Like