2 /******************************************************************************
4 * DESCRIPTION: QT display class
5 * COPYRIGHT : (C) 2008 Massimiliano Gubinelli
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
12 #include "iterator.hpp"
13 #include "dictionary.hpp"
15 #include "analyze.hpp"
17 #include "language.hpp"
18 #include "message.hpp"
19 #include <QDesktopWidget>
21 #include <QFileOpenEvent>
22 #include <QSocketNotifier>
23 #include <QSetIterator>
24 #include "QTMGuiHelper.hpp"
25 #include "QTMWidget.hpp"
26 #include "qt_renderer.hpp" // for the_qt_renderer
28 #include "tm_link.hpp" // for number_of_servers
30 #include "Scheme/object.hpp"
31 //#include "TeXmacs/server.hpp" // for get_server
33 #include "qt_simple_widget.hpp"
35 extern window (*get_current_window
) (void);
37 qt_gui_rep
* the_gui
= NULL
;
38 int nr_windows
= 0; // FIXME: fake variable, referenced in tm_server
40 time_t time_credit
; // interval to interrupt long redrawings
41 time_t timeout_time
; // new redraw interruption
42 time_t lapse
= 0; // optimization for delayed commands
44 // marshalling flags between update, needs_update and check_event.
45 bool updating
= false;
46 bool needing_update
= false;
47 bool wait_for_delayed_commands
= true;
48 // this flag is used in update() to insert QP_DELAYED_COMMANDS events in TeXmacs
49 // event queue so to have delayed command handling properly interspersed with
52 /******************************************************************************
53 * Constructor and geometry
54 ******************************************************************************/
56 qt_gui_rep::qt_gui_rep(int &argc
, char **argv
):
59 (void) argc
; (void) argv
;
65 timeout_time
= texmacs_time () + time_credit
;
67 set_output_language (get_locale_language ());
68 gui_helper
= new QTMGuiHelper (this);
69 qApp
-> installEventFilter (gui_helper
);
70 updatetimer
= new QTimer (gui_helper
);
71 updatetimer
->setSingleShot (true);
72 QObject::connect ( updatetimer
, SIGNAL(timeout()),
73 gui_helper
, SLOT(doUpdate()));
74 // (void) default_font ();
77 /* important routines */
79 qt_gui_rep::get_extents (SI
& width
, SI
& height
) {
80 QDesktopWidget
* d
= QApplication::desktop();
81 int w
= d
->width(); // returns desktop width
82 int h
= d
->height(); // returns desktop height
83 width
= ((SI
) w
) * PIXEL
;
84 height
= ((SI
) h
) * PIXEL
;
88 qt_gui_rep::get_max_size (SI
& width
, SI
& height
) {
94 qt_gui_rep::~qt_gui_rep() {
96 // delete updatetimer; we do not need this given that gui_helper is the
97 // parent of updatetimer
100 /******************************************************************************
101 * interclient communication
102 ******************************************************************************/
105 qt_gui_rep::get_selection (string key
, tree
& t
, string
& s
) {
106 QClipboard
*cb
= QApplication::clipboard();
108 QClipboard::Mode mode
;
109 if (key
== "primary") {
110 //owns= cb->ownsClipboard(); // This does not work on Mac/Win
111 mode
= QClipboard::Clipboard
;
113 else if (key
== "mouse" && cb
->supportsSelection()) {
114 //owns= cb->ownsSelection();
115 mode
= QClipboard::Selection
;
117 const QMimeData
*md
= cb
->mimeData (mode
);
118 if (md
) owns
= md
->hasFormat ("application/x-texmacs");
123 if (!selection_t
->contains (key
)) return false;
124 t
= copy (selection_t
[key
]);
125 s
= copy (selection_s
[key
]);
129 QString originalText
= cb
->text (mode
);
130 QByteArray buf
= originalText
.toAscii ();
131 if (!(buf
.isEmpty())) s
<< string (buf
.constData(), buf
.size());
132 t
= tuple ("extern", s
);
138 qt_gui_rep::set_selection (string key
, tree t
, string s
) {
139 selection_t (key
)= copy (t
);
140 selection_s (key
)= copy (s
);
142 QClipboard
*cb
= QApplication::clipboard();
143 QClipboard::Mode mode
;
145 if (key
== "primary")
146 mode
= QClipboard::Clipboard
;
147 else if (key
== "mouse" && cb
->supportsSelection())
148 mode
= QClipboard::Selection
;
152 char *selection
= as_charp (s
);
153 cb
->setText (selection
, mode
);
154 QByteArray
ba (selection
);
155 QMimeData
*md
= new QMimeData
;
156 md
->setData ("application/x-texmacs", ba
);
157 md
->setText (selection
);
158 cb
->setMimeData (md
, mode
);
159 // according to the docs, ownership of mimedata is transferred to clipboard
160 // so no memory leak here
161 tm_delete_array (selection
);
167 qt_gui_rep::clear_selection (string key
) {
168 selection_t
->reset (key
);
169 selection_s
->reset (key
);
171 QClipboard
*cb
= QApplication::clipboard();
172 QClipboard::Mode mode
;
175 if (key
== "primary")
176 mode
= QClipboard::Clipboard
;
177 else if (key
== "mouse" && cb
->supportsSelection())
178 mode
= QClipboard::Selection
;
180 const QMimeData
*md
= cb
->mimeData(mode
);
181 if (md
) owns
= md
->hasFormat ("application/x-texmacs");
182 if (owns
) cb
->clear (mode
);
186 /******************************************************************************
188 ******************************************************************************/
190 void qt_gui_rep::image_gc (string name
) { (void) name
; }
191 // FIXME: remove this unused function
192 void qt_gui_rep::set_mouse_pointer (string name
) { (void) name
; }
193 // FIXME: implement this function
194 void qt_gui_rep::set_mouse_pointer (string curs_name
, string mask_name
)
195 { (void) curs_name
; (void) mask_name
; } ;
197 /******************************************************************************
199 ******************************************************************************/
202 qt_gui_rep::show_wait_indicator (widget w
, string message
, string arg
) {
203 (void) w
; (void) message
; (void) arg
;
206 void (*the_interpose_handler
) (void) = NULL
;
208 void gui_interpose (void (*r
) (void)) { the_interpose_handler
= r
; }
211 qt_gui_rep::event_loop () {
212 QApplication
*app
= (QApplication
*) QApplication::instance();
219 /******************************************************************************
220 * Sockets notifications
221 ******************************************************************************/
223 static hashmap
<socket_notifier
,pointer
> read_notifiers
;
224 static hashmap
<socket_notifier
,pointer
> write_notifiers
;
227 qt_gui_rep::add_notifier (socket_notifier sn
)
229 QSocketNotifier
*qsn
;
231 // replace any already present notifier
233 remove_notifier (sn
);
235 if (DEBUG_QT
) cout
<< "ADD NOTIFIER " << sn
->fd
<< LF
;
238 // installs both a read and a write notifier
239 // (the texmacs interface does not specify enough its needs)
241 qsn
= new QSocketNotifier(sn
->fd
, QSocketNotifier::Read
, gui_helper
);
242 read_notifiers (sn
) = (pointer
) (qsn
);
243 QObject::connect( qsn
, SIGNAL(activated(int)),
244 gui_helper
, SLOT(doReadSocketNotification(int)) );
246 qsn
= new QSocketNotifier(sn
->fd
, QSocketNotifier::Write
, gui_helper
);
247 write_notifiers (sn
) = (pointer
) (qsn
);
248 QObject::connect( qsn
, SIGNAL(activated(int)),
249 gui_helper
, SLOT(doWriteSocketNotification(int)) );
253 qt_gui_rep::remove_notifier (socket_notifier sn
)
255 QSocketNotifier
*qsn
;
257 if (DEBUG_QT
) cout
<< "REMOVE NOTIFIER" << LF
;
259 // disable the (r/w) notifiers to prevent them to fire past this point
260 // and schedule them for deletion at the end of the current runloop
262 qsn
= (QSocketNotifier
*)read_notifiers
[sn
];
264 qsn
->setEnabled (false);
267 read_notifiers
->reset (sn
);
269 qsn
= (QSocketNotifier
*)write_notifiers (sn
);
271 qsn
->setEnabled (false);
274 write_notifiers
->reset (sn
);
278 qt_gui_rep::enable_notifier (socket_notifier sn
, bool flag
)
280 QSocketNotifier
*qsn
;
281 qsn
= (QSocketNotifier
*)read_notifiers (sn
);
282 if (qsn
) qsn
->setEnabled (flag
);
283 qsn
= (QSocketNotifier
*)write_notifiers (sn
);
284 if (qsn
) qsn
->setEnabled (flag
);
289 /******************************************************************************
291 ******************************************************************************/
293 //FIXME: the code below is almost a copy of the code in Guile/Scheme/object.cpp
294 // maybe some refactoring would be necessary
296 static array
<object
> delayed_queue
;
297 static array
<time_t> start_queue
;
300 exec_delayed (object cmd
) {
301 delayed_queue
<< cmd
;
302 start_queue
<< (((time_t) texmacs_time ()) - 1000000000);
303 lapse
= texmacs_time();
308 exec_delayed_pause (object cmd
) {
309 delayed_queue
<< cmd
;
310 start_queue
<< ((time_t) texmacs_time ());
311 lapse
= texmacs_time();
316 exec_pending_commands () {
317 array
<object
> a
= delayed_queue
;
318 array
<time_t> b
= start_queue
;
319 delayed_queue
= array
<object
> (0);
320 start_queue
= array
<time_t> (0);
322 for (i
=0; i
<n
; i
++) {
323 time_t now
= texmacs_time ();
324 if ((now
- b
[i
]) >= 0) {
325 object obj
= call (a
[i
]);
326 if (is_int (obj
) && (now
- b
[i
] < 1000000000)) {
327 time_t pause
= as_int (obj
);
328 //cout << "pause= " << obj << "\n";
329 delayed_queue
<< a
[i
];
330 start_queue
<< (now
+ pause
);
334 delayed_queue
<< a
[i
];
338 if (N(delayed_queue
)>0) {
339 lapse
= start_queue
[0];
340 int n
= N(start_queue
);
341 for (i
=1; i
<n
; i
++) {
342 if (lapse
> start_queue
[i
]) lapse
= start_queue
[i
];
348 clear_pending_commands () {
349 delayed_queue
= array
<object
> (0);
350 start_queue
= array
<time_t> (0);
353 /******************************************************************************
355 ******************************************************************************/
359 gui_open (int& argc
, char** argv
) {
361 // new QApplication (argc,argv); now in texmacs.cpp
362 the_gui
= tm_new
<qt_gui_rep
> (argc
, argv
);
367 // start the main loop
368 the_gui
->event_loop ();
373 // cleanly close the gui
374 ASSERT (the_gui
!= NULL
, "gui not yet open");
380 gui_root_extents (SI
& width
, SI
& height
) {
381 // get the screen size
382 the_gui
->get_extents (width
, height
);
384 cout
<< "gui_root_extents (" << width
<< "," << height
<< ")" << LF
;
388 gui_maximal_extents (SI
& width
, SI
& height
) {
389 // get the maximal size of a window (can be larger than the screen size)
390 the_gui
->get_max_size (width
, height
);
392 cout
<< "gui_maximal_extents (" << width
<< "," << height
<< ")" << LF
;
397 // update and redraw all windows (e.g. on change of output language)
398 // FIXME: add suitable code
402 /******************************************************************************
403 * QTMGuiHelper methods
404 ******************************************************************************/
407 QTMGuiHelper::doUpdate () {
408 // cout << "UPDATE " << texmacs_time () << LF;
413 QTMGuiHelper::eventFilter (QObject
*obj
, QEvent
*event
) {
414 if (event
->type() == QEvent::FileOpen
) {
415 QFileOpenEvent
*openEvent
= static_cast<QFileOpenEvent
*>(event
);
416 const char *s
= openEvent
->file().toAscii().constData();
417 //qDebug ("File Open Event %s", s);
418 call ( "texmacs-load-buffer", object(url_system (s
)),
419 object("generic"), object(1), object(false));
422 // standard event processing
423 return QObject::eventFilter(obj
, event
);
428 QTMGuiHelper::doWriteSocketNotification (int socket
) {
430 cout
<< "WRITE SOCKET NOTIFICATION " << socket
<< " "
431 << texmacs_time () << LF
;
432 iterator
<socket_notifier
> it
= iterate (write_notifiers
);
433 while (it
->busy ()) {
434 socket_notifier sn
= it
->next ();
435 if (sn
->fd
== socket
) {
437 the_gui
->process_socket_notification (sn
);
438 the_gui
->enable_notifier (sn
, false);
444 QTMGuiHelper::doReadSocketNotification (int socket
) {
446 cout
<< "READ SOCKET NOTIFICATION " << socket
<< " "
447 << texmacs_time () << LF
;
448 iterator
<socket_notifier
> it
= iterate (read_notifiers
);
449 while (it
->busy ()) {
450 socket_notifier sn
= it
->next ();
451 if (sn
->fd
== socket
) {
453 the_gui
->process_socket_notification (sn
);
454 the_gui
->enable_notifier (sn
, false);
460 /******************************************************************************
462 ******************************************************************************/
470 QP_SOCKET_NOTIFICATION
,
478 inline qp_type (qp_type_id sid2
= QP_NULL
): sid (sid2
) {}
479 inline qp_type (const qp_type
& s
): sid (s
.sid
) {}
480 inline qp_type
& operator = (qp_type s
) { sid
= s
.sid
; return *this; }
481 inline operator qp_type_id () { return sid
; }
482 inline bool operator == (qp_type_id sid2
) { return sid
== sid2
; }
483 inline bool operator != (qp_type_id sid2
) { return sid
!= sid2
; }
484 inline bool operator == (qp_type s
) { return sid
== s
.sid
; }
485 inline bool operator != (qp_type s
) { return sid
!= s
.sid
; }
486 inline friend tm_ostream
& operator << (tm_ostream
& out
, qp_type s
)
487 { return out
<< s
.sid
; }
490 class queued_event
: public pair
<qp_type
, blackbox
>
493 queued_event(qp_type _type
= qp_type(), blackbox _bb
= blackbox())
494 : pair
<qp_type
, blackbox
>(_type
, _bb
) {};
498 static array
<queued_event
> waiting_events
;
502 process_event (queued_event ev
) {
503 switch ((qp_type_id
) ev
.x1
) {
508 typedef triple
<widget
, string
, time_t > T
;
509 T x
= open_box
<T
> (ev
.x2
) ;
510 concrete_simple_widget(x
.x1
) -> handle_keypress (x
.x2
, x
.x3
) ;
513 case QP_KEYBOARD_FOCUS
:
515 typedef triple
<widget
, bool, time_t > T
;
516 T x
= open_box
<T
> (ev
.x2
) ;
517 concrete_simple_widget(x
.x1
) -> handle_keyboard_focus (x
.x2
, x
.x3
) ;
518 send_invalidate_all(x
.x1
);
519 //FIXME: the above invalidate is due to incorrect repainting when
520 // the widget loose the focus. I should investigate better
526 typedef quintuple
<string
, SI
, SI
, int, time_t > T1
;
527 typedef pair
<widget
, T1
> T
;
528 T x
= open_box
<T
> (ev
.x2
) ;
529 concrete_simple_widget(x
.x1
) -> handle_mouse (x
.x2
.x1
, x
.x2
.x2
, x
.x2
.x3
, x
.x2
.x4
, x
.x2
.x5
) ;
534 typedef triple
<widget
, SI
, SI
> T
;
535 T x
= open_box
<T
> (ev
.x2
) ;
536 concrete_simple_widget(x
.x1
) -> handle_notify_resize (x
.x2
, x
.x3
) ;
539 case QP_SOCKET_NOTIFICATION
:
541 socket_notifier sn
= open_box
<socket_notifier
> (ev
.x2
) ;
542 // cout << "QP_SOCKET_NOTIFICATION " << sn->fd << LF;
544 the_gui
->enable_notifier (sn
, true);
549 command cmd
= open_box
<command
> (ev
.x2
) ;
550 // cout << "QP_COMMAND" << LF;
554 case QP_DELAYED_COMMANDS
:
556 // cout << "QP_DELAYED_COMMANDS" << LF;
557 exec_pending_commands();
558 wait_for_delayed_commands
= true;
562 FAILED("Unexpected queued event");
568 qt_gui_rep::process_queued_events (int max
) {
569 // we process a maximum of max events. There are two kind of events: those
570 // which need a pass on interpose_handler just after and the others. We count
571 // only the first kind of events. In update() we call this function with
572 // max=1 so that only one of these "sensible" events is handled. Otherwise
573 // updating of internal TeXmacs structure become very slow. This can be
574 // considerer a limitation of the current implementation of interpose_handler
575 // Likewise this function is just an hack to get things working properly.
577 array
<queued_event
> a
= waiting_events
, b
;
578 waiting_events
= array
<queued_event
> ();
582 //cout << "(" << n << " events)";
583 for (i
=0; i
<n
; i
++) {
584 //cout << (int)a[i].x1 << ",";
585 if ((max
< 0) || (count
<max
)) {
589 case QP_SOCKET_NOTIFICATION
:
591 case QP_DELAYED_COMMANDS
:
606 add_event(const queued_event
&ev
)
609 waiting_events
<< ev
;
610 needing_update
= true;
613 waiting_events
<< ev
;
614 // process_event(ev);
620 qt_gui_rep::process_keypress (simple_widget_rep
*wid
, string key
, time_t t
) {
621 typedef triple
<widget
, string
, time_t > T
;
622 add_event( queued_event ( QP_KEYPRESS
, close_box
<T
> (T(wid
, key
, t
))));
623 // wid -> handle_keypress (key, t);
628 qt_gui_rep::process_keyboard_focus ( simple_widget_rep
*wid
, bool has_focus
,
630 typedef triple
<widget
, bool, time_t > T
;
632 queued_event ( QP_KEYBOARD_FOCUS
, close_box
<T
> (T(wid
, has_focus
, t
))));
633 //wid -> handle_keyboard_focus (has_focus, t);
638 qt_gui_rep::process_mouse ( simple_widget_rep
*wid
, string kind
, SI x
, SI y
,
639 int mods
, time_t t
) {
640 typedef quintuple
<string
, SI
, SI
, int, time_t > T1
;
641 typedef pair
<widget
, T1
> T
;
643 queued_event ( QP_MOUSE
, close_box
<T
> ( T (wid
, T1 (kind
, x
, y
, mods
, t
)))));
644 // wid -> handle_mouse (kind, x, y, mods, t);
649 qt_gui_rep::process_resize ( simple_widget_rep
*wid
, SI x
, SI y
) {
650 typedef triple
<widget
, SI
, SI
> T
;
651 add_event( queued_event ( QP_RESIZE
, close_box
<T
> (T(wid
, x
, y
))));
652 // wid -> handle_notify_resize (x, y);
657 qt_gui_rep::process_socket_notification ( socket_notifier sn
) {
659 queued_event (QP_SOCKET_NOTIFICATION
, close_box
< socket_notifier
> (sn
)));
661 // enable_notifier (sn, true);
666 qt_gui_rep::process_command (command _cmd
) {
668 queued_event (QP_COMMAND
, close_box
< command
> (_cmd
)));
672 qt_gui_rep::process_delayed_commands () {
674 queued_event (QP_DELAYED_COMMANDS
, blackbox()));
680 if (N(waiting_events
) == 0) {
681 qApp
->processEvents(QEventLoop::ExcludeSocketNotifiers
, 0);
682 // if (N(waiting_events) > 0) cout << "addins some events" << LF;
687 qt_gui_rep::check_event (int type
) {
688 //FIXME: add more types and refine, compare with X11 version.
690 // cout << "."; cout.flush();
693 case INTERRUPT_EVENT
:
694 if (interrupted
) return true;
696 time_t now
= texmacs_time ();
697 if (now
- timeout_time
< 0) return false;
699 timeout_time
= now
+ (100 / (N(waiting_events
) + 1));
700 interrupted
= (N(waiting_events
) > 0);
701 //if (interrupted) cout << "INTERRUPT "
702 // << now << "------------------" << LF;
705 case INTERRUPTED_EVENT
:
714 qt_gui_rep::update () {
715 // this is called by doUpdate, which in turns is fired by a timer activated in
716 // needs_update, and ensuring that interpose_handler is run during a pass in
717 // the eventloop afterwards we reactivate the timer with a pause
724 int count_events
= 0;
725 int max_proc_events
= 2;
728 time_t now
= texmacs_time();
729 needing_update
= false;
733 if (wait_for_delayed_commands
&& (lapse
<= now
)) process_delayed_commands();
735 if (N(waiting_events
) > 0) {
736 //cout << "PROCESS QUEUED EVENTS START..."; cout.flush();
737 process_queued_events (1);
738 //cout << "AND END" << LF;
741 //cout << "TYPESET START..."; cout.flush();
742 // if ((N(waiting_events)==0) && (lapse <= now)) exec_pending_commands();
743 if (the_interpose_handler
) the_interpose_handler();
744 //cout << "AND END" << LF;
748 if ((count_events
> max_proc_events
) || (N(waiting_events
) == 0)) {
749 //if (count_events > max_proc_events) cout << "PARTIAL REDRAW" << LF;
752 // repaint invalid regions
754 timeout_time
= texmacs_time() + time_credit
/(N(waiting_events
)+1);
756 //cout << "REPAINT START..."; cout.flush();
758 QSetIterator
<QTMWidget
*> i(QTMWidget::all_widgets
);
759 while (i
.hasNext()) {
760 QTMWidget
*w
= i
.next();
761 w
->repaint_invalid_regions();
764 if (interrupted
) needing_update
= true;
765 //cout << "AND END" << LF;
768 } while ((N(waiting_events
)>0) || needing_update
);
774 if (nr_windows
== 0) {
779 time_t delay
= lapse
- texmacs_time();
780 if (delay
> 1000/6) delay
= 1000/6;
781 if (delay
< 0) delay
= 0;
782 if (needing_update
|| interrupted
) delay
= 0;
783 updatetimer
->start (delay
);
785 // FIXME: we need to ensure that the interpose_handler is run at regular
786 // intervals (1/6th of sec) so that informations on the footbar are
787 // updated. (this should be better handled by promoting code in
788 // tm_editor::apply_changes (which is activated only after idle
789 // periods) at the level of delayed commands in the gui.
790 // The interval cannot be too small to keep CPU usage low in idle state
795 /******************************************************************************
797 ******************************************************************************/
800 set_default_font (string name
) {
802 // set the name of the default font
803 // this is ignored since Qt handles fonts for the widgets
807 get_default_font (bool tt
) {
809 // get the default font or monospaced font (if tt is true)
811 // return a null font since this function is not called in the Qt port.
812 if (DEBUG_QT
) cout
<< "get_default_font(): SHOULD NOT BE CALLED\n";
814 //return tex_font (this, "ecrm", 10, 300, 0);
817 // load the metric and glyphs of a system font
818 // you are not obliged to provide any system fonts
821 load_system_font (string family
, int size
, int dpi
,
822 font_metric
& fnm
, font_glyphs
& fng
)
824 (void) family
; (void) size
; (void) dpi
; (void) fnm
; (void) fng
;
825 if (DEBUG_QT
) cout
<< "load_system_font(): SHOULD NOT BE CALLED\n";
828 /******************************************************************************
830 ******************************************************************************/
833 set_selection (string key
, tree t
, string s
) {
834 // Copy a selection 't' with string equivalent 's' to the clipboard 'cb'
835 // Returns true on success
836 return the_gui
->set_selection (key
, t
, s
);
840 get_selection (string key
, tree
& t
, string
& s
) {
841 // Retrieve the selection 't' with string equivalent 's' from clipboard 'cb'
842 // Returns true on success; sets t to (extern s) for external selections
843 return the_gui
->get_selection (key
, t
, s
);
847 clear_selection (string key
) {
848 // Clear the selection on clipboard 'cb'
849 the_gui
->clear_selection (key
);
852 /******************************************************************************
854 ******************************************************************************/
860 QApplication::beep();
865 // 0 ms - call immediately when all other events have
867 //cout << "needs_update" << LF;
869 needing_update
= true;
872 the_gui
->updatetimer
->start (0);
877 check_event (int type
) {
878 // Check whether an event of one of the above types has occurred;
879 // we check for keyboard events while repainting windows
880 return the_gui
->check_event(type
);
883 void image_gc (string name
) {
884 // Garbage collect images of a given name (may use wildcards)
885 // This routine only needs to be implemented if you use your own image cache
886 the_qt_renderer()->image_gc(name
);
890 show_help_balloon (widget balloon
, SI x
, SI y
) {
891 // Display a help balloon at position (x, y); the help balloon should
892 // disappear as soon as the user presses a key or moves the mouse
893 (void) balloon
; (void) x
; (void) y
;
897 show_wait_indicator (widget base
, string message
, string argument
) {
898 // Display a wait indicator with a message and an optional argument
899 // The indicator might for instance be displayed at the center of
900 // the base widget which triggered the lengthy operation;
901 // the indicator should be removed if the message is empty
902 the_gui
->show_wait_indicator(base
,message
,argument
);
905 font
x_font (string family
, int size
, int dpi
)
907 (void) family
; (void) size
; (void) dpi
;
908 if (DEBUG_QT
) cout
<< "x_font(): SHOULD NOT BE CALLED\n";