Exemples
XVIII.IV.I. Simple
This example allows copy and pasting of application-specific data, using the standard text format. Although this is simple, it's not ideal because it does not identify the Clipboard data as being of a particular type.
File: examplewindow.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: void on_button_copy(); void on_button_paste(); void on_clipboard_text_received(Glib::RefPtr<Gio::AsyncResult>& result); Glib::ustring m_strData; //Child widgets: Gtk::Box m_VBox; Gtk::Label m_Label; Gtk::Grid m_Grid; Gtk::ToggleButton m_ButtonA1, m_ButtonA2, m_ButtonB1, m_ButtonB2; Gtk::Box m_ButtonBox; Gtk::Button m_Button_Copy, m_Button_Paste; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { // Gio::Application::Flags::NON_UNIQUE because it shall be possible to run // several instances of this application simultaneously. auto app = Gtk::Application::create( "org.gtkmm.example", Gio::Application::Flags::NON_UNIQUE); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv); }
File: examplewindow.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> ExampleWindow::ExampleWindow() : m_VBox(Gtk::Orientation::VERTICAL), m_Label("Select cells in the grid, click Copy, then open a second " "instance of this example to try pasting the copied data."), m_ButtonA1("A1"), m_ButtonA2("A2"), m_ButtonB1("B1"), m_ButtonB2("B2"), m_Button_Copy("_Copy", /* mnemonic= */ true), m_Button_Paste("_Paste", true) { set_title("Gtk::Clipboard example"); m_VBox.set_margin(12); set_child(m_VBox); m_VBox.append(m_Label); //Fill Grid: m_VBox.append(m_Grid); m_Grid.set_expand(true); m_Grid.set_row_homogeneous(true); m_Grid.set_column_homogeneous(true); m_Grid.attach(m_ButtonA1, 0, 0); m_Grid.attach(m_ButtonA2, 1, 0); m_Grid.attach(m_ButtonB1, 0, 1); m_Grid.attach(m_ButtonB2, 1, 1); //Add ButtonBox to bottom: m_VBox.append(m_ButtonBox); m_VBox.set_spacing(6); //Fill ButtonBox: m_ButtonBox.append(m_Button_Copy); m_Button_Copy.set_hexpand(true); m_Button_Copy.set_halign(Gtk::Align::END); m_Button_Copy.signal_clicked().connect(sigc::mem_fun(*this, &ExampleWindow::on_button_copy) ); m_ButtonBox.append(m_Button_Paste); m_Button_Paste.signal_clicked().connect(sigc::mem_fun(*this, &ExampleWindow::on_button_paste) ); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_copy() { //Build a string representation of the stuff to be copied: //Ideally you would use XML, with an XML parser here: m_strData = m_ButtonA1.get_active() ? "1" : "0"; m_strData += m_ButtonA2.get_active() ? "1" : "0"; m_strData += m_ButtonB1.get_active() ? "1" : "0"; m_strData += m_ButtonB2.get_active() ? "1" : "0"; // Gdk::Clipboard::set_text() does not take a copy of the text. // The text can only be pasted (in this program or in some other program) // for as long as it exists. get_clipboard()->set_text(m_strData); } void ExampleWindow::on_button_paste() { //Tell the clipboard to call our method when it is ready: get_clipboard()->read_text_async(sigc::mem_fun(*this, &ExampleWindow::on_clipboard_text_received)); } void ExampleWindow::on_clipboard_text_received(Glib::RefPtr<Gio::AsyncResult>& result) { Glib::ustring text; try { text = get_clipboard()->read_text_finish(result); } catch (const Glib::Error& err) { // Print an error about why pasting failed. // Usually you probably want to ignore such failures, // but for demonstration purposes, we show the error. std::cout << "Pasting failed: " << err.what() << std::endl; } //See comment in on_button_copy() about this silly clipboard format. if(text.size() >= 4) { m_ButtonA1.set_active( text[0] == '1' ); m_ButtonA2.set_active( text[1] == '1' ); m_ButtonB1.set_active( text[2] == '1' ); m_ButtonB2.set_active( text[3] == '1' ); } }
XVIII.IV.II. Idéal
This is like the simple example, but it
Defines a custom clipboard target, though the format is still text.
It uses the Gdk::ContentFormats::signal_changed() signal and disables the Paste button if it can't use anything on the clipboard.
File: examplewindow.h (For use with gtkmm 4)
#ifndef GTKMM_EXAMPLEWINDOW_H #define GTKMM_EXAMPLEWINDOW_H #include <gtkmm.h> class ExampleWindow : public Gtk::Window { public: ExampleWindow(); virtual ~ExampleWindow(); protected: //Signal handlers: void on_button_copy(); void on_button_paste(); void on_clipboard_content_changed(); void on_clipboard_received(Glib::RefPtr<Gio::AsyncResult>& result); void on_clipboard_received_status(Glib::RefPtr<Gio::AsyncResult>& result); void update_paste_status(); //Disable the paste button if there is nothing to paste. Glib::ustring m_strData; //Child widgets: Gtk::Box m_VBox; Gtk::Label m_Label; Gtk::Grid m_Grid; Gtk::ToggleButton m_ButtonA1, m_ButtonA2, m_ButtonB1, m_ButtonB2; Gtk::Box m_ButtonBox; Gtk::Button m_Button_Copy, m_Button_Paste; }; #endif //GTKMM_EXAMPLEWINDOW_H
File: main.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <gtkmm/application.h> int main(int argc, char *argv[]) { // Gio::Application::Flags::NON_UNIQUE because it shall be possible to run // several instances of this application simultaneously. auto app = Gtk::Application::create( "org.gtkmm.example", Gio::Application::Flags::NON_UNIQUE); //Shows the window and returns when it is closed. return app->make_window_and_run<ExampleWindow>(argc, argv); }
File: examplewindow.cc (For use with gtkmm 4)
#include "examplewindow.h" #include <iostream> #include <string> namespace { const char example_format_custom[] = "gtkmmclipboardexample"; } // anonymous namespace ExampleWindow::ExampleWindow() : m_VBox(Gtk::Orientation::VERTICAL), m_Label("Select cells in the grid, click Copy, then open a second instance " "of this example to try pasting the copied data.\nOr try pasting the " "text representation into gedit."), m_ButtonA1("A1"), m_ButtonA2("A2"), m_ButtonB1("B1"), m_ButtonB2("B2"), m_Button_Copy("_Copy", /* mnemonic= */ true), m_Button_Paste("_Paste", true) { set_title("Gtk::Clipboard example"); m_VBox.set_margin(12); set_child(m_VBox); m_VBox.append(m_Label); //Fill Grid: m_VBox.append(m_Grid); m_Grid.set_expand(true); m_Grid.set_row_homogeneous(true); m_Grid.set_column_homogeneous(true); m_Grid.attach(m_ButtonA1, 0, 0); m_Grid.attach(m_ButtonA2, 1, 0); m_Grid.attach(m_ButtonB1, 0, 1); m_Grid.attach(m_ButtonB2, 1, 1); //Add ButtonBox to bottom: m_VBox.append(m_ButtonBox); m_VBox.set_spacing(6); //Fill ButtonBox: m_ButtonBox.append(m_Button_Copy); m_Button_Copy.set_hexpand(true); m_Button_Copy.set_halign(Gtk::Align::END); m_Button_Copy.signal_clicked().connect(sigc::mem_fun(*this, &ExampleWindow::on_button_copy) ); m_ButtonBox.append(m_Button_Paste); m_Button_Paste.signal_clicked().connect(sigc::mem_fun(*this, &ExampleWindow::on_button_paste) ); //Connect a signal handler that will be called when the contents of //the clipboard change. get_clipboard()->signal_changed().connect(sigc::mem_fun(*this, &ExampleWindow::on_clipboard_content_changed)); update_paste_status(); } ExampleWindow::~ExampleWindow() { } void ExampleWindow::on_button_copy() { //Build a string representation of the stuff to be copied: //Ideally you would use XML, with an XML parser here: m_strData = example_format_custom; m_strData += m_ButtonA1.get_active() ? " A1" : ""; m_strData += m_ButtonA2.get_active() ? " A2" : ""; m_strData += m_ButtonB1.get_active() ? " B1" : ""; m_strData += m_ButtonB2.get_active() ? " B2" : ""; // Gdk::Clipboard::set_text() does not take a copy of the text. // The text can only be pasted (in this program or in some other program) // for as long as it exists. get_clipboard()->set_text(m_strData); } void ExampleWindow::on_button_paste() { //Tell the clipboard to call our method when it is ready: get_clipboard()->read_text_async(sigc::mem_fun(*this, &ExampleWindow::on_clipboard_received)); } void ExampleWindow::on_clipboard_content_changed() { update_paste_status(); } void ExampleWindow::on_clipboard_received(Glib::RefPtr<Gio::AsyncResult>& result) { Glib::ustring text; try { text = get_clipboard()->read_text_finish(result); } catch (const Glib::Error& err) { // Print an error about why pasting failed. // Usually you probably want to ignore such failures, // but for demonstration purposes, we show the error. std::cout << "Pasting failed: " << err.what() << std::endl; } if (text.find(example_format_custom) == 0) { // It's the expected format. m_ButtonA1.set_active(text.find("A1") != std::string::npos); m_ButtonA2.set_active(text.find("A2") != std::string::npos); m_ButtonB1.set_active(text.find("B1") != std::string::npos); m_ButtonB2.set_active(text.find("B2") != std::string::npos); } else { // Unexpected format. Disable the Paste button. std::cout << "Unexpected pasted text: \"" << text << "\"" << std::endl; m_Button_Paste.set_sensitive(false); } } void ExampleWindow::update_paste_status() { // Disable the paste button if there is nothing to paste. get_clipboard()->read_text_async(sigc::mem_fun(*this, &ExampleWindow::on_clipboard_received_status)); } void ExampleWindow::on_clipboard_received_status(Glib::RefPtr<Gio::AsyncResult>& result) { Glib::ustring text; try { text = get_clipboard()->read_text_finish(result); } catch (const Glib::Error&) { } const bool bPasteIsPossible = text.find(example_format_custom) == 0; // Enable/Disable the Paste button appropriately: m_Button_Paste.set_sensitive(bPasteIsPossible); }