用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按下
剪贴板get_func调用
收到:file:/// home / marcel / Downloads / .gitignore
CTRL V按下
剪贴板get_func调用
收到:file:/// home / marcel /下载
尝试粘贴:file:/ // home / marcel / Downloads
这是我用于测试的代码 CTRL + V
:
print(\\\
CTRL V pressd\\\
);
clipboard.request_uris((剪贴板,uris)=> {
foreach(uris中的字符串内容){
print(Try Pasting:);
print(content) ;
print(\\\
);
}
});
,这是 get_func
for CTRL + C
:
clipboard.set_with_owner(
clipboard_targets,
(clipboard,selection_data,info,user_data_or_owner)=> {
print(clipboard get_func called \\\
);
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文件){
print(file.get_uri());
print(\ n);
uris + = file.get_uri();
}
selection_data.set_uris(uris);
break;
正如你在上面的终端输出中看到的那样,它只是重新填充剪贴板,扔掉它的前一个值
根据要求,我提供了将URI写入剪贴板并从剪贴板获取URI的示例。这些示例基本上是命令行程序,可立即获取/设置剪贴板。在实际的GUI应用程序中,您可能会对按钮按下或作出反应,以捕获 Ctrl C / Ctrl V 事件中,使用 Gtk.Widget.add_events()
并在处理时获取/设置剪贴板> Gtk.Widget.event
信号。
$ b
获取剪贴板
您可以使用从X11剪贴板请求URI, Gtk.Clipboard.request_uris()
。这个函数接受一个回调函数,一旦URIs可用就会调用它。
例子:
public void main(string [] args){
Gtk.init(ref args);
Gdk.Display display = Gdk.Display.get_default();
Gtk.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剪贴板,字符串[] uris){
foreach(uri中的var uri) {
print(uri +\\\
);
}
Gtk.main_quit();
}
用 valac clipget.vala进行编译 - pkg = gtk + -3.0
设定剪贴板
理论:
由于在X11上的
应用程序之间没有标准的复制和粘贴文件的方法,因此各种MIME类型和约定目前使用的是
。例如,Nautilus预计文件将以
x-special / gnome-copied-files MIME类型提供,数据以
cut / copy操作开头,换行符和文件的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参数。 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剪贴板= 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剪贴板,
Gtk.SelectionData selection_data,
uint info,
void * user_data_or_owner
){
print(GET FUNC!\\\
);
文件my_file = File.new_for_path(/home/lukas/tmp/test.txt);
文件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文件){
uris + = file.get_uri();
}
selection_data.set_uris(uris);
休息;
案例ClipboardProtocol.GNOME_COPIED_FILES:
var prefix =copy\\\
;
// var prefix =cut\\\
;
/ *使用上面的一个* /
var builder = new StringBuilder(prefix);
for(int i = 0; i< files.length; i ++){
builder.append(files [i] .get_uri());
/ *如果这是最后一个文件,不要放入换行符* /
if(i!= files.length - 1)
builder.append_c('\\\
');
}
selection_data.set(
selection_data.get_target(),
8,
builder.data
);
休息;
案例ClipboardProtocol.UTF8_STRING:
var builder = new StringBuilder();
foreach(文件中的var文件){
builder.append(file.get_parse_name());
}
builder.append_c('\\\
');
selection_data.set_text(builder.str,-1);
休息;
默认值:
assert_not_reached();
}
Gtk.main_quit();
}
/ * Gtk.ClipboardClearFunc * /
private void clear_func(Gtk.Clipboard剪贴板,void * 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剪贴板= 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剪贴板,
Gtk.SelectionData selection_data,
uint info,
void * user_data_or_owner
){
print(GET FUNC!\\\
);
文件my_file = File.new_for_path(/home/lukas/tmp/test.txt);
文件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文件){
uris + = file.get_uri();
}
selection_data.set_uris(uris);
休息;
案例ClipboardProtocol.GNOME_COPIED_FILES:
var prefix =copy\\\
;
// var prefix =cut\\\
;
/ *使用上面的一个* /
var builder = new StringBuilder(prefix);
for(int i = 0; i< files.length; i ++){
builder.append(files [i] .get_uri());
/ *如果这是最后一个文件,不要放入换行符* /
if(i!= files.length - 1)
builder.append_c('\\\
');
}
selection_data.set(
selection_data.get_target(),
8,
builder.data
);
休息;
案例ClipboardProtocol.UTF8_STRING:
var builder = new StringBuilder();
foreach(文件中的var文件){
builder.append(file.get_parse_name());
}
builder.append_c('\\\
');
selection_data.set_text(builder.str,-1);
休息;
默认值:
assert_not_reached();
}
Gtk.main_quit();
}
/ * Gtk.ClipboardClearFunc * /
private void clear_func(Gtk.Clipboard剪贴板,void * data){
;
}
编译时使用 在我的示例中,我只能测试 I am currently trying to implement copy and paste for my application, the problem is that i can only plaintext or images to the clipboard according to the documentation of But then there is also this method https://valadoc.org/gtk+-3.0/Gtk.Clipboard.set_with_data.html UPDATE Using the given answer i can fill the clipboard with an array of uris, but i can read them, when i try it just calls the This is the code i use for testing and this is the relevant part of the As you can see in the terminal output above, it just refills the clipboard, throwing away its previous values. 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 You can request URIs from the X11 clipboard using Example: To be compiled with From the 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. Instead, you should set the clipboard by providing a callback that X11 gets the clipboard contents from once requested. These are the steps required: Create a bunch of Implement a method of the type Register the callback and the protocols implemented to X11 using valac clipset.vala - pkg = gtk + -3.0
$ b x-special / gnome-copied-files
,因为我目前只安装了Nautilus。我修改了Thunar源代码中的所有协议(请参阅下面的源代码),但它们可能仍然需要排除故障*
$ b
Gtk.Clipboard
: https://valadoc.org/gtk+-3.0/Gtk.Clipboard.html set_text
/ set_image
.set_with_data
, which i think i can use for adding a uri or an array of uris. But i can't figure out how and didn't find any good examples either.get_func
again and refills it.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;
Gtk.Widget.add_events()
and get / set the clipboard when handling the Gtk.Widget.event
signal.Getting the clipboard
Gtk.Clipboard.request_uris ()
. This function takes a callback that will be called once the URIs are available.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
Setting the clipboard
Theory:
Gtk.Clipboard
does not pre-implement setting the clipboard for copying / cutting files. As you said, there is no such Gtk.Clipboard.set_uris()
.
Gtk.TargetEntry
s that specify what clipboard protocols your app can handle. You'll want to handle the protocolstext/uri-list
, x-special/gnome-copied-files
and UTF8_STRING
. Each TargetEntry
is identified by its info
field, so that number should be unique (see enum ClipboardProtocol
in the example below)Gtk.ClipboardGetFunc
. This method should fill the Gtk.SelectionData
object that is passed with the file paths to copy / cut. Check for the info
parameter to set the SelectionData argument according to the protocol specified.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) {
;
}
To be compiled with valac clipset.vala --pkg=gtk+-3.0
A couple of notes:
In my example, I could only test
x-special/gnome-copied-files
since I only have Nautilus installed at the moment. I adapted all of the protocols from the Thunar source code (see sources below) but they might still require troubleshooting*If you do not want to go through the trouble of implementing this yourself, you could also use the xclip command line tool: https://askubuntu.com/a/210428/345569 However, IMHO implementing this yourself is a little more elegant.
Sources:
- Article from the Ubuntu Forums: https://ubuntuforums.org/archive/index.php/t-2135919.html
- Thunar source code (especially thunar/thunar/thunar-clipboard-manager.c): https://github.com/xfce-mirror/thunar/blob/3de231d2dec33ca48b73391386d442231baace3e/thunar/thunar-clipboard-manager.c
- Qt4 documentation: http://doc.qt.io/archives/qt-4.8/qclipboard.html
这篇关于用vala将uris插入Gtk.Clipboard的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!