Back to index

texmacs  1.0.7.15
qt_tm_widget.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003  * MODULE     : qt_tm_widget.cpp
00004  * DESCRIPTION: The main TeXmacs widget for the Qt GUI
00005  * COPYRIGHT  : (C) 2008  Massimiliano Gubinelli
00006  *******************************************************************************
00007  * This software falls under the GNU general public license version 3 or later.
00008  * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009  * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010  ******************************************************************************/
00011 
00012 #include <QtGui>
00013 
00014 #include "analyze.hpp"
00015 
00016 #include "qt_tm_widget.hpp"
00017 #include "qt_utilities.hpp"
00018 #include "qt_renderer.hpp"
00019 #include "qt_gui.hpp"
00020 
00021 #include "qt_basic_widgets.hpp"
00022 #include "qt_simple_widget.hpp"
00023 #include "qt_window_widget.hpp"
00024 #include "QTMWindow.hpp"
00025 #include "QTMStyle.hpp"      // qtstyle()
00026 #include "QTMGuiHelper.hpp"  // needed to connect()
00027 #include "QTMInteractivePrompt.hpp"
00028 #include "QTMInteractiveInputHelper.hpp"
00029 
00030 
00031 #ifdef Q_WS_MAC
00032 #define UNIFIED_TOOLBAR
00033 // enable the unified toolbar style on the mac. To work properly this requires
00034 // a modification of the widget hierarchy of the main window.
00035 #endif
00036 
00037 int menu_count = 0;
00038 list<qt_tm_widget_rep*> waiting_widgets;
00039 
00040 void
00041 replaceActions (QWidget* dest, QWidget* src) {
00042     //NOTE: the parent hierarchy of the actions is not modified while installing
00043     //      the menu in the GUI (see qt_menu.cpp for this memory management 
00044     //      policy)
00045   dest->setUpdatesEnabled(false);
00046   QList<QAction *> list = dest->actions();
00047   while (!list.isEmpty()) {
00048     QAction* a= list.takeFirst();
00049     dest->removeAction (a);
00050   }
00051   list = src->actions();
00052   while (!list.isEmpty()) {
00053     QAction* a= list.takeFirst();
00054     dest->addAction (a);
00055   }
00056   dest->setUpdatesEnabled(true);
00057 }
00058 
00059 void
00060 replaceButtons(QToolBar* dest, QWidget* src) {
00061   dest->setUpdatesEnabled(false);
00062   bool visible = dest->isVisible();
00063   if (visible) dest->hide(); //TRICK: this is a trick to avoid flicker of the dest widget
00064   replaceActions (dest, src);
00065   QList<QObject*> list= dest->children();
00066   for (int i=0; i<list.count(); i++) {
00067     QToolButton* button= qobject_cast<QToolButton*> (list[i]);
00068     if (button) {
00069       button->setPopupMode (QToolButton::InstantPopup);
00070       button->setStyle( qtmstyle() );
00071     }
00072   }
00073   if (visible) dest->show(); //TRICK: see above
00074   dest->setUpdatesEnabled(true);
00075 }
00076 
00077 void QTMInteractiveInputHelper::commit(int result) {
00078   if (wid) {
00079     if (result == QDialog::Accepted) {
00080       QString item = "#f";
00081       QComboBox *cb = sender()->findChild<QComboBox*>("input");
00082       if (cb) {
00083         item = cb->currentText();
00084       }      
00085       ((qt_input_text_widget_rep*) wid->int_input.rep) -> text=
00086 //      scm_quote (from_qstring (item));
00087       from_qstring (item);
00088       ((qt_input_text_widget_rep*) wid->int_input.rep) -> cmd ();      
00089     }
00090   }
00091   sender()->deleteLater();
00092 }
00093 
00094 
00095 /******************************************************************************
00096 * qt_tm_widget_rep
00097 ******************************************************************************/
00098 
00099 static void
00100 tweek_iconbar_size (QSize& sz) {
00101   if (sz.height () >= 24) {
00102     sz.setWidth (sz.width () + 2);
00103     sz.setHeight (sz.height () + 6);
00104   }
00105   else if (sz.height () >= 20) {
00106     sz.setHeight (sz.height () + 2);
00107   }
00108   else if (sz.height () >= 16) {
00109     sz.setHeight (sz.height () + 2);
00110   }
00111 }
00112 
00113 qt_tm_widget_rep::qt_tm_widget_rep(int mask, command _quit)
00114  : qt_view_widget_rep (new QTMWindow (this)), helper (this), 
00115    full_screen(false), quit(_quit) 
00116 {
00117   // decode mask
00118   visibility[0] = (mask & 1)  == 1;  // header
00119   visibility[1] = (mask & 2)  == 2;  // main
00120   visibility[2] = (mask & 4)  == 4;  // mode
00121   visibility[3] = (mask & 8)  == 8;  // focus
00122   visibility[4] = (mask & 16) == 16; // user
00123   visibility[5] = (mask & 32) == 32; // footer
00124   
00125   // general setup for main window
00126   
00127   QMainWindow* mw= tm_mainwindow ();
00128   mw->setStyle (qtmstyle ());
00129   mw->menuBar()->setStyle (qtmstyle ());
00130   
00131   // there is a bug in the early implementation of toolbars in Qt 4.6
00132   // which has been fixed in 4.6.2 (at least)
00133   // this is why we change dimension of icons
00134   
00135 #if (defined(Q_WS_MAC)&&(QT_VERSION>=QT_VERSION_CHECK(4,6,0))&&(QT_VERSION<QT_VERSION_CHECK(4,6,2)))
00136   mw->setIconSize (QSize (22, 30));  
00137 #else
00138   mw->setIconSize (QSize (17, 17));
00139 #endif
00140   mw->setFocusPolicy (Qt::NoFocus);
00141   
00142   
00143   // central widget
00144   
00145   QStackedWidget* tw = new QStackedWidget (mw);
00146   tw->setObjectName("stacked widget"); // to easily find this object
00147   
00148   // status bar
00149   
00150   QStatusBar* bar= new QStatusBar(mw);
00151   leftLabel= new QLabel ("Welcome to TeXmacs", mw);
00152   rightLabel= new QLabel ("Booting", mw);
00153   leftLabel->setFrameStyle (QFrame::NoFrame);
00154   rightLabel->setFrameStyle (QFrame::NoFrame);
00155   {
00156     QFont f=  leftLabel->font();
00157     f.setPixelSize(12);
00158     leftLabel->setFont(f);
00159     rightLabel->setFont(f);
00160   }
00161   bar->addWidget (leftLabel, 1);
00162   bar->addPermanentWidget (rightLabel);
00163   bar->setStyle (qtmstyle ());
00164   
00165   // NOTE (mg): the following setMinimumWidth command disable automatic 
00166   // enlarging of the status bar and consequently of the main window due to 
00167   // long messages in the left label. I found this strange solution here
00168   // http://www.archivum.info/qt-interest@trolltech.com/2007-05/01453/Re:-QStatusBar-size.html
00169   // The solution if due to Martin Petricek. He adds:
00170   //    The docs says: If minimumSize() is set, the minimum size hint will be ignored.
00171   //    Probably the minimum size hint was size of the lengthy message and
00172   //    internal layout was enlarging the satusbar and the main window
00173   //    Maybe the notice about QLayout that is at minimumSizeHint should be
00174   //    also at minimumSize, didn't notice it first time and spend lot of time
00175   //    trying to figure this out :)
00176   
00177   bar->setMinimumWidth(2);
00178   mw->setStatusBar (bar);
00179  
00180   
00181   // toolbars
00182   
00183   mainToolBar  = new QToolBar ("main toolbar", mw);
00184   modeToolBar  = new QToolBar ("mode toolbar", mw);
00185   focusToolBar = new QToolBar ("focus toolbar", mw);
00186   userToolBar   = new QToolBar ("user toolbar", mw);
00187 
00188   mainToolBar->setStyle (qtmstyle ());
00189   modeToolBar->setStyle (qtmstyle ());
00190   focusToolBar->setStyle (qtmstyle ());
00191   userToolBar->setStyle (qtmstyle ());
00192   
00193   {
00194     // set proper sizes for icons
00195     QPixmap *pxm = the_qt_renderer()->xpm_image ("tm_new.xpm");
00196     QSize sz = (pxm ? pxm->size() : QSize(24,24));
00197     tweek_iconbar_size (sz);
00198     mainToolBar->setIconSize (sz);
00199     pxm = the_qt_renderer()->xpm_image ("tm_section.xpm");
00200     sz = (pxm ? pxm->size() : QSize(20,20));
00201     tweek_iconbar_size (sz);
00202     modeToolBar->setIconSize(sz);
00203     pxm = the_qt_renderer()->xpm_image ("tm_add.xpm");
00204     sz = (pxm ? pxm->size() : QSize(16,16));
00205     tweek_iconbar_size (sz);
00206     focusToolBar->setIconSize(sz);
00207   }  
00208   
00209 //#if 0
00210 #ifdef UNIFIED_TOOLBAR
00211 
00212   mw->setUnifiedTitleAndToolBarOnMac(true);
00213 
00214   QWidget *cw= new QWidget ();  // QMainWindow will take ownership later and delete it when needed.
00215   cw->setObjectName("central widget"); // this is important for styling toolbars.
00216   
00217   QBoxLayout *bl = new QBoxLayout(QBoxLayout::TopToBottom, cw);
00218   bl->setContentsMargins(2,2,2,2);
00219   bl->setSpacing(0);
00220   cw->setLayout(bl);
00221   bl->addWidget(tw);
00222   
00223   mw->setCentralWidget(cw);
00224   
00225   
00226   //WARNING: dumbToolBar is the toolbar installed on the top area of the
00227   //main widget which is  then unified in the title bar. 
00228   //to overcome some limitations of the unified toolbar implementation we
00229   //install the real toolbars as widgets in this toolbar.
00230   
00231   dumbToolBar = mw->addToolBar("dumb toolbar");
00232   dumbToolBar->setMinimumHeight(30);
00233 
00234   //these are the actions related to the various toolbars to be installed in
00235   //the dumb toolbar.
00236   
00237   mainToolBarAction = dumbToolBar->addWidget(mainToolBar);
00238   modeToolBarAction = NULL;
00239 
00240   
00241   //a ruler
00242   rulerWidget = new QWidget(cw);
00243   rulerWidget->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
00244   rulerWidget->setMinimumHeight(1);
00245   rulerWidget->setBackgroundRole(QPalette::Mid);
00246   // FIXME: how to use 112 (active) and 146 (passive)
00247   rulerWidget->setVisible(false);
00248   rulerWidget->setAutoFillBackground(true);
00249   // rulerWidget = new QLabel("pippo", cw);
00250   
00251 
00252   bl->insertWidget(0, modeToolBar);
00253   bl->insertWidget(1, rulerWidget);
00254   bl->insertWidget(2, focusToolBar);
00255   bl->insertWidget(3, userToolBar);
00256 
00257   tw->setContentsMargins (2, 0, 2, 0);
00258   mw->setContentsMargins (-2, -2, -2, -2);
00259   bar->setContentsMargins (0, 0, 0, 2);
00260 
00261 #else
00262   mw->setCentralWidget(tw);
00263   
00264   mw->addToolBar (mainToolBar);
00265   mw->addToolBarBreak ();
00266   mw->addToolBar (modeToolBar);
00267   mw->addToolBarBreak ();
00268   mw->addToolBar (focusToolBar);
00269   mw->addToolBarBreak ();
00270   mw->addToolBar (userToolBar);
00271  // mw->addToolBarBreak ();
00272 #endif
00273   
00274   // handles visibility
00275   // at this point all the toolbars are empty so we avoid showing them
00276   // same for the menu bar if we are not on the Mac (where we do not have
00277   // other options)
00278   
00279   mainToolBar->setVisible (false);
00280   modeToolBar->setVisible (false);
00281   focusToolBar->setVisible (false);
00282   userToolBar->setVisible (false);
00283   tm_mainwindow()->statusBar()->setVisible (true);
00284 #ifndef Q_WS_MAC
00285   tm_mainwindow()->menuBar()->setVisible (false);
00286 #endif  
00287 }
00288 
00289 qt_tm_widget_rep::~qt_tm_widget_rep () {
00290   if (DEBUG_QT)
00291     cout << "qt_tm_widget_rep::~qt_tm_widget_rep\n";
00292   
00293   
00294     // clear any residual waiting menu installation
00295   waiting_widgets = remove(waiting_widgets, this);
00296   
00297     // we must detach the QTMWidget canvas from the Qt widget hierarchy otherwise
00298     // it will be destroyed when the view member of this object is deallocated
00299     // this is another problem related to our choice of letting qt_widget own its
00300     // underlying QWidget.
00301   
00302   QTMWidget *canvas = tm_canvas();
00303   QStackedWidget* tw= tm_centralwidget();
00304   if (canvas) {
00305     tw->removeWidget(canvas);
00306     canvas->setParent(NULL);
00307     QTMWidget::all_widgets.remove(canvas);
00308   }
00309   
00310 }
00311 
00312 void qt_tm_widget_rep::updateVisibility()
00313 {
00314 #define XOR(exp1,exp2) (((!exp1) && (exp2)) || ((exp1) && (!exp2)))
00315 
00316   bool old_mainVisibility = mainToolBar->isVisible();
00317   bool old_modeVisibility = modeToolBar->isVisible();
00318   bool old_focusVisibility = focusToolBar->isVisible();
00319   bool old_userVisibility = userToolBar->isVisible();
00320   bool old_statusVisibility = tm_mainwindow()->statusBar()->isVisible();
00321 
00322   bool new_mainVisibility = visibility[1] && visibility[0];
00323   bool new_modeVisibility = visibility[2] && visibility[0];
00324   bool new_focusVisibility = visibility[3] && visibility[0];
00325   bool new_userVisibility = visibility[4] && visibility[0];
00326   bool new_statusVisibility = visibility[5];
00327   
00328   if ( XOR(old_mainVisibility,  new_mainVisibility) )
00329     mainToolBar->setVisible (new_mainVisibility);
00330   if ( XOR(old_modeVisibility,  new_modeVisibility) )
00331     modeToolBar->setVisible (new_modeVisibility);
00332   if ( XOR(old_focusVisibility,  new_focusVisibility) )
00333     focusToolBar->setVisible (new_focusVisibility);
00334   if ( XOR(old_userVisibility,  new_userVisibility) )
00335     userToolBar->setVisible (new_userVisibility);
00336   if ( XOR(old_statusVisibility,  new_statusVisibility) )
00337     tm_mainwindow()->statusBar()->setVisible (new_statusVisibility);
00338 
00339 #ifndef Q_WS_MAC
00340   bool old_menuVisibility = tm_mainwindow()->menuBar()->isVisible();
00341   bool new_menuVisibility = visibility[0];
00342 
00343   if ( XOR(old_menuVisibility,  new_menuVisibility) )
00344     tm_mainwindow()->menuBar()->setVisible (new_menuVisibility);
00345 #endif
00346 
00347 //#if 0
00348 #ifdef UNIFIED_TOOLBAR
00349 
00350   // do modifications only if needed to reduce flicker
00351   if ( XOR(old_mainVisibility,  new_mainVisibility) ||
00352       XOR(old_modeVisibility,  new_modeVisibility) )
00353   {
00354     // ensure that the topmost visible toolbar is always unified on Mac
00355     // (actually only for main and mode toolbars, unifying focus is not
00356     // appropriate)
00357     
00358     QBoxLayout *bl = qobject_cast<QBoxLayout*>(tm_mainwindow()->centralWidget()->layout());
00359     
00360     if (modeToolBarAction)
00361       modeToolBarAction->setVisible(modeToolBar->isVisible());
00362     mainToolBarAction->setVisible(mainToolBar->isVisible());
00363     
00364     //WARNING: jugglying around bugs in Qt unified toolbar implementation
00365     //do not try to change the order of the following operations....
00366     
00367     if (mainToolBar->isVisible()) {       
00368       bool tmp = modeToolBar->isVisible();
00369       dumbToolBar->removeAction(modeToolBarAction);
00370       dumbToolBar->addAction(mainToolBarAction);
00371       bl->insertWidget(0, rulerWidget);
00372       bl->insertWidget(0, modeToolBar);
00373       mainToolBarAction->setVisible(true);
00374       rulerWidget->setVisible(true);
00375       modeToolBar->setVisible(tmp);
00376       if (modeToolBarAction)
00377         modeToolBarAction->setVisible(tmp);
00378       dumbToolBar->setVisible(true);
00379     } else { 
00380       dumbToolBar->removeAction(mainToolBarAction);
00381       if (modeToolBar->isVisible()) {
00382         bl->removeWidget(rulerWidget);
00383         rulerWidget->setVisible(false);
00384         bl->removeWidget(modeToolBar);
00385         if (modeToolBarAction == NULL) {
00386           modeToolBarAction = dumbToolBar->addWidget(modeToolBar);
00387         } else {
00388           dumbToolBar->addAction(modeToolBarAction);
00389         }
00390         dumbToolBar->setVisible(true);
00391       } else {
00392         dumbToolBar->setVisible(false);
00393         dumbToolBar->removeAction(modeToolBarAction);
00394       }
00395     }
00396   }
00397 #endif // UNIFIED_TOOLBAR
00398 #undef XOR
00399 }
00400 
00401 
00402 void
00403 qt_tm_widget_rep::send (slot s, blackbox val) {
00404   if (DEBUG_QT)
00405     cout << "qt_tm_widget_rep::send " << slot_name (s) << LF;
00406   
00407   switch (s) {
00408     case SLOT_INVALIDATE:
00409     {
00410       TYPE_CHECK (type_box (val) == type_helper<coord4>::id);
00411       coord4 p= open_box<coord4> (val);
00412       if (DEBUG_QT)
00413         cout << "Invalidating rect " << rectangle(p.x1,p.x2,p.x3,p.x4) << LF;
00414       qt_renderer_rep* ren = (qt_renderer_rep*)get_renderer (this);
00415       QTMWidget *canvas = qobject_cast <QTMWidget*>(view);
00416       if (ren && canvas) {
00417         SI x1 = p.x1, y1 = p.x2, x2 = p.x3, y2 = p.x4;    
00418         ren->outer_round (x1, y1, x2, y2);
00419         ren->decode (x1, y1);
00420         ren->decode (x2, y2);
00421         canvas->invalidate_rect (x1,y2,x2,y1);
00422       }
00423     }
00424       break;
00425     case SLOT_INVALIDATE_ALL:
00426     {
00427       ASSERT (is_nil (val), "type mismatch");
00428       if (DEBUG_QT)
00429         cout << "Invalidating all"<<  LF;
00430       QTMWidget *canvas = qobject_cast <QTMWidget*>(view);
00431       if (canvas) canvas->invalidate_all ();
00432     }
00433       break;
00434       
00435     case SLOT_EXTENTS:
00436     {
00437       TYPE_CHECK (type_box (val) == type_helper<coord4>::id);
00438       coord4 p= open_box<coord4> (val);
00439       QRect rect = to_qrect (p);
00440         //NOTE: rect.topLeft is ignored since it is always (0,0)
00441       tm_canvas() -> setExtents(rect);
00442 #if 0
00443         //cout << "p= " << p << "\n";
00444       QSize sz= to_qrect (p).size ();
00445       QSize ws= tm_scrollarea () -> size ();
00446       sz.setHeight (max (sz.height (), ws.height () - 4));
00447         //FIXME: the above adjustment is not very nice and useful only in papyrus 
00448         //       mode. When setting the size we should ask the GUI of some 
00449         //       preferred max size and set that without post-processing.
00450         //      tm_canvas () -> setFixedSize (sz);
00451       tm_canvas() -> setExtentsSize(sz);
00452 #endif
00453     }
00454       break;
00455     case SLOT_HEADER_VISIBILITY:
00456     {
00457       TYPE_CHECK (type_box (val) == type_helper<bool>::id);
00458       bool f= open_box<bool> (val);
00459       visibility[0] = f;
00460       updateVisibility();
00461     }
00462       break;
00463     case SLOT_MAIN_ICONS_VISIBILITY:
00464     {
00465       TYPE_CHECK (type_box (val) == type_helper<bool>::id);
00466       bool f= open_box<bool> (val);
00467       visibility[1] = f;
00468       updateVisibility();
00469     }
00470       break;
00471     case SLOT_MODE_ICONS_VISIBILITY:
00472     {
00473       TYPE_CHECK (type_box (val) == type_helper<bool>::id);
00474       bool f= open_box<bool> (val);
00475       visibility[2] = f;
00476       updateVisibility();
00477     }
00478       break;
00479     case SLOT_FOCUS_ICONS_VISIBILITY:
00480     {
00481       TYPE_CHECK (type_box (val) == type_helper<bool>::id);
00482       bool f= open_box<bool> (val);
00483       visibility[3] = f;
00484       updateVisibility();
00485     }
00486       break;
00487     case SLOT_USER_ICONS_VISIBILITY:
00488     {
00489       TYPE_CHECK (type_box (val) == type_helper<bool>::id);
00490       bool f= open_box<bool> (val);
00491       visibility[4] = f;
00492       updateVisibility();
00493     }
00494       break;
00495     case SLOT_FOOTER_VISIBILITY:
00496     {
00497       TYPE_CHECK (type_box (val) == type_helper<bool>::id);
00498       bool f= open_box<bool> (val);
00499       visibility[5] = f;
00500       updateVisibility();
00501     }
00502       break;
00503       
00504     case SLOT_LEFT_FOOTER:
00505     {
00506       TYPE_CHECK (type_box (val) == type_helper<string>::id);
00507       string msg= open_box<string> (val);
00508       leftLabel->setText (to_qstring (tm_var_encode (msg)));
00509       leftLabel->update ();
00510     }
00511       break;
00512     case SLOT_RIGHT_FOOTER:
00513     {
00514       TYPE_CHECK (type_box (val) == type_helper<string>::id);
00515       string msg= open_box<string> (val);
00516       rightLabel->setText (to_qstring (tm_var_encode (msg)));
00517       rightLabel->update ();
00518     }
00519       break;
00520       
00521     case SLOT_SCROLL_POSITION:
00522     {
00523       TYPE_CHECK (type_box (val) == type_helper<coord2>::id);
00524       coord2 p= open_box<coord2> (val);
00525       QPoint pt= to_qpoint (p);
00526       if (DEBUG_QT)
00527         cout << "Position (" << pt.x() << "," << pt.y() << ")\n ";
00528       tm_scrollarea()->setOrigin(pt);
00529     }
00530       break;
00531       
00532     case SLOT_SCROLLBARS_VISIBILITY:
00533         // ignore this: qt handles scrollbars independently
00534         //                send_int (THIS, "scrollbars", val);
00535       break;
00536       
00537     case SLOT_INTERACTIVE_MODE:
00538     {
00539       TYPE_CHECK (type_box (val) == type_helper<bool>::id);
00540 
00541       if (open_box<bool> (val) == true) {
00542         prompt = new QTMInteractivePrompt (int_prompt, int_input);
00543         tm_mainwindow()->statusBar()->removeWidget(leftLabel);
00544         tm_mainwindow()->statusBar()->removeWidget(rightLabel);
00545         tm_mainwindow()->statusBar()->addWidget(prompt, 1);
00546         prompt->start();
00547       } else {
00548         if (prompt) prompt->end();
00549         tm_mainwindow()->statusBar()->removeWidget(prompt);
00550         tm_mainwindow()->statusBar()->addWidget(leftLabel);
00551         tm_mainwindow()->statusBar()->addPermanentWidget(rightLabel);
00552         leftLabel->show();
00553         rightLabel->show();
00554         delete prompt;
00555         prompt = NULL;
00556       }
00557     }
00558       break;
00559       
00560     case SLOT_SHRINKING_FACTOR:
00561       TYPE_CHECK (type_box (val) == type_helper<int>::id);
00562       if (QTMWidget* tmw= qobject_cast<QTMWidget*> (tm_canvas())) {
00563         int new_sf = open_box<int> (val);
00564         if (DEBUG_QT) cout << "New shrinking factor :" << new_sf << LF;
00565         tmw->tm_widget()->handle_set_shrinking_factor (new_sf);
00566       }
00567       break;
00568       
00569     case SLOT_FILE:
00570     {
00571       TYPE_CHECK (type_box (val) == type_helper<string>::id);
00572       string file = open_box<string> (val);
00573       if (DEBUG_QT) cout << "File: " << file << LF;
00574 #if (QT_VERSION >= 0x040400)
00575       view->window()->setWindowFilePath(to_qstring(tm_var_encode(file)));
00576 #endif
00577     }
00578       break;
00579       
00580       
00581     default:
00582       qt_view_widget_rep::send (s, val);
00583   }
00584 }
00585 
00586 
00587 blackbox
00588 qt_tm_widget_rep::query (slot s, int type_id) {
00589   if (DEBUG_QT)
00590     cout << "qt_tm_widget_rep::query " << slot_name (s) << LF;
00591   
00592   switch (s) {
00593     case SLOT_SCROLL_POSITION:
00594     {
00595       TYPE_CHECK (type_id == type_helper<coord2>::id);
00596       QPoint pt= tm_canvas()->origin();
00597       if (DEBUG_QT)
00598         cout << "Position (" << pt.x() << "," << pt.y() << ")\n";
00599       return close_box<coord2> (from_qpoint (pt));
00600     }
00601       
00602     case SLOT_EXTENTS:
00603     {
00604       TYPE_CHECK (type_id == type_helper<coord4>::id);
00605       QRect rect= tm_canvas()->extents();
00606       coord4 c= from_qrect (rect);
00607       //if (DEBUG_QT) 
00608         cout << "Canvas geometry " << rect << LF;
00609       return close_box<coord4> (c);
00610     }
00611       
00612     case SLOT_VISIBLE_PART:
00613     {
00614       TYPE_CHECK (type_id == type_helper<coord4>::id);
00615       QSize sz = tm_canvas()->surface()->size();
00616         //sz.setWidth(sz.width()-2);
00617       QPoint pos = tm_canvas()->backing_pos;
00618       coord4 c = from_qrect(QRect(pos,sz));
00619       if (DEBUG_QT) 
00620         cout << "Visible Region " << c << LF;
00621       return close_box<coord4> (c);
00622     }
00623       
00624     case SLOT_USER_ICONS_VISIBILITY:
00625       TYPE_CHECK (type_id == type_helper<bool>::id);
00626       return close_box<bool> (visibility[4]);
00627       
00628     case SLOT_FOCUS_ICONS_VISIBILITY:
00629       TYPE_CHECK (type_id == type_helper<bool>::id);
00630       return close_box<bool> (visibility[3]);
00631       
00632     case SLOT_MODE_ICONS_VISIBILITY:
00633       TYPE_CHECK (type_id == type_helper<bool>::id);
00634       return close_box<bool> (visibility[2]);
00635       
00636     case SLOT_MAIN_ICONS_VISIBILITY:
00637       TYPE_CHECK (type_id == type_helper<bool>::id);
00638       return close_box<bool> (visibility[1]);
00639       
00640     case SLOT_HEADER_VISIBILITY:
00641       TYPE_CHECK (type_id == type_helper<bool>::id);
00642       return close_box<bool> (visibility[0]);
00643       
00644     case SLOT_FOOTER_VISIBILITY:
00645       TYPE_CHECK (type_id == type_helper<bool>::id);
00646       return close_box<bool> (visibility[5]);
00647       
00648     case SLOT_INTERACTIVE_INPUT:
00649       TYPE_CHECK (type_id == type_helper<string>::id);
00650     {
00651       qt_input_text_widget_rep* w =((qt_input_text_widget_rep*) int_input.rep);
00652       if (w->ok) {
00653         return close_box<string>(scm_quote(w->text));
00654       } else {
00655         return close_box<string>("#f");
00656       }
00657     }
00658       
00659     case SLOT_INTERACTIVE_MODE:
00660       TYPE_CHECK (type_id == type_helper<bool>::id);
00661       return close_box<bool> (false); // FIXME: who needs this info?
00662       
00663     default:
00664       return qt_view_widget_rep::query (s, type_id);
00665   }
00666 }
00667 
00668 widget
00669 qt_tm_widget_rep::read (slot s, blackbox index) {
00670   if (DEBUG_QT) cout << "[qt_tm_widget_rep] ";
00671   return qt_view_widget_rep::read (s, index);
00672 }
00673 
00674 
00675 void
00676 qt_tm_widget_rep::install_main_menu () {
00677   widget tmp = main_menu_widget;
00678   main_menu_widget = waiting_main_menu_widget;
00679   QMenu* m= concrete (main_menu_widget)->get_qmenu();
00680   if (m) {
00681     {
00682       // REMARK: We do not want the menubar shared across windows as suggested  
00683       // in http://doc.qt.nokia.com/4.7/qmainwindow.html#menuBar
00684       // e.g. :
00685       //
00686       //     QMenuBar *dest = new QMenuBar(0);
00687       //     tm_mainwindow()->setMenuBar(dest);
00688       //
00689       // as the default behavior on MacOS. The main reason is that in TeXmacs
00690       // different widows can have different main menus so that it is indeed
00691       // appropriate change the main menu as the window focus changes. 
00692       // So we kindly ask to each window to give us its own menu and we install
00693       // there our actions.
00694       // So we do:
00695 
00696       QMenuBar *dest = tm_mainwindow()->menuBar();
00697       
00698       // and everything is fine.
00699       // Also please note that we have to do the replacement and not simply 
00700       // install the menu returned by get_qmenu() since the main menu there 
00701       // could contain some defaults items appropriate for the give OS (like the
00702       // service menu on MacOS) which are not present in our menu widget.
00703       
00704       QWidget *src = m;
00705       replaceActions(dest,src);
00706       QList<QAction*> list = dest->actions();
00707       for (int i= 0; i < list.count(); i++) {
00708         QAction* a= list[i];
00709         if (a->menu()) {
00710           QObject::connect(a->menu(), SIGNAL(aboutToShow()),
00711                            the_gui->gui_helper, SLOT(aboutToShowMainMenu()));
00712           QObject::connect(a->menu(), SIGNAL(aboutToHide()),
00713                            the_gui->gui_helper, SLOT(aboutToHideMainMenu()));
00714         }
00715       }
00716     }
00717   }
00718 }
00719 
00720 void
00721 qt_tm_widget_rep::write (slot s, blackbox index, widget w) {
00722   if (DEBUG_QT)
00723     cout << "qt_tm_widget_rep::write " << slot_name (s) << LF;
00724   
00725   switch (s) {
00726     case SLOT_SCROLLABLE:
00727     {
00728       check_type_void (index, "SLOT_SCROLLABLE");
00729       QStackedWidget* tw= tm_centralwidget();
00730       QWidget *new_widget= concrete(w)->get_canvas();
00731       QWidget *old_widget= tw->currentWidget();
00732       if (old_widget) {
00733         tw->removeWidget(old_widget);
00734         old_widget->setParent(NULL);
00735       }
00736       if (new_widget) {
00737         tw->addWidget(new_widget);
00738       }
00739       QTMWidget* new_canvas= qobject_cast<QTMWidget*>(new_widget);
00740       QTMWidget* old_canvas= qobject_cast<QTMWidget*>(old_widget);
00741       if (old_canvas) {
00742           QTMWidget::all_widgets.remove(old_canvas);
00743       }
00744       if (new_canvas) {
00745         QTMWidget::all_widgets.insert(new_canvas);
00746         new_canvas->setFocusPolicy (Qt::StrongFocus);
00747         new_canvas->setFocus ();
00748       }        
00749     }
00750       break;
00751       
00752     case SLOT_MAIN_MENU:
00753       check_type_void (index, "SLOT_MAIN_MENU");
00754     {
00755       waiting_main_menu_widget = w;
00756       if (menu_count <=0) {
00757         install_main_menu();
00758       } else { 
00759           // menu interaction ongoing.
00760           // postpone menu installation when the menu interaction is done
00761         if (DEBUG_QT)
00762           cout << "Main menu is busy: postponing menu installation" << LF;
00763         if (!contains(waiting_widgets,this))
00764           waiting_widgets << this;
00765       }
00766     }
00767       break;
00768       
00769     case SLOT_MAIN_ICONS:
00770       check_type_void (index, "SLOT_MAIN_ICONS");
00771     {
00772         //cout << "widget :" << (void*)w.rep << LF;
00773       main_icons_widget = w;
00774       QMenu* m= concrete (w)->get_qmenu();
00775       replaceButtons (mainToolBar, m);
00776       updateVisibility();
00777     }
00778       break;
00779       
00780     case SLOT_MODE_ICONS:
00781       check_type_void (index, "SLOT_MODE_ICONS");
00782     {   
00783       mode_icons_widget = w;
00784       QMenu* m= concrete (w)->get_qmenu();
00785       replaceButtons (modeToolBar, m);
00786       updateVisibility();
00787     }
00788       break;
00789       
00790     case SLOT_FOCUS_ICONS:
00791       check_type_void (index, "SLOT_FOCUS_ICONS");
00792     {   
00793       focus_icons_widget = w;
00794       QMenu* m= concrete (w)->get_qmenu();
00795       replaceButtons (focusToolBar, m);
00796       updateVisibility();
00797     }
00798       break;
00799       
00800     case SLOT_USER_ICONS:
00801       check_type_void (index, "SLOT_USER_ICONS");
00802     {   
00803       user_icons_widget = w;
00804       QMenu* m= concrete (w)->get_qmenu();
00805       replaceButtons (userToolBar, m);
00806       updateVisibility();
00807     }
00808       break;
00809       
00810     case SLOT_INTERACTIVE_PROMPT:
00811       check_type_void (index, "SLOT_INTERACTIVE_PROMPT");
00812       int_prompt= concrete (w);
00813       break;
00814       
00815     case SLOT_INTERACTIVE_INPUT:
00816       check_type_void (index, "SLOT_INTERACTIVE_INPUT");
00817       int_input= concrete (w);
00818       break;
00819       
00820     default:
00821       qt_view_widget_rep::write (s, index, w);
00822   }
00823 }
00824 
00825 
00826 void
00827 qt_tm_widget_rep::set_full_screen(bool flag) {
00828   full_screen = flag;
00829   QWidget *win = tm_mainwindow()->window();  
00830   if (win) {
00831     if (flag ) {
00832       // remove the borders from some widgets
00833       tm_scrollarea()->setFrameShape(QFrame::NoFrame);
00834 #ifdef UNIFIED_TOOLBAR
00835       //HACK: we disable unified toolbar since otherwise
00836       //  the application will crash when we return in normal mode
00837       // (bug in Qt? present at least with 4.7.1)
00838       tm_mainwindow()->setUnifiedTitleAndToolBarOnMac(false);
00839       tm_mainwindow()->centralWidget()->layout()->setContentsMargins(0,0,0,0);
00840 #endif
00841 //      tm_mainwindow()->window()->setContentsMargins(0,0,0,0);
00842       //win->showFullScreen();
00843        win->setWindowState(win->windowState() ^ Qt::WindowFullScreen);
00844     } else {
00845       bool cache = visibility[0];
00846       visibility[0] = false;
00847       updateVisibility();
00848 //      win->showNormal();
00849       win->setWindowState(win->windowState() ^ Qt::WindowFullScreen);
00850 
00851       visibility[0] = cache;
00852       updateVisibility();
00853       // reset the borders of some widgets
00854       tm_scrollarea()->setFrameShape(QFrame::Box);
00855 #ifdef UNIFIED_TOOLBAR
00856       tm_mainwindow()->centralWidget()->layout()->setContentsMargins(2,2,2,2);
00857       //HACK: we reenable unified toolbar (see above HACK) 
00858       //  the application will crash return in normal mode
00859       tm_mainwindow()->setUnifiedTitleAndToolBarOnMac(true);
00860 #endif
00861     }
00862   }
00863   
00864   tm_scrollarea()->setHorizontalScrollBarPolicy(flag ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAsNeeded);
00865   tm_scrollarea()->setVerticalScrollBarPolicy(flag ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAsNeeded);
00866 }
00867 
00868 // creates a decorated window with name s and contents w
00869 widget
00870 qt_tm_widget_rep::plain_window_widget (string s, command q) {
00871 
00872   widget w= qt_view_widget_rep::plain_window_widget (s, q);
00873   qt_window_widget_rep* wid= (qt_window_widget_rep*) (w.rep);   // to manage correctly retain counts
00874   return wid;
00875 }