Обрабатывать файлы, переданные в качестве аргументов в командной строке в Gjs Gtk.Application

Я пытаюсь написать приложение GNOME GTK3, используя Gjs, который обрабатывает файлы, передаваемые в качестве аргументов командной строки. Для этого я подключаю сигнал open Gtk.Application и устанавливаю флаг Gio.ApplicationFlags.HANDLES_OPEN:

#!/usr/bin/gjs

const Gio = imports.gi.Gio
const Gtk = imports.gi.Gtk
const Lang = imports.lang

const MyApplication = new Lang.Class({
  Name: 'MyApplication',

  _init: function() {
    this.application = new Gtk.Application({
      application_id: 'com.example.my-application',
      flags: Gio.ApplicationFlags.HANDLES_OPEN
    })

    this.application.connect('startup', this._onStartup.bind(this))
    this.application.connect('open', this._onOpen.bind(this))
    this.application.connect('activate', this._onActivate.bind(this))
  },

  _onStartup: function() {
    log('starting application')
  },

  _onOpen: function(application, files) {
    log('opening ' + files.length + ' files')
    this._onStartup()
  },

  _onActivate: function() {
    log('activating application')
  }
})

let app = new MyApplication()
app.application.run(ARGV)

Когда я запускаю программу с файловым аргументом, я ожидаю, что _onOpen будет вызываться с переданным GFile. Но вместо этого вызывается _onActivate, как если бы я запускал ее без каких-либо файловых аргументов:

$ ./open-files.js open-files.js 
Gjs-Message: JS LOG: starting application
Gjs-Message: JS LOG: activating application

Я использую [email protected].


person Johannes J. Schmidt    schedule 03.02.2016    source источник


Ответы (1)


Существует несоответствие в том, как определяется ARGV GJS, по сравнению с соглашениями на других языках. Например, в C argv[0] — это имя программы, а первый аргумент начинается с argv[1]. В GJS имя программы — System.programInvocationName, а первый аргумент — ARGV[0].

К сожалению, будучи частью библиотеки C, Gtk.Application требует от вас передачи аргументов в соответствии с соглашением C. Ты можешь это сделать:

ARGV.unshift(System.programInvocationName);

Происходило то, что ./open-files.js open-files.js помещал ['open-files.js'] как ARGV, что Gtk.Application интерпретировал как имя программы без каких-либо других аргументов. Если бы вы запустили программу с двумя файловыми аргументами, то увидели бы, что она «открыла» только второй файл.

PS. К сожалению, похоже, что в GJS 1.44 есть ошибка, которая мешает правильной работе сигнала open. На данный момент я бы предложил обойти проблему, создав подкласс Gtk.Application вместо его проксирования. Ваша программа будет выглядеть так:

const Gio = imports.gi.Gio
const Gtk = imports.gi.Gtk
const Lang = imports.lang
const System = imports.system

const MyApplication = new Lang.Class({
  Name: 'MyApplication',
  Extends: Gtk.Application,

  _init: function(props={}) {
    this.parent(props)
  },

  vfunc_startup: function() {
    log('starting application')
    this.parent()
  },

  vfunc_open: function(files, hint) {
    log('opening ' + files.length + ' files')
  },

  vfunc_activate: function() {
    log('activating application')
    this.parent()
  }
})

let app = new MyApplication({
  application_id: 'com.example.my-application',
  flags: Gio.ApplicationFlags.HANDLES_OPEN
})
ARGV.unshift(System.programInvocationName)
app.run(ARGV)
person ptomato    schedule 06.02.2016