如何制作一个可拖动的 GTK 小部件,将文件放到其他程序中

Tyi*_*ilo 5 c++ drag-and-drop gtkmm gtk3

我想制作一个 GTK 小部件,当在另一个程序中拖放时,它会像一个文件被拖放一样(行为与从 Nautilus 拖放文件的方式相同)。

我尝试了 3 种不同的方法在回调中设置拖动数据,但似乎没有任何效果:

#include <bits/stdc++.h>
#include <gtkmm.h>

#define FILENAME "/tmp/foo.txt"

int main(int argc, char *argv[]) {
    auto app = Gtk::Application::create(argc, argv, "com.tyilo.foo");

    Gtk::Window window;
    window.set_default_size(200, 200);
    window.set_keep_above();

    Gtk::Button button("Drag this");
    window.add(button);

    std::vector<Gtk::TargetEntry> listTargets;
    listTargets.push_back(Gtk::TargetEntry("text/uri-list"));
    //listTargets.push_back(Gtk::TargetEntry("text/plain"));
    //listTargets.push_back(Gtk::TargetEntry("text/plain;charset=utf-8"));
    //listTargets.push_back(Gtk::TargetEntry("UTF8_STRING"));
    //listTargets.push_back(Gtk::TargetEntry("COMPOUND_STRING"));
    //listTargets.push_back(Gtk::TargetEntry("TEXT"));
    //listTargets.push_back(Gtk::TargetEntry("STRING"));

    button.drag_source_set(listTargets, Gdk::ModifierType(GDK_BUTTON1_MASK | GDK_BUTTON3_MASK),
                           Gdk::DragAction(GDK_ACTION_COPY | GDK_ACTION_MOVE));
    button.drag_source_set_icon("document-save");

    button.signal_drag_data_get().connect([&](auto, auto selection_data, auto, auto) {
        std::cout << "Data get: " << selection_data.get_target() << std::endl;

        auto uri = Glib::filename_to_uri(FILENAME);
        std::cout << uri << std::endl;

        // All but one of (1), (2) and (3) should be commented out

        // (1)
        selection_data.set_uris({uri});

        // (2)
        //uri += "\r\n";
        //selection_data.set(selection_data.get_target(), 8, (const guchar*)uri.c_str(), uri.bytes());


        // (3)
        //selection_data.set("text/uri-list", "file:///tmp/foo.txt\r\n");
    });

    window.show_all();
    return app->run(window);
}
Run Code Online (Sandbox Code Playgroud)

我需要指定更多的目标text/uri-list吗?我需要以不同的方式处理这些吗?

或者我在设置选择数据时做错了什么?

我正在使用gtkmm3版本3.24.1gtk3版本3.24.8,我正在编译:

g++ foo.cpp $(pkg-config gtkmm-3.0 --cflags --libs)
Run Code Online (Sandbox Code Playgroud)

测试它是否有效的一种简单方法是尝试将文件拖动到<input>浏览器中的以下标签:

g++ foo.cpp $(pkg-config gtkmm-3.0 --cflags --libs)
Run Code Online (Sandbox Code Playgroud)

小智 0

#include <gtkmm.h>
#include <glibmm.h>
#include <iostream>
#include <vector>

#define FILENAME "/tmp/foo.txt"

static void on_drag_data_get(  const Glib::RefPtr<Gdk::DragContext>& context,
                                    Gtk::SelectionData& selection_data, guint info, guint time){

    std::vector<Glib::ustring> vec_uris;
    vec_uris.push_back(Glib::filename_to_uri(FILENAME));
    std::cout << "File = " << vec_uris[0] << '\n';
    selection_data.set_uris(vec_uris);
}

int main(int argc, char *argv[])
{
    auto app = Gtk::Application::create(argc, argv, "com.tyilo.foo");

    Gtk::Window window;
    window.set_default_size(200, 200);
    window.set_keep_above();

    Gtk::Button button("Drag this");
    window.add(button);


    std::vector<Gtk::TargetEntry> listTargets;
    listTargets.push_back(Gtk::TargetEntry("text/uri-list"));
    button.drag_source_set(listTargets, Gdk::ModifierType::BUTTON1_MASK, Gdk::DragAction::ACTION_COPY);
    button.drag_source_add_uri_targets();
    button.drag_source_set_icon("document-save"); // x-office-spreadsheet, document


    button.signal_drag_data_get().connect(sigc::ptr_fun(&on_drag_data_get));


    window.show_all();
    return app->run(window);
}
Run Code Online (Sandbox Code Playgroud)