Библиотека сайта 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 г.
20. Печать
На уровне разрабатываемого приложения API печати gtkmm предоставляет диалоги, которые являются однообразными во всех приложениях и позволяют использовать стандартный API для рисования на основе библиотеки Cairo вместе с системой вывода текста на основе библиотеки Pango. В основе реализации данного обобщенного API лежат специфичные для платформ механизмы и специфичные для принтеров драйверы.
20.1. Объект операции печати PrintOperation
Основным объектом, создаваемым для каждой из операций печати, является объект на основе класса Gtk::PrintOperation. Для обработки результатов формирования страницы следует устанавливать обработчики для его сигналов или наследовать класс от лежащего в основе данного объекта класса и перекрывать виртуальные обработчики сигналов. Объект операции печати PrintOperation автоматически обрабатывает все настройки, касающиеся цикла печати.
20.1.1. Сигналы
Gtk::PrintOperation::run() позволяет начать цикл печати, в процессе которого генерируются различные сигналы:
begin_print: Вы должны обрабатывать этот сигнал, так как на данном этапе вы должны создать и настроить набор объектов областей вывода текста на основе классаPango::Layoutс помощью передаваемого объекта контекста печати на основе классаGtk::PrintContext, а также разделить ваш печатаемый документ на страницы.paginate: Операция разделения документа на страницы может выполняться достаточно медленно, поэтому в том случае, если вы хотите следить за процессом разделения документа на страницы, вы можете осуществить вызов методаGtk::PrintOperation::set_show_progress()с последующей обработкой данного сигнала.- Для каждой страницы, изображение которой должно быть сформировано, генерируются следующие сигналы:
request_page_setup: Предоставляет объект контекста печатиPrintContext, номер страницы и объект настроек страницы на основе классаGtk::PageSetup. Обрабатывайте этот сигнал в том случае, если вам необходимо модифицировать настройки страниц с доступом к настройками каждой из них.draw_page: вы должны обрабатывать этот сигнал, предоставляющий объект контекста печатиPrintContextи номер страницы. Объект контекста печатиPrintContextдолжен использоваться для создания контекста Cairo на основе классаCairo::Context, с помощью которого обрабатываемая страница должна прорисовываться. Для вывода текста следует осуществить обход набора объектов областей вывода текста на основе классаPango::Layout, который вы создали в рамках обработчика сигнала"begin_print".
end_print: Обработчик данного сигнала является безопасным местом для освобождения любых ресурсов, относящихся к представленной объектом на основе классаGtk::PrintOperationоперации печати. В том случае, если вы используете специальный унаследованный от классаGtk::PrintOperationкласс, обычно проще выполнить описанные действия в дестукторе.done: Данный сигнал генерируется в момент окончания печати и сообщает о том, что все предназначенные для печати данные были обработаны. Учтите, что передаваемый объект результата печати на основе классаGtk::PrintOperationResultможет сообщать о том, что произошла ошибка. В любом случае, вы, скорее всего, захотите уведомить пользователя о конечном результате операции.status_changed: Генерируется всегда, когда изменяется статус задачи печати до ее завершения. Следует вызывать методGtk::PrintOperation::set_track_print_status()для отслеживания состояния задачи после начала печати. Для просмотра статуса следует использовать методget_status()или методget_status_string().
20.2. Настройка параметров страницы
Класс операции печати Gtk::PrintOperation содержит метод с именем set_default_page_setup(), который устанавливает стандартный размер бумаги, ориентацию листа и размеры полей. Для показа диалога настройки страницы в вашем приложении следует использовать метод Gtk::run_page_setup_dialog(), который возвращает объект настроек страницы на основе класса Gtk::PageSetup, хранящий заданне с помощью диалога настройки. Используйте этот объект для обновления настроек объекта операции печати на основе класса Gtk::PrintOperation, для доступа к выбранным настройкам размера страницы типа Gtk::PaperSize и ориентации страницы типа Gtk::PageOrientation, а также к специфичным для принтера размерам полей.
Вы должны сохранить созданный на основе класса Gtk::PageSetup объект настроек страницы для того, чтобы иметь возможность использовать его в будущем в том случае, если диалог настроек страницы будет показан снова.
//В рамках класса, унаследованного от класса Gtk::Window и хранящего объекты m_refPageSetup и m_refSettings в качестве дочерних объектов... Glib::RefPtr<Gtk::PageSetup> new_page_setup = Gtk::run_page_setup_dialog(*this, m_refPageSetup, m_refSettings); m_refPageSetup = new_page_setup;
Координатная система Cairo в рамках обработчика сигнала "draw_page" автоматически поворачивается в соответствии с текущей ориентацией страницы. Она обычно располагается внутри установленных принтером полей, но вы можете изменить ее расположение с помощью метода Gtk::PrintOperation::set_use_full_page(). Стандартной единицей измерения являются пиксели устройства. Для выбора других единиц измерения используйте метод Gtk::PrintOperation::set_unit().
20.3. Вывод текста
Вывод текста осуществляется с помощью библиотеки Pango. Создание объекта области вывода текста на основе класса Pango::Layout осуществляется с помощью метода Gtk::PrintContext::create_pango_layout(). Объект контекста печати также предоставляет метрики страницы, которые могут быть получены с помощью методов get_width() и get_height(). Количество страниц может быть установлено с помощью вызова метода Gtk::PrintOperation::set_n_pages(). Для непосредственного вывода текста с помощью библиотеки Pango в рамках обработчика сигналов "on_draw_page" следует получить контекст Cairo с помощью метода Gtk::PrintContext::get_cairo_context() и показать текст Pango, представленный объектом на основе класса Pango::LayoutLines, который появится на странице с заданным номером.
Обратитесь к примеру для ознакомления с реализацией описанного механизма.
20.4. Асинхронные операции
По умолчанию метод Gtk::PrintOperation::run() возвращает управление тогда, когда операция печати завершается. Если вам необходимо выполнить операцию без блокировки, следует осуществить вызов метода Gtk::PrintOperation::set_allow_async(). Учтите, что метод set_allow_aync() не поддерживается на всех платформах, однако сигнал "done" будет генерироваться в любом случае.
Метод run() может возвращать результат PRINT_OPERATION_RESULT_IN_PROGRESS. Для отслеживания статуса и обработки результата выполнения операции печати или ошибки вам придется реализовать обработчики сигналов "done" и "status_changed":
// В рамках метода класса ExampleWindow... Glib::RefPtr<PrintOperation> op = PrintOperation::create(); // ...настройка объекта операции печати... op->signal_done().connect(sigc::bind(sigc::mem_fun(*this, &ExampleWindow::on_printoperation_done), op)); // выполнение операции печати
"status_changed". Например, это может быть сделано следующим образом:
void ExampleWindow::on_printoperation_done(Gtk::PrintOperationResult result, const Glib::RefPtr<PrintOperation>& op)
{
if (result == Gtk::PRINT_OPERATION_RESULT_ERROR)
//вывод уведомления для пользователя
else if (result == Gtk::PRINT_OPERATION_RESULT_APPLY)
//Обновление параметров объекта настроек печати PrintSettings с использованием параметров объекта операции печати PrintOperation.
if (! op->is_finished())
op->signal_status_changed().connect(sigc::bind(sigc::mem_fun(*this, &ExampleWindow::on_printoperation_status_changed), op));
}
void ExampleWindow::on_printoperation_status_changed(const Glib::RefPtr<PrintFormOperation>& op)
{
if (op->is_finished())
//операция печати завершена
else
//получение статуса операции с помощью метода get_status() или get_status_string()
//обновление состояния пользовательского интерфейса
}
20.5. Экспорт в файл формата PDF
Glib::RefPtr<Gtk::PrintOperation> op = Gtk::PrintOperation::create();
// ...установка параметров объекта операции печати...
op->set_export_filename("test.pdf");
Gtk::PrintOperationResult res = op->run(Gtk::PRINT_OPERATION_ACTION_EXPORT);
20.6. Расширение функций диалога печати
- После установки заголовка вкладки с помощью метода
Gtk::PrintOperation::set_custom_tab_label()следует создать новый виджет и вернуть соответствующий ему объект из обработчика сигнала"create_custom_widget". Скорее всего, вы захотите сделать этот виджет контейнерным для упаковки каких-либо других виджетов. - После работы с диалогом следует получать данные от созданных виджетов с помощью обработчика сигналов
"custom_widget_apply".
"custom_widget_apply" и передает объект виджета, который вы создали ранее, для упрощения кода вы можете сделать виджеты, которые будут участвовать в процессе ввода пользователем каких-либо данных, дочерними виджетами класса. К примеру, предположим, что вы объявили виджет ввода строки на основе класса Gtk::Entry с именем m_Entry дочерним виджетом вашего класса CustomPrintOperation:
Gtk::Widget* CustomPrintOperation::on_create_custom_widget()
{
set_custom_tab_label("Моя специальная вкладка");
Gtk::Box* hbox = new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL, 8);
hbox->set_border_width(6);
Gtk::Label* label = Gtk::manage(new Gtk::Label("Введите какой-либо текст: "));
hbox->pack_start(*label, false, false);
label->show();
hbox->pack_start(m_Entry, false, false);
m_Entry.show();
return hbox;
}
void CustomPrintOperation::on_custom_widget_apply(Gtk::Widget* /* widget */)
{
Glib::ustring user_input = m_Entry.get_text();
//...
}
Пример в директории examples/book/printing/advanced демонстрирует описанный подход.
20.7. Предварительный просмотр
// в рамках класса, унаследованного от класса Gtk::Window... Glib::RefPtr<PrintOperation> op = PrintOperation::create(); // ...настройка параметров объекта операции печати... op->run(Gtk::PRINT_OPERATION_ACTION_PREVIEW, *this);
На платформах Unix стандартный механизм предварительного просмотра использует внешнюю программу для просмотра документов. На платформе Windows при этом будет показан стандартный системный диалог предварительного просмотра. В случае необходимости вы можете изменить это поведение и показывать специальный диалог предварительного просмотра. Обратитесь к примеру в директории /examples/book/printing/advanced.
Следующий раздел : 20.8. Пример.
