Библиотека сайта rus-linux.net
Программирование с использованием gtkmm 3. Буфер обмена
Оригинал: Programming with gtkmm 3Авторы: Murray Cumming, Bernhard Rieder, Jonathon Jongsma, Ole Laursen, Marko Anastasov, Daniel Elstner, Chris Vine, David King, Pedro Ferreira, Kjell Ahlstedt
Дата публикации: 15 Октября 2013 г.
Перевод: А.Панин
Дата перевода: 28 марта 2014 г.
19. Буфер обмена
Простые функции копирования и вставки текста предоставляются по умолчанию таким виджетам, как представленный классом Gtk::Entry
виджет ввода строки и представленный классом Gtk::TextView
виджет поля ввода текста, но вы можете ощутить потребность в реализации специального кода для работы с вашими собственными форматами данных. Например, программа для рисования может использовать специальный код для предоставления возможности копирования и вставки данных в рамках текущего изображения или различных документов.
Практически в любой ситуации вы можете рассматривать класс Gtk::Clipboard
как синглтон. При этом вы можете получить экземпляр стандартного буфера обмена с помощью метода Gtk::Clipboard::get()
. Скорее всего, это единственный буфер обмена, который вам когда-либо потребуется.
Вашему приложению не потребуется ожидать завершения операций с буфером обмена, особенно в период между активацией пользователем функции "Копировать" и активацией пользователем функции "Вставить". Большая часть методов класса Gtk::Clipboard
принимает слоты типа std::slot
, которые указывают на методы обратного вызова. В момент, когда объект буфера обмена на основе класса Gtk::Clipboard
получает сигнал о готовности, он осуществляет вызов этих методов либо предоставляя запрашиваемые данные, либо запрашивая данные.
19.1. Цели
Различные приложения работают с различными типами данных, причем они могут преобразовывать эти данные во множество форматов. В рамках gtkmm эти типы данных называются целями.
Например, приложение gedit может предоставлять и принимать цель "UTF8_STRING"
, поэтому вы можете вставить данные, переданные любым предоставляющим эту цель приложением, в поле редактирования текста приложения gedit. Также два приложения для редактирования изображений могут предоставлять и принимать изображения во множестве форматов, рассматривая эти форматы в качестве целей. Если одно приложение может принимать одну из целей, которую также предоставляет другое приложение, у вас будет возможность копировать данные из одного приложения в другое.
Цель может быть представлена множеством бинарных форматов. В данной главе и в соответствующих примерах мы будем считать, что наши данные являются исключительно 8-битным текстом. Это позволит нам использовать формат разметки текста XML для данных в буфере обмена. Однако, этот формат, вероятно, не подходит для хранения бинарных данных, таких, как изображения. Класс Gtk::Clipboard
предоставляет перегруженные методы, которые позволят вам описать формат более подробно в случае необходимости.
API захвата и перемещения данных (Drag and Drop) использует аналогичный механизм. Вам, скорее всего, придется использовать одни и те же цели и форматы данных как для операций с буфером обмена, так и операций захвата и перемещения данных.
19.2. Копирование
В момент, когда пользователь выполняет копирование каких-либо данных, вы должны сообщить объекту буфера обмена о том, какие цели доступны и передать ему методы обратного вызова, которые он сможет использовать для получения данных. В этот же момент вы должны сохранить копию ваших данных для передачи ее методу обратного вызова в ответ на осуществление пользователем вставки данных.
Glib::RefPtr<Gtk::Clipboard> refClipboard = Gtk::Clipboard::get(); //Цели: std::vector<Gtk::TargetEntry> targets; targets.push_back( Gtk::TargetEntry("example_custom_target") ); targets.push_back( Gtk::TargetEntry("UTF8_STRING") ); refClipboard->set( targets, sigc::mem_fun(*this, &ExampleWindow::on_clipboard_get), sigc::mem_fun(*this, &ExampleWindow::on_clipboard_clear) );
void ExampleWindow::on_clipboard_get( Gtk::SelectionData& selection_data, guint /* info */) { const std::string target = selection_data.get_target(); if(target == "example_custom_target") selection_data.set("example_custom_target", m_ClipboardStore); }
В идеальном примере ниже может передаваться более чем одна цель буфера обмена.
Метод обратного вызова clear
позволяет вам освободить зарезервированную память, в которой хранились данные, в момент, когда текущие данные буфера обмена заменяются на какие-либо другие данные.
19.3. Вставка
refClipboard->request_contents("example_custom_target", sigc::mem_fun(*this, &ExampleWindow::on_clipboard_received) );
void ExampleWindow::on_clipboard_received( const Gtk::SelectionData& selection_data) { Glib::ustring clipboard_data = selection_data.get_data_as_string(); //Выполнение каких-либо операций с вставленными данными. }
19.3.1. Установление доступных целей
request_targets()
, указав метод, который будет вызван для передачи информации. Примером может служить следующий код:
refClipboard->request_targets( sigc::mem_fun(*this, &ExampleWindow::on_clipboard_received_targets) );
void ExampleWindow::on_clipboard_received_targets( const std::vector<Glib::ustring>& targets) { const bool bPasteIsPossible = std::find(targets.begin(), targets.end(), example_target_custom) != targets.end(); // Активация/дективация элемента "Вставить" в соответствии с наличием возможности вставки данных: m_Button_Paste.set_sensitive(bPasteIsPossible); }
19.4. Примеры
19.4.1. Простой пример
Данный пример позволяет копировать и вставлять специфичные для приложения данные с использованием стандартной текстовой цели. Хотя этот пример и является достаточно простым, он не является идеальным, поскольку не идентифицирует данные буфера обмена в плане принадлежности к определенному типу данных.
Рисунок 19-1: Буфер обмена - Простой пример
Файл: examplewindow.h
(Для использования совместно с gtkmm 3, а не с gtkmm 2)
Файл: examplewindow.cc
(Для использования совместно с gtkmm 3, а не с gtkmm 2)
Файл: main.cc
(Для использования совместно с gtkmm 3, а не с gtkmm 2)
19.4.2. Идеальный пример
- Устанавливает специальную цель для буфера обмена, хотя форматом этой цели все равно является текст.
- Поддерживает вставку с использованием 2 целей - как с помощью специальной цели, так и с помощью текстовой цели, которая создает произвольное текстовое представление специфических данных.
- Использует метод
request_targets()
и сигнал"owner_change"
и деактивирует кнопку "Вставить" в том случае, если данные из буфера не могут быть использованы.
Рисунок 19-2: Буфер обмена - Идеальный пример
Файл: examplewindow.h
(Для использования совместно с gtkmm 3, а не с gtkmm 2)
Файл: examplewindow.cc
(Для использования совместно с gtkmm 3, а не с gtkmm 2)
Файл: main.cc
(Для использования совместно с gtkmm 3, а не с gtkmm 2)
Следующий раздел : 20.Печать.