Inspector.cxx

Go to the documentation of this file.
00001 
00012 #ifdef HAVE_CONFIG_H
00013 #include "config.h"
00014 #endif
00015 
00016 #ifdef _MSC_VER
00017 #include "msdevstudio/MSconfig.h"
00018 #endif
00019 
00020 #include "Inspector.h"
00021 
00022 #include "CanvasSelectionEvent.h"
00023 #include "CanvasWindow.h"
00024 #include "PlotterEvent.h"
00025 #include "WindowController.h"
00026 #include "AxisWidget.h"
00027 #include "QtFont.h"
00028 
00029 #include <qapplication.h>
00030 
00031 #if QT_VERSION < 0x040000
00032 #include "qlistview.h"
00033 #include "qbuttongroup.h"
00034 #include "qgroupbox.h"
00035 #include "qwidgetstack.h"
00036 #include "qlayout.h"
00037 #else
00038 #include <QtCore/QCustomEvent>
00039 #include <QtGui/QHBoxLayout>
00040 #include <QtGui/QVBoxLayout>
00041 #include "q3button.h"
00042 #include "q3listview.h"
00043 #include "q3buttongroup.h"
00044 #include "q3groupbox.h"
00045 #include "q3widgetstack.h"
00046 #endif
00047 
00048 #include "qtooltip.h"
00049 #include "qcheckbox.h"
00050 #include "qcolordialog.h"
00051 #include "qcombobox.h"
00052 #include "qlineedit.h"
00053 #include "qmessagebox.h"
00054 #include "qpushbutton.h"
00055 #include "qradiobutton.h"
00056 #include "qslider.h"
00057 #include "qlabel.h"
00058 #include "qinputdialog.h"
00059 #include "qfontdialog.h"
00060 #include "qtabwidget.h"
00061 #include "qsettings.h"
00062 #include "qstringlist.h"
00063 #include "qtextstream.h"
00064 
00065 
00066 #include "colorreps/BinToColor.h"
00067 #include "controllers/CutController.h"
00068 #include "controllers/DataRepController.h"
00069 #include "controllers/DisplayController.h"
00070 #include "controllers/FunctionController.h"
00071 
00072 #include "datareps/FunctionParameter.h"
00073 #include "datareps/CompositeFunctionRep.h"
00074 
00075 #include "datasrcs/DataSourceController.h"
00076 #include "datasrcs/NTuple.h"
00077 #include "datasrcs/TupleCut.h"
00078 
00079 #include "plotters/CutPlotter.h"
00080 #include "plotters/TextPlotter.h"
00081 
00082 #include "projectors/NTupleProjector.h"
00083 
00084 #include "reps/ContourPointRep.h"
00085 #include "transforms/PeriodicBinaryTransform.h"
00086 
00087 #ifdef HAVE_ROOT
00088 #include "root/RootController.h"
00089 #include "boost/tokenizer.hpp"
00090 #include "boost/lexical_cast.hpp"
00091 #endif
00092 
00093 #include "pattern/string_convert.h"
00094 
00095 #include <algorithm>
00096 #include <iostream>
00097 #include <stdexcept>
00098 
00099 using std::cout;
00100 using std::endl;
00101 
00102 #include <cmath>
00103 #include <cassert>
00104 
00105 using std::map;
00106 using std::runtime_error;
00107 using std::string;
00108 using std::vector;
00109 
00110 using namespace hippodraw;
00111 
00112 namespace {
00113    void stringTokenize(std::string input, const std::string & delimiters,
00114                        std::vector<std::string> & tokens, bool clear=true) {
00115       if (clear) {
00116          tokens.clear();
00117       }
00118       std::string::size_type j;
00119       while ( (j = input.find_first_of(delimiters)) != std::string::npos ) {
00120          if (j != 0) {
00121             tokens.push_back(input.substr(0, j));
00122          }
00123          input = input.substr(j+1);
00124       }
00125       tokens.push_back(input);
00126       if (tokens.back() == "") {
00127          tokens.pop_back();
00128       }
00129    }
00130 }
00131 
00132 QString    Inspector::s_registry ( "/Trolltech" );
00133 
00134 
00135 Inspector::
00136 Inspector ( QWidget * parent, const char * name, bool modal, Qt::WFlags flags )
00137   : InspectorBase ( parent, name, modal, flags ),
00138     m_plotter ( 0 ),
00139     m_is_updating ( false ),
00140     m_user_models_loaded ( false )
00141 {
00142   init ();
00143   FunctionController * controller = FunctionController::instance();
00144   const vector < string > & names = controller -> getFitterNames ();
00145     for ( unsigned int i = 0; i < names.size(); i++ ) {
00146     QString name ( names[i].c_str() );
00147     m_fitter_names -> insertItem ( name );
00148   }
00149 #if QT_VERSION < 0x040000
00150 #else // correct code generated by uic3 with release 4.1.1
00151 //     for ( int i = 0; i < 3; i++ ) {
00152 // o      QAbstractButton * b = axis_button_group -> find ( i );
00153 //       axis_button_group -> remove ( b );
00154 //     }
00155 //     radioButton38 = new QRadioButton(axis_button_group);
00156 //     radioButton38->setObjectName(QString::fromUtf8("radioButton38"));
00157 //     radioButton38->setEnabled(true);
00158 //     radioButton38->setGeometry(QRect(10, 0, 65, 30));
00159 //     radioButton38->setMinimumSize(QSize(60, 0));
00160 //     radioButton38->setChecked(true);
00161 
00162 //     radioButton39 = new QRadioButton(axis_button_group);
00163 //     radioButton39->setObjectName(QString::fromUtf8("radioButton39"));
00164 //     radioButton39->setEnabled(true);
00165 //     radioButton39->setGeometry(QRect(80, 0, 65, 30));
00166 //     radioButton39->setMinimumSize(QSize(65, 0));
00167 //     radioButton39->setChecked(false);
00168 
00169 //     radioButton40 = new QRadioButton(axis_button_group);
00170 //     radioButton40->setObjectName(QString::fromUtf8("radioButton40"));
00171 //     radioButton40->setEnabled(true);
00172 //     radioButton40->setGeometry(QRect(150, 0, 65, 30));
00173 //     radioButton40->setMinimumSize(QSize(65, 0));
00174 //     radioButton40->setChecked(false);
00175 
00176     // add index change for Qt 4
00177     connect ( m_all_ntuples, SIGNAL ( currentIndexChanged ( int ) ),
00178               this, SLOT ( dataNTupleSelChanged ( int ) ) );
00179 #endif
00180 
00181 
00182   connect ( axisWidget1, SIGNAL ( lowTextReturnPressed() ),
00183             this, SLOT ( setLowText() ) );
00184 
00185   connect ( axisWidget2, SIGNAL ( lowTextReturnPressed() ),
00186             this, SLOT ( cutText_returnPressed() ) );
00187 
00188   connect ( axisWidget1, SIGNAL ( highTextReturnPressed() ),
00189             this, SLOT ( setHighText() ) );
00190 
00191   connect ( axisWidget2, SIGNAL ( highTextReturnPressed() ),
00192             this, SLOT ( cutText_returnPressed() ) );
00193 
00194   connect ( axisWidget1, SIGNAL ( lowSliderReleased() ),
00195             this, SLOT ( lowRangeDrag() ) );
00196 
00197   connect ( axisWidget2, SIGNAL ( lowSliderReleased() ),
00198             this, SLOT ( cutLowSlider_sliderReleased() ) );
00199 
00200   connect ( axisWidget1, SIGNAL ( lowSliderPressed() ),
00201             this, SLOT ( setDragOn() ) );
00202 
00203   connect ( axisWidget1, SIGNAL ( highSliderPressed() ),
00204             this, SLOT ( setDragOn() ) );
00205 
00206   connect ( axisWidget1, SIGNAL ( lowSliderValueChanged ( int ) ),
00207             this, SLOT ( setLowRange ( int ) ) );
00208 
00209   connect ( axisWidget2, SIGNAL ( lowSliderValueChanged ( int ) ),
00210             this, SLOT ( cutLowSlider_sliderMoved ( int ) ) );
00211 
00212   connect ( axisWidget1, SIGNAL ( highSliderReleased() ),
00213             this, SLOT ( highRangeDrag() ) );
00214 
00215   connect ( axisWidget2, SIGNAL ( highSliderReleased() ),
00216             this, SLOT ( cutHighSlider_sliderReleased() ) );
00217 
00218   connect ( axisWidget1, SIGNAL ( highSliderValueChanged ( int ) ),
00219             this, SLOT ( setHighRange ( int ) ) );
00220 
00221   connect ( axisWidget2, SIGNAL ( highSliderValueChanged ( int ) ),
00222             this, SLOT ( cutHighSlider_sliderMoved ( int ) ) );
00223 
00224   connect ( axisWidget1, SIGNAL ( zoomPanCheckBoxClicked () ),
00225             this, SLOT ( axisZoomPanCheckBox_clicked () ) );
00226 
00227   connect ( axisWidget2, SIGNAL ( zoomPanCheckBoxClicked () ),
00228             this, SLOT ( cutZoomPanCheckBox_clicked () ) );
00229 
00230   axisWidget2 -> setCut ( true );
00231   // Default position of the sliders is center which corrosponds to
00232   // a value of 50. So initialization takes place as 50.
00233   m_lowslider1_last_val  = 50;
00234   m_highslider1_last_val = 50;
00235 
00236   updatePlotTypes ();
00237 
00238 }
00239 
00240 Inspector::
00241 ~Inspector ()
00242 {
00243   DisplayController * controller = DisplayController::instance ();
00244   delete controller;
00245 
00246 }
00247 
00248 void
00249 Inspector::
00250 init()
00251 {
00252 
00253   unsigned int n = 5;
00254   m_new_labels.reserve ( n );
00255   m_new_labels.push_back ( new_binding_0 );
00256   m_new_labels.push_back ( new_binding_1 );
00257   m_new_labels.push_back ( new_binding_2 );
00258   m_new_labels.push_back ( new_binding_3 );
00259   m_new_labels.push_back ( new_binding_4 );
00260 
00261   m_new_combos.reserve ( n );
00262   m_new_combos.push_back ( new_combo_0 );
00263   m_new_combos.push_back ( new_combo_1 );
00264   m_new_combos.push_back ( new_combo_2 );
00265   m_new_combos.push_back ( new_combo_3 );
00266   m_new_combos.push_back ( new_combo_4 );
00267 
00268   m_sel_labels.reserve ( n );
00269   m_sel_labels.push_back ( sel_binding_0 );
00270   m_sel_labels.push_back ( sel_binding_1 );
00271   m_sel_labels.push_back ( sel_binding_2 );
00272   m_sel_labels.push_back ( sel_binding_3 );
00273   m_sel_labels.push_back ( sel_binding_4 );
00274 
00275   m_sel_combos.reserve ( n );
00276   m_sel_combos.push_back ( sel_combo_0 );
00277   m_sel_combos.push_back ( sel_combo_1 );
00278   m_sel_combos.push_back ( sel_combo_2 );
00279   m_sel_combos.push_back ( sel_combo_3 );
00280   m_sel_combos.push_back ( sel_combo_4 );
00281 
00282   QSize cur_size = size();
00283   setFixedSize ( cur_size );
00284 
00285   m_min_entries = 0;
00286   m_rotate_enable = true;
00287   m_dragging = false;
00288   m_axis = Axes::X;
00289   m_layoutWidget = new QWidget( currentPlot, "m_Layout" );
00290   m_layoutWidget->setGeometry( QRect ( 7, 75, 360, 0 ) );
00291   m_vLayout = new QVBoxLayout( m_layoutWidget, 0, 6, "m_vLayout");
00292 
00293   newPlotButton->setEnabled( false );
00294 
00295   m_newLayoutWidget = new QWidget ( m_new_plot_box, "m_newLayout" );
00296   m_newLayoutWidget->setGeometry( QRect ( 7, 75, 360, 0 ) );
00297   m_newVLayout = new QVBoxLayout( m_newLayoutWidget, 0, 6,
00298                                   "m_newVLayout");
00299 
00300   updateValueCombo ();
00301 
00302   m_interval_le->setDisabled ( true );
00303 
00304   // Add fixed sized column headers to the function params group box
00305   // This we could not do using the designer.
00306   m_FunctionParamsListView -> addColumn( QString( "Function" ),40 );
00307   m_FunctionParamsListView -> addColumn( QString( "Params" ),  20 );
00308   m_FunctionParamsListView -> addColumn( QString( "Value" ),   20 );
00309   m_FunctionParamsListView -> addColumn( QString( "Error" ),   20 );
00310   m_FunctionParamsListView -> addColumn( QString( "Fixed"  ),   3 );
00311   m_FunctionParamsListView -> setSorting ( -1 );
00312 
00313   // vector of QRadioButtons on transform tabbed panel.  Needed for
00314   // workaround of faulty code generation of Qt 4.1.1
00315   m_transform_buttons.push_back ( m_linear );
00316   m_transform_buttons.push_back ( m_logy );
00317   m_transform_buttons.push_back ( m_logx );
00318   m_transform_buttons.push_back ( m_logxy );
00319   m_transform_buttons.push_back ( m_hammer );
00320   m_transform_buttons.push_back ( m_lambert );
00321   m_transform_buttons.push_back ( m_Car );
00322   m_transform_buttons.push_back ( m_Mer );
00323   m_transform_buttons.push_back ( m_Gls );
00324   m_transform_buttons.push_back ( m_Arc );
00325   m_transform_buttons.push_back ( m_Tan );
00326   m_transform_buttons.push_back ( m_Sin );
00327   m_transform_buttons.push_back ( m_Stg );
00328   m_transform_buttons.push_back ( m_Air );
00329 }
00330 
00331 void
00332 Inspector::
00333 updateValueCombo ()
00334 {
00335   DisplayController * controller = DisplayController::instance ();
00336   const vector < string > & names = controller -> getValueTransformTypes ();
00337   m_value_combo -> clear ();
00338   unsigned int size = names.size ();
00339   for ( unsigned int i = 0; i < size; i++ ) {
00340     m_value_combo -> insertItem ( names[i].c_str() );
00341   }
00342 }
00343 
00344 void
00345 Inspector::
00346 enableNewPlotBox ( bool yes )
00347 {
00348   m_new_plot_box->setEnabled ( yes );
00349   m_summary->setEnabled ( yes );
00350 }
00351 
00352 #if QT_VERSION < 0x040000
00353 void Inspector::customEvent ( QCustomEvent * event )
00354 #else
00355 void Inspector::customEvent ( QEvent * event )
00356 #endif
00357 {
00358   PlotterEvent * pev = dynamic_cast < PlotterEvent * > ( event );
00359   if ( pev != 0 ) {
00360     m_plotter = pev -> plotter ();
00361     update ();
00362   }
00363 
00364   CanvasSelectionEvent * ev
00365     = dynamic_cast < CanvasSelectionEvent * > ( event );
00366   if ( ev != 0  ) {
00367     m_plotter_list = ev -> getPlotters ();
00368     if ( m_plotter_list.size () == 1 ) {
00369       m_plotter = m_plotter_list.front ();
00370     }
00371     else {
00372       m_plotter = 0;
00373     }
00374     update ();
00375   }
00376 }
00377 
00378 PlotterBase *
00379 Inspector::
00380 getPlotter ()
00381 {
00382   return m_plotter;
00383 }
00384 
00385 void
00386 Inspector::
00387 setZRadioButton ( bool enabled )
00388 {
00389   if (!enabled && m_axis == Axes::Z )
00390     {
00391 #if QT_VERSION < 0x040000
00392       QButton * b = axis_button_group -> find ( 0 );
00393 #else
00394       QAbstractButton * b = axis_button_group -> find ( 2 );
00395 #endif
00396       QRadioButton * button = dynamic_cast< QRadioButton * > ( b );
00397       button -> setChecked ( true );
00398       m_axis = Axes::X;
00399       updateAxisTab ();
00400     }
00401 
00402 #if QT_VERSION < 0x040000
00403   QButton * button = axis_button_group -> find ( 2 );
00404 #else
00405   QAbstractButton * button = axis_button_group -> find ( 2 );
00406 #endif
00407 
00408   button -> setEnabled ( enabled );
00409 }
00410 
00411 void
00412 Inspector::
00413 tabChanged ()
00414 {
00415   update ();
00416 }
00417 
00418 void
00419 Inspector::
00420 update ()
00421 { 
00422   if ( isHidden() == true ) return;
00423   m_is_updating = true;
00424   int index = m_plot_tab -> currentPageIndex ();
00425 
00426   switch ( index )
00427     {
00428     case ( 0 ) :
00429       updateDataTab();
00430       break;
00431     case ( 1 ) :
00432       updatePlotTab();
00433       break;
00434     case ( 2 ) :
00435       updateAxisTab();
00436       break;
00437     case ( 3 ) :
00438       updateCutsTab();
00439       break;
00440     case ( 4 ) :
00441       updateFunctionsTab();
00442       break;
00443     case ( 5 ) :
00444       updateSummaryTab ();
00445       break;
00446     case ( 6 ) :
00447       updateTransformTab ();
00448       break;
00449     default :
00450       assert ( false );
00451       break;
00452     }
00453   
00454 //   if ( m_plotter != 0 ) {
00455 //     bool hasZ = m_plotter -> hasAxis ( Axes::Z );
00456 //     setZRadioButton ( hasZ );
00457         
00458 //   }
00459 
00460   m_is_updating = false;
00461   updateCutsActive ();
00462   
00463 }
00464 
00465 void
00466 Inspector::
00467 updateCutsActive ()
00468 {
00469   PlotterBase * plotter = getPlotter ();
00470   if ( plotter == 0 ) {
00471     setAllCutsActive ( true );
00472   }
00473   else {
00474     vector < PlotterBase * > cutlist;
00475     CutController * controller = CutController::instance ();
00476     controller -> fillCutList ( plotter, cutlist );
00477 
00478     if ( cutlist.empty () ) {
00479       setAllCutsActive ( false );
00480       return;
00481     }
00482     else {
00483       setAllCutsActive ( false );
00484       vector < PlotterBase * >::iterator first = cutlist.begin();
00485       while ( first != cutlist.end () ) {
00486         PlotterBase * pb = *first++;
00487         CutPlotter * cutter = dynamic_cast < CutPlotter * > ( pb );
00488         assert ( cutter );
00489         cutter -> setActive ( true );
00490       }
00491     }
00492   }
00493 }
00494 
00495 std::string
00496 Inspector::
00497 getSelectedDataSourceName () const
00498 {
00499   string s;
00500   const vector < string > & names
00501     = DataSourceController::instance () -> getNTupleNames ();
00502   int index = m_all_ntuples -> count () == 0 ? -1 : m_all_ntuples -> currentItem ();
00503   if ( index >= 0 &&
00504        names.empty () == false ) {
00505     s = names [ index ];
00506   }
00507 
00508   return s;
00509 }
00510 
00511 void
00512 Inspector::
00513 updateNewPlotControls ()
00514 {
00515   const vector < string > & nt_vector
00516     = DataSourceController::instance() -> getNTupleNames ();
00517 
00518   
00519   if ( nt_vector.empty () ) {
00520    
00521     m_all_ntuples -> clear ();
00522     return;
00523   }
00524 
00525   unsigned int count = m_all_ntuples -> count ();
00526   if ( count == nt_vector.size () ) return;
00527 
00528 #ifdef ITERATOR_MEMBER_DEFECT
00529   //std::
00530 #endif
00531 
00532   m_all_ntuples -> clear();
00533   vector < string > ::const_iterator first = nt_vector.begin();
00534   while ( first != nt_vector.end() ) {
00535     const string & name = *first++;
00536     m_all_ntuples->insertItem ( name.c_str() );
00537   }
00538 
00539   if ( m_all_ntuples -> count () != 0 ) {
00540     const string & name = nt_vector.back ();
00541 
00542     setNewPlotNTuple ( name );
00543     
00544 
00545     availPlotTypesActivated ( name.c_str() );
00546         
00547   }
00548   else {
00549     availPlotTypesActivated ( QString::null );
00550         
00551   }
00552 }
00553 
00554 void
00555 Inspector::
00556 setNewPlotNTuple ( const std::string & name )
00557 {
00558   const vector < string > & nt_vector
00559     = DataSourceController::instance() -> getNTupleNames ();
00560 
00561   for ( unsigned int i = 0; i < nt_vector.size(); i++ ) {
00562     if ( nt_vector[i] == name ) {
00563       unsigned int current = m_all_ntuples -> currentItem ();
00564       if ( current != i ) {
00565         m_all_ntuples -> setCurrentItem ( i );
00566       }
00567       break;
00568     }
00569   }
00570 
00571   // Update tip tool.
00572   QToolTip::remove(m_all_ntuples);
00573   const QString tip=getSelectedDataSourceName().c_str();
00574   QToolTip::add( m_all_ntuples, tip );
00575 
00576 }
00577 
00578 void
00579 Inspector::
00580 dataTupleNameChanged ( const QString & )
00581 {
00582   m_last_ntuple_edited = m_all_ntuples -> currentItem ();
00583 
00584 }
00585 
00586 void
00587 Inspector::
00588 changeNTupleName ( const QString & text )
00589 {
00590   DataSourceController * controller = DataSourceController::instance ();
00591   vector < DataSource * > nt_vector;
00592   controller -> getDataSources ( nt_vector ); // get all
00593   DataSource * ds = nt_vector [ m_last_ntuple_edited ];
00594   if ( ds == 0 ) return;
00595 
00596   const string new_name = text.latin1();
00597 
00598   ds -> setName ( new_name );
00599 }
00600 
00601 void
00602 Inspector::
00603 dataNTupleSelChanged ( int item )
00604 {
00605   DataSourceController * controller = DataSourceController::instance ();
00606   controller -> setCurrentIndex ( item );
00607 
00608   m_all_ntuples -> setCurrentItem ( item );
00609   QString text ( "" );
00610 
00611   availPlotTypesActivated ( text );
00612 
00613   // Update tip tool.
00614   QToolTip::remove(m_all_ntuples);
00615   const QString tip=getSelectedDataSourceName().c_str();
00616   QToolTip::add( m_all_ntuples, tip );
00617 
00618 }
00619 
00620 void
00621 Inspector::
00622 allNtupleComboActivated ( const QString & text )
00623 {
00624   // Change the number and type of axes depending on what is selected
00625   // inside m_availPlotTypes. Then insert the axis labels based on the
00626   // selection of nTupleNameComboBox.
00627 
00628   changeNTupleName ( text );
00629   m_all_ntuples -> setCurrentItem ( m_last_ntuple_edited );
00630   m_all_ntuples -> changeItem ( text, m_last_ntuple_edited );
00631 
00632   DataSourceController * controller = DataSourceController::instance ();
00633   int index = m_all_ntuples -> currentItem ();
00634   controller -> setCurrentIndex( index );
00635 
00636   availPlotTypesActivated ( text );
00637 }
00638 
00639 void
00640 Inspector::
00641 sel_combo_0_activated ( const QString & label )
00642 {
00643   axisLabelChanged ( 0, label );
00644 }
00645 
00646 void
00647 Inspector::
00648 sel_combo_1_activated ( const QString & label )
00649 {
00650   axisLabelChanged ( 1, label );
00651 }
00652 
00653 void
00654 Inspector::
00655 sel_combo_2_activated ( const QString & label )
00656 {
00657   axisLabelChanged ( 2, label );
00658 }
00659 
00660 void
00661 Inspector::
00662 sel_combo_3_activated ( const QString & label )
00663 {
00664   axisLabelChanged ( 3, label );
00665 }
00666 
00667 void
00668 Inspector::
00669 axisLabelChanged ( int index, const QString & label )
00670 {
00671   if ( m_plotter_list.size () > 1 ) {
00672     multiplePlotError ();
00673     return;
00674   }
00675 
00676   PlotterBase * plotter = getPlotter ();
00677   if ( !plotter ) return ;
00678 
00679   QString axisName = m_sel_labels [index] -> text();
00680   const std::string strAxisName ( axisName.latin1() );
00681   const std::string strLabel( label.latin1() );
00682 
00683   DisplayController * controller = DisplayController::instance();
00684   controller -> setAxisBinding ( plotter, strAxisName, strLabel );
00685 
00686   bool valid = controller -> isDataValid ( plotter );
00687   if ( valid == false ) {
00688     invalidDataWarning ();
00689   }
00690 }
00691 
00692 void
00693 Inspector::
00694 updatePlotTypes ()
00695 {
00696   const vector < string > & dataRepNames
00697     = DisplayController::instance() -> getDisplayTypes ();
00698   if ( dataRepNames.empty () ) return;
00699   unsigned int size = m_availPlotTypes -> count ();
00700 
00701   if ( dataRepNames.size() != size ) {
00702     m_availPlotTypes->clear();
00703 
00704     vector < string > ::const_iterator first = dataRepNames.begin ();
00705     while ( first != dataRepNames.end() ) {
00706       const string & name = *first++;
00707       if ( name.find ( "Static" ) != string::npos ) continue;
00708       m_availPlotTypes->insertItem ( name.c_str() );
00709         }
00710      m_availPlotTypes->setCurrentItem ( 2 ); //Histogram
00711   }
00712 
00713   newPlotButton->setEnabled( true );
00714 }
00715 
00716 void
00717 Inspector::
00718 clear ( std::vector < QLabel * > & labels,
00719         std::vector < QComboBox * > & combos )
00720 {
00721   unsigned int size = combos.size ();
00722   for ( unsigned int i = 0; i < size; i++ ) {
00723     QComboBox * box = combos [ i ];
00724     box -> clear ();
00725     box -> setEnabled ( false );
00726     QLabel * label = labels [ i ];
00727     label -> setEnabled ( false );
00728   }
00729 }
00730 
00731 void
00732 Inspector::
00733 availPlotTypesActivated ( const QString & )
00734 {
00735   int index = m_all_ntuples -> count () == 0 ? -1 : m_all_ntuples -> currentItem ();
00736   vector < DataSource * > nt_vector;
00737   DataSourceController::instance() -> getDataSources ( nt_vector );
00738 
00739 
00740   int size = static_cast < int > ( nt_vector.size() );
00741   if ( size == 0 ) {
00742     clear ( m_new_labels, m_new_combos );
00743     return;
00744   }
00745  
00746 
00747   if ( ! (index < size ) ) {
00748     index = 0;
00749   }
00750   std::string plotTypeStr( (m_availPlotTypes->currentText()).latin1() );
00751 
00752   DisplayController * controller = DisplayController::instance ();
00753 
00754   const vector < string > & bindingOptions
00755     = controller -> bindingOptions ( plotTypeStr );
00756 
00757   if ( bindingOptions.empty () ) return;
00758 
00759   //Layout the stuff.
00760 
00761   m_newLayoutWidget->hide();
00762 
00763   vector < int > indices;
00764   unsigned int s = m_new_combos.size ();
00765   for ( unsigned int i = 0; i < s; i++ ) {
00766     indices.push_back ( m_new_combos[i] -> currentItem () );
00767   }
00768   clear ( m_new_labels, m_new_combos );
00769   QString qs1;
00770 
00771   if ( index >= 0 ) {
00772     DataSource * nt = nt_vector[index];
00773     const vector < string > & cols = nt->getLabels();
00774 
00775     for ( unsigned int i = 0; i < m_new_combos.size (); i++ ) {
00776       if ( i < bindingOptions.size () ) {
00777         const string & axisName = bindingOptions[i];
00778         
00779         qs1 = ( axisName.c_str() );
00780         m_new_labels [i] -> setEnabled ( true );
00781         m_new_labels [i] -> setText ( qs1 );
00782         m_new_combos [i] -> setEnabled ( true );
00783         for (std::vector<string>::size_type j = 0; j < cols.size(); j++){
00784           m_new_combos [i] -> insertItem ( cols [j].c_str() );
00785         }
00786         
00787         if ( axisName.find ( "optional" ) != string::npos ) {
00788           m_new_combos [i] -> insertItem ( "nil" );
00789           m_new_combos [i] -> setCurrentText ( "nil" );
00790           indices[i] = -1;
00791         }
00792       }
00793     }
00794   }
00795   
00796 
00797   for ( unsigned int i = 0; i < m_new_combos.size(); i++ ) {
00798           
00799 
00800     if ( indices[i] >= 0 &&
00801          indices[i] < m_new_combos[i] -> count () ) {
00802       m_new_combos[i] ->setCurrentItem ( indices[i] );
00803     }
00804   }
00805   
00806 }
00807 
00808 void
00809 Inspector::
00810 updateDataTab()
00811 {
00812 
00813   
00814   updateNewPlotControls ();
00815   
00816 
00817   dataClearSelectedControls ();
00818   
00819 
00820   PlotterBase * plotter = getPlotter ();
00821   updateSelectedPlotType ( plotter );
00822 
00823   
00824 
00825   if ( plotter != 0 ) {
00826           
00827     currentPlot->setEnabled ( true );
00828     bool yes = plotter -> isTargetable ();
00829     if ( yes == false ) return;
00830   }
00831   else {
00832           
00833     if ( m_plotter_list.empty () == true ) {
00834                 
00835       currentPlot -> setDisabled ( true );
00836     }
00837     else {
00838 
00839           currentPlot -> setDisabled ( false );
00840     }
00841         
00842     return;
00843   }
00844   
00845   
00846 
00847   updateSelectedPlotData ( plotter );
00848   
00849 
00850   
00851 
00852 }
00853 
00854 void
00855 Inspector::
00856 updateSelectedPlotDataSource ( const std::string & name )
00857 {
00858   const vector < string > & nt_vector
00859     = DataSourceController::instance () -> getNTupleNames ();
00860 
00861   unsigned int size = nt_vector.size ();
00862   unsigned int count = m_sel_ntuple_name -> count ();
00863   bool refresh = count != size;
00864   if ( refresh ) m_sel_ntuple_name -> clear ();
00865   int jndex = -1;
00866   for ( std::size_t i = 0; i < size; i++ ) {
00867     const string & ntname = nt_vector[i];
00868     if ( ntname == name ) jndex = i;
00869     if ( refresh ) m_sel_ntuple_name -> insertItem ( ntname.c_str () );
00870   }
00871 
00872   if ( jndex < 0 ) { // not bound to ntuple
00873     m_sel_ntuple_name -> setEnabled ( false );
00874   }
00875   else {
00876     m_sel_ntuple_name -> setEnabled ( true );
00877     m_sel_ntuple_name -> setCurrentItem ( jndex );
00878   }
00879   // Update tip tool.
00880   QToolTip::remove(m_sel_ntuple_name );
00881   const QString tip = m_sel_ntuple_name -> currentText ();
00882   QToolTip::add( m_sel_ntuple_name, tip );
00883 
00884 
00885 }
00886 
00887 void
00888 Inspector::
00889 updateSelectedPlotType ( const PlotterBase * plotter )
00890 {
00891   bool yes = plotter != 0;
00892   if ( yes ) {
00893     yes = plotter -> isTargetable ();
00894     if ( yes ) {
00895       DataRep * datarep = plotter -> getTarget ();
00896       yes = datarep != 0;
00897       if ( yes ) {
00898         int index = plotter -> indexOf ( datarep );
00899         DisplayController * controller = DisplayController::instance ();
00900         const string & dataRepName
00901           = controller -> getType ( plotter, index );
00902         QString qst2 ( dataRepName.c_str() );
00903         m_dataRepNameText->setText ( qst2 );
00904       }
00905     }
00906   }
00907 
00908   m_dataRepNameText -> setEnabled ( yes );
00909 }
00910 
00911 void
00912 Inspector::
00913 dataClearSelectedControls ()
00914 {
00915   QLayoutIterator it = m_vLayout->iterator();
00916   while ( it.current() != 0 )
00917     {
00918       QLayoutItem * ptr = it.current();
00919       QHBoxLayout * hbox = static_cast <QHBoxLayout *> (ptr);
00920 
00921       QLayoutIterator hit = hbox->iterator();
00922       while ( hit.current() != 0 )
00923         {
00924           QLayoutItem * hptr = hit.current();
00925           QWidget * hwidget = hptr->widget();
00926           hit.deleteCurrent();
00927           if ( hwidget ) delete ( hwidget );
00928         }
00929 
00930       it.deleteCurrent();
00931 
00932     }
00933 }
00934 
00935 void
00936 Inspector::
00937 updateSelectedPlotData ( const PlotterBase * plotter )
00938 {
00939   DisplayController * controller = DisplayController::instance ();
00940   DataRep * datarep = plotter -> getTarget ();
00941   int index = plotter -> indexOf ( datarep );
00942   assert ( datarep != 0 );
00943 
00944   bool ntuple_bindings = datarep -> hasNTupleBindings ( );
00945   string name;
00946 
00947   if ( ntuple_bindings ) {
00948      name  = controller -> getDataSourceName ( plotter, index );
00949     setNewPlotNTuple ( name );
00950   }
00951   else {
00952     name = "<none>";
00953   }
00954   updateSelectedPlotDataSource ( name );
00955 
00956   //Layout the stuff.
00957 
00958   m_layoutWidget->hide();
00959 
00960   const vector < string > & bindings
00961     = controller -> axisBindings ( plotter, index );
00962   const vector < string > & bindingOptions
00963     = controller -> bindingOptions ( plotter, index );
00964   unsigned int listSize;
00965 
00966   if ( bindings.size() < bindingOptions.size() )
00967     {
00968       listSize = bindings.size();
00969     }
00970   else
00971     {
00972       listSize = bindingOptions.size();
00973     }
00974 
00975   bool yes = plotter -> isTargetable ();
00976   if ( ntuple_bindings == false ||
00977        yes == false ) return;
00978 
00979   // Now add the new hlayouts.
00980 
00981   QString qs1, qs2;
00982 
00983   const vector < string > & cols
00984     = controller -> getDataSourceLabels ( plotter, index );
00985 
00986   if ( cols.empty () ) return;
00987 
00988   clear ( m_sel_labels, m_sel_combos );
00989 
00990   for ( unsigned int i = 0; i < m_sel_combos.size (); i++ )
00991     {
00992       if ( i == listSize ) break;
00993       const string & axisLabel = bindings[i];
00994       const string & axisName = bindingOptions[i];
00995 
00996       qs1 = ( axisName.c_str() );
00997       m_sel_labels [i] -> setEnabled ( true );
00998       m_sel_labels [i] -> setText ( qs1 );
00999 
01000       qs2 = ( axisLabel.c_str() );
01001 
01002       // Insert all column labels from the vector cols, and make qs2
01003       // the current text.
01004 
01005       m_sel_combos [i] -> setEnabled ( true );
01006       for (std::vector<string>::size_type j = 0; j < cols.size(); j++ )
01007         {
01008           m_sel_combos [i] -> insertItem ( cols [j].c_str() );
01009         }
01010       if ( axisName.find ( "optional" ) != string::npos )
01011         {
01012           m_sel_combos [i] -> insertItem ( "nil" );
01013         }
01014       m_sel_combos [i] -> setCurrentText ( qs2 );
01015     }
01016 }
01017 
01018 void
01019 Inspector::
01020 invalidDataWarning ()
01021 {
01022   const QString message = 
01023     "One or more columns of the bound data source\n"
01024     "contains invalid data.";
01025  QMessageBox::warning ( this, // parent
01026                         "Invalid data", // caption
01027                         message,
01028                         QMessageBox::Ok,
01029                         Qt::NoButton,
01030                         Qt::NoButton );
01031 }
01032 
01033 void
01034 Inspector::
01035 noNTupleSelectedError ()
01036 {
01037   const QString message =
01038     "No n-tuple selected error\n"
01039     "Need to load n-tuple to create a plot";
01040   QMessageBox::critical ( this, // parent
01041                           "No n-tuple selected error", // cpation
01042                           message,
01043                           QMessageBox::Ok,
01044                           Qt::NoButton,
01045                           Qt::NoButton );
01046 }
01047 
01048 void
01049 Inspector::
01050 incompatibleDataRepError ( const std::string & type )
01051 {
01052   QString message ("Plot of type " );
01053   message += type.c_str();
01054   message += " can not be added\n"
01055     "to selected plot\n\n"
01056     "It might be incompatible.   For example, \n"
01057     "requiring a Z axis display while selected\n"
01058     "does not have one.";
01059   QMessageBox::critical ( this, // parent
01060                           "Add to plot error", // caption
01061                           message,
01062                           QMessageBox::Ok,
01063                           Qt::NoButton,
01064                           Qt::NoButton );
01065 }
01066 void
01067 Inspector::
01068 incompatibleFitterError ( const std::string & type )
01069 {
01070   QString message ( "Fitter of type " );
01071   message += type.c_str();
01072   message += " can not be used\n"
01073     "with selected plot\n\n"
01074     "It might be incompatible.   For example, \n"
01075     "Maximum Likelihood fitting requires binned\n"
01076     "data representation.";
01077   QMessageBox::critical ( this, // parent
01078                           "Set fitter error", // caption
01079                           message,
01080                           QMessageBox::Ok,
01081                           Qt::NoButton,
01082                           Qt::NoButton );
01083 }
01084 
01085 void
01086 Inspector::
01087 badFunctionError ( const std::string & name, const char * what )
01088 {
01089   QString message = "Function`";
01090   message += name.c_str();
01091   message += "' could not be used because ...\n";
01092   message += what;
01093   message +="\nMaybe the copy constructor or clone function is bad.";
01094 
01095   QMessageBox::critical ( this, // parent
01096                           "Function error", // caption
01097                           message,
01098                           QMessageBox::Ok,
01099                           Qt::NoButton,
01100                           Qt::NoButton );
01101 }
01102 
01103 void
01104 Inspector::
01105 incompatibleFunctionError ( const std::string & type )
01106 {
01107   QString message ( "Funtion of type " );
01108   message += type.c_str();
01109   message  += " can not be used\n"
01110     "with selected fitter\n\n"
01111     "It might be incompatible.   For example, \n"
01112     "the fitter requires derivatives\n"
01113     "that the function can not supply.";
01114   QMessageBox::critical ( this, // parent
01115                           "Set fitter error", // caption
01116                           message,
01117                           QMessageBox::Ok,
01118                           Qt::NoButton,
01119                           Qt::NoButton );
01120 }
01121 
01122 void
01123 Inspector::
01124 invalidRangeError ( const std::string & bad )
01125 {
01126   QString message ( "Attempt to apply invalid range:\n\n" );
01127   message += bad.c_str();
01128   message  += "\n\n Low end of range must be less than high end.";
01129 
01130   QMessageBox::critical ( this, // parent
01131                           "Range error", // caption
01132                           message,
01133                           QMessageBox::Ok,
01134                           Qt::NoButton,
01135                           Qt::NoButton );
01136 }
01137                         
01138 void
01139 Inspector::
01140 multipleDataRepError ( const std::string & type )
01141 {
01142   QString message ( "Multiple data representations are active.\n"
01143                     "Can not apply a " );
01144   message += type.c_str();
01145 #ifdef Q_OS_MACX
01146   message  += ".\n\n"
01147     "Use Command-click to select only one data representation.";
01148 #else
01149   message  += ".\n\n"
01150     "Use Control-click to select only one data representation.";
01151 #endif
01152   QMessageBox::information ( this, // parent
01153                              "Multiple data representation error", // caption
01154                              message,
01155                              QMessageBox::Ok,
01156                              Qt::NoButton,
01157                              Qt::NoButton );
01158 }
01159 
01160 bool
01161 Inspector::
01162 multipleDataRepInfo ( const std::string & type )
01163 {
01164   bool ok = false;
01165   QString message ( "Multiple data representations are active.\n"
01166                     "Apply " );
01167   message += type.c_str();
01168   message += " to each?\n\n";
01169 
01170 #ifdef Q_OS_MACX
01171   message += "One can use Control-click to apply a ";
01172 #else
01173   message += "One can use Command-click to apply a ";
01174 #endif
01175   message += type.c_str();
01176   message +=" to a selected data representation.";
01177 
01178   int result = QMessageBox::
01179     information ( this, // parent
01180                   "Multiple data representation error", // caption
01181                   message,
01182                   QMessageBox::Yes,
01183                   QMessageBox::No,
01184                   QMessageBox::NoButton );
01185 
01186   ok = result == QMessageBox::Ok;
01187 
01188   return ok;
01189 }
01190 
01191 void
01192 Inspector::
01193 cutOnCutError ()
01194 {
01195   const QString message ( "Attempt to add cut to itself\n"
01196                           "The request was ignorned" );
01197   QMessageBox::information ( this, // parent
01198                              "Applying cut error", // caption
01199                              message,
01200                              QMessageBox::Ok,
01201                              Qt::NoButton,
01202                              Qt::NoButton );
01203 }
01204 
01205 void
01206 Inspector::
01207 multiplePlotError ( )
01208 {
01209   const QString  message (
01210     "Multiple plots are selected.\n"
01211     "Can not apply change until only one is selected\n\n"
01212     "Use shift-click to deselect a selected plot" );
01213   QMessageBox::information ( this, // parent
01214                              "Multiple plot error", // caption
01215                              message, // .c_str(),
01216                              QMessageBox::Ok,
01217                              Qt::NoButton,
01218                              Qt::NoButton );
01219 }
01220 
01221 void Inspector::functionAddError ()
01222 {
01223   const QString message =
01224     "Functions are not supported on the selected data reaxisWitation.";
01225 
01226   QMessageBox::critical ( this, "Function Add Error",
01227                           message,
01228                           QMessageBox::Ok,
01229                           Qt::NoButton,
01230                           Qt::NoButton );
01231 }
01232 
01236 void
01237 Inspector::
01238 newPlotError ( const std::exception & e )
01239 {
01240   QString message ( "New plot could not be created because:\n" );
01241   message += e.what ();
01242   QMessageBox::critical ( this, // parent
01243                           "New plot error", // caption
01244                           message,
01245                           QMessageBox::Ok,
01246                           Qt::NoButton,
01247                           Qt::NoButton );
01248 }
01249 
01250 std::string
01251 Inspector::
01252 getArrayTupleLabel( const DataSource * rtuple, const std::string & column )
01253 {
01254 #ifdef HAVE_ROOT
01255   RootController * controller = RootController::instance ();
01256   vector < int > dimSize;
01257   controller -> fillDimSize ( dimSize, rtuple, column );
01258 
01259   // Set the caption
01260   QString caption( "MultiDimensional data in rows of the column ");
01261   caption.append( QString( column.c_str() ) );
01262 
01263   // Set the label
01264   std::ostringstream ost;
01265   ost << " Rows of this column are of size ";
01266 
01267   unsigned int i;
01268   for( i = 0; i < dimSize.size() - 1; i++ )
01269     ost << dimSize[i] << " x ";
01270   ost << dimSize[i];
01271 
01272   ost << "\n Enter C-style index of a single element of this";
01273   ost << "\n multidimentional data which you wish to analyse.";
01274   ost << "\n Index should be a comma separated list of ";
01275   ost << dimSize.size() << " integers.";
01276 
01277   ost << "\n For e.g. ";
01278   for( i = 0; i < dimSize.size() - 1; i++ )
01279     ost << "0, ";
01280   ost << "0 \n";
01281 
01282   string label( ost.str() );
01283 
01284   bool ok;
01285   QString text = QInputDialog::getText( caption, QString( label.c_str() ),
01286                                         QLineEdit::Normal,
01287                                         QString::null, &ok, this );
01288 
01289   // Also create the array tuple label
01290   std::ostringstream labelstream;
01291   labelstream << column;
01292 
01293   if ( ok && !text.isEmpty() )
01294     {
01295       vector< unsigned int > index;
01296       string s( text.ascii() );
01297 
01298       // User entered something and pressed OK
01299       // Creating the list of dropped delimiters.
01300       boost::char_separator< char > sep( "," );
01301 
01302       // A tokenizer with above dropped delimiters.
01303       typedef boost::tokenizer< boost::char_separator< char > >  tokenizer;
01304       tokenizer tok( s, sep );
01305 
01306       // Start extracting the dimension sizes.
01307       for( tokenizer::iterator tok_iter = tok.begin();
01308            tok_iter != tok.end();
01309            ++tok_iter )
01310         {
01311           unsigned int idx = boost::lexical_cast< unsigned int >( *tok_iter );
01312           index.push_back( idx );
01313           labelstream << "[" << idx << "]";
01314         }
01315     }
01316 
01317   return labelstream.str();
01318 #else
01319   return string(); // will not be used.
01320 #endif
01321 }
01322 
01323 void
01324 Inspector::
01325 newPlotButton_clicked()
01326 {
01327   vector < DataSource * > nt_vector;
01328   DataSourceController::instance() -> getDataSources ( nt_vector );
01329 
01330   if ( nt_vector.empty() )
01331     {
01332       noNTupleSelectedError ();
01333       return;
01334     }
01335 
01336   // See all comboboxes and create a new plotter.
01337   int current = m_all_ntuples->currentItem ();
01338   DataSource * ds = nt_vector[current];
01339 
01340   // Find the datarep.
01341   std::string plotTypeStr( (m_availPlotTypes -> currentText()).latin1() );
01342 
01343   // Find the axis bindings.
01344   vector < string > bindings;
01345   for ( unsigned int i = 0; i < m_new_combos.size(); i++ )
01346     {
01347       if ( m_new_combos [i] -> count () == 0 ) break;
01348 
01349       QString qstring = m_new_combos [ i ] -> currentText();
01350       string column ( qstring.latin1() );
01351       string label = column;
01352 
01353 #ifdef HAVE_ROOT
01354       if( column != "nil" && ds -> isMultiDimensional( column ) ) {
01355         bool yes = ds -> isUseable ( column );
01356         if ( yes == false ) {
01357           const QString
01358             message ( "This column is not useable because it contains\n"
01359                       "a multidimension array that varies is size or is\n"
01360                       "an unsupported data type." );
01361           QMessageBox::critical ( this, // parent
01362                                   "DataSource error",
01363                                   message,
01364                                   QMessageBox::Ok,
01365                                   QMessageBox::NoButton,
01366                                   QMessageBox::NoButton );
01367           return;
01368         }
01369 
01370         label = getArrayTupleLabel ( ds, column );
01371         RootController * rcontroller = RootController::instance();
01372         rcontroller -> smartExpandRootNTuple ( ds, column );
01373       }
01374 #endif
01375       bindings.push_back ( label );
01376     }
01377 
01378   // Create the plotter.
01379   try {
01380     DisplayController * controller =  DisplayController::instance();
01381     PlotterBase * newDisplay =
01382       controller -> createDisplay ( plotTypeStr, * ds, bindings );
01383     CanvasWindow * canvas = WindowController::instance() -> currentCanvas();
01384     canvas->addPlotDisplay ( newDisplay, true );
01385 
01386     bool valid = controller -> isDataValid ( newDisplay );
01387     if ( valid == false ) {
01388       invalidDataWarning ();
01389     }
01390   }
01391 //   catch ( const DataSourceException & e ) {
01392   catch ( const std::exception & e ) {
01393     newPlotError ( e );
01394   }
01395 }
01396 
01397 
01398 void
01399 Inspector::
01400 addDataRepButton_clicked()
01401 {
01402   // Find the display.
01403 
01404   PlotterBase * plotter = getPlotter ();
01405   if ( !plotter ) return;
01406 
01407   // Find the datarep.
01408   std::string plotTypeStr( (m_availPlotTypes->currentText()).latin1() );
01409 
01410   vector < DataSource * > nt_vector;
01411   DataSourceController::instance() -> getDataSources ( nt_vector );
01412 
01413   int current = m_all_ntuples->currentItem ();
01414   DataSource * ds = nt_vector[current];
01415 
01416   // Find the axis bindings.
01417 
01418   vector < string > bindings;
01419   for ( unsigned int i = 0; i < m_new_combos.size(); i++ )
01420     {
01421       if ( m_new_combos [i] -> count () == 0 ) break;
01422 
01423       QString qstring = m_new_combos [ i ] -> currentText();
01424       string column ( qstring.latin1() );
01425       string label = column;
01426 #ifdef HAVE_ROOT
01427       if ( column != "nil" && ds -> isMultiDimensional ( column ) ) {
01428         label = getArrayTupleLabel ( ds, column );
01429         RootController * rcontroller = RootController::instance ();
01430         rcontroller -> smartExpandRootNTuple ( ds, column );
01431       }
01432 #endif
01433       bindings.push_back ( label );
01434     }
01435 
01436   // Add the data rep.
01437 
01438   DisplayController * controller = DisplayController::instance();
01439   DataRep * rep = controller -> addDataRep ( plotter, plotTypeStr, ds,
01440                                              bindings );
01441 
01442   // If incompatible, do nothing.
01443   if ( rep == 0 ) 
01444     {
01445       incompatibleDataRepError ( plotTypeStr );
01446       return;
01447     }
01448 
01449   rep->set(Color::getColor());
01450 
01451   plotter -> autoScale ();
01452   bool valid = controller -> isDataValid ( rep );
01453   if ( valid == false ) {
01454     invalidDataWarning ();
01455   }
01456 
01457   update ();
01458 }
01459 
01460 void
01461 Inspector::
01462 removeDataRepButton_clicked()
01463 {
01464   PlotterBase * plotter = getPlotter ();
01465   if ( !plotter ) return;
01466 
01467   int num_active = plotter->activePlotIndex();
01468   int num_rep = plotter -> getNumDataReps();
01469 
01470   // If more than one active datarep or only one datarep 
01471   // in the plot, show warning message and do nothing.
01472   if (( num_active < 0) || ( num_rep <= 1 ))
01473     {
01474       const QString message=
01475         "You must have more than one DataReps \n"
01476         "in this view AND only one DataRep \n"
01477         "selected to be removed.";
01478 
01479       QMessageBox::warning ( this, // parent
01480                              "Unable to remove DataRep", // caption
01481                              message,
01482                              QMessageBox::Ok,
01483                              Qt::NoButton,
01484                              Qt::NoButton );
01485       return;
01486     }
01487 
01488   DataRep * rep = plotter -> getDataRep( num_active );
01489   //Reset index before remove the datarep.
01490   plotter->setActivePlot(-1,false);
01491   plotter -> removeDataRep ( rep );
01492   plotter -> autoScale ();
01493   delete rep;
01494 
01495   update();
01496 }
01497 
01498 
01499 void
01500 Inspector::
01501 dataCreateNTuple ()
01502 {
01503   const PlotterBase * plotter = getPlotter ();
01504   if ( plotter == 0 ) return;
01505   FunctionController * fc = FunctionController::instance ();
01506   NTuple * ntuple = fc -> createNTuple ( plotter, 0 );
01507   DataSourceController::instance () -> registerNTuple ( ntuple );
01508 
01509   update ();
01510 }
01511 
01512 
01513 void
01514 Inspector::
01515 fillPlotterList ( std::vector < PlotterBase * > & plotterlist )
01516 {
01517   plotterlist.clear();
01518   CanvasWindow * canvaz = WindowController::instance () ->currentCanvas();
01519 
01520   if ( canvaz != 0 ) {
01521     canvaz -> fillPlotterList ( plotterlist );
01522   }
01523 }
01524 
01525 void
01526 Inspector::
01527 ntupleChanged ( int index )
01528 {
01529   // Update tip tool.
01530   QToolTip::remove ( m_sel_ntuple_name );
01531   const QString tip = m_sel_ntuple_name -> currentText ();
01532   QToolTip::add ( m_sel_ntuple_name, tip );
01533 
01534   unsigned int size = m_plotter_list.size ();
01535   if ( size == 0 ) return;
01536 
01537   CutController * controller = CutController::instance ();
01538   vector < PlotterBase * > web;
01539   controller -> fillCutWeb ( m_plotter_list, web );
01540   size = web.size ();
01541 
01542   for ( unsigned int i = 0; i < size; i++ ) {
01543     PlotterBase * plotter = web [ i ];
01544     bool yes = plotter != 0;
01545     if ( yes ) yes = plotter -> isTargetable ();
01546     if ( yes == false ) continue;
01547 
01548     DataRep * rep = plotter -> getTarget ();
01549     yes = rep -> hasNTupleBindings ();
01550     if ( yes == false ) continue;
01551 
01552     DataSourceController * ds_controller = DataSourceController::instance ();
01553     const vector < string > & names = ds_controller -> getNTupleNames ();
01554     const string & ds_name = names [ index ];
01555     const DataSource * source = ds_controller -> getDataSource ( ds_name );
01556     DataRepController * dr_controller = DataRepController::instance ();
01557 
01558     try {
01559       dr_controller -> changeDataSource ( rep, source );
01560     }
01561     catch ( const runtime_error & e ) {
01562       QString message ( "Could not change binding because\n" );
01563       message += e.what ();
01564       QMessageBox::critical ( this, // parent
01565                               "Data source error",
01566                               message,
01567                               QMessageBox::Ok,
01568                               Qt::NoButton,
01569                               Qt::NoButton );
01570     }
01571   }
01572 }
01573 
01574 void
01575 Inspector::
01576 updateColorMapCtrls (const PlotterBase * plotter )
01577 {
01578   DisplayController * controller = DisplayController::instance ();
01579 
01580   const vector < double > & sv =
01581     controller -> getValueCtrlPts ( plotter );
01582   unsigned int size = sv.size ();
01583   if ( size > 0 ) {
01584     brk_pt -> setEnabled ( true );
01585     brk_label -> setEnabled ( true );
01586     brk_pt -> setValue ( static_cast <int> ( sv[0] * brk_pt -> maxValue() ));
01587   }
01588   if ( size > 1 ) {
01589     flat_width -> setEnabled ( true );
01590     flatlabel -> setEnabled ( true );
01591     flat_width->setValue(static_cast <int>( sv[1] * flat_width->maxValue()));
01592   }
01593   if ( size > 2 ) {
01594     color_scale -> setEnabled ( true );
01595     colorlabel -> setEnabled ( true);
01596     color_scale->setValue(static_cast<int>( sv[2] * color_scale->maxValue()));
01597   }
01598   if ( size < 3 ) {
01599     color_scale -> setEnabled ( false );
01600     colorlabel -> setEnabled ( false);
01601   }
01602   if ( size < 2 ) {
01603     flat_width -> setEnabled ( false );
01604     flatlabel -> setEnabled ( false );
01605   }
01606   if ( size < 1 ) {
01607     brk_pt -> setEnabled ( false );
01608     brk_label -> setEnabled ( false );
01609   }
01610 }
01611 
01615 void
01616 Inspector::
01617 updatePlotTab()
01618 { 
01619   
01620   loadAllUserModels ();
01621 
01622   bool yes = m_plotter_list.empty();
01623 
01624   m_plot_title -> setDisabled ( yes );
01625 
01626   PlotterBase * plotter = getPlotter ();
01627 
01628   yes = plotter != 0;
01629   if ( yes ) {
01630     int number = plotter -> getNumDataReps ();
01631     int index = plotter -> activePlotIndex ();
01632     yes = ( number < 2 ) || index >= 0;
01633   }
01634 
01635   m_plot_symbols->setEnabled ( yes );
01636 //   m_plot_color->setEnabled ( yes );
01637 //   m_selectedColor -> setEnabled ( yes );
01638   m_interval_le->setEnabled ( yes );
01639   m_interval_cb->setEnabled ( yes );
01640   m_errorBars ->setEnabled ( yes );
01641   m_grid -> setEnabled ( yes );
01642   m_boxedge->setEnabled ( yes );
01643   m_pointRepComboBox->setEnabled ( yes );
01644   if ( yes == false ) {
01645     m_selectedColor->setPaletteBackgroundColor ( "black" );
01646     return;
01647   }
01648 
01649 
01650   // Point Reps stuff.
01651 
01652   m_pointRepComboBox->clear();
01653 
01654   DisplayController * controller = DisplayController::instance ();
01655 
01656   DataRep * datarep = controller -> activeDataRep ( plotter );
01657 
01658   assert ( datarep != 0 );
01659 
01660   yes = datarep -> hasErrorDisplay ();
01661   m_errorBars -> setEnabled ( yes );
01662 
01663   ProjectorBase * proj = datarep -> getProjector();
01664 
01665   if ( proj != 0 ) {
01666     const vector <string> & pointreps = proj -> getPointReps();
01667         
01668 
01669     if ( pointreps.empty () == false ) {
01670       for (std::vector<string>::size_type i = 0; i < pointreps.size(); i++ ) {
01671                   
01672 
01673         m_pointRepComboBox->insertItem ( pointreps[i].c_str() );
01674       }
01675     }
01676     RepBase * rep = datarep->getRepresentation();
01677         
01678     const string & curRep = rep->name();
01679     m_pointRepComboBox->setCurrentText ( curRep.c_str() );
01680   }
01681 
01682   if ( plotter -> hasAxis ( Axes::Z ) == false ) { // no Z axis (colormap)
01683     m_value_combo -> setDisabled ( true );
01684     m_slider_control -> setDisabled ( true );
01685   }
01686   else { // has z axis (colormap)
01687 
01688     int jndex = controller -> getValueTransformIndex ( plotter ); // return the index to the list
01689 
01690         
01691         // of value to color transform names of the plotter. from 0 to size-1
01692     if ( jndex < 0 ) {  // no value available, jndex=-1
01693       m_value_combo -> setDisabled ( true );
01694     }
01695     else {
01696       m_value_combo -> setEnabled ( true );
01697       m_value_combo -> setCurrentItem ( jndex );
01698      
01699           // ***************************
01700          const BinToColor * repp=plotter -> getValueRep ();
01701          
01702          if (repp != 0) {
01703          bool yess = repp -> acceptChangeColor ();
01704          m_plot_color -> setEnabled (yess);
01705          m_selectedColor -> setEnabled (yess);
01706          }
01707          // *****************************
01708 
01709           bool yes = controller -> hasControlPoints ( plotter ); //return true if the value to color transform has control points
01710       m_slider_control -> setEnabled ( yes );
01711       yes = controller -> isUserDefinedValueTransform ( plotter );
01712       edit_model -> setEnabled ( yes );
01713       updateColorMapCtrls ( plotter );
01714     }// end of jndex<0
01715   }// end of plotter -> hasAxis ( Axes::Z ) == false
01716 
01717   // data source
01718   const DataSource * nt = controller -> getDataSource ( plotter, 0 );
01719 
01720   if ( nt && nt -> empty () ) {
01721     m_plot_symbols->setDisabled ( true );
01722     m_plot_title->setDisabled ( true );
01723     m_plot_color->setDisabled ( true );
01724     m_selectedColor -> setDisabled ( true );
01725     return;
01726   }
01727 
01728   //title
01729   const std::string & st = plotter->getTitle();
01730   QString qst ( st.c_str() );
01731   m_titleText->setText ( qst );
01732 
01733   // error bar and show grid checkbox
01734   m_errorBars->setChecked ( plotter->errorDisplay ( Axes::Y ) );
01735   m_grid->setChecked ( plotter->getShowGrid () );
01736   m_boxedge->setChecked (plotter->getBoxEdge ());
01737 
01738   // whether use symbols(triangle,plus,circle...) to represent data
01739   yes = controller -> hasSymbolRep ( plotter );
01740   m_symbol_group -> setEnabled ( yes );
01741 
01742   if ( yes  ) {
01743     m_point_stack -> raiseWidget ( 0 );
01744     unsigned int index = controller ->getRepStyle ( plotter );
01745     m_symbol_group -> setButton ( index );
01746   }
01747 
01748   // whether use line(solid, dash...)to represent data
01749   yes = controller -> hasLineRep ( plotter );
01750   m_line_group -> setEnabled ( yes );
01751   if ( yes ) {
01752     m_point_stack -> raiseWidget ( 1 );
01753     unsigned int style = controller -> getRepStyle ( plotter );
01754 #if QT_VERSION < 0x040000
01755     QButton * button = m_line_group -> find ( style );
01756 #else
01757    QAbstractButton * button = m_line_group -> find ( style );
01758 #endif
01759     QRadioButton * rb = dynamic_cast < QRadioButton * > ( button );
01760     rb -> setChecked ( true );
01761   }
01762   // set the point size
01763   float ptsize =  controller -> pointSize ( plotter );
01764   m_symbolPointSize -> setText ( QString ("%1").arg (ptsize) );
01765 
01766   // set color the user choose by RGB
01767   const Color & color = plotter->repColor ();
01768   QColor qcolor ( color.getRed(), color.getGreen(), color.getBlue () ); // constructor
01769   m_selectedColor->setPaletteBackgroundColor ( qcolor );
01770 
01771   // display interval
01772   if ( nt == 0 ) {
01773     m_interval_cb -> setEnabled ( false );
01774     m_interval_le -> setEnabled ( false );
01775     return;
01776   }
01777   const NTuple * ntuple = dynamic_cast < const NTuple * > ( nt );
01778   yes = ntuple != 0 && ntuple -> isIntervalEnabled ();
01779   m_interval_cb->setChecked ( yes );
01780   m_interval_le->setEnabled ( yes );
01781 
01782   if ( yes ) {
01783     unsigned int count = ntuple->getIntervalCount ();
01784     m_interval_le->setText ( QString ("%1").arg ( count ) );
01785   }
01786 }
01787 
01788 void
01789 Inspector::
01790 valueChanged ( int index )
01791 {
01792   PlotterBase * plotter = getPlotter ();
01793   if ( plotter != 0 ) {
01794 
01795     DisplayController * controller = DisplayController::instance ();
01796     controller -> setValueTransform ( plotter, index );
01797 
01798     const BinToColor * rep = plotter -> getValueRep();
01799     bool yes = false;
01800     if ( rep != 0 ) {
01801       yes = rep -> acceptChangeColor ();
01802     }
01803     m_plot_color -> setEnabled ( yes );
01804     m_selectedColor -> setEnabled ( yes );
01805 
01806      yes = controller -> hasControlPoints ( plotter );
01807      m_slider_control -> setEnabled ( yes );
01808      bool y = rep -> isUserDefined ();
01809      edit_model -> setEnabled ( y );
01810      if ( yes ) {
01811        m_is_updating = true;
01812          updateColorMapCtrls ( plotter );
01813            m_is_updating = false;
01814      }
01815   }
01816 }
01817 
01818 void
01819 Inspector::
01820 setAppKey ()
01821 {
01822   CanvasWindow * canvas = WindowController::instance () ->currentCanvas();
01823   if ( canvas != 0 ) {
01824     m_app_key = canvas -> getAppKey ();
01825     m_model_name  = m_app_key + "/Model Name/";
01826     m_break_point = m_app_key + "/break point/";
01827     m_flat_width  = m_app_key + "/flat width/";
01828     m_color_scale = m_app_key + "/color scale/";
01829   }
01830 }
01831 
01832 void
01833 Inspector::
01834 loadAllUserModels ()
01835 {
01836   if ( m_user_models_loaded == false ) {    
01837     setAppKey ();
01838 
01839     QSettings settings;
01840     settings.insertSearchPath ( QSettings::Windows, s_registry );
01841 
01842     QString model_name_key ( m_model_name );
01843     QStringList model_list 
01844         = settings.entryList ( model_name_key );
01845 
01846     QStringList::size_type size = model_list.size ();
01847     for ( QStringList::size_type i = 0; i < size ; i++ )
01848       {
01849         QString number = model_list [ i ];
01850         QString name 
01851           = settings.readEntry ( model_name_key + number );
01852         
01853         double brk_pt 
01854           = settings.readDoubleEntry ( m_break_point + number );
01855         double flat_width 
01856           = settings.readDoubleEntry ( m_flat_width + number );
01857         double color_scale 
01858           = settings.readDoubleEntry ( m_color_scale + number );
01859 
01860         string mname ( name.latin1() );
01861         vector < double > cpts;
01862         cpts.push_back ( brk_pt );
01863         cpts.push_back ( flat_width );
01864         cpts.push_back ( color_scale );
01865 
01866         DisplayController * controller = DisplayController::instance ();
01867         controller -> addValueTransform ( mname, cpts );
01868       }
01869 
01870     updateValueCombo ();
01871     m_user_models_loaded = true;
01872   }
01873 }
01874 
01875 void
01876 Inspector::
01877 sliderChanged ( int )
01878 {
01879   if ( m_is_updating == false ) {
01880     vector < double > sv;
01881 
01882     double m = brk_pt -> maxValue ();
01883     assert(m != 0);
01884     sv.push_back ( (brk_pt -> value()) / m + 0.001);
01885 
01886     double w = flat_width -> maxValue();
01887     assert(w != 0);
01888     sv.push_back ( (flat_width -> value()) / w + 0.001);
01889 
01890     double c = color_scale -> maxValue ();
01891     assert( c!= 0 );
01892     sv.push_back ( ( ( (color_scale -> value()) / c ) ) * 1.5 );
01893 
01894     PlotterBase * plotter = getPlotter ();
01895     if ( plotter != 0 ) {
01896       DisplayController * controller = DisplayController::instance ();
01897       controller -> setValueCtrlPts (plotter,sv );
01898     }
01899   }
01900 }
01901 
01902 void
01903 Inspector::
01904 resetSlider ( )
01905 {
01906   if ( m_slider_control -> isEnabled () )
01907     {
01908       brk_pt -> setValue ( 50 );
01909       flat_width -> setValue ( 50 );
01910       color_scale -> setValue ( 0 );
01911     }
01912 }
01913 
01914 
01915 void
01916 Inspector::
01917 convertCtrlPts ( std::vector < double > & sv )
01918 {
01919   sv.clear();
01920 
01921   int ibp = brk_pt -> value ();
01922   int ifw = flat_width -> value ();
01923   int ics = color_scale -> value ();
01924 
01925   double bp = static_cast < double > ( ibp) /
01926     static_cast <double>( brk_pt -> maxValue () );
01927 
01928   double fw = static_cast < double > ( ifw ) /
01929     static_cast <double>( flat_width -> maxValue () );
01930 
01931   double cs = static_cast < double > ( ics ) /
01932     static_cast <double>(color_scale -> maxValue () );
01933 
01934   sv.push_back ( bp );
01935   sv.push_back ( fw );
01936   sv.push_back ( cs );
01937 }
01938 
01939 void
01940 Inspector::
01941 newColorModel ( )
01942 {
01943   setAppKey ();
01944 
01945   bool ok = false;
01946   QString text =  QInputDialog::getText ( "Save color model", // caption
01947                                           "Enter name", // label
01948                                           QLineEdit::Normal,
01949                                           QString::null, // default text
01950                                           & ok, this );
01951 
01952   if ( ok )
01953     {
01954       const string name ( text.latin1() );
01955       vector < double > sv;
01956       convertCtrlPts ( sv );
01957       DisplayController * controller = DisplayController::instance ();
01958       controller -> addValueTransform ( name, sv );
01959 
01960       updateValueCombo ();
01961 
01962       PlotterBase * plotter = getPlotter ();
01963       controller -> setValueTransform ( plotter, name );
01964       int index = controller -> getValueTransformIndex ( plotter );
01965       m_value_combo -> setCurrentItem ( index );
01966 
01967       QSettings settings;
01968       settings.insertSearchPath ( QSettings::Windows, s_registry );
01969       QString model_name_key ( m_model_name );
01970 
01971       QStringList model_list 
01972         = settings.entryList ( model_name_key );
01973       
01974       int iat = 0;
01975       while ( true ) {
01976         int index = model_list.findIndex ( QString::number ( iat )) ;
01977         if ( index == -1 ) break;
01978         iat++;
01979       }
01980 
01981       QString at ( QString::number ( iat ) );
01982       settings.writeEntry ( m_model_name + at, text );
01983       settings.writeEntry ( m_break_point + at, sv[0] );
01984       settings.writeEntry ( m_flat_width + at, sv[1] );
01985       settings.writeEntry ( m_color_scale + at, sv[2] );
01986     }
01987 }
01988 
01989 void
01990 Inspector::
01991 editColorModel ( )
01992 {
01993   // If it's the first time to save the variable rainbow color scale,
01994   // we will need special handling. 
01995   bool isFirstVR = true;
01996   
01997   QString item = m_value_combo -> currentText ();
01998   vector < double > sv;
01999   convertCtrlPts ( sv );
02000 
02001   PlotterBase * plotter = getPlotter ();
02002   DisplayController * controller = DisplayController::instance ();
02003   // Use saveValueCtrlPts instead of setValueCtrlPts to make the 
02004   // changes effective in this session.
02005   controller -> saveValueCtrlPts ( plotter, sv );
02006       
02007   QSettings settings;
02008   settings.insertSearchPath ( QSettings::Windows, s_registry );
02009 
02010   QString model_name_key ( m_model_name );
02011   QStringList model_list 
02012     = settings.entryList ( model_name_key );
02013 
02014 #if QT_VERSION < 0x040000
02015   for ( unsigned int i = 0; i < model_list.size(); i++ ) {
02016 #else
02017   for ( int i = 0; i < model_list.size(); i++ ) {
02018 #endif
02019     QString at ( QString::number ( i ) );
02020     QString name_key ( model_name_key + at );
02021     QString name = settings.readEntry ( name_key );
02022     if ( name == item ) {
02023       settings.writeEntry ( m_break_point + at, sv[0] );
02024       settings.writeEntry ( m_flat_width + at, sv[1] );
02025       settings.writeEntry ( m_color_scale + at, sv[2] );
02026       isFirstVR = false;
02027       break;
02028     }
02029   }
02030 
02031   // For the first time, save the variable rainbow color scale.
02032   if ( isFirstVR ) {
02033     // Find the end of the settings.
02034     int iat = 0;
02035     while ( true ) {
02036       int index = model_list.findIndex ( QString::number ( iat )) ;
02037       if ( index == -1 ) break;
02038       iat++;
02039     }
02040     
02041     QString at ( QString::number ( iat ) );
02042     settings.writeEntry ( m_model_name + at, item );
02043     settings.writeEntry ( m_break_point + at, sv[0] );
02044     settings.writeEntry ( m_flat_width + at, sv[1] );
02045     settings.writeEntry ( m_color_scale + at, sv[2] );
02046   }
02047 }
02048 
02049 void
02050 Inspector::
02051 deleteColorModel ( )
02052 {
02053   QString item = m_value_combo -> currentText ();
02054   const string name ( item.latin1() );
02055 
02056   DisplayController * controller = DisplayController::instance ();
02057   bool yes =  controller -> removeValueTransform ( name );  
02058 
02059   if ( yes ) {
02060     PlotterBase * plotter = getPlotter ();
02061     controller -> setValueTransform ( plotter, "Rainbow" );
02062 
02063     QSettings settings;
02064     settings.insertSearchPath ( QSettings::Windows, s_registry );
02065     QString model_name_key ( m_model_name );
02066     QStringList model_list 
02067       = settings.entryList ( model_name_key );
02068     QStringList::size_type size = model_list.size ();
02069 
02070     for (QStringList::size_type i = 0; i < size; i++ ) {
02071       QString at ( model_list [ i ] );
02072       QString name_key ( model_name_key + at );
02073       QString name = settings.readEntry ( name_key );
02074       if ( name == item ) {
02075         settings.removeEntry ( name_key );
02076         settings.removeEntry ( m_break_point + at );
02077         settings.removeEntry ( m_flat_width + at );
02078         settings.removeEntry ( m_color_scale + at );
02079         break;
02080       }
02081     }
02082     updateValueCombo ();
02083   }
02084 }
02085 
02086 void
02087 Inspector::
02088 errorBars_toggled( bool )
02089 {
02090   PlotterBase * plotter = getPlotter ();
02091   if ( !plotter ) return;
02092 
02093   bool checked = m_errorBars->isChecked();
02094   DisplayController * controller = DisplayController::instance ();
02095 
02096   controller -> setErrorDisplayed ( plotter, Axes::Y, checked );
02097 }
02098 void
02099 Inspector::warningTex ()
02100 {
02101     const QString message ( "HippoDraw was not built with TeX support on "
02102                             "this platfrom." );
02103     QMessageBox::information ( this, /* parent */
02104                                "Input error",
02105                                message,
02106                                QMessageBox::Ok,
02107                                Qt::NoButton,
02108                                Qt::NoButton );
02109 }
02110 
02111 void
02112 Inspector::
02113 titleText_returnPressed()
02114 {
02115   std::string s( (m_titleText->text()).latin1() );
02116   unsigned int size = m_plotter_list.size();
02117 
02118   for ( unsigned int i = 0; i < size; i++ ) {
02119     PlotterBase * plotter = m_plotter_list [ i ];
02120 
02121     /* The size of drawrect, marginrect, need to be updated
02122        according to title text format. LaTeX format starts with
02123        "tex:" (case insensitive).
02124     */
02125     bool needMargin = String::ci_find(s, "tex:")==0;  
02126     if ( needMargin ) {
02127 #ifdef HAVE_TEX_UTILS
02128     plotter -> setTopMargin ( needMargin?10.0:0.0 );
02129     plotter -> setNeedUpdate(true);
02130     plotter -> notifyObservers ();
02131 #else
02132     warningTex ();
02133     s.erase ( 0, 4 );
02134 
02135 #endif
02136     }
02137     plotter->setTitle ( s );
02138   }
02139   
02140 
02141 }
02142 
02143 void Inspector::symbolTypeButtonGroup_clicked ( int id )
02144 {
02145   m_symbol_group -> setButton ( id );
02146   PlotterBase * plotter = getPlotter ();
02147   if ( !plotter ) return ;
02148 
02149   DisplayController * controller = DisplayController::instance ();
02150   DataRep * rep = controller -> activeDataRep ( plotter );
02151   if ( rep == 0 ) {
02152     multipleDataRepError ( "plot symbol change" );
02153     return;
02154   }
02155 
02156   rep -> setRepStyle ( id );
02157 }
02158 
02159 void Inspector::lineStyleButtonGroup_clicked ( int id )
02160 {
02161 
02162   m_line_group -> setButton ( id );
02163   PlotterBase * plotter = getPlotter ();
02164   if ( !plotter ) return ;
02165 
02166   DisplayController * controller = DisplayController::instance ();
02167   DataRep * rep = controller -> activeDataRep ( plotter );
02168   if ( rep == 0 ) {
02169     multipleDataRepError ( "plot symbol change" );
02170     return;
02171   }
02172 
02173   rep -> setRepStyle ( id );
02174 }
02175 
02176 void Inspector::symbolPointSize_returnPressed()
02177 {
02178 
02179   PlotterBase * plotter = getPlotter ();
02180   if ( !plotter ) return;
02181 
02182   DisplayController * controller = DisplayController::instance ();
02183   DataRep * rep = controller -> activeDataRep ( plotter );
02184   if ( rep == 0 ) {
02185     multipleDataRepError ( "plot symbol size change" );
02186     return;
02187   }
02188 
02189   QString text = m_symbolPointSize->text();
02190   float size = text.toFloat();
02191 
02192   rep->setRepSize ( size );
02193 
02194 }
02195 
02196 void Inspector::intervalStateChanged ( bool state )
02197 {
02198   PlotterBase * plotter = getPlotter ();
02199   if ( plotter == 0 ) return;
02200 
02201   DisplayController * controller = DisplayController::instance ();
02202   controller->setIntervalEnabled ( plotter, state );
02203   m_interval_le->setEnabled ( state );
02204 }
02205 
02206 void
02207 Inspector::
02208 intervalTextChanged ( const QString & text )
02209 {
02210   PlotterBase * plotter = getPlotter ();
02211   if ( plotter == 0 ) return;
02212 
02213   DisplayController * controller = DisplayController::instance ();
02214 
02215   unsigned int interval = text.toUInt ();
02216   controller->setIntervalCount ( plotter, interval );
02217 }
02218 
02219 void
02220 Inspector::
02221 colorSelect_clicked()
02222 {
02223   PlotterBase * plotter = getPlotter ();
02224   if ( !plotter ) return;
02225 
02226   int index = plotter->activePlotIndex ();
02227 
02228   if ( index < 0 ) {
02229     multipleDataRepError ( "color change" );
02230     return;
02231   }
02232 
02233   const Color & rep_color = plotter->repColor();
02234   QColor color ( rep_color.getRed(),
02235                  rep_color.getGreen(),
02236                  rep_color.getBlue() );
02237   color = QColorDialog::getColor ( color );
02238   if ( color.isValid() == false ) return;
02239 
02240   m_selectedColor->setPaletteBackgroundColor ( color );
02241 
02242   Color c ( color.red(), color.green(), color.blue() );
02243   plotter->setRepColor ( c );
02244 }
02245 
02246 void
02247 Inspector::
02248 pointRepComboBox_activated ( const QString & qstr )
02249 {
02250   PlotterBase * plotter = getPlotter ();
02251 
02252   if ( plotter != 0 ) {
02253     DisplayController * controller = DisplayController::instance ();
02254     const string rep ( qstr.latin1() );
02255 
02256     controller -> setPointRep ( plotter, rep );
02257 
02258     if ( plotter -> hasAxis ( Axes::Z ) == true ) {
02259 
02260       int index = m_value_combo -> currentItem ();
02261       controller -> setValueTransform ( plotter, index );
02262     }
02263 
02264     updatePlotTab (); // to update the m_point_stack and size.
02265   }
02266 }
02267 
02268 void
02269 Inspector::
02270 axis_button_group_clicked ( int id )
02271 {
02272 // #if QT_VERSION < 0x040000
02273 // #else
02274 //   id -= 3; // The re-inserted ones have wrong id
02275 // #endif
02276   m_axis = hippodraw::Axes::convert ( id );
02277   updateAxisTab ();
02278 }
02279 
02280 void
02281 Inspector::
02282 axisZoomPanCheckBox_clicked()
02283 {
02284   PlotterBase * plotter = getPlotter ();
02285   if ( !plotter ) return;
02286 
02287   plotter->setAutoRanging ( m_axis, false );
02288   const Range & r = plotter->getRange ( m_axis, true );
02289 
02290   m_autoScale->setChecked ( false );
02291 
02292   if ( axisWidget1->isZoomPanChecked() ) {
02293     m_zoompan[plotter] = true;
02294   }
02295 
02296   else {
02297 
02298     std::map < const PlotterBase *, bool >::const_iterator it
02299       = m_zoompan.find ( plotter );
02300     if ( it != m_zoompan.end () ) {
02301       m_zoompan[plotter] = false;
02302     }
02303 
02304   }
02305 
02306   axisWidget1->processZoomPanCheckBoxClicked ( r, r );
02307 }
02308 
02309 void
02310 Inspector::
02311 highRangeDrag()
02312 {
02313   int value = axisWidget1->getHighSliderValue ();
02314   setHighRange ( value, false );
02315 
02316   axisWidget1->setHighSliderValue ( 50 );
02317 }
02318 
02319 void
02320 Inspector::
02321 lowRangeDrag()
02322 {
02323   int value = axisWidget1->getLowSliderValue ();
02324   setLowRange ( value, false  );
02325 
02326   axisWidget1->setLowSliderValue ( 50 );
02327 }
02328 
02329 void
02330 Inspector::
02331 offsetDrag()
02332 {
02333   int value = m_offset_range->value ();
02334   setOffset ( value, false );
02335   m_offset_range->setValue ( 50 );
02336 }
02337 
02338 void
02339 Inspector::
02340 widthDrag ()
02341 {
02342   int value = m_width_range->value ();
02343   setBinWidth ( value, false );
02344 
02345   m_width_range->setValue ( 50 );
02346 }
02347 
02348 void
02349 Inspector::
02350 entriesDrag ()
02351 {
02352   int value = min_entries_slider->value ();
02353   m_dragging = false;
02354   setMinEntries(value);
02355 
02356   //  min_entries_slider->setValue ( 50 );
02357 }
02358 
02359 void
02360 Inspector::
02361 setWidthText()
02362 {
02363   PlotterBase * plotter = getPlotter ();
02364   if ( !plotter ) return;
02365 
02366   DisplayController * controller = DisplayController::instance ();
02367   int index = controller -> activeDataRepIndex ( plotter );
02368   bool yes = controller -> hasNTupleBindings ( plotter, index );
02369   if ( yes ) {
02370     //Get the string and convert it to double.
02371     QString text = m_width_text->text();
02372     double width = text.toDouble();
02373 
02374     if ( width == 0 ) return;    // To prevent it from crashing.
02375     plotter -> setBinWidth ( m_axis, width );
02376   }
02377 
02378   updateAxisTab();
02379 }
02380 
02381 void
02382 Inspector::
02383 setDragOn ()
02384 {
02385   m_dragging = true;
02386   m_min_entries = getMinEntries();
02387 
02388   if ( ! axisWidget1->isZoomPanChecked() )
02389     {
02390       m_autoScale->setChecked ( false );
02391       autoScale_clicked ();
02392     }
02393   else
02394     {
02395       // Save current width and position.
02396       m_autoScale->setChecked ( false );
02397       autoScale_clicked ();
02398 
02399       PlotterBase * plotter = getPlotter ();
02400       if ( !plotter ) return;
02401       const Range & r = plotter->getRange ( m_axis, true );
02402      m_range.setRange ( r.low(), r.high(), r.pos() );
02403     }
02404 
02405 }
02406 
02407 void
02408 Inspector::
02409 setOffsetText()
02410 {
02411   PlotterBase * plotter = getPlotter ();
02412   if ( !plotter ) return;
02413 
02414   DisplayController * controller = DisplayController::instance ();
02415   int index = controller -> activeDataRepIndex ( plotter );
02416   bool yes = controller -> hasNTupleBindings ( plotter, index );
02417   if ( yes ) {
02418     //Get the string and convert it to double.
02419     QString text = m_offset_text->text();
02420     double offset = text.toDouble();
02421 
02422     int value = static_cast < int > ( 50.0 * offset ) + 49;
02423     setDragOn ();
02424     setOffset( value );
02425     offsetDrag ();
02426   }
02427 
02428   updateAxisTab ();
02429 }
02430 
02431 void
02432 Inspector::
02433 setBinWidth ( int value )
02434 {
02435   setBinWidth ( value, m_dragging );
02436 
02437   if ( m_dragging == false ) m_width_range -> setValue ( 50 );
02438 }
02439 
02440 void
02441 Inspector::
02442 setBinWidth ( int value, bool drag )
02443 {
02444   PlotterBase * plotter = getPlotter ();
02445   if ( !plotter ) return;
02446   m_dragging = drag;
02447 
02448   plotter -> setBinWidth ( m_axis, value, m_dragging );
02449   updateAxisTab ();
02450 }
02451 
02452 void
02453 Inspector::
02454 axisLabelText()
02455 {
02456   PlotterBase * plotter = getPlotter ();
02457   if ( plotter != 0 ) {
02458     QString text = m_axis_label -> text ();
02459     string ltext = text.latin1();
02460     const string axis = convertToString ( m_axis );
02461 
02462     /* The size of drawrect, marginrect, need to be updated
02463        according to title text format. LaTeX format starts with
02464        "tex:" (case insensitive).
02465     */
02466     bool needMargin = String::ci_find(ltext, "tex:")==0;
02467     if ( needMargin ) {
02468 #ifdef HAVE_TEX_UTILS
02469     if (m_axis==Axes::X)
02470       plotter -> setBottomMargin ( needMargin?8.0:0.0 );
02471     else if (m_axis==Axes::Y)
02472       plotter -> setLeftMargin ( needMargin?0.0:0.0 );
02473     else if (m_axis==Axes::Z)
02474       plotter -> setZMargin ( needMargin?7.0:0.0 );
02475     plotter -> setNeedUpdate(true);
02476     plotter -> notifyObservers ();
02477 #else
02478     warningTex();
02479     ltext.erase( 0, 4 );
02480 #endif
02481     plotter -> setLabel ( m_axis, ltext );
02482     }
02483   }
02484   
02485 
02486 }
02487 
02488 void
02489 Inspector::
02490 setLowText()
02491 {
02492 
02493   PlotterBase * plotter = getPlotter ();
02494   if ( !plotter ) return;
02495 
02496   Range r = plotter->getRange ( m_axis, true );
02497 
02498   axisWidget1->processTextBoxReturnPressed ( r, r );
02499 
02500   plotter->setRange ( m_axis, r, true, false ); // scaled, keep bin width
02501   m_autoScale->setChecked ( false );
02502 
02503   updateAxisTab ();
02504 }
02505 
02506 void
02507 Inspector::
02508 setLowRange ( int value )
02509 {
02510   if ( m_is_updating == false ) {
02511     setLowRange ( value, m_dragging );
02512     if ( m_dragging == false ) {
02513       axisWidget1->setLowSliderValue ( 50 );
02514     }
02515   }
02516 }
02517 
02518 void
02519 Inspector::
02520 setLowRange ( int value, bool yes )
02521 {
02522   PlotterBase * plotter = getPlotter ();
02523   if ( !plotter ) return;
02524   m_dragging = yes;
02525 
02526   plotter->setAutoRanging ( m_axis, false );
02527 
02528   if ( ! axisWidget1->isZoomPanChecked() )
02529     {
02530       const string axis = convertToString ( m_axis );
02531       plotter->setLowRange ( m_axis, value, m_dragging );
02532       const Range & r = plotter->getRange ( m_axis, true );
02533       double low = r.low();
02534       axisWidget1 -> setLowText ( QString("%1").arg(low));
02535     }
02536   else
02537     {
02538       const Range & r = plotter->getRange ( m_axis, true );
02539       Range range ( r.low(), r.high(), r.pos() );
02540       axisWidget1->processLowSliderMoved ( value, range, m_range );
02541       if ( m_dragging ) plotter->setRange ( m_axis, range, true, false );
02542     }
02543 }
02544 
02545 void
02546 Inspector::
02547 setHighRange ( int value )
02548 {
02549   if ( m_is_updating == false ) {
02550     setHighRange ( value, m_dragging );
02551     if ( m_dragging == false ) {
02552       axisWidget1->setHighSliderValue ( 50 );
02553     }
02554   }
02555 }
02556 
02557 void
02558 Inspector::
02559 setHighRange ( int value, bool yes )
02560 {
02561   PlotterBase * plotter = getPlotter ();
02562   if ( !plotter ) return;
02563   m_dragging = yes;
02564 
02565   plotter->setAutoRanging ( m_axis, false );
02566 
02567   if ( !axisWidget1->isZoomPanChecked() )
02568     {
02569       const string axis = convertToString ( m_axis );
02570       plotter->setHighRange ( m_axis, value, m_dragging );
02571       const Range & r = plotter->getRange ( m_axis, true );
02572       double high = r.high();
02573       axisWidget1 -> setHighText ( QString("%1").arg(high));
02574       return;
02575     }
02576 
02577   BinaryTransform *t =
02578     dynamic_cast<  BinaryTransform* > ( plotter->getTransform() );
02579 
02580   if ( axisWidget1->isZoomPanChecked() && ! t->isPeriodic() )
02581     {
02582       const Range & r = plotter->getRange ( m_axis, true );
02583       Range range ( r.low(), r.high(), r.pos() );
02584       axisWidget1->processHighSliderMoved ( value, range, m_range );
02585       if ( m_dragging ) plotter->setRange ( m_axis, range, true, false );
02586       return;
02587     }
02588 
02589   double offset(0.0), incr(0.0);
02590 
02591   if ( axisWidget1->isZoomPanChecked() && t->isPeriodic() )
02592     {
02593           
02594       PeriodicBinaryTransform *tp =
02595         dynamic_cast< PeriodicBinaryTransform* > ( t );
02596 
02597       const Range & r = plotter->getRange ( m_axis, true );
02598       Range range (r.low(), r.high(), r.pos());
02599 
02600       incr = ( value - m_highslider1_last_val ) * r.length() / 100;
02601       m_highslider1_last_val = value;
02602 
02603       // Exchange axes to make the GUI more understandable.
02604       if ( m_axis == Axes::Y )
02605         {
02606           offset = tp->xOffset();
02607           offset = tp->moduloAddY( offset, incr );
02608           tp->setXOffset( offset );
02609         }
02610       else if ( m_axis == Axes::X )
02611         {
02612           offset = tp->yOffset();
02613           offset = tp->moduloAddX( offset, incr );
02614           tp->setYOffset( offset );
02615         }
02616 
02617       
02618       axisWidget1 -> setHighText ( QString( "%1" ).arg( offset ) );
02619       if ( m_dragging ) plotter->setRange ( m_axis, range, true, false );
02620       return;
02621     }
02622 }
02623 
02624 void
02625 Inspector::
02626 setHighText()
02627 {
02628 
02629   PlotterBase * plotter = getPlotter ();
02630   if ( !plotter ) return;
02631 
02632   Range r = plotter->getRange ( m_axis, true );
02633 
02634   axisWidget1->processTextBoxReturnPressed ( r, r );
02635 
02636   plotter->setRange ( m_axis, r, true, false ); // scaled and keep bin width
02637   m_autoScale->setChecked ( false );
02638 
02639   updateAxisTab ();
02640 }
02641 
02642 void
02643 Inspector::
02644 setOffset ( int value  )
02645 {
02646   setOffset( value, m_dragging );
02647 }
02648 
02649 void
02650 Inspector::
02651 setOffset ( int value, bool yes  )
02652 {
02653   PlotterBase * plotter = getPlotter ();
02654   if ( !plotter ) return;
02655   m_dragging = yes;
02656 
02657   const string axis = convertToString ( m_axis );
02658   DisplayController * controller = DisplayController::instance();
02659   controller ->  setOffset ( plotter, axis, value, m_dragging );
02660   double offset = plotter->getOffset ( m_axis );
02661   m_offset_text -> setText ( QString ("%1").arg (offset) );
02662 
02663   updateAxisTab ();
02664 }
02665 
02666 const std::vector < PlotterBase * > &
02667 Inspector::
02668 getDataCutList ( PlotterBase * plotter )
02669 {
02670   vector < PlotterBase * > plotterlist;
02671   fillPlotterList ( plotterlist );
02672 
02673 
02674   DisplayController * controller = DisplayController::instance ();
02675   const DataSource * tuple = controller -> getDataSource ( plotter );
02676   CutController * cutcontroller = CutController::instance();
02677   return cutcontroller->getCutList ( plotterlist, tuple );
02678 }
02679 
02680 void
02681 Inspector::
02682 cutText_returnPressed ()
02683 {
02684   m_is_updating = true;
02685 
02686   int id = cutRadioId ();
02687   bool fit_cut = id == 2;
02688 
02689   int index = m_selCutComboBox -> currentItem ();
02690   Range currentRange = m_tuple_cuts [index] -> getRange();
02691   PlotterBase * plotter = getSelectedCut();
02692 
02693   if ( fit_cut == false ) {
02694     Axes::Type cut_axis = getAxes ( index );
02695     const Range & fullRange = plotter -> getRange ( cut_axis, false );
02696     axisWidget2->processTextBoxReturnPressed ( currentRange, fullRange );
02697     plotter->setCutRangeAt ( currentRange, cut_axis );
02698   }
02699   else {
02700     const Range & fullRange = plotter -> getRange ( Axes::X, false );
02701     axisWidget2->processTextBoxReturnPressed ( currentRange, fullRange );
02702     plotter->setCutRangeAt ( currentRange, index );
02703   }
02704 }
02705 
02706 void Inspector::disableCutControls ( bool yes )
02707 {
02708   axisWidget2->setAllDisabled ( yes );
02709   colorSelect_2->setDisabled ( yes );
02710   cutRemovePushButton->setDisabled ( yes );
02711   cutInvertPushButton->setDisabled ( yes );
02712   cutEnablePushButton -> setDisabled ( yes );
02713   m_cutAddSelected->setDisabled ( yes );
02714   m_cutAddAll -> setDisabled ( yes );
02715 
02716   if ( yes ) {
02717     int number = m_selCutComboBox -> count ();
02718     while ( number-- > 0 ) {
02719       m_selCutComboBox -> removeItem ( 0 );
02720     }
02721   }
02722   m_selCutComboBox -> setDisabled ( yes );
02723 }
02724 
02725 void
02726 Inspector::
02727 updateTupleCuts ( const std::vector < PlotterBase * > & cutlist )
02728 {
02729   m_tuple_cuts.clear ();
02730   m_tuple_cut_plotters.clear ();
02731 
02732   unsigned int size = cutlist.size ();
02733 
02734   for ( unsigned int i = 0; i < size; i++ ) {
02735     PlotterBase * plotter = cutlist[i];
02736     TupleCutList_t cuts;
02737     plotter -> fillCutList ( cuts );
02738 
02739     for ( unsigned int j = 0; j < cuts.size (); j++ ) {
02740       m_tuple_cuts.push_back ( cuts[j] );
02741       m_tuple_cut_plotters.push_back ( plotter );
02742     }
02743   }
02744 }
02745 
02746 void
02747 Inspector::
02748 updateCutControls ( const std::vector < PlotterBase * > & cutlist )
02749 {
02750   QString old_current = m_selCutComboBox -> currentText ();
02751   int numberItems = m_selCutComboBox->count();
02752 
02753   while ( numberItems-- > 0 ) {
02754     m_selCutComboBox->removeItem(0);
02755   }
02756 
02757   m_selCutComboBox -> setEnabled ( true );
02758 
02759   updateTupleCuts ( cutlist );
02760   bool yes = m_tuple_cuts.empty ();
02761   if ( yes ) {
02762     cutRemovePushButton -> setEnabled ( false );
02763     return;
02764   }
02765 
02766   int index = -1;
02767   unsigned int size = m_tuple_cuts.size ();
02768 
02769   for ( unsigned int i = 0; i < size; i++ ) {
02770     const TupleCut * cut = m_tuple_cuts[i];
02771     const string & label = cut -> getLabel ();
02772     QString item = label.c_str ();
02773     m_selCutComboBox -> insertItem ( item );
02774     if ( item == old_current ) index = i;
02775   }
02776 
02777   PlotterBase * plotter = getPlotter ();
02778   assert ( plotter );
02779   index = -1;
02780   map < PlotterBase *, int > ::iterator first
02781     = m_cut_map.find ( plotter );
02782 
02783   if ( first == m_cut_map.end () ) { // not found
02784     index = 0;
02785     m_cut_map [ plotter ] = index;
02786   }
02787   else {
02788     index = first -> second;
02789   }
02790   int count = m_selCutComboBox -> count ();
02791   if ( index >= count ) {
02792     index = count -1;
02793     m_cut_map [ plotter] = index;
02794   }
02795 
02796   m_selCutComboBox -> setCurrentItem ( index );
02797   updateCutEnableButton ();
02798 }
02799 
02803 void
02804 Inspector::
02805 updateCutEnableButton ( )
02806 {
02807   if ( m_tuple_cuts.empty () ) return;
02808 
02809   int index = m_selCutComboBox -> currentItem ();
02810   const TupleCut * cut = m_tuple_cuts [ index ];
02811   assert ( cut != 0 );
02812   bool yes = cut -> isEnabled ();
02813   m_cut_enable_updating = true;
02814   cutEnablePushButton -> setOn ( ! yes );
02815   m_cut_enable_updating = false;
02816 }
02817 
02818 Axes::Type
02819 Inspector::
02820 getAxes ( unsigned int index )
02821 {
02822   Axes::Type axis = Axes::Y;
02823 
02824   PlotterBase * plotter = m_tuple_cut_plotters [ index ];
02825   unsigned int size = m_tuple_cut_plotters.size ();
02826   for ( unsigned int i = 0; i < size; i++ ) {
02827     if ( m_tuple_cut_plotters[i] == plotter ) {
02828       if ( i == index ) {
02829         axis = Axes::X;
02830       }
02831       break;
02832     }
02833   }
02834 
02835   return axis;
02836 }
02837 
02838 void
02839 Inspector::
02840 updateCutControlValues ( const PlotterBase * cplotter )
02841 {
02842   m_is_updating = true;
02843   int index = m_selCutComboBox -> currentItem ();
02844   const Range & currentRange = m_tuple_cuts[index] -> getRange ();
02845 
02846   Axes::Type cut_axis = Axes::X;
02847   int id = cutRadioId ();
02848   bool fit_cut = id == 2;
02849   if ( fit_cut == false ) {
02850     cut_axis = getAxes ( index );
02851   }
02852   const Range & fullRange = cplotter->getRange ( cut_axis, false );
02853 
02854   axisWidget2->updateCutControlValues ( currentRange, fullRange );
02855   CutController * controller = CutController::instance ();
02856 
02857   bool yes
02858     = controller -> isZoomPan ( cplotter, cut_axis );
02859   axisWidget2 -> setZoomPan ( yes );
02860   axisWidget2->processZoomPanCheckBoxClicked ( currentRange, fullRange );
02861   m_is_updating = false;
02862 }
02863 
02864 // void
02865 // Inspector::
02866 // fillCutsOn ( const PlotterBase * plotter,
02867 //           std::vector < PlotterBase * > & cutlist )
02868 // {
02869 //   cutlist.clear();
02870 
02871 //   DisplayController * controller = DisplayController::instance ();
02872 //   const DataRep * datarep = controller -> activeDataRep ( plotter );
02873 //   if ( datarep != 0 ) {
02874 //     CutController * cutcontroller = CutController::instance();
02875 
02876 //     cutcontroller->fillCutList ( datarep, cutlist );
02877 //   }
02878 // }
02879 
02880 const std::vector < const TupleCut * > &
02881 Inspector::
02882 getCutList ( const PlotterBase * plotter ) const
02883 {
02884   DisplayController * controller = DisplayController::instance ();
02885   int index = controller -> activeDataRepIndex ( plotter );
02886   if ( index < 0 ) {
02887     string what ( "Inspector::getCutList: " );
02888     what += "no active DataRep in PlotterBase object.";
02889     throw std::logic_error ( what );
02890   }
02891   const DataRep * datarep = plotter -> getDataRep ( index );
02892   CutController * cut_controller = CutController::instance ();
02893 
02894   return cut_controller -> getCutList ( datarep );
02895 }
02896 
02897 void
02898 Inspector::
02899 selectedCutsRadioButton_toggled ( bool )
02900 {
02901   if ( !m_selectedPlotRadioButton->isChecked() ) return;
02902 
02903   // Change the items in the combo box to only cuts over selected datarep.
02904 
02905   PlotterBase * plotter = getPlotter ();
02906   bool yes = plotter != 0;
02907   if ( yes ) yes = plotter -> isTargetable ();
02908   disableCutControls ( yes == false );
02909   if ( yes == false ) return;
02910 
02911   vector < PlotterBase * > cutlist;
02912 
02913   if ( cutRadioId () != 2 ) {
02914     CutController * controller = CutController::instance ();
02915     controller -> fillCutList ( plotter, cutlist );
02916 
02917     // Clear the combobox and insert the new strings.
02918 
02919     if ( cutlist.empty () ) {
02920       disableCutControls ( true );
02921       cutRemovePushButton->setEnabled ( false );
02922       return;
02923     }
02924   }
02925   else { // fitting cut
02926     cutlist.push_back ( plotter );
02927   }
02928 
02929   updateCutControls ( cutlist );
02930 
02931   if ( m_tuple_cuts.empty () ) {
02932     disableCutControls ( true );
02933     cutRemovePushButton->setEnabled ( false );
02934     return;
02935   }
02936 
02937   // Update Controls.
02938 
02939   disableCutControls ( false );
02940   cutRemovePushButton->setEnabled ( true );
02941   m_cutAddSelected -> setDisabled ( true );
02942   m_cutAddAll -> setDisabled ( true );
02943 
02944   // Update texts and sliders.
02945 
02946   int index = m_selCutComboBox -> currentItem ();
02947   const PlotterBase * cut_plotter = m_tuple_cut_plotters [ index ];
02948   updateCutControlValues ( cut_plotter );
02949 }
02950 
02951 void
02952 Inspector::
02953 cutAddSelected ()
02954 {
02955   // Take the selected cut from cutlistcombobox and add it to selected
02956   // plotter on canvas.
02957 
02958   // Find the selected cutplotter.
02959 
02960   CutPlotter * cp = getSelectedCut();
02961 
02962   // Find the selected Plotter.
02963   PlotterBase * plotter = getPlotter ();
02964   if ( !plotter ) return ;
02965 
02966   // Add the cut to the plotter.
02967   CutController * controller = CutController::instance();
02968   controller -> addCut ( cp, plotter );
02969 
02970 }
02971 
02972 void
02973 Inspector::
02974 cutAddAll ()
02975 {
02976   PlotterBase * plotter = getPlotter ();
02977   if ( plotter == 0 ) return;
02978 
02979   CutController * controller = CutController::instance ();
02980   const vector < PlotterBase * > & cut_list = getDataCutList ( plotter );
02981 
02982   controller -> addCuts ( cut_list, plotter );
02983 
02984   unsigned int size = cut_list.size ();
02985   for ( unsigned int i = 0; i < size; i++ ) {
02986     PlotterBase * pb = cut_list[i];
02987     CutPlotter * cut_plotter = dynamic_cast < CutPlotter * > ( pb );
02988     if ( cut_plotter == plotter ) {
02989       cutOnCutError ();
02990     }
02991   }
02992 }
02993 
02994 /* Take the selected cut from cutlistcombobox and remove it from the selected
02995     plotter on canvas.
02996 */
02997 void
02998 Inspector::
02999 cutRemovePushButton_clicked()
03000 {
03001   PlotterBase * plotter = getPlotter ();
03002   if ( !plotter ) return ;
03003 
03004   bool is_fit_radio = cutRadioId () == 2;
03005   if ( is_fit_radio ) {
03006     DisplayController * controller = DisplayController::instance ();
03007     int index = controller->activeDataRepIndex ( plotter );
03008     DataRep * rep = plotter -> getDataRep ( index );
03009     FunctionController::instance () -> removeTupleCut ( plotter, rep );
03010   }
03011   else {
03012     // Find the selected cutplotter.
03013     CutPlotter * cp = getSelectedCut();
03014     CutController::instance() -> removeCut ( cp, plotter );
03015   }
03016 
03017   if ( m_selectedPlotRadioButton -> isChecked () ) {
03018     // post event so we don't delete item that sent us the signal.
03019     PlotterEvent * event = new PlotterEvent ( plotter );
03020     QApplication::postEvent ( this, event );
03021   }
03022 }
03023 
03024 void
03025 Inspector::
03026 allCutsRadioButton_toggled ( bool )
03027 {
03028   if ( !allCutsRadioButton->isChecked() ) return;
03029 
03030   PlotterBase * plotter = getPlotter ();
03031 
03032   bool yes = plotter != 0;
03033   if ( yes ) yes = plotter -> isTargetable ();
03034 
03035   disableCutControls ( yes == false );
03036   if ( yes == false )  return;
03037 
03038   const vector < PlotterBase * > & cutlist = getDataCutList ( plotter );
03039 
03040   // Clear the combobox and insert the new strings.
03041 
03042   updateCutControls ( cutlist );
03043 
03044   if ( cutlist.empty () ) {
03045     disableCutControls ( true );
03046     return;
03047   }
03048 
03049   // Update Controls.
03050 
03051   disableCutControls ( false );
03052   cutRemovePushButton->setDisabled ( true );
03053   m_cutAddSelected -> setEnabled ( true );
03054   m_cutAddAll -> setEnabled ( true );
03055 
03056   // Update texts and sliders.
03057 
03058   const PlotterBase * cut_plotter = cutlist.back ();
03059   updateCutControlValues ( cut_plotter );
03060 }
03061 
03062 void Inspector::selCutChanged ( )
03063 {
03064   CutPlotter * cut_plotter = getSelectedCut ();
03065   updateCutControlValues ( cut_plotter );
03066 
03067   PlotterBase * plotter = getPlotter (); // the target
03068   int index = m_selCutComboBox -> currentItem ();
03069   m_cut_map [ plotter ] = index;
03070 
03071   updateCutEnableButton ();
03072 }
03073 
03074 CutPlotter *
03075 Inspector::
03076 getSelectedCut ()
03077 {
03078   if ( cutRadioId() != 2 ) {
03079     PlotterBase * plotter = getPlotter ();
03080     if ( plotter == 0 ) return 0;
03081 
03082     m_last_cut_index = m_selCutComboBox->currentItem();
03083 
03084     PlotterBase * pb = m_tuple_cut_plotters [ m_last_cut_index ];
03085     return dynamic_cast < CutPlotter * > ( pb );
03086   }
03087   else { // fitting cut
03088     PlotterBase * pb = getPlotter ();
03089     CutPlotter * plotter = dynamic_cast < CutPlotter * > ( pb);
03090     return plotter;
03091   }
03092 }
03093 
03097 void
03098 Inspector::
03099 cutNew()
03100 {
03101   // Get the column label from m_CutVariableComboBox1, and create a cut on
03102   // the selected plotter with that column label. Also update the list of
03103   // cuts and the high and low range.
03104 
03105   PlotterBase * plotter = getPlotter ();
03106   bool yes = plotter != 0;
03107 
03108   if ( yes ) yes = plotter -> isTargetable ();
03109   if ( yes == false ) {
03110     int index = plotter -> activePlotIndex ();
03111     if ( index <  0 ) {
03112       multipleDataRepError ( "Cut" );
03113     }
03114     else { // must be a function
03115       const QString message ( "Can not apply cut to a function" );
03116       QMessageBox::information ( this, /* parent */
03117                                  "Cut application error",
03118                                  message,
03119                                  QMessageBox::Ok,
03120                                  Qt::NoButton,
03121                                  Qt::NoButton );
03122     }
03123     return;
03124   }
03125 
03126   DisplayController * controller = DisplayController::instance ();
03127   int index = controller->activeDataRepIndex ( plotter );
03128   assert ( index >= 0 );
03129 
03130   const DataRep * rep = plotter -> getDataRep ( index );
03131   if ( rep -> hasNTupleBindings () == false ) {
03132       const QString message ( "Can not apply cut to a static histogram" );
03133       QMessageBox::information ( this, /* parent */
03134                                  "Cut application error",
03135                                  message,
03136                                  QMessageBox::Ok,
03137                                  Qt::NoButton,
03138                                  Qt::NoButton );
03139       return;
03140   }
03141 
03142   vector < string > bindings;
03143   int id = cutRadioId ();
03144   if ( id != 2 ) {
03145 #if QT_VERSION < 0x030100 // 3.1.0
03146     string label1 ( m_CutVariableComboBox1 -> currentText() );
03147     string label2 ( m_CutVariableComboBox2 -> currentText() );
03148 #else
03149     QString text1 = m_CutVariableComboBox1 -> currentText();
03150     string label1 = text1.latin1();
03151     QString text2 = m_CutVariableComboBox2 -> currentText();
03152     string label2 = text2.latin1();
03153 #endif
03154 
03155     switch ( id ) {
03156     case 0 : // 1d data cut
03157       bindings.push_back( label1 );
03158       break;
03159     case 1 : // 2d data cut
03160       bindings.push_back( label1 );
03161       bindings.push_back( label2 );
03162     break;
03163     }
03164     CutController * cutcontroller = CutController::instance();
03165     PlotterBase * cutplotter = cutcontroller -> addCut ( plotter, bindings );
03166     CanvasWindow * canvas = WindowController::instance () ->currentCanvas();
03167     if ( canvas == 0 ) return;
03168 
03169     canvas -> addPlotDisplay ( cutplotter, false );
03170   }
03171   else {
03172     DataRep * datarep = plotter -> getDataRep ( index );
03173     FunctionController * controller = FunctionController::instance ();
03174     controller -> setTupleCut ( plotter, datarep );
03175   }
03176 
03177   // Update other guys.
03178   selectedCutsRadioButton_toggled ( true );
03179   allCutsRadioButton_toggled ( true );
03180 }
03181 
03182 int
03183 Inspector::
03184 findCutIndex ( const QString & label )
03185 {
03186   int index = -1;
03187 
03188   int size = m_selCutComboBox -> count ();
03189   for ( int i = 0; i < size; i++ ) {
03190     QString text = m_selCutComboBox -> text ( i );
03191     if ( text == label ) {
03192       index = i;
03193       break;
03194     }
03195   }
03196     return index;
03197 }
03198 
03199 void
03200 Inspector::
03201 updateCutsTab ()
03202 {
03203   if ( m_new_plot_box->isEnabled () == false ) return;
03204 
03205   PlotterBase * plotter = getPlotter ();
03206   bool yes = plotter != 0;
03207   m_new_cut_box->setEnabled ( yes );
03208 
03209   if ( yes ) yes = plotter -> isTargetable ();
03210   m_cut_selected_box->setEnabled ( yes );
03211 
03212   if ( yes ) {
03213     int id = cutRadioId ();
03214     bool is_fit_radio = id == 2;
03215     selectedCutsRadioButton_toggled (true  );
03216     allCutsRadioButton_toggled ( true );
03217 
03218     if ( is_fit_radio == false ) {
03219       updateDataCutsTab ();
03220     }
03221     else {
03222       updateFitCutsTab ();
03223     }
03224   }
03225 }
03226 
03227 void
03228 Inspector::
03229 updateFitCutsTab ()
03230 {
03231 }
03232 
03233 void
03234 Inspector::
03235 updateDataCutsTab ()
03236 {
03237   int id = cutRadioId ();
03238 
03239   if ( id == 0 ) {
03240     m_CutVariableComboBox2 -> setEnabled ( false );
03241   }
03242 
03243   PlotterBase * plotter = getPlotter ();
03244   DisplayController * controller = DisplayController::instance ();
03245   int index = controller->activeDataRepIndex ( plotter );
03246   if ( index < 0 ) {
03247     m_new_cut_box -> setDisabled ( true );
03248     m_cut_selected_box -> setDisabled ( true );
03249   }
03250   else {
03251     DataRep * datarep = plotter->getDataRep ( index );
03252     if ( datarep->hasZeroRows() )
03253       {
03254         m_new_cut_box->setDisabled ( true );
03255         m_cut_selected_box->setDisabled ( true );
03256         return;
03257       }
03258 
03259     m_new_cut_box->setDisabled ( false );
03260     const vector < PlotterBase * > & cuts = getDataCutList ( plotter );
03261     if ( cuts.empty() ) {
03262       m_cut_selected_box->setDisabled ( true );
03263     }
03264     else {
03265       m_cut_selected_box -> setDisabled ( false );
03266     }
03267   }
03268 
03269   updateCutVarGroupBox ( plotter, index );
03270 }
03271 
03272 void
03273 Inspector::
03274 setAllCutsActive ( bool yes )
03275 {
03276   vector < PlotterBase * > plotters;
03277   fillPlotterList ( plotters );
03278 
03279   if ( plotters.empty () == false ) {
03280     CutController * controller = CutController::instance ();
03281     vector < CutPlotter * > cutters;
03282     controller -> fillCutList ( plotters, cutters );
03283     vector < CutPlotter * > ::iterator first = cutters.begin ();
03284 
03285     while ( first != cutters.end () ) {
03286       CutPlotter * cutter = *first++;
03287       cutter -> setActive ( yes );
03288     }
03289   }
03290 }
03291 
03292 void
03293 Inspector::
03294 updateCutVarGroupBox ( const PlotterBase * plotter, int index )
03295 {
03296   const DataSource * tuple
03297     = DisplayController::instance() -> getDataSource ( plotter, index );
03298 
03299   if (!tuple) return;
03300   int index1 = -1;
03301   int index2 = -1;
03302   if ( m_CutVariableComboBox1 -> count() > 0 ) {
03303     index1 = m_CutVariableComboBox1 -> currentItem ();
03304   }
03305   if ( m_CutVariableComboBox2 -> count() > 0 ) {
03306     index2 = m_CutVariableComboBox2 -> currentItem ();
03307   }
03308   m_CutVariableComboBox1->clear();
03309   m_CutVariableComboBox2->clear();
03310 
03311   const vector < string > & cols = tuple->getLabels();
03312 #ifdef ITERATOR_MEMBER_DEFECT
03313   std::
03314 #endif
03315     vector < string > ::const_iterator first = cols.begin ();
03316   while ( first != cols.end() ) {
03317     const string & str = *first++;
03318     m_CutVariableComboBox1 -> insertItem ( str.c_str() );
03319     m_CutVariableComboBox2 -> insertItem ( str.c_str() );
03320   }
03321   if ( index1 >= m_CutVariableComboBox1 -> count () ) {
03322     index1 = 0;
03323   }
03324   if ( index2 >= m_CutVariableComboBox2 -> count () ) {
03325     index2 = 0;
03326   }
03327 
03328   if ( index1 >= 0 ) {
03329     m_CutVariableComboBox1 -> setCurrentItem ( index1 );
03330   }
03331   if ( index2 >= 0 ) {
03332     m_CutVariableComboBox2 -> setCurrentItem ( index2 );
03333   }
03334 
03335   cut_button_group -> setEnabled ( true );
03336   int id = cutRadioId ();
03337   if ( id == 1 ) {
03338     m_CutVariableComboBox2 -> setEnabled( true );
03339   }
03340 }
03341 
03342 int
03343 Inspector::
03344 cutRadioId () const
03345 {
03346   int id = -1;
03347   if ( m_cut_data1 -> isChecked () ) id = 0;
03348   if ( m_cut_data2 -> isChecked () ) id = 1;
03349   if ( m_cut_fit_radio -> isChecked () ) id = 2;
03350 
03351   return id;
03352 }
03353 
03354 void
03355 Inspector::
03356 cut_button_group_clicked ( )
03357 {
03358   int id = cutRadioId ();
03359 
03360   switch  ( id ) {
03361   case 0 : // 1d data cut
03362     m_CutVariableComboBox1 -> setEnabled ( true );
03363     m_CutVariableComboBox2 -> setEnabled ( false );
03364     break;
03365   case 1 : // 2d data cut
03366     m_CutVariableComboBox1 -> setEnabled ( true );
03367     m_CutVariableComboBox2 -> setEnabled ( true );
03368     break;
03369   case 2 : // fit cut
03370     m_CutVariableComboBox1 -> setEnabled ( false );
03371     m_CutVariableComboBox2 -> setEnabled ( false );
03372     break;
03373   }
03374 
03375   updateCutsTab (); // in case of switching from data to fitting
03376 }
03377 void
03378 Inspector::
03379   setSelectedFitter ( const std::string & name )
03380 {
03381   FunctionController * controller = FunctionController::instance ();
03382   const vector < string > & fitters = controller -> getFitterNames ();
03383   for ( unsigned int i = 0; i < fitters.size(); i++ ) {
03384     if ( name == fitters[i] )
03385       {
03386         m_fitter_names -> setCurrentItem ( i );
03387         break;
03388       }
03389   }
03390 }
03391 
03392 void
03393 Inspector::
03394 updateFunctionsTab ()
03395 {
03396   FunctionController * controller = FunctionController::instance ();
03397   const vector < string > & names = controller -> getFunctionNames ();
03398   int current = newFunctionsComboBox->currentItem ();
03399 
03400   if ( newFunctionsComboBox -> count () !=
03401        static_cast < int > ( names.size () ) ) {
03402     newFunctionsComboBox->clear();
03403 
03404     for ( unsigned int i = 0; i < names.size(); i++) {
03405       if ( names[i] != "Linear Sum" ) {
03406         newFunctionsComboBox->insertItem ( names[i].c_str() );
03407       }
03408     }
03409   }
03410 
03411   PlotterBase * plotter = getPlotter();
03412   bool yes = plotter != 0;
03413   m_func_new->setEnabled ( yes );
03414 
03415   if ( yes ) yes = plotter -> isTargetable ();
03416   functionsRemoveButton -> setEnabled ( yes );
03417   m_IgnoreErrorCheckBox -> setEnabled (yes);
03418   functionsFitToDataButton -> setEnabled ( yes );
03419   functionsResetButton -> setEnabled ( yes );
03420   m_resid->setEnabled ( yes );
03421   if ( yes == false ) {
03422     return;
03423   }
03424 
03425   const DataSource * nt
03426     = DisplayController::instance()->getDataSource ( plotter, 0 );
03427 
03428   if ( nt && nt -> empty () )
03429     {
03430       m_func_new->setDisabled ( true );
03431       functionsRemoveButton -> setEnabled ( false );
03432       m_IgnoreErrorCheckBox -> setDisabled (true);
03433       functionsFitToDataButton -> setEnabled ( false );
03434       functionsResetButton -> setEnabled ( false );
03435       return;
03436     }
03437 
03438   // Update new functions section //
03439   //------------------------------//
03440   newFunctionsAddButton->setEnabled ( true );
03441   m_func_new->setEnabled ( true );
03442 
03443   if ( current >= 0 ) {
03444     newFunctionsComboBox->setCurrentItem(current);
03445   }
03446   newFunctionsComboBox->setEnabled ( true );
03447 
03448   // Update functionsAppliedComboBox. //
03449   //----------------------------------//
03450   bool to_enable = false;
03451   DisplayController * d_controller = DisplayController::instance ();
03452   int index = d_controller -> activeDataRepIndex ( plotter );
03453 
03454   FunctionController * f_controller = FunctionController::instance ();
03455 
03456   if ( index >= 0 ) {
03457     DataRep * datarep = plotter ->getDataRep ( index );
03458     if ( f_controller -> hasFunction ( plotter, datarep ) ) {
03459 
03460       const vector < string > & fnames
03461         = f_controller -> functionNames ( plotter, datarep );
03462         
03463       if ( fnames.size() != 0 )
03464         {
03465           to_enable = true;
03466           m_functionIndexMap.clear();
03467         
03468           for ( unsigned i = 0; i < fnames.size(); i++)
03469             {
03470               if ( fnames[i].find ( "Linear Sum" ) == string::npos )
03471                 {
03472                   m_functionIndexMap.push_back ( i );
03473                 }
03474             }
03475         }
03476     }
03477   }
03478 
03479   functionsRemoveButton -> setEnabled ( to_enable );
03480   m_IgnoreErrorCheckBox -> setEnabled (to_enable);
03481   functionsFitToDataButton -> setEnabled ( to_enable );
03482   functionsResetButton -> setEnabled ( to_enable );
03483   if ( to_enable == false ) {
03484     m_FunctionParamsListView -> clear();
03485   }
03486 
03487   if ( to_enable )
03488     {
03489       Fitter * fitter = f_controller -> getFitter ( plotter );
03490       string name = "none";
03491       if ( fitter != 0 ) {
03492         name = f_controller -> getFitterName ( plotter );
03493         setSelectedFitter ( name );
03494       }
03495     }
03496 
03497   m_resid->setEnabled ( to_enable );
03498 
03499   // Update function parameters tab //
03500   //--------------------------------//
03501 
03502   // Set Parameters in list view as well as in line editor and
03503   // the check box. Focus is set to the current selected item
03504   // or in case none is selected 1st item.
03505   if ( to_enable ) setParameters ( index, plotter );
03506 
03507   // Set the slider to be in the center
03508   m_FunctionParamsSlider -> setValue(50);
03509 
03510 }
03511 
03512 void
03513 Inspector::
03514 functionsRemoveButton_clicked()
03515 {
03516   PlotterBase * plotter = getPlotter ();
03517   if ( !plotter ) return ;
03518 
03519   FunctionRep * frep = getFunctionRep ( );
03520   FunctionController * controller = FunctionController::instance ();
03521   controller -> removeFunction ( plotter, frep );
03522   if ( plotter->activePlotIndex ( ) != 0 )
03523     plotter->setActivePlot ( -1, true );
03524   else
03525     plotter->setActivePlot ( 0, true );
03526 
03527   // Update the rest.
03528   updateFunctionsTab();
03529 }
03530 
03531 void
03532 Inspector::
03533 functionsResetButton_clicked()
03534 {
03535   PlotterBase * plotter = getPlotter ();
03536   if ( !plotter ) return ;
03537 
03538   DisplayController * dcontroller = DisplayController::instance ();
03539   int index = dcontroller -> activeDataRepIndex ( plotter );
03540   if ( index < 0 ) return;
03541   DataRep * datarep = plotter -> getDataRep ( index );
03542 
03543   FunctionController * fcontroller = FunctionController::instance();
03544   if ( ! ( fcontroller -> hasFunction ( plotter, datarep ) ) ) {
03545     return;
03546   }
03547 
03548   fcontroller -> restoreParameters ( plotter );
03549 
03550   // Set the parameters
03551   setParameters ( index, plotter );
03552 }
03553 
03554 void
03555 Inspector::
03556 setParameters ( int index, PlotterBase * plotter )
03557 {
03558   m_FunctionParamsListView -> clear();
03559   m_FunctionParamsCheckBox -> setChecked( false );
03560   m_FunctionParamsLineEdit -> clear();
03561 
03562   DataRep * datarep = plotter -> getDataRep ( index );
03563   assert ( datarep != 0 );
03564 
03565   FunctionController * controller = FunctionController::instance ();
03566   if ( ! ( controller -> hasFunction ( plotter, datarep ) ) )
03567     {
03568       return;
03569     }
03570 
03571   const vector < string > & fnames
03572     = controller -> functionNames ( plotter, datarep );
03573 
03574   if ( fnames.empty () ) {
03575     return;
03576   }
03577 
03578   m_function_lv_map.clear ();
03579   vector < FunctionRep * > freps;
03580   controller -> fillTopLevelFunctionReps ( freps, plotter, datarep );
03581   for ( unsigned int i = 0; i < freps.size (); i++ ) {
03582     FunctionRep * frep = freps [ i ];
03583     const string & func_name = frep -> functionName ();
03584 
03585 #if QT_VERSION < 0x040000
03586     QListViewItem * parent
03587       = new QListViewItem ( m_FunctionParamsListView );
03588 #else
03589     Q3ListViewItem * parent
03590       = new Q3ListViewItem ( m_FunctionParamsListView );
03591 #endif
03592     parent -> setOpen ( true );
03593     parent -> setText ( Index, QString ( func_name.c_str() ) );
03594     m_function_lv_map [ parent ] = frep;
03595 
03596   //Ignore errors flag, conected with the ignoreError check box.
03597     bool ignoreFlag = true;
03598 
03599     Fitter * fitter = frep -> getFitter ();
03600     if ( fitter != 0 ) {
03601       //Get the ignore errors flag of the current function.
03602       ignoreFlag = frep -> getIgnoreErrors ();
03603     }
03604     const vector < double > & parms = frep -> parameters ();
03605     unsigned int start_index = parms.size();
03606     fillFunctionParameters ( parent, frep, start_index );
03607 
03608     m_FunctionParamsListView -> setAllColumnsShowFocus ( true );
03609 #if QT_VERSION < 0x040000
03610     QListViewItem * firstItem = parent -> firstChild ();
03611 #else
03612     Q3ListViewItem * firstItem = parent -> firstChild ();
03613 #endif
03614     m_IgnoreErrorCheckBox -> setChecked(ignoreFlag);
03615 
03616     if ( firstItem != 0 ) {
03617       m_FunctionParamsLineEdit -> setText ( firstItem -> text( Value ) );
03618       m_FunctionParamsListView -> setSelected ( firstItem, true );
03619       m_FunctionParamsListView -> setCurrentItem ( firstItem );
03620     
03621       QString fixedFlag = firstItem -> text( Fixed );
03622       m_FunctionParamsCheckBox->setChecked((fixedFlag == QString ( "Yes" ) ) ? 
03623                                            true : false );
03624     }
03625   }
03626 }
03627 
03628 void
03629 Inspector::
03630 #if QT_VERSION < 0x040000
03631 fillFunctionParameters ( QListViewItem * parent,
03632                          const FunctionRep * frep,
03633                          unsigned int & index )
03634 #else
03635 fillFunctionParameters ( Q3ListViewItem * parent,
03636                          const FunctionRep * frep,
03637                          unsigned int & index )
03638 #endif
03639 {
03640   const CompositeFunctionRep * composite
03641     = dynamic_cast < const CompositeFunctionRep * > ( frep );
03642 
03643   if ( composite != 0 ) {
03644     const vector < FunctionRep * > & freps 
03645       = composite -> getFunctionReps ();
03646     unsigned int size = freps.size();
03647 
03648     //  because children are inserted at the beginning, we must do things
03649     // backwards
03650     for ( int i = size -1; i >= 0; i-- ) {
03651       FunctionRep * rep = freps[i];
03652       const string & func_name = rep -> functionName ();
03653 #if QT_VERSION < 0x040000
03654       QListViewItem * child
03655         = new QListViewItem ( parent );
03656 #else
03657       Q3ListViewItem * child
03658         = new Q3ListViewItem ( parent );
03659 #endif
03660       child -> setOpen ( true );
03661       child -> setText ( Index, QString ( func_name.c_str() ) );
03662       m_function_lv_map [ child ] = rep;
03663 
03664       fillFunctionParameters ( child, rep, index );
03665     }
03666   }
03667   else { // not composite
03668     vector < FunctionParameter > function_parameters;
03669     frep -> fillFunctionParameters ( function_parameters );
03670 
03671     QString qyes( "Yes" );
03672     QString qno( "No" );
03673 
03674     // Because items are inserted at the begining, we must do things
03675     // backwards
03676     unsigned int size = function_parameters.size ();
03677 
03678     for ( int pindex = size-1; pindex >= 0; pindex-- ) {
03679       FunctionParameter fp = function_parameters[pindex];
03680       QString dummy;
03681 #if QT_VERSION < 0x040000
03682       QCheckListItem * item
03683         = new QCheckListItem ( parent, dummy,
03684                                QCheckListItem::CheckBox );
03685 #else
03686       Q3CheckListItem * item
03687         = new Q3CheckListItem ( parent, dummy,
03688                                 Q3CheckListItem::CheckBox );
03689 #endif
03690       item -> setText( Index, QString( "%1" ).arg( index-- ) );
03691 
03692       const string & name = fp.name ();
03693       QString pname = name.c_str();
03694       QString fixedFlag ( qno );
03695       fixedFlag = fp.isFixed () ? qyes : qno;
03696 
03697       item -> setText( Name, QString( "%1" ).arg( pname ) );
03698       item -> setText( Value, QString( "%1" ).arg( fp.value() ) );
03699       item -> setText( Error, QString( "%1" ).arg( fp.error() ));
03700       item -> setText( Fixed, QString( "%1" ).arg( fixedFlag ) );
03701       item -> setText( Dummy, QString( "%1" ).arg( pindex ) );
03702     }
03703   }
03704 }
03705 
03709 void
03710 Inspector::
03711 functionAdd ()
03712 {
03713   PlotterBase * plotter = getPlotter ();
03714   if ( !plotter ) return ;
03715 
03716   bool yes = plotter -> isTargetable ();
03717   if ( yes == false ) {
03718     multipleDataRepError ( "function" );
03719     return;
03720   }
03721 
03722   DisplayController * dc = DisplayController::instance();
03723 
03724   DataRep * datarep = dc -> activeDataRep ( plotter );
03725   assert ( datarep != 0 );
03726 
03727   if ( !datarep->acceptFunction(1) ){
03728     functionAddError ();
03729     return;
03730   }
03731 
03732   // Get the selected function name.
03733 
03734   QString qstr  =  newFunctionsComboBox->currentText();
03735   std::string fun_name = qstr.latin1();
03736 
03737   // Add the function.
03738 
03739   QString s = m_fitter_names -> currentText ( );
03740   const string fit_name = s.latin1();
03741 
03742   FunctionController * fc = FunctionController::instance();
03743   yes = fc -> isCompatible ( fun_name, fit_name );
03744 
03745   if ( yes == false ) {
03746     incompatibleFunctionError ( fun_name );
03747     return;
03748   }
03749 
03750   FunctionRep * new_rep = 0;
03751   try {
03752 #if QT_VERSION < 0x040000
03753     QListViewItem * item = m_FunctionParamsListView -> currentItem ();
03754 #else
03755     Q3ListViewItem * item = m_FunctionParamsListView -> currentItem ();
03756 #endif
03757     bool is_selected = m_FunctionParamsListView -> isSelected ( item );
03758     FunctionRep * frep = 0;
03759     if ( is_selected ) {
03760       frep = getFunctionRep ( item );
03761     }
03762 
03763     new_rep = fc->addFunction ( plotter, fun_name, frep, datarep );
03764   }
03765   catch ( std::exception & e ) {
03766     badFunctionError ( fun_name, e.what() );
03767   }
03768 
03769   int index = m_fitter_names -> currentItem ();
03770   fitterNamesActivated ( index ); // sets the fitter
03771 
03772   functionsRemoveButton -> setEnabled ( true );
03773   m_IgnoreErrorCheckBox -> setEnabled (true);
03774   functionsFitToDataButton -> setEnabled ( true );
03775   functionsResetButton -> setEnabled ( true );
03776   fc->saveParameters ( plotter );
03777 
03778   bool ok = false;
03779   if ( new_rep != 0 ) {
03780     ok = fc -> tryFitFunction ( plotter, new_rep ); // try fit
03781   }
03782   if ( ! ok ) {
03783     fitFailedError ();
03784   }
03785   // Update other tabs that need it.
03786 
03787   updateFunctionsTab();
03788 }
03789 
03790 void
03791 Inspector::
03792 fitterNamesActivated ( int index )
03793 {
03794   FunctionController * controller = FunctionController::instance ();
03795   const vector < string > & names = controller -> getFitterNames ();
03796   const string & def_fitter = names [ index ];
03797   controller -> setDefaultFitter ( def_fitter );
03798 
03799   PlotterBase * plotter = getPlotter ();
03800   if ( plotter != 0 ) {
03801     const DataRep * datarep = plotter -> getTarget ();
03802     bool yes = controller -> hasFunction ( plotter, datarep );
03803     if ( yes ) {
03804       bool ok = controller -> changeFitter ( plotter, datarep,
03805                                              def_fitter );
03806       if ( ok == false ) {
03807         incompatibleFitterError ( def_fitter );
03808         functionsFitToDataButton -> setEnabled ( false );
03809       }
03810       else {
03811         functionsFitToDataButton -> setEnabled ( true );
03812       }
03813     }
03814   }
03815 }
03816 
03817 void
03818 Inspector::
03819 fitFailedError ()
03820 {
03821   const QString message ( "The Fit failed to converge" );
03822   QMessageBox::critical ( this, // parent
03823                           "Fit failed",
03824                           message,
03825                           QMessageBox::Ok,
03826                           Qt::NoButton,
03827                           Qt::NoButton );
03828 }
03829 
03830 FunctionRep *
03831 Inspector::
03832 #if QT_VERSION < 0x040000
03833 getFunctionRep ( QListViewItem * item )
03834 #else
03835 getFunctionRep ( Q3ListViewItem * item )
03836 #endif
03837 {
03838   FunctionRep * rep = 0;
03839   if ( item != 0 ) {
03840     item = getTopParent ( item );
03841     rep = m_function_lv_map [ item ];
03842   }
03843   return rep;
03844 }
03845 
03846 FunctionRep *
03847 Inspector::
03848 getFunctionRep ()
03849 {
03850 #if QT_VERSION < 0x040000
03851   QListViewItem * item = m_FunctionParamsListView -> currentItem();
03852 #else
03853   Q3ListViewItem * item = m_FunctionParamsListView -> currentItem();
03854 #endif
03855 
03856   return getFunctionRep ( item );
03857 }
03858 
03859 void
03860 Inspector::
03861 functionsFitToDataButton_clicked()
03862 {
03863   PlotterBase * plotter = getPlotter ();
03864   if ( !plotter ) return ;
03865 
03866   FunctionController * fcnt = FunctionController::instance();
03867   if ( ! ( fcnt -> hasFunction ( plotter, 0 ) ) ) { // any function
03868     return;
03869   }
03870 
03871   fcnt -> saveParameters ( plotter );
03872 
03873   FunctionRep * fun_rep = getFunctionRep ();
03874 
03875   bool ok = fcnt -> fitFunction ( plotter, fun_rep );
03876   if ( ! ok ) {
03877     fitFailedError ();
03878   }
03879 
03880   // Set the parameters
03881