linux - 使用 vala 将 uris 插入 Gtk.Clipboard

标签 linux gtk uri clipboard vala

我目前正在尝试为我的应用程序实现复制和粘贴,问题是我只能根据 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; 

正如您在上面的终端输出中看到的,它只是重新填充剪贴板,丢弃了之前的值。

最佳答案

根据要求,我提供了将 URI 写入剪贴板和从剪贴板获取 URI 的示例。这些示例基本上是立即获取/设置剪贴板的命令行程序。在实际的 GUI 应用程序中,您可能会对按下按钮使用react,或者捕捉 CtrlC/CtrlV事件,使用 Gtk.Widget.add_events() 并在处理 Gtk.Widget.event 信号时获取/设置剪贴板。

获取剪贴板

您可以使用 Gtk.Clipboard.request_uris () 从 X11 剪贴板请求 URI。此函数接受一个回调,一旦 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 documentation :

Since there is no standard way to copy and paste files between applications on X11, various MIME types and conventions are currently in use. For instance, Nautilus expects files to be supplied with a x-special/gnome-copied-files MIME type with data beginning with the cut/copy action, a newline character, and the URL of the file.

Gtk.Clipboard 没有预先实现设置复制/剪切文件的剪贴板。正如您所说,没有这样的 Gtk.Clipboard.set_uris()

相反,您应该通过提供一个回调来设置剪贴板,以便 X11 在收到请求后从中获取剪贴板内容。

这些是所需的步骤:

  • 创建一组 Gtk.TargetEntry 来指定您的应用可以处理的剪贴板协议(protocol)。您需要处理协议(protocol) text/uri-listx-special/gnome-copied-filesUTF8_STRING。每个 TargetEntry 都由其 info 字段标识,因此该编号应该是唯一的(参见下面示例中的 enum ClipboardProtocol)

  • 实现 Gtk.ClipboardGetFunc 类型的方法。此方法应填充与要复制/剪切的文件路径一起传递的 Gtk.SelectionData 对象。检查 info 参数以根据指定的协议(protocol)设置 SelectionData 参数。

  • 使用 Gtk.Clipboard.set_with_ownerGtk.Clipboard.set_with_data

    将回调和实现的协议(protocol)注册到 X11

示例:

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 源代码中的所有协议(protocol)(请参阅下面的源代码),但它们可能仍需要进行故障排除*

  • 如果您不想亲自执行此操作,您也可以使用 xclip 命令行工具:https://askubuntu.com/a/210428/345569然而,恕我直言,自己实现这个更优雅一些。

来源:

关于linux - 使用 vala 将 uris 插入 Gtk.Clipboard,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50319438/

相关文章:

c++ - Linux 中使用三元运算符从 const char * 到 char * 的无效转换

linux - 从 Linux 命令行连接到远程 DB2

c++ - Linux 中用于 C++ 的 Sublime Build 系统允许从文件输入

GtkWindow 改变时改变 GtkButton 颜色

ruby - 规范化 HTTP URI

android - Intent 未从联系人应用传递

linux - 使用 nccmp 配置失败

gtk style/gtkrc 相关问题

gtk - 获取股票 ID 的图标名称?

xml - 文件 ://. 是有效的 URI吗?