用vala将uris插入Gtk.Clipboard [英] Inserting uris into Gtk.Clipboard with vala

查看:115
本文介绍了用vala将uris插入Gtk.Clipboard的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



设定剪贴板



理论:



Qt4文档 a>:
$ b


由于在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

    实现给X11的协议。 li>


示例:

  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){
;
}

编译时使用 valac clipset.vala - pkg = gtk + -3.0




$ b

  • 在我的示例中,我只能测试 x-special / gnome-copied-files ,因为我目前只安装了Nautilus。我修改了Thunar源代码中的所有协议(请参阅下面的源代码),但它们可能仍然需要排除故障*

  • 如果您不想通过您自己也可以使用xclip命令行工具:
    https://askubuntu.com/a/210428/345569 然而,恕我直言,你自己实现这一点更加优雅。
    $ b

    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 Gtk.Clipboard: https://valadoc.org/gtk+-3.0/Gtk.Clipboard.html set_text / set_image.

    But then there is also this method https://valadoc.org/gtk+-3.0/Gtk.Clipboard.set_with_data.html 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.

    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 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
    

    This is the code i use for testing CTRL + V:

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

    and this is the relevant part of the 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 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 Gtk.Widget.add_events() and get / set the clipboard when handling the Gtk.Widget.event signal.

    Getting the clipboard

    You can request URIs from the X11 clipboard using Gtk.Clipboard.request_uris (). This function takes a callback that will be called once the URIs are available.

    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 ();
    }
    

    To be compiled with valac clipget.vala --pkg=gtk+-3.0

    Setting the clipboard

    Theory:

    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.

    Gtk.Clipboard does not pre-implement setting the clipboard for copying / cutting files. As you said, there is no such Gtk.Clipboard.set_uris().

    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 Gtk.TargetEntrys 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)

    • Implement a method of the type 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.

    • Register the callback and the protocols implemented to X11 using 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:

    这篇关于用vala将uris插入Gtk.Clipboard的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆