c++-gtk-utils
text_print_manager.h
Go to the documentation of this file.
1 /* Copyright (C) 2007, 2011 and 2013 Chris Vine
2 
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public License
9  as published by the Free Software Foundation; either version 2.1 of
10  the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful, but
13  WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License, version 2.1, for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License, version 2.1, along with this library (see the file LGPL.TXT
19  which came with this source code package in the c++-gtk-utils
20  sub-directory); if not, write to the Free Software Foundation, Inc.,
21  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 
23 */
24 
25 #ifndef CGU_TEXT_PRINTMANAGER_H
26 #define CGU_TEXT_PRINTMANAGER_H
27 
28 #include <vector>
29 #include <string>
30 #include <memory>
31 
33 
34 #ifdef CGU_USE_GTK
35 #include <gtk/gtk.h>
36 #include <pango/pango-layout.h>
37 #include <glib-object.h>
38 #endif
39 
43 #include <c++-gtk-utils/notifier.h>
44 #include <c++-gtk-utils/mutex.h>
45 
46 
47 namespace Cgu {
48 
49 #if defined(DOXYGEN_PARSING) || defined(CGU_USE_GTK)
50 
51 #ifndef DOXYGEN_PARSING
52 
53 // deleter functor for SharedHandle
54 class TPMPangoLayoutIterFree {
55 public:
56  void operator()(PangoLayoutIter* obj_p) {
57  if (obj_p) {
58  pango_layout_iter_free(obj_p);
59  }
60  }
61 };
62 
63 typedef SharedHandle<PangoLayoutIter*, TPMPangoLayoutIterFree> TPMPangoLayoutIterSharedHandle;
64 
65 #endif // DOXYGEN_PARSING
66 
67 /**
68  * @class TextPrintManager text_print_manager.h c++-gtk-utils/text_print_manager.h
69  * @brief A class to print plain text using the GTK+ print system.
70  *
71  * The TextPrintManager class prints text (say, from a GtkTextBuffer
72  * object or from a plain text file) using the GTK+ printer interface.
73  * To obtain a TextPrintManager object, call
74  * TextPrintManager::create_manager(). TextPrintManager::set_text()
75  * passes the text to be printed. The text passed with
76  * TextPrintManager::set_text() must form valid UTF-8 (all ASCII
77  * characters form valid UTF-8). To print the text entered, call
78  * TextPrintManager::print(). The TextPrintManager::view() and
79  * TextPrintManager::print_to_file() methods are also available.
80  *
81  * The TextPrintManager::page_setup() method can be used as a callback
82  * to display a document page setup dialog prior to printing, and this
83  * method should only be called in the thread in which the main GTK+
84  * event loop runs. It is a static method (a TextPrintManager object
85  * does not need to have been created before it is called).
86  *
87  * Once TextPrintManager::print(), TextPrintManager::view() or
88  * TextPrintManager::print_to_file() has been called, the
89  * TextPrintManager class owns a reference to itself and so manages
90  * its own lifetime - so once one of the methods has been called it
91  * doesn't matter if the IntrusivePtr object returned by
92  * TextPrintManager::create_manager() goes out of scope (however, once
93  * TextPrintManager::print(), TextPrintManager::view() or
94  * TextPrintManager::print_to_file() has been called, the object will
95  * not be deleted until both printing has completed or failed AND the
96  * IntrusivePtr object returned by TextPrintManager::create_manager()
97  * has gone out of scope or has been reset()).
98  *
99  * Normally, a user would probably only want to use any one
100  * TextPrintManager object to print a single print job (it has been
101  * designed with that in mind). Nevertheless, if a reference to the
102  * object is kept alive via an active IntrusivePtr object, it can be
103  * used to print more than one print job. However, if that is done it
104  * is not possible to called TextPrintManager::print()
105  * TextPrintManager::view(), TextPrintManager::print_to_file() or
106  * TextPrintManager::set_text() until the previous print job (if any)
107  * has been dispatched to the GTK+ print system (or cancelled). If
108  * the TextPrintManager object is not ready because it is in the
109  * middle of handling an earlier print job, then the call to
110  * TextPrintManager::print(), TextPrintManager::view(),
111  * TextPrintManager::print_to_file() or TextPrintManager::set_text()
112  * will return false; if however the new print job was successfully
113  * started or text successfully set, they will return true. It is not
114  * necessary to check the return value of these methods for the first
115  * print job despatched by any one TextPrintManager object.
116  *
117  * TextPrintManager::print_to_file() will also return false if no file
118  * name to which to print was specified.
119  *
120  * This class is not compiled into the library if the library is built
121  * with the \--without-gtk configuration option.
122  */
123 
125  enum Mode {print_mode, view_mode, file_mode} mode;
126 
127  Thread::Mutex mutex;
128  GtkWindow* parent_p;
129  GobjHandle<PangoLayout> text_layout_h;
130  int current_line;
131  TPMPangoLayoutIterSharedHandle current_line_iter_h;
132  std::unique_ptr<std::string> text_u;
133  std::string file_name;
134  std::vector<int> pages;
135  Notifier print_notifier;
136  std::string font_family;
137  int font_size;
138  bool ready;
139  bool cancelled_when_drawing;
140 
141  GobjHandle<GtkWidget> font_entry_h;
142  GobjHandle<GtkWidget> font_size_spin_button_h;
143 
144  static GobjHandle<GtkPrintSettings> print_settings_h;
145  static GobjHandle<GtkPageSetup> page_setup_h;
146  static std::string default_font_family;
147  static int default_font_size;
148 
149  void paginate(GtkPrintContext*);
150  void print_text();
151  void begin_print_impl(GtkPrintOperation*, GtkPrintContext*);
152  void draw_page_impl(GtkPrintOperation*, GtkPrintContext*, int);
153  GObject* create_custom_widget_impl(GtkPrintOperation*);
154  static void strip(std::string&);
155 
156  // private constructor
157  TextPrintManager() {}
158 public:
159 #ifndef DOXYGEN_PARSING
160  // this helper class avoids exposing GObject callbacks with C
161  // linkage to the global namespace
162  class CB;
163  friend class CB;
164 #endif
165 /**
166  * This class cannot be copied: it is intended to be held by
167  * IntrusivePtr. The copy constructor is deleted.
168  */
169  TextPrintManager(const TextPrintManager&) = delete;
170 
171 /**
172  * This class cannot be copied: it is intended to be held by
173  * IntrusivePtr. The assignment operator is deleted.
174  */
175  TextPrintManager& operator=(const TextPrintManager&) = delete;
176 
177 /**
178  * Creates a new TextPrintManager object. No GTK+/GDK functions are
179  * called by this method, and it is thread safe provided that, if it
180  * is called in a thread other than the one in which the GTK+ event
181  * loop runs, Cgu::Notifier::init() has previously been called in the
182  * GTK+ event loop thread.
183  * @param parent The parent of the print dialog which will be created
184  * by the TextPrintManager object (optional, NULL may be passed).
185  * @param font_family If a particular font is wanted, then this can be
186  * entered as the font_family and font_size arguments to this method..
187  * If the default of an empty string for font_family is used, then
188  * printing will use the previous font family setting (if any), or if
189  * not a font of "Mono". The font passed in this method can in any
190  * event be overridden from the "Print font" page in the print dialog.
191  * @param font_size If a particular font is wanted, then this can be
192  * entered as the font_family and font_size arguments to this method..
193  * If the default of 0 for font_size is used, then printing will use
194  * the previous font size setting (if any), or if not a size of
195  * 10. The font passed in this method can in any event be overridden
196  * from the "Print font" page in the print dialog. If a font size is
197  * passed as an argument, then the value must be 0 (default) or
198  * between 8 and 24 (actual).
199  * @exception std::bad_alloc This method might throw std::bad_alloc if
200  * memory is exhausted and the system throws in that case.
201  * @exception Cgu::Thread::MutexError This method might throw
202  * Cgu::Thread::MutexError if initialisation of the contained mutex
203  * fails. (It is often not worth checking for this, as it means
204  * either memory is exhausted or pthread has run out of other
205  * resources to create new mutexes.)
206  * @exception Cgu::PipeError This method might throw Cgu::PipeError if
207  * the contained Notifier object is the first Notifier object in the
208  * program to be constructed and Cgu::Notifier::init() has not
209  * previously been called.
210  */
211  static Cgu::IntrusivePtr<Cgu::TextPrintManager> create_manager(GtkWindow* parent = 0,
212  const std::string& font_family = "",
213  int font_size = 0);
214 
215 /**
216  * Runs a page set-up dialog. (If no settings are set using this
217  * dialog, then page defaults will be used with a page margin of 15
218  * millimetres.) In a multi-threaded program, this must be called in
219  * the thread in which the main GTK+ event loop runs. If the program
220  * by which it is called calls GTK+ directly in more than one thread
221  * and thus employs gdk_threads_enter()/gdk_threads_leave() (rather
222  * than, say, Cgu::Notifier or Cgu::Callback::post()), it must also be
223  * surrounded by gdk_threads_enter()/gdk_threads_leave() if called
224  * otherwise than in a GTK+ signal handler. (The best approach
225  * however is for a program only to address GTK+/GDK in the main
226  * program thread, for which purpose this library provides various
227  * functions and classes for inter-thread communication, such as
228  * Cgu::Notifier and Cgu::Callback::post().) It will not throw.
229  * @param parent The parent of the page set-up dialog which will be
230  * created by the TextPrintManager object (optional, NULL may be
231  * passed).
232  */
233  static void page_setup(GtkWindow* parent = 0);
234 
235 /**
236  * Sets the text to be printed. This method is thread-safe and may be
237  * called in any thread. No GTK+/GDK functions are called. It will
238  * not throw.
239  * @param text The text to be printed. It must be in valid UTF-8
240  * format. Ownership is taken of the text string (a move operation is
241  * carried out) unless false is returned.
242  * @return Returns true, unless the same TextPrintManager object is
243  * being used to print more than one print job and when this method is
244  * called it is already printing another print job (in which case it
245  * returns false). If it returns false, ownership is not taken of the
246  * text string (it can be reused).
247  * @note If the library is compiled using the \--with-auto-ptr
248  * configuration option, then this function's signature is bool
249  * set_text(std::auto_ptr<std::string>& text) in order to retain
250  * compatibility with the 1.2 series of the library.
251  */
252  // for efficiency reasons (the string could hold a lot of text and we do not
253  // want more copies than necessary hanging around) the text is passed by
254  // reference (by std::unique_ptr<>). We pass by std::unique_ptr so that the
255  // string cannot be modified after it has been passed to the TextPrintManager
256  // object - we take ownership of it
257 #ifdef CGU_USE_AUTO_PTR
258  bool set_text(std::auto_ptr<std::string>& text);
259 #else
260  bool set_text(std::unique_ptr<std::string>& text);
261 #endif
262 
263 /**
264  * Prints the text set with set_text(). This method is thread-safe
265  * and may be called in any thread (it hands off its work to the main
266  * program thread via a Cgu::Notifier object), unless the program by
267  * which it is called calls GTK+ directly in more than one thread and
268  * thus employs gdk_threads_enter()/gdk_threads_leave() (rather than,
269  * say, Cgu::Notifier or Cgu::Callback::post()), in which case it must
270  * be called in the main GUI thread only and surrounded by
271  * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
272  * a GTK+ signal handler. (The best approach however is for a program
273  * only to address GTK+/GDK in the main program thread, for which
274  * purpose this library provides various functions and classes for
275  * inter-thread communication, such as Cgu::Notifier and
276  * Cgu::Callback::post().)
277  * @return Returns true, unless the same TextPrintManager object is
278  * being used to print more than one print job and when this method is
279  * called it is already printing another print job (in which case it
280  * returns false).
281  * @exception std::bad_alloc This method might throw std::bad_alloc if
282  * memory is exhausted and the system throws in that case, but only if
283  * it is called in the main program thread. Otherwise it will not
284  * throw.
285  */
286  bool print();
287 
288 /**
289  * Provides a print pre-view of the text set with set_text(). This
290  * method is thread-safe and may be called in any thread (it hands off
291  * its work to the main program thread via a Cgu::Notifier object),
292  * unless the program by which it is called calls GTK+ directly in
293  * more than one thread and thus employs
294  * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
295  * Cgu::Notifier or Cgu::Callback::post()), in which case it must be
296  * called in the main GUI thread only and surrounded by
297  * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
298  * a GTK+ signal handler. (The best approach however is for a program
299  * only to address GTK+/GDK in the main program thread, for which
300  * purpose this library provides various functions and classes for
301  * inter-thread communication, such as Cgu::Notifier and
302  * Cgu::Callback::post().)
303  * @return Returns true, unless the same TextPrintManager object is
304  * being used to print more than one print job and when this method is
305  * called it is already printing another print job (in which case it
306  * returns false).
307  * @exception std::bad_alloc This method might throw std::bad_alloc if
308  * memory is exhausted and the system throws in that case, but only if
309  * it is called in the main program thread. Otherwise it will not
310  * throw.
311  */
312  bool view();
313 
314 /**
315  * Prints the text set with set_text() to file. This method is
316  * thread-safe and may be called in any thread (it hands off its work
317  * to the main program thread via a Cgu::Notifier object), unless the
318  * program by which it is called calls GTK+ directly in more than one
319  * thread and thus employs gdk_threads_enter()/gdk_threads_leave()
320  * (rather than, say, Cgu::Notifier or Cgu::Callback::post()), in
321  * which case it must be called in the main GUI thread only and
322  * surrounded by gdk_threads_enter()/gdk_threads_leave() if called
323  * otherwise than in a GTK+ signal handler. (The best approach
324  * however is for a program only to address GTK+/GDK in the main
325  * program thread, for which purpose this library provides various
326  * functions and classes for inter-thread communication, such as
327  * Cgu::Notifier and Cgu::Callback::post().)
328  * @param filename The filename of the file to which the text is to be
329  * printed.
330  * @return Returns true, unless the same TextPrintManager object is
331  * being used to print more than one print job and when this method is
332  * called it is already printing another print job, or no filename to
333  * print was specified (in either of which case it returns false).
334  * @exception std::bad_alloc This method might throw std::bad_alloc if
335  * memory is exhausted and the system throws in that case.
336  */
337  bool print_to_file(const char* filename);
338 
339 /**
340  * The destructor will not throw. It is thread safe (the
341  * TextPrintManager object may be destroyed in any thread), and does
342  * not call any GTK+/GDK functions.
343  */
345 
346 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
348 #endif
349 };
350 
351 #endif // CGU_USE_GTK
352 
353 } // namespace Cgu
354 
355 #endif // TEXT_PRINTMANAGER_H
Cgu
Definition: application.h:44
Cgu::TextPrintManager::page_setup
static void page_setup(GtkWindow *parent=0)
Cgu::GobjHandle< PangoLayout >
Cgu::IntrusivePtr
This is a smart pointer for managing objects allocated on freestore which maintain their own referenc...
Definition: intrusive_ptr.h:98
Cgu::TextPrintManager::print_to_file
bool print_to_file(const char *filename)
Cgu::TextPrintManager
A class to print plain text using the GTK+ print system.
Definition: text_print_manager.h:124
intrusive_ptr.h
Cgu::Notifier
Provides thread-safe signalling between a worker thread and the main program thread.
Definition: notifier.h:181
gobj_handle.h
Cgu::TextPrintManager::create_manager
static Cgu::IntrusivePtr< Cgu::TextPrintManager > create_manager(GtkWindow *parent=0, const std::string &font_family="", int font_size=0)
Cgu::TextPrintManager::~TextPrintManager
~TextPrintManager()
Cgu::TextPrintManager::operator=
TextPrintManager & operator=(const TextPrintManager &)=delete
notifier.h
This file provides a Notifier class to provide thread-safe signalling between a worker thread and the...
CGU_GLIB_MEMORY_SLICES_FUNCS
#define CGU_GLIB_MEMORY_SLICES_FUNCS
Definition: cgu_config.h:84
shared_handle.h
Cgu::IntrusiveLockCounter
This is a counter class providing the ref() and unref() functions required by IntrusivePtr,...
Definition: intrusive_ptr.h:349
mutex.h
Provides wrapper classes for pthread mutexes and condition variables, and scoped locking classes for ...
Cgu::TextPrintManager::print
bool print()
Cgu::TextPrintManager::set_text
bool set_text(std::unique_ptr< std::string > &text)
Cgu::Thread::Mutex
A wrapper class for pthread mutexes.
Definition: mutex.h:117
cgu_config.h
Cgu::TextPrintManager::view
bool view()