gtk-rs / gtk4-rs

Rust bindings of GTK 4
https://gtk-rs.org/gtk4-rs/
MIT License
1.9k stars 174 forks source link

[HELP] CLI conflicting with gtk #730

Open mcer1 opened 3 years ago

mcer1 commented 3 years ago

When I add any extra arguments (for subcommands for my cli), there is a critical GTK error.

GLib-GIO-CRITICAL **: 20:55:32.443: This application can not open files.

This happens with the basic hello world example from the book. (Even with no command line code the error happens)

use gtk::prelude::*;
use gtk::{Application, ApplicationWindow};

fn main() {
    // Create a new application
    let app = Application::builder()
        .application_id("org.gtk-rs.example")
        .build();

    // Connect to "activate" signal of `app`
    app.connect_activate(build_ui);

    // Run the application
    app.run();
}

fn build_ui(app: &Application) {
    // Create a window and set the title
    let window = ApplicationWindow::builder()
        .application(app)
        .title("My GTK App")
        .build();

    // Present window to the user
    window.present();
}

I did some searching and people say to use the command line signal or using ":handles_command_line" I can't find any way to do this with this API though.

Hofer-Julian commented 3 years ago

You have to run_with_args instead of run when you don't want the application to parse the cli flags. Can you open an issue to mention that in the book?

Hofer-Julian commented 3 years ago

Plus one issue, to mention this in the docs I guess.

jasper-zanjani commented 2 years ago

I have also been running into this problem on my learning journey. As I'm more comfortable with the terminal I was trying to bridge the gap to GTK by creating a parameterized Hello, World!, passing in an argument from the command-line. Providing any arguments to a gtk-rs application naively will cause this error.

I have been able to make some progress but I have not yet found a complete solution:

As far as run_with_args(), it apparently takes an array of strings but the documentation on it is... sparse...

In the implementation below I've tried to provide the boilerplate needed to get an application to run. Something is still missing, but aside from some unused variable warnings there is no explicit error and it exits silently (exit code 0). (By the way this exit code does not appear to have anything to do with the integer returned by the command-line signal handler.)

use gio::ApplicationFlags;
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow};

fn main() {
    let app = Application::builder()
        .application_id("org.gtk-rs.example")
        .flags(ApplicationFlags::HANDLES_COMMAND_LINE)
        .build();
    app.connect_command_line(|app, arg| {
        println!("Handling command-line...");
        0
    });
    app.connect_activate(build_ui);
    app.run();
}

fn build_ui(app: &Application) {
    let window = ApplicationWindow::builder()
        .application(app)
        .title("My GTK App")
        .build();

    window.present();
}

It is troubling that so much cruft is necessary, when implementing the same solution in other bindings like PyGTK is much simpler, although to be fair it is certainly the Python interpreter handling command-line arguments and not trying to use GTK's own arcane inner workings.

I checked in the repo and the only occurrence of the ApplicationFlags struct appears to be here and it is ApplicationFlags::empty().

At the moment documentation depends heavily on the developer already being familiar with the GTK toolkit and API from C programming. I believe implementing even a cursory example of how to integrate command-line arguments would assist novice programmers understand how to navigate this pitfall, and certainly handling filenames passed in from the command-line seems to be something that many GTK programs do as a matter of course.