使用 vala 将 uris 插入 Gtk.Clipboard

2024-03-26

我目前正在尝试为我的应用程序实现复制和粘贴,问题是我只能根据文档将纯文本或图像复制到剪贴板Gtk.Clipboard: https://valadoc.org/gtk+-3.0/Gtk.Clipboard.html 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 https://valadoc.org/gtk+-3.0/Gtk.Clipboard.set_with_data.html set_with_data,我想我可以用它来添加 uri 或 uri 数组。但我不知道如何做,也没有找到任何好的例子。

UPDATE

使用给定的答案,我可以用 uri 数组填充剪贴板,但我可以读取它们,当我尝试时,它只会调用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 for 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; 

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


As requested I am providing both an example for writing URIs to clipboard and getting URIs from clipboard. These examples are basically command line programs that get / set the clipboard immediately. In an actual GUI application you would probably react to a button press or, to catch CtrlC / CtrlV events, use Gtk.Widget.add_events() and get / set the clipboard when handling the Gtk.Widget.event signal.

获取剪贴板

您可以使用以下命令从 X11 剪贴板请求 URIGtk.Clipboard.request_uris ()。此函数采用回调,一旦 URI 可用,就会调用该回调。

Example:

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

设置剪贴板

Theory:

来自Qt4 文档 http://doc.qt.io/archives/qt-4.8/qclipboard.html:

由于没有标准方法可以在之间复制和粘贴文件 X11 上的应用程序,目前有各种 MIME 类型和约定 正在使用。例如,Nautilus 希望提供的文件带有 x-special/gnome-copied-files MIME 类型,数据以 剪切/复制操作、换行符和文件的 URL。

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

相反,您应该通过提供回调来设置剪贴板,X11 在收到请求后即可获取剪贴板内容。

这些是所需的步骤:

  • 创建一堆Gtk.TargetEntry指定您的应用程序可以处理哪些剪贴板协议。你需要处理协议text/uri-list, x-special/gnome-copied-files and UTF8_STRING. Each TargetEntry由其标识info字段,因此该数字应该是唯一的(请参阅enum ClipboardProtocol在下面的例子中)

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

  • 使用以下命令注册回调和 X11 实现的协议Gtk.Clipboard.set_with_owner or Gtk.Clipboard.set_with_data

Example:

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 https://askubuntu.com/a/210428/345569然而,恕我直言,你自己实现这个会更优雅一些。

Sources:

  • 来自 Ubuntu 论坛的文章:https://ubuntuforums.org/archive/index.php/t-2135919.html https://ubuntuforums.org/archive/index.php/t-2135919.html
  • Thunar 源代码(特别是 thunar/thunar/thunar-clipboard-manager.c):https://github.com/xfce-mirror/thunar/blob/3de231d2dec33ca48b73391386d442231baace3e/thunar/thunar-clipboard-manager.c https://github.com/xfce-mirror/thunar/blob/3de231d2dec33ca48b73391386d442231baace3e/thunar/thunar-clipboard-manager.c
  • Qt4文档:http://doc.qt.io/archives/qt-4.8/qclipboard.html http://doc.qt.io/archives/qt-4.8/qclipboard.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 vala 将 uris 插入 Gtk.Clipboard 的相关文章

  • 包名中的“dev”后缀?

    使用 apt get 时 我看到一些软件包的名称后面有一个 dev 后缀 libreadline5 libreadline dev zlib1g zlib1g dev 这些到底是什么 我应该安装它们吗 你需要这些编译并链接因为它们提供了要链
  • 执行bash脚本时如何显示行号

    我有一个测试脚本 其中有很多命令并将生成大量输出 我使用set x or set v and set e 因此当发生错误时脚本将停止 但我还是很难定位到哪一行执行停止了 从而定位问题所在 有没有一种方法可以在每行执行之前输出脚本的行号 或者
  • 为什么我们可以将 sockaddr 转换为 sockaddr_in

    我明白为什么强制转换很有用sockaddr to sockaddr in 但我不明白这怎么可能 据我所知 它们的大小相同sockaddr in添加了sin zero使其大小相同 我想知道编译器如何知道从哪里获取信息sockaddr in如果
  • 请求失败的错误:GLXBadDrawable (C++ bgfx)

    我试图用 glfw 和 bgfx 创建一个紫色窗口作为我的游戏引擎的起点 但是在启动二进制文件时它会抛出一个错误 我正在尝试创建紫色窗口 如下图所示 我正在使用 cmake 错误是 anuj fedora D C C c o build g
  • 当非特权用户运行 C/asm 程序时,会对 Linux 造成什么危害?

    我一直在考虑一种场景 让用户 可以是任何人 可能有恶意 提交在 Linux PC 我们称之为基准节点 上运行的代码 目标是为单线程例程创建一种自动化基准测试环境 假设一个网站向代理发布了一些代码 该代理将此代码交给基准节点 而基准节点仅与代
  • 删除损坏的链接 Unix

    我想删除损坏的链接 但在此之前我想确认目录中是否存在链接文件 我们来调用一下链接A if a A then print ya A is ther fi But if A链接已损坏 那么我该如何检查 find L type l找到损坏的符号链
  • 来自外部 .diff 文件的交互式补丁

    Linux 是否有命令或程序允许交互式地修补源代码 在屏幕上打印每个块并在将其应用到文件之前等待确认 就像是git add p 但是从另一个 diff 文件中进行更改 您始终可以在 shell ruby python 中编写脚本 逐行读取该
  • accept() 创建一个新套接字是什么意思?

    我的问题基于以下理解 套接字由 ip port 定义 服务器和客户端都有自己的套接字 Socket连接由五组server ip server port client ip client port protocol定义 套接字描述符是标识套接
  • find 命令的“exec”功能可以在后台启动程序吗?

    我想做这样的事情 find iname Advanced Linux Program exec kpdf 可能的 还有其他类似的方法吗 首先 它不会像你输入的那样工作 因为 shell 会将其解释为 find iname Advanced
  • 如何在 Docker 容器中运行 Nginx 而不停止?

    我在 Docker 容器上安装了 Nginx 并尝试像这样运行它 docker run i t p 80 80 mydockerimage usr sbin nginx 问题是 Nginx 的工作方式是 初始进程立即生成一个 Nginx 主
  • 堆内存和Slab分配

    我很困惑heap and free list 我有几个问题 我对C中malloc的工作原理有自己的理解 如果我错了 请纠正我 堆内存是否被组织为数据的链表 空闲列表 块 堆内存和空闲列表有区别吗 我对存储分配的理解 有待改进 当我们调用ma
  • linux命令行:如何简单地将任意字符串输入管道?

    我正在寻找一个非常简单的技巧 假设文件中error txt 有一个很长的字符串 errorMessage key1 some message key2 message 2 由于它的格式不适合读者 如果我想在终端中以格式良好的形式查看它 我可
  • 如何获得 GTK 中的默认颜色?

    Context 在 GTK 3 中 人们可以设置自己的主题 甚至默认主题 Adwaita 也提供两种变体 浅色和深色 当我编写自己的小部件 用Python 时 我需要获取这些颜色以避免在黑色上绘制黑色或在白色上绘制白色 Question 如
  • 如何在 C++ 中检查文件是否已被另一个应用程序打开?

    我知道 有is open C 中的函数 但我希望一个程序检查文件是否尚未被另一个应用程序打开 有没有办法使用标准库来做到这一点 编辑 在答案中澄清这是针对 Linux 应用程序的 不仅标准库没有这个功能 一般来说也是不可能的 你可以 在li
  • 如何检查程序是否在 Windows 上的 Ubuntu 上的 Bash 中运行,而不仅仅是普通的 Ubuntu?

    非常简单 确定您所使用的操作系统的通常位置似乎与 Ubuntu for Windows 上的普通 Ubuntu 相同 例如uname a与本机 GNU Linux 安装相同并且 etc os version与 Ubuntu Trusty T
  • 自动将 Linux 文件名重命名为 Windows 中合法的新文件名

    我想将 linux 文件重命名为在 windows 中合法的文件名 它的长度不应超过允许的长度 并且不应包含 Windows 中不允许的字符 有时我将论文的标题复制到文件名 它们有特殊字符 例如 or 另外 从 pdf 中复制和粘贴标题时
  • 如何在 Amazon Linux 上安装最新版本的 GDAL?

    我想安装GDAL https gdal org 在运行 Amazon Linux 的 EC2 实例上 我认为它基于 RHEL 6 如果可能的话 我想避免从源代码编译 EPEL Yum 存储库中包含的 GDAL 版本对于我的目的来说太旧了 g
  • 将静态链接的 elf 二进制文件转换为动态链接的

    我有一个 elf 二进制文件 它已静态链接到 libc 我无权访问其 C 代码 我想使用 OpenOnload 库 它在用户空间中实现了套接字 因此与标准 libc 版本相比提供了更低的延迟 OpenOnload 实现标准套接字 api 并
  • 如何有效地将许多文件移动到新服务器?

    我正在更换托管提供商 需要将数百万个上传的文件传输到新服务器 所有文件都位于同一目录中 是的 你读对了 过去我这样做过 压缩源服务器中的所有文件 scp到新服务器的 zip Unzip Move directory to appropria
  • 将文件夹中结构化的预构建文件集添加到 android out 文件夹

    我为arm编译了glibc 这与Android glibc或bionic C不同 因为我编译的glibc环境将有助于提供更多api 现在我可以在 Android 运行时将 glibc 环境复制到 system 文件夹中 并且在执行 chro

随机推荐