Вставка мочи в Gtk.Clipboard с Vala - PullRequest
0 голосов
/ 13 мая 2018

Я сейчас пытаюсь реализовать копирование и вставку для моего приложения, проблема в том, что я могу только текст или изображения в буфер обмена в соответствии с документацией Gtk.Clipboard: https://valadoc.org/gtk+-3.0/Gtk.Clipboard.html set_text / set_image.

Но есть и такой метод https://valadoc.org/gtk+-3.0/Gtk.Clipboard.set_with_data.html set_with_data, который, я думаю, я могу использовать для добавления URI или массива Uris.Но я не могу понять, как и не нашел хороших примеров.

ОБНОВЛЕНИЕ

Используя данный ответ, я могу заполнить буфер обмена массивомUris, но я могу их прочитать, когда я пытаюсь, он просто снова вызывает get_func и заполняет его.

CTRL C pressed
clipboard get_func called
Received: file:///home/marcel/Downloads/.gitignore

CTRL V pressd
clipboard get_func called
Received: file:///home/marcel/Downloads
Try Pasting: file:///home/marcel/Downloads

Это код, который я использую для тестирования CTRL + V:

print ("\nCTRL V pressd\n");
clipboard.request_uris ((clipboard, uris) => {
    foreach ( string content in uris ) {
        print ("Try Pasting: ");
        print (content);
        print ("\n");
    }
});

и это соответствующая часть get_func для CTRL + C:

clipboard.set_with_owner (
    clipboard_targets,
    (clipboard, selection_data, info, user_data_or_owner) => {
    print ("clipboard get_func called\n");
    var w = user_data_or_owner as Window;
    File[] files = { w.get_selected_file () };

    switch ( info ) {
        case ClipboardProtocol.TEXT_URI_LIST:
            print ("Received: ");
            string[] uris = {};
            foreach ( var file in files ) {
                print (file.get_uri ());
                print ("\n");
                uris += file.get_uri ();
            }
            selection_data.set_uris (uris);
            break; 

Как видно из вывода терминала выше, он просто пополняет буфер обмена, отбрасывая его предыдущие значения.

1 Ответ

0 голосов
/ 13 мая 2018

По запросу я предоставляю пример записи URI в буфер обмена и получения URI из буфера обмена.Эти примеры в основном программы командной строки, которые сразу же получают / устанавливают буфер обмена.В реальном приложении с графическим интерфейсом вы, вероятно, отреагируете на нажатие кнопки или, чтобы поймать Ctrl C / Ctrl V события, используйте Gtk.Widget.add_events() и получить / установить буфер обмена при обработке сигнала Gtk.Widget.event.

Получение буфера обмена

Вы можете запросить URI из буфера обмена X11, используя Gtk.Clipboard.request_uris ().Эта функция принимает обратный вызов, который будет вызываться после того, как станут доступны URI.

Пример:

public void main (string[] args) {
    Gtk.init (ref args);

    Gdk.Display display = Gdk.Display.get_default ();
    Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);

    clipboard.request_uris (recieved_func);
    Gtk.main ();
}

/* Gtk.ClipboardURIRecievedFunc */
private void recieved_func (Gtk.Clipboard clipboard, string[] uris) {
    foreach (var uri in uris) {
        print (uri + "\n");
    }
    Gtk.main_quit ();
}

Для компиляции с valac clipget.vala --pkg=gtk+-3.0

Настройка буфера обмена

Теория:

Из документации Qt4 :

Поскольку не существует стандартного способа копирования и вставки файлов между приложениями на X11, различные MIMEтипы и соглашения в настоящее время используются.Например, Nautilus ожидает, что файлы будут снабжены MIME-типом x-special / gnome-copied-files с данными, начинающимися с действия вырезания / копирования, символом новой строки и URL-адресом файла.

Gtk.Clipboard не предусматривает предварительную настройку буфера обмена для копирования / вырезания файлов.Как вы сказали, такого Gtk.Clipboard.set_uris().

нет. Вместо этого вы должны установить буфер обмена, предоставив обратный вызов, чтобы X11 получал содержимое буфера обмена после запроса.

Это необходимые шаги:

  • Создайте группу Gtk.TargetEntry s, которые определяют, какие протоколы буфера обмена могут обрабатывать ваше приложение.Вы захотите обработать протоколы text/uri-list, x-special/gnome-copied-files и UTF8_STRING.Каждый TargetEntry идентифицируется своим полем info, поэтому номер должен быть уникальным (см. enum ClipboardProtocol в приведенном ниже примере)

  • Реализуйте метод типа Gtk.ClipboardGetFunc,Этот метод должен заполнить объект Gtk.SelectionData, который передается путями файла для копирования / вырезания.Проверьте параметр info для установки аргумента SelectionData в соответствии с указанным протоколом.

  • Зарегистрируйте обратный вызов и протоколы, реализованные для X11, используя Gtk.Clipboard.set_with_owner или Gtk.Clipboard.set_with_data

Пример:

enum ClipboardProtocol {
    TEXT_URI_LIST,
    GNOME_COPIED_FILES,
    UTF8_STRING
}

public void main (string[] args) {
    Gtk.init (ref args);

    Gdk.Display display = Gdk.Display.get_default ();
    Gtk.Clipboard clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);

    var clipboard_targets = new Gtk.TargetEntry[3];

    Gtk.TargetEntry target_entry = { "text/uri-list", 0, ClipboardProtocol.TEXT_URI_LIST };
    clipboard_targets[0] = target_entry;

    target_entry = { "x-special/gnome-copied-files", 0, ClipboardProtocol.GNOME_COPIED_FILES };
    clipboard_targets[1] = target_entry;

    target_entry = { "UTF8_STRING", 0, ClipboardProtocol.UTF8_STRING };
    clipboard_targets[2] = target_entry;

    var owner = new Object ();

    var rc = clipboard.set_with_owner (
        clipboard_targets,
        get_func,
        clear_func,
        owner
    );
    assert (rc);
    clipboard.store ();

    Gtk.main ();
}

/* Gtk.ClipboardGetFunc */
private void get_func (
    Gtk.Clipboard clipboard,
    Gtk.SelectionData selection_data,
    uint info, 
    void* user_data_or_owner
) {
    print ("GET FUNC!\n");

    File my_file = File.new_for_path ("/home/lukas/tmp/test.txt");
    File my_2nd_file = File.new_for_path ("/home/lukas/tmp/test2.txt");
    File[] files = { my_file, my_2nd_file };

    switch (info) {
        case ClipboardProtocol.TEXT_URI_LIST:
            string[] uris = {};
            foreach (var file in files) {
                uris += file.get_uri ();
            }
            selection_data.set_uris (uris);
            break;

        case ClipboardProtocol.GNOME_COPIED_FILES:
            var prefix = "copy\n"; 
            //var prefix = "cut\n";
            /* use one of the above */

            var builder = new StringBuilder (prefix);
            for (int i = 0; i < files.length; i++) {
                builder.append (files[i].get_uri ()); 
                /* dont put the newline if this is the last file */
                if (i != files.length - 1)
                    builder.append_c ('\n');
            }
            selection_data.set (
                selection_data.get_target (),
                8,
                builder.data
            );
            break;

        case ClipboardProtocol.UTF8_STRING:
            var builder = new StringBuilder ();
            foreach (var file in files) {
                builder.append (file.get_parse_name ());
            }
            builder.append_c ('\n');
            selection_data.set_text (builder.str, -1);
            break;
        default:
            assert_not_reached ();
    }
    Gtk.main_quit ();
}

/* Gtk.ClipboardClearFunc */
private void clear_func (Gtk.Clipboard clipboard, void* data) {
    ;
}

Для компиляции с valac clipset.vala --pkg=gtk+-3.0

Пара примечаний:

  • В моем примере я мог только протестировать x-special/gnome-copied-files, так как на данный момент у меня установлен только Nautilus.Я адаптировал все протоколы из исходного кода Thunar (см. Источники ниже), но они могут по-прежнему требовать устранения неполадок *

  • Если вы не хотите испытывать проблемы с реализацией этого самостоятельно,Вы также можете использовать инструмент командной строки xclip: https://askubuntu.com/a/210428/345569 Однако, IMHO, реализующий это самостоятельно, немного элегантнее.

Источники:

...