Fix for bug #28662
[texmacs.git] / src / src / Plugins / Qt / qt_gui.cpp
blob8ec0269be29706bb58a533af529829d6f79e597c
2 /******************************************************************************
3 * MODULE : qt_gui.cpp
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"
14 #include "qt_gui.hpp"
15 #include "analyze.hpp"
16 #include <locale.h>
17 #include "language.hpp"
18 #include "message.hpp"
19 #include <QDesktopWidget>
20 #include <QClipboard>
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
50 // the other events
52 /******************************************************************************
53 * Constructor and geometry
54 ******************************************************************************/
56 qt_gui_rep::qt_gui_rep(int &argc, char **argv):
57 interrupted (false)
59 (void) argc; (void) argv;
60 // argc= argc2;
61 // argv= argv2;
63 interrupted = false;
64 time_credit = 25;
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 */
78 void
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;
87 void
88 qt_gui_rep::get_max_size (SI& width, SI& height) {
89 width = 8000 * PIXEL;
90 height= 6000 * PIXEL;
94 qt_gui_rep::~qt_gui_rep() {
95 delete gui_helper;
96 // delete updatetimer; we do not need this given that gui_helper is the
97 // parent of updatetimer
100 /******************************************************************************
101 * interclient communication
102 ******************************************************************************/
104 bool
105 qt_gui_rep::get_selection (string key, tree& t, string& s) {
106 QClipboard *cb= QApplication::clipboard();
107 bool owns= false;
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");
120 s= "";
121 t= "none";
122 if (owns) {
123 if (!selection_t->contains (key)) return false;
124 t= copy (selection_t [key]);
125 s= copy (selection_s [key]);
126 return true;
128 else {
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);
133 return true;
137 bool
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;
149 else return true;
150 cb->clear (mode);
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);
163 return true;
166 void
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;
173 bool owns = false;
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 /******************************************************************************
187 * Miscellaneous
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 /******************************************************************************
198 * Main loop
199 ******************************************************************************/
201 void
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; }
210 void
211 qt_gui_rep::event_loop () {
212 QApplication *app = (QApplication*) QApplication::instance();
214 update();
215 //needs_update();
216 app->exec();
219 /******************************************************************************
220 * Sockets notifications
221 ******************************************************************************/
223 static hashmap<socket_notifier,pointer> read_notifiers;
224 static hashmap<socket_notifier,pointer> write_notifiers;
226 void
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)) );
252 void
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];
263 if (qsn) {
264 qsn->setEnabled (false);
265 qsn->deleteLater ();
267 read_notifiers->reset (sn);
269 qsn = (QSocketNotifier *)write_notifiers (sn);
270 if (qsn) {
271 qsn->setEnabled (false);
272 qsn->deleteLater ();
274 write_notifiers->reset (sn);
277 void
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 /******************************************************************************
290 * Delayed commands
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;
299 void
300 exec_delayed (object cmd) {
301 delayed_queue << cmd;
302 start_queue << (((time_t) texmacs_time ()) - 1000000000);
303 lapse = texmacs_time();
304 needs_update();
307 void
308 exec_delayed_pause (object cmd) {
309 delayed_queue << cmd;
310 start_queue << ((time_t) texmacs_time ());
311 lapse = texmacs_time();
312 needs_update();
315 void
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);
321 int i, n= N(a);
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);
333 else {
334 delayed_queue << a[i];
335 start_queue << b[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];
347 void
348 clear_pending_commands () {
349 delayed_queue= array<object> (0);
350 start_queue= array<time_t> (0);
353 /******************************************************************************
354 * Main routines
355 ******************************************************************************/
358 void
359 gui_open (int& argc, char** argv) {
360 // start the gui
361 // new QApplication (argc,argv); now in texmacs.cpp
362 the_gui = tm_new<qt_gui_rep> (argc, argv);
365 void
366 gui_start_loop () {
367 // start the main loop
368 the_gui->event_loop ();
371 void
372 gui_close () {
373 // cleanly close the gui
374 ASSERT (the_gui != NULL, "gui not yet open");
375 tm_delete (the_gui);
376 the_gui=NULL;
379 void
380 gui_root_extents (SI& width, SI& height) {
381 // get the screen size
382 the_gui->get_extents (width, height);
383 if (DEBUG_QT)
384 cout << "gui_root_extents (" << width << "," << height << ")" << LF;
387 void
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);
391 if (DEBUG_QT)
392 cout << "gui_maximal_extents (" << width << "," << height << ")" << LF;
395 void
396 gui_refresh () {
397 // update and redraw all windows (e.g. on change of output language)
398 // FIXME: add suitable code
402 /******************************************************************************
403 * QTMGuiHelper methods
404 ******************************************************************************/
406 void
407 QTMGuiHelper::doUpdate () {
408 // cout << "UPDATE " << texmacs_time () << LF;
409 gui->update();
412 bool
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));
420 return true;
421 } else {
422 // standard event processing
423 return QObject::eventFilter(obj, event);
427 void
428 QTMGuiHelper::doWriteSocketNotification (int socket) {
429 if (DEBUG_QT)
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) {
436 //sn->notify();
437 the_gui->process_socket_notification (sn);
438 the_gui->enable_notifier (sn, false);
443 void
444 QTMGuiHelper::doReadSocketNotification (int socket) {
445 if (DEBUG_QT)
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) {
452 //sn->notify();
453 the_gui->process_socket_notification (sn);
454 the_gui->enable_notifier (sn, false);
460 /******************************************************************************
461 * Queued processing
462 ******************************************************************************/
464 enum qp_type_id {
465 QP_NULL,
466 QP_KEYPRESS,
467 QP_KEYBOARD_FOCUS,
468 QP_MOUSE,
469 QP_RESIZE,
470 QP_SOCKET_NOTIFICATION,
471 QP_COMMAND,
472 QP_DELAYED_COMMANDS
475 class qp_type {
476 public:
477 qp_type_id sid;
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>
492 public:
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;
501 void
502 process_event (queued_event ev) {
503 switch ((qp_type_id) ev.x1) {
504 case QP_NULL :
505 break;
506 case QP_KEYPRESS :
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) ;
512 break;
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
521 // the problem.
523 break;
524 case QP_MOUSE :
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) ;
531 break;
532 case QP_RESIZE :
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) ;
538 break;
539 case QP_SOCKET_NOTIFICATION :
541 socket_notifier sn = open_box <socket_notifier> (ev.x2) ;
542 // cout << "QP_SOCKET_NOTIFICATION " << sn->fd << LF;
543 sn -> notify ();
544 the_gui->enable_notifier (sn, true);
546 break;
547 case QP_COMMAND :
549 command cmd = open_box <command> (ev.x2) ;
550 // cout << "QP_COMMAND" << LF;
551 cmd->apply();
553 break;
554 case QP_DELAYED_COMMANDS :
556 // cout << "QP_DELAYED_COMMANDS" << LF;
557 exec_pending_commands();
558 wait_for_delayed_commands = true;
560 break;
561 default:
562 FAILED("Unexpected queued event");
567 void
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> ();
580 int i, n = N(a);
581 int count = 0;
582 //cout << "(" << n << " events)";
583 for (i=0; i<n; i++) {
584 //cout << (int)a[i].x1 << ",";
585 if ((max < 0) || (count<max)) {
586 process_event(a[i]);
587 switch (a[i].x1) {
588 case QP_COMMAND:
589 case QP_SOCKET_NOTIFICATION:
590 case QP_RESIZE:
591 case QP_DELAYED_COMMANDS:
592 break;
593 default:
594 count++;
595 break;
597 } else
598 b << a[i];
600 b << waiting_events;
601 waiting_events = b;
605 void
606 add_event(const queued_event &ev)
608 if (updating) {
609 waiting_events << ev;
610 needing_update = true;
611 //needs_update();
612 } else {
613 waiting_events << ev;
614 // process_event(ev);
615 the_gui->update();
619 void
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);
624 // needs_update ();
627 void
628 qt_gui_rep::process_keyboard_focus ( simple_widget_rep *wid, bool has_focus,
629 time_t t ) {
630 typedef triple<widget, bool, time_t > T;
631 add_event(
632 queued_event ( QP_KEYBOARD_FOCUS, close_box<T> (T(wid, has_focus, t))));
633 //wid -> handle_keyboard_focus (has_focus, t);
634 //needs_update ();
637 void
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;
642 add_event (
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);
645 // needs_update ();
648 void
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);
653 // needs_update ();
656 void
657 qt_gui_rep::process_socket_notification ( socket_notifier sn ) {
658 add_event (
659 queued_event (QP_SOCKET_NOTIFICATION, close_box< socket_notifier > (sn)));
660 // sn -> notify ();
661 // enable_notifier (sn, true);
662 // needs_update ();
665 void
666 qt_gui_rep::process_command (command _cmd) {
667 add_event (
668 queued_event (QP_COMMAND, close_box< command > (_cmd)));
671 void
672 qt_gui_rep::process_delayed_commands () {
673 add_event (
674 queued_event (QP_DELAYED_COMMANDS, blackbox()));
678 void
679 fill_event_queue() {
680 if (N(waiting_events) == 0) {
681 qApp->processEvents(QEventLoop::ExcludeSocketNotifiers, 0);
682 // if (N(waiting_events) > 0) cout << "addins some events" << LF;
686 bool
687 qt_gui_rep::check_event (int type) {
688 //FIXME: add more types and refine, compare with X11 version.
690 // cout << "."; cout.flush();
691 // return false;
692 switch (type) {
693 case INTERRUPT_EVENT:
694 if (interrupted) return true;
695 else {
696 time_t now= texmacs_time ();
697 if (now - timeout_time < 0) return false;
698 fill_event_queue();
699 timeout_time= now + (100 / (N(waiting_events) + 1));
700 interrupted= (N(waiting_events) > 0);
701 //if (interrupted) cout << "INTERRUPT "
702 // << now << "------------------" << LF;
703 return interrupted;
705 case INTERRUPTED_EVENT:
706 return interrupted;
707 default:
708 return false;
713 void
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
718 // (see FIXME below)
720 time_credit = 100;
721 updating = true;
722 updatetimer->stop();
724 int count_events = 0;
725 int max_proc_events = 2;
727 do {
728 time_t now = texmacs_time();
729 needing_update = false;
731 count_events++;
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;
746 fill_event_queue();
748 if ((count_events > max_proc_events) || (N(waiting_events) == 0)) {
749 //if (count_events > max_proc_events) cout << "PARTIAL REDRAW" << LF;
750 count_events = 0;
752 // repaint invalid regions
753 interrupted = false;
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);
771 updating = false;
774 if (nr_windows == 0) {
775 qApp->quit();
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 /******************************************************************************
796 * Font support
797 ******************************************************************************/
799 void
800 set_default_font (string name) {
801 (void) name;
802 // set the name of the default font
803 // this is ignored since Qt handles fonts for the widgets
806 font
807 get_default_font (bool tt) {
808 (void) 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";
813 return NULL;
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
820 void
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 /******************************************************************************
829 * Clipboard support
830 ******************************************************************************/
832 bool
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);
839 bool
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);
846 void
847 clear_selection (string key) {
848 // Clear the selection on clipboard 'cb'
849 the_gui->clear_selection (key);
852 /******************************************************************************
853 * Miscellaneous
854 ******************************************************************************/
855 int char_clip=0;
857 void
858 beep () {
859 // Issue a beep
860 QApplication::beep();
863 void
864 needs_update () {
865 // 0 ms - call immediately when all other events have
866 // been processed
867 //cout << "needs_update" << LF;
868 if (updating) {
869 needing_update = true;
871 else {
872 the_gui->updatetimer->start (0);
876 bool
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);
889 void
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;
896 void
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";
909 return NULL;