使用 vala 将 uris 插入 Gtk.Clipboard
Inserting uris into Gtk.Clipboard with 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 应用程序中,您可能会对按下按钮做出反应,或者捕捉 CtrlC / CtrlV事件,在处理Gtk.Widget.event
信号时使用Gtk.Widget.add_events()
并获取/设置剪贴板。
获取剪贴板
您可以使用 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
一起编译
设置剪贴板
理论:
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
来指定您的应用可以处理的剪贴板协议。您需要处理协议 text/uri-list
、x-special/gnome-copied-files
和 UTF8_STRING
。每个 TargetEntry
由其 info
字段标识,因此该数字应该是唯一的(参见下面示例中的 enum ClipboardProtocol
)
实现 Gtk.ClipboardGetFunc
类型的方法。此方法应填充与要复制/剪切的文件路径一起传递的 Gtk.SelectionData
对象。检查 info
参数以根据指定的协议设置 SelectionData 参数。
使用Gtk.Clipboard.set_with_owner
或Gtk.Clipboard.set_with_data
将回调和实现的协议注册到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 源代码中的所有协议(请参阅下面的源代码),但它们可能仍需要进行故障排除*
如果你不想自己实现这个麻烦,你也可以使用 xclip 命令行工具:https://askubuntu.com/a/210428/345569但是,恕我直言,自己实现这个有点多优雅.
来源:
- 来自 Ubuntu 论坛的文章: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
- Qt4 文档:http://doc.qt.io/archives/qt-4.8/qclipboard.html
我目前正在尝试为我的应用程序实现复制和粘贴,问题是我只能根据 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 应用程序中,您可能会对按下按钮做出反应,或者捕捉 CtrlC / CtrlV事件,在处理Gtk.Widget.event
信号时使用Gtk.Widget.add_events()
并获取/设置剪贴板。
获取剪贴板
您可以使用 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
设置剪贴板
理论:
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
来指定您的应用可以处理的剪贴板协议。您需要处理协议text/uri-list
、x-special/gnome-copied-files
和UTF8_STRING
。每个TargetEntry
由其info
字段标识,因此该数字应该是唯一的(参见下面示例中的enum ClipboardProtocol
)实现
Gtk.ClipboardGetFunc
类型的方法。此方法应填充与要复制/剪切的文件路径一起传递的Gtk.SelectionData
对象。检查info
参数以根据指定的协议设置 SelectionData 参数。使用
Gtk.Clipboard.set_with_owner
或Gtk.Clipboard.set_with_data
将回调和实现的协议注册到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 源代码中的所有协议(请参阅下面的源代码),但它们可能仍需要进行故障排除*如果你不想自己实现这个麻烦,你也可以使用 xclip 命令行工具:https://askubuntu.com/a/210428/345569但是,恕我直言,自己实现这个有点多优雅.
来源:
- 来自 Ubuntu 论坛的文章: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
- Qt4 文档:http://doc.qt.io/archives/qt-4.8/qclipboard.html