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  */
170 
171 /**
172  * This class cannot be copied: it is intended to be held by
173  * IntrusivePtr. The assignment operator is deleted.
174  */
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  */
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  */
248  // for efficiency reasons (the string could hold a lot of text and we do not
249  // want more copies than necessary hanging around) the text is passed by
250  // reference (by std::unique_ptr<>). We pass by std::unique_ptr so that the
251  // string cannot be modified after it has been passed to the TextPrintManager
252  // object - we take ownership of it
253  bool set_text(std::unique_ptr<std::string>& text);
254 
255 /**
256  * Prints the text set with set_text(). This method is thread-safe
257  * and may be called in any thread (it hands off its work to the main
258  * program thread via a Cgu::Notifier object), unless the program by
259  * which it is called calls GTK directly in more than one thread and
260  * thus employs gdk_threads_enter()/gdk_threads_leave() (rather than,
261  * say, Cgu::Notifier or Cgu::Callback::post()), in which case it must
262  * be called in the main GUI thread only and surrounded by
263  * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
264  * a GTK signal handler. (The best approach however is for a program
265  * only to address GTK/GDK in the main program thread, for which
266  * purpose this library provides various functions and classes for
267  * inter-thread communication, such as Cgu::Notifier and
268  * Cgu::Callback::post().)
269  * @return Returns true, unless the same TextPrintManager object is
270  * being used to print more than one print job and when this method is
271  * called it is already printing another print job (in which case it
272  * returns false).
273  * @exception std::bad_alloc This method might throw std::bad_alloc if
274  * memory is exhausted and the system throws in that case, but only if
275  * it is called in the main program thread. Otherwise it will not
276  * throw.
277  */
278  bool print();
279 
280 /**
281  * Provides a print pre-view of the text set with set_text(). This
282  * method is thread-safe and may be called in any thread (it hands off
283  * its work to the main program thread via a Cgu::Notifier object),
284  * unless the program by which it is called calls GTK directly in
285  * more than one thread and thus employs
286  * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
287  * Cgu::Notifier or Cgu::Callback::post()), in which case it must be
288  * called in the main GUI thread only and surrounded by
289  * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
290  * a GTK signal handler. (The best approach however is for a program
291  * only to address GTK/GDK in the main program thread, for which
292  * purpose this library provides various functions and classes for
293  * inter-thread communication, such as Cgu::Notifier and
294  * Cgu::Callback::post().)
295  * @return Returns true, unless the same TextPrintManager object is
296  * being used to print more than one print job and when this method is
297  * called it is already printing another print job (in which case it
298  * returns false).
299  * @exception std::bad_alloc This method might throw std::bad_alloc if
300  * memory is exhausted and the system throws in that case, but only if
301  * it is called in the main program thread. Otherwise it will not
302  * throw.
303  */
304  bool view();
305 
306 /**
307  * Prints the text set with set_text() to file. This method is
308  * thread-safe and may be called in any thread (it hands off its work
309  * to the main program thread via a Cgu::Notifier object), unless the
310  * program by which it is called calls GTK directly in more than one
311  * thread and thus employs gdk_threads_enter()/gdk_threads_leave()
312  * (rather than, say, Cgu::Notifier or Cgu::Callback::post()), in
313  * which case it must be called in the main GUI thread only and
314  * surrounded by gdk_threads_enter()/gdk_threads_leave() if called
315  * otherwise than in a GTK signal handler. (The best approach
316  * however is for a program only to address GTK/GDK in the main
317  * program thread, for which purpose this library provides various
318  * functions and classes for inter-thread communication, such as
319  * Cgu::Notifier and Cgu::Callback::post().)
320  * @param filename The filename of the file to which the text is to be
321  * printed.
322  * @return Returns true, unless the same TextPrintManager object is
323  * being used to print more than one print job and when this method is
324  * called it is already printing another print job, or no filename to
325  * print was specified (in either of which case it returns false).
326  * @exception std::bad_alloc This method might throw std::bad_alloc if
327  * memory is exhausted and the system throws in that case.
328  */
329  bool print_to_file(const char* filename);
330 
331 /**
332  * The destructor will not throw. It is thread safe (the
333  * TextPrintManager object may be destroyed in any thread), and does
334  * not call any GTK/GDK functions.
335  */
337 
338 #ifdef CGU_USE_GLIB_MEMORY_SLICES_NO_COMPAT
340 #endif
341 };
342 
343 #endif // CGU_USE_GTK
344 
345 } // namespace Cgu
346 
347 #endif // TEXT_PRINTMANAGER_H
Cgu
Definition: application.h:44
Cgu::TextPrintManager::page_setup
static void page_setup(GtkWindow *parent=0)
Cgu::GobjHandle< PangoLayout >
Cgu::TextPrintManager::TextPrintManager
TextPrintManager(const TextPrintManager &)=delete
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:214
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()