CanvasView.cxx
Go to the documentation of this file.
1 
13 // for MEMFUN1 and others
14 #ifdef HAVE_CONFIG_H
15 // for wcslib also
16 #include "config.h"
17 #endif
18 
19 #if QT_VERSION < 0x040000
20 #else
21 //Added by the Qt porting tool:
22 #include <QMouseEvent>
23 #endif
24 
25 #ifdef _MSC_VER
26 #include "msdevstudio/MSconfig.h"
27 #endif
28 
29 #include "CanvasView.h"
30 
31 #include "CanvasSelectionEvent.h"
32 #include "CanvasSettings.h"
33 #include "CanvasWindow.h"
34 #include "Inspector.h"
35 #include "PlotterEvent.h"
36 #include "QtViewFactory.h"
37 #include "PickTable.h"
38 #include "WindowController.h"
39 #include "CreateNTuple.h"
40 #include "QtGroupView.h"
41 
44 #include "datareps/ScatterPlot.h"
47 #include "graphics/EpsView.h"
48 #include "plotters/PlotterBase.h"
49 #include "plotters/Cut1DPlotter.h"
50 #include "plotters/Cut2DPlotter.h"
51 #include "qtxml/QtXMLController.h"
53 
54 #ifdef HAVE_CFITSIO
55 #include "fits/FitsController.h"
56 #endif
57 
58 #ifdef HAVE_ROOT
59 #include "root/RootController.h"
60 #endif
61 
62 #ifdef HAVE_WCSLIB
63 /* The following were defined in generated ../config.h. */
64 #undef PACKAGE_BUGREPORT
65 #undef PACKAGE_NAME
66 #undef PACKAGE_STRING
67 #undef PACKAGE_TARNAME
68 #undef PACKAGE_VERSION
69 #ifdef _WIN32
70 #include "wcslib/C/config.h"
71 #else
72 #include "wcslib/config.h"
73 #endif
74 #endif
75 
76 #include <qapplication.h>
77 #include <qaction.h>
78 
79 #if QT_VERSION < 0x040000
80 #include <qfiledialog.h>
81 #include <qimage.h>
82 #else
83 #include <q3action.h>
84 #include <q3filedialog.h>
85 #include <QtGui/QImageWriter>
86 #endif
87 
88 #include <qcursor.h>
89 #include <qiconset.h>
90 #include <qmessagebox.h>
91 #include <qpainter.h>
92 #include <qsettings.h>
93 #include <qstatusbar.h>
94 #include <qwaitcondition.h>
95 #include <qfont.h>
96 
97 #include <algorithm>
98 #include <exception>
99 
100 #include <cctype>
101 #include <cmath>
102 
103 #include <cassert>
104 
105 using std::bind2nd;
106 using std::for_each;
107 using std::map;
108 using std::mem_fun;
109 using std::list;
110 using std::string;
111 using std::tolower;
112 using std::vector;
113 
114 namespace {
116 }
117 
118 using namespace hippodraw;
119 
120 /* Use `=' syntax so that Doxygen picks it up. */
121 const string CanvasView::s_app_name = "HippoDraw";
123 
125 
126 #if QT_VERSION < 0x040000
128  const char * name, Qt::WFlags f )
129 #else
130 CanvasView::CanvasView ( Q3Canvas * c, QWidget * parent,
131  const char * name, Qt::WFlags f )
132 #endif
133  : FigureEditor ( c, parent, name, f ),
134  m_inspector ( 0 ),
135  m_image_dialog ( 0 ),
136  m_num_width ( 2 ),
137  m_num_height ( 3 ),
138  m_cut_mode ( 1 ),
139  m_edge ( 0 ),
140  m_clicked( false )
141 
142 {
143  s_xml_controller = QtXMLController::instance ();
144  m_table_map.clear();
145  m_drag_rect = 0;
146 
147  initSettings ();
148 }
149 
150 void
153 {
154  QSettings settings;
155  settings.insertSearchPath ( QSettings::Windows, s_registry );
156 
158  = settings.readNumEntry ( s_app_key + "Canvas/Number/Width", 2 );
160  = settings.readNumEntry ( s_app_key + "Canvas/Number/Height", 3 );
162  = settings.readBoolEntry ( s_app_key + "Canvas/AddSelected" );
164  = settings.readBoolEntry ( s_app_key + "Canvas/IgnoreMargin" );
165 }
166 
167 void
168 CanvasView::
169 #if QT_VERSION < 0x040000
170 initDockWindows ( QMainWindow * mw )
171 #else
172 initDockWindows ( Q3MainWindow * mw )
173 #endif
174 {
175  QSettings settings;
176  settings.insertSearchPath ( QSettings::Windows, s_registry );
177  bool ok = false;
178  QString dockSetting = settings.readEntry ( s_app_key + "DockWindow/Position",
179  QString::null, &ok );
180 
181  if ( ok == false ) return;
182  QTextStream stream( &dockSetting, IO_ReadOnly );
183  stream >> *mw;
184 }
185 
186 void
189 {
190 #if QT_VERSION < 0x040000
191 #else
192  QObject * parent = ag -> parent ();
193 #endif
194  QSettings settings;
195  settings.insertSearchPath ( QSettings::Windows, s_registry );
196  bool ok = false;
197 
198  // Read every entries from the settings.
199  for (unsigned int i = 0; i<5; i++){
200  QString number=QString::number(i);
201  QString entry = settings.readEntry ( s_app_key + "Files/File"+number,
202  QString::null, &ok );
203 
204  // No entry or empty entry.
205  if ((ok==false) || ( entry == "" )) return;
206 
207 
208 #if QT_VERSION < 0x040000
209  QAction * action = new QAction ( "", // text
210  QIconSet(),
211  entry, // menu test
212  0, // accel
213  ag ); // parent
214 #else
215  QAction * action = new QAction ( entry, parent );
216  ag -> addAction ( action );
217 #endif
218  m_recent_list.push_back( action );
219  action -> setToggleAction ( true );
220  }
221 }
222 
223 
224 void
227 {
228  QSettings settings;
229  settings.insertSearchPath ( QSettings::Windows, s_registry );
230  bool ok = false;
231  QString entry = settings.readEntry ( s_app_key + "Fitter/Name",
232  QString::null, &ok );
233  if ( ok == true ) {
234  const string name ( entry.latin1() );
235  try { // might not be available
236  setFitterDefault ( name );
237  if ( m_inspector != 0 ) {
238  m_inspector -> setSelectedFitter ( name );
239  }
240  }
241  catch ( ... ) { // not available in this build
242  // could raise error dialog, but not nice on initialization
243  }
244  }
245 }
246 
247 void
249 setFitterDefault ( const QString & name )
250 {
251  QSettings settings;
252  settings.insertSearchPath ( QSettings::Windows, s_registry );
253  settings.writeEntry ( s_app_key + "Fitter/Name", name );
254 
255  const string fitter ( name.latin1() );
256  setFitterDefault ( fitter );
257 }
258 void
260 setFitterDefault ( const std::string & name )
261 {
263  controller -> setDefaultFitter ( name );
264 }
265 
266 void
269 {
271  initFitterMenu ( ag );
272 }
273 
274 void
277 {
279  const vector < string > & fitters = controller -> getFitterNames ();
280  const string & def_fitter = controller -> getDefaultFitter ();
281 #if QT_VERSION < 0x040000
282 #else
283  QObject * parent = ag -> parent ();
284 #endif
285  for ( unsigned int i = 0; i < fitters.size(); i++ ) {
286 #if QT_VERSION < 0x040000
287  const QString name ( fitters[i].c_str() );
288  QAction * action = new QAction ( "", // text
289  QIconSet(),
290  name, // menu test
291  0, // accel
292  ag ); // parent
293 #else
294  const QString name ( fitters[i].c_str() );
295  QAction * action = new QAction ( name, parent );
296  ag -> addAction ( action );
297 #endif
298  action -> setToggleAction ( true );
299  if ( def_fitter == fitters[i] ) {
300  action -> setOn ( true );
301  }
302  }
303 }
304 
305 
306 void
308 saveSettings () const
309 {
310  QSettings settings;
311  settings.insertSearchPath ( QSettings::Windows, s_registry );
312 
313  int orientation;
314  if( s_printer -> orientation() == QPrinter::Portrait )
315  orientation = 0;
316  else
317  orientation = 1;
318 
319  settings.writeEntry ( s_app_key + "Printer/Orientation", orientation );
320  settings.writeEntry ( s_app_key + "Canvas/Number/Width", m_num_width );
321  settings.writeEntry ( s_app_key + "Canvas/Number/Height", m_num_height );
322  settings.writeEntry ( s_app_key + "Canvas/AddSelected", m_add_selected );
323  settings.writeEntry ( s_app_key + "Canvas/IgnoreMargin", m_ignore_margin );
324 
325  if( m_printer_bounds == false )
326  settings.writeEntry ( s_app_key + "Canvas/Margin", 0 );
327  else
328  settings.writeEntry ( s_app_key + "Canvas/Margin", 1 );
329 }
330 
331 void
333 setAddedSelected ( bool yes )
334 {
335  m_add_selected = yes;
336 }
337 
338 void CanvasView::initFrom ( const std::list < ViewBase * > & views )
339 {
340  std::list < ViewBase * > ::const_iterator first = views.begin();
341  for ( ; first != views.end(); ++first ) {
342  QtView * view = dynamic_cast < QtView * > ( *first );
343  if ( view -> height () < 0 ||
344  view -> width () < 0 ) {
345  sizeAndPlace ( view );
346  }
347  add ( view ); // ignore the rest
348  }
349 
350 #if QT_VERSION < 0x040000
352 #else
354 #endif
355 }
356 
357 void
359 initFromFile ( const std::string & filename )
360 {
361  XmlController::Status status = s_xml_controller->openFile ( filename );
362 
363  // If file not found, change the directory and try again.
364  if ( status == XmlController::NTupleError ) {
365 
366  std::list < std::string > & missing_tuples =
367  s_xml_controller -> getMissingTuples ();
368  std::list< std::string>::iterator it;
369 
370  for ( it=missing_tuples.begin(); it!=missing_tuples.end(); ++it )
371  {
372  string shortFileName;
373  string::size_type pos1 = (*it).find_last_of ("/");
374  string::size_type pos2 = (*it).find_last_of (":");
375  shortFileName = (*it).substr(pos1+1); // get the short filename
376 
377  QString cap ( "Select the DataSource: " );
378  cap += shortFileName.c_str(); // Caption of the open file dialog
379  QString filter ( "All files(*.*);;Text NTuple(*.tnt);;FITS file(*.fits);;Compressed FITS file(*.fits.gz);;ROOT file(*.root)");
380 
381  QString filename =
382 #if QT_VERSION < 0x040000
383  QFileDialog::getOpenFileName ( QString::null, // starting directory
384  filter, // filter
385  this,
386  "Open file dialog",
387  cap ); // caption
388 #else
389  Q3FileDialog::getOpenFileName ( QString::null, // starting directory
390  filter, // filter
391  this,
392  "Open file dialog",
393  cap ); // caption
394 #endif
395 
396  string newFileName = filename.latin1();
397 
398 
399  if ( ( pos2!= string::npos) && (pos2 != 1) ) {
400  ( *it ).replace (0, pos2, newFileName); // keep the name
401  // after ":"
402  // unchanged
403  }
404  else {
405  ( *it )=newFileName; // with no name
406  }
407 
408  }
409 
410  status = s_xml_controller->openUpdatedNTuples ( );
411  }
412 
413 
414  // Second try failed, show failed message.
415  if ( status != XmlController::Success ) {
416  const string & app_name = applicationName ();
417 
418  QString fn = filename.c_str ();
419  QString message;
420  message = QString("Unable to open document file:\n%1\n").arg ( fn );
421  if ( status == XmlController::OpenError ) {
422  message += "\nFile could not be read\n";
423  } else
424  if ( status == XmlController::ParseError ) {
425  message += "\nThere was a XML parsing error\n";
426  } else {
427  message += "\nThere were one or more referenced\n";
428  message += "NTuple files that could not be found.";
429  }
430  QMessageBox::critical ( this, // parent
431  app_name.c_str(), // caption
432  message,
433  QMessageBox::Ok,
434  Qt::NoButton,
435  Qt::NoButton );
436  show ();
437  return;
438  }
439 
440  ViewFactory * factory = QtViewFactory::instance ();
441  const list < ViewBase * > & view_list
442  = s_xml_controller->getViews ( factory );
443 
444  initFrom ( view_list );
445 
446  notifyObservers ();
447 }
448 
449 void
451 invalidImageFormatError ( const std::string & filename )
452 {
453  if ( s_image_filters.empty () ) createImageFilters ();
454 
455  string types;
456  string::size_type size = s_image_filters.size ();
457  for ( string::size_type i = 0; i < size; i++ ) {
458  string::value_type c = s_image_filters[i];
459  if ( c != '(' &&
460  c != ')' &&
461  c != ';' ) types += c;
462  }
463 
464  string message ( "Attempt to save image to file:\n" );
465  message += filename;
466  message += "\nwhose suffix indicates unsupported image format.\n\n";
467  message += "Supported image formats are:\n";
468  message += types;
469 
470  QMessageBox::critical ( this, // parent
471  "Image format error", // caption
472  message.c_str() );
473 
474 }
475 
476 bool
478 existingFileWarning ( const std::string & filename )
479 {
480  string message ( "The file:\n" );
481  message += filename;
482  message += "\nalready exists.\n\n";
483  message += "Over-write existing file?";
484 
485  int yes = QMessageBox::warning ( this, //parent
486  "Existing file warning", // caption
487  message.c_str(),
488  QMessageBox::Yes,
489  QMessageBox::No,
490  Qt::NoButton );
491 
492  return yes == QMessageBox::Yes;
493 }
494 
498 void
501 {
502  const vector < const ViewBase * > & selViews = selectedViews();
503  if ( selViews.empty () ) return;
504 
505  vector < const ViewBase * > view_list;
506  fillSelectedWithObservers ( view_list );
507  s_xml_controller->saveToPasteboard ( view_list );
508 
510 }
511 
512 void
515 {
516  const vector < const ViewBase * > & targets = views ();
517  ViewFactory * factory = QtViewFactory::instance ();
518 
519  const list < ViewBase * > & pb_views
520  = s_xml_controller->getFromPasteboard ( factory, targets );
521  pasteViews ( pb_views );
522 }
523 
524 void
527 {
528  const vector < const ViewBase * > & targets = views ();
529  ViewFactory * factory = QtViewFactory::instance ();
530 
531  const list < ViewBase * > & pb_views
532  = s_xml_controller->getFromPasteboard ( factory, targets );
533  list < ViewBase * >::const_iterator first = pb_views.begin ();
534  while ( first != pb_views.end () ) {
535  ViewBase * view = *first++;
536  QtView * qtview = dynamic_cast < QtView * > ( view );
537  placeGraph ( qtview );
538  addView ( qtview, true );
539  }
540 }
541 
542 void
544 deleteSelected ( bool pasteboard )
545 {
546  const vector < const ViewBase * > & selViews = selectedViews();
547  if ( selViews.empty () ) return;
548 
549  vector < const ViewBase * > view_list;
550  fillSelectedWithObservers ( view_list );
551  if ( pasteboard ) {
552  s_xml_controller->saveToPasteboard ( view_list );
553  }
554 
556  controller->removeTextObservers ( view_list );
557 
558  // Remove views from the canvas.
559 
560 #ifdef ITERATOR_MEMBER_DEFECT
561  std::
562 #endif
563  vector < const ViewBase * > ::const_iterator iter = view_list.begin();
564 
565  // Remove views or group views.
566  while ( iter != view_list.end() ) {
567  const ViewBase * curview = ( * iter++ );
568  const QtView * view = dynamic_cast < const QtView * > ( curview );
569  QtView * v = 0;
570  if (view) v = const_cast < QtView * > ( view );
571  const QtGroupView * groupview =
572  dynamic_cast < const QtGroupView * > ( curview );
573  QtGroupView * gv = 0;
574  if (groupview) gv = const_cast < QtGroupView * > (groupview);
575  if (v) remove ( v );
576  if (gv) remove (gv);
577  }
578 
579  notifyObservers ();
580 }
581 
582 void
585 {
587 
588  notifyObservers ();
589 }
590 
596 {
597  const vector < const ViewBase * > & views = selectedViews ();
598 #ifdef ITERATOR_MEMBER_DEFECT
599  std::
600 #endif
601  vector < const ViewBase * > ::const_iterator first = views.begin();
602  while ( first != views.end() ) {
603  const QtView * view = dynamic_cast < const QtView * > ( *first++ );
604  QtView * v = const_cast < QtView * > ( view );
605  remove ( v );
606  }
607 }
608 
612 void CanvasView::pasteViews ( const std::list < ViewBase * > & views )
613 {
615  std::list < ViewBase * > ::const_iterator first = views.begin();
616  for ( ; first != views.end(); ++first ) {
617  QtView * view = dynamic_cast < QtView * > ( *first );
618  paste ( view );
619  addSelectedItem ( view );
620  }
621 
622  setChanged ( true );
623 }
624 
626 {
627  m_inspector = inspector;
629 }
630 
632 {
633  return m_inspector;
634 }
635 
636 void CanvasView::setChanged ( bool flag )
637 {
638  QWidget * parent = parentWidget ();
639  if ( parent != 0 ) {
640  PlotterEvent * event = new PlotterEvent ( 0 );
641  QApplication::postEvent ( parent, event );
642  }
643 }
644 
646 {
647  setChanged ( true );
648  if ( m_inspector != 0 ) {
649  vector < PlotterBase * > plotters = getSelectedPlotters ();
650 
651  CanvasSelectionEvent * event = new CanvasSelectionEvent ( plotters );
653  }
654 
656  controller -> updateActions ();
657 }
658 
659 vector < PlotterBase * >
662 {
663  vector < PlotterBase * > plotters;
664 
665  const vector < const ViewBase * > & viewList = selectedViews ();
666  unsigned int size = viewList.size ();
667  for ( unsigned int i = 0; i < size; i++ ) {
668  const ViewBase * view = viewList [ i ];
669 
670  const QtGroupView * groupView = dynamic_cast <const QtGroupView *> (view);
671 
672  if (groupView) {
673  const vector <PlotterBase *> groupPlotters = groupView -> getPlotters ();
674  plotters.insert ( plotters.end(),
675  groupPlotters.begin(), groupPlotters.end() );
676  break;
677  }
678 
679  //else
680  PlotterBase * plotter = view -> getPlotter ();
681  if ( plotter != 0 ) {
682  plotters.push_back ( plotter );
683  }
684  }
685 
686  return plotters;
687 }
688 
690 {
691  const vector < const ViewBase * > & viewList = selectedViews ();
692 
693  if ( viewList.size() != 1 )
694  {
695  return 0;
696  }
697 
698  PlotterBase * plotter = viewList[0]->getPlotter ();
699  //assert ( plotter ); // Can return 0, handle by caller.
700 
701  return plotter;
702 }
703 
704 void
706 addView ( QtView * view, bool select )
707 {
708  add ( view ); // in FigureEditor
709  if ( select ) {
710  ensureVisible ( view );
711  setSelectedItem ( view );
712  vector < const ViewBase * > view_list;
713  fillSelectedWithObservers ( view_list );
714  s_xml_controller -> saveToSelectionCopy ( view_list );
715  }
716  notifyObservers ();
717 }
718 
719 void
721 setPlotMatrix ( unsigned int columns, unsigned int rows )
722 {
723  m_num_width = columns;
724  m_num_height = rows;
725 }
726 
727 void
730 {
731 #if QT_VERSION < 0x040000
732  QCanvas * can = canvas();
733 #else
734  Q3Canvas * can = canvas();
735 #endif
736  int numpages = static_cast<int> ( can -> height()
737  / (double) m_apage_h );
738  std::swap( m_upage_w, m_upage_h );
739  std::swap( m_apage_w, m_apage_h );
740 
741  can -> resize ( static_cast<int> ( 1.2 * m_upage_w ),
742  numpages * m_apage_h );
743 
744  showPrinterMargins ( false ); // Delete old ones ( if any )
745  showPrinterMargins ( true ); // Redraw new ones ( if needed )
746 }
747 
748 void
751 {
752  CanvasSettings * cs = new CanvasSettings ( this );
753  cs -> setOrientation ( s_printer -> orientation() );
754  cs -> setWidthNumber ( m_num_width );
755  cs -> setHeightNumber ( m_num_height );
756  cs -> setAddSelected ( m_add_selected );
757  cs -> setPrinterBounds ( m_printer_bounds );
758  cs -> setIgnorePrinterMargin ( m_ignore_margin );
759 
760  int retval = cs -> exec ();
761 
762  if ( retval == CanvasSettings::AcceptedAndRetile ||
763  retval == CanvasSettings::Retile )
764  {
765  m_add_selected = cs -> getAddSelected ();
766 
767 
768  if ( cs -> orientation() != s_printer -> orientation() ) {
769  s_printer -> setOrientation( cs -> orientation() );
770  swapOrientation ();
771  }
772 
773  if( cs -> printerBounds() == false )
774  showPrinterMargins ( false ); // Delete old ones ( if any )
775  else
776  {
777  showPrinterMargins ( false ); // Delete old ones ( if any )
778  showPrinterMargins ( true ); // Redraw new ones ( if needed )
779  }
780 
781  m_ignore_margin = cs -> ignorePrinterMargin ();
782  }
783 
784  if ( retval == CanvasSettings::AcceptedAndRetile ||
785  retval == CanvasSettings::Retile ) {
786  unsigned int columns = cs -> getWidthNumber ();
787  unsigned int rows = cs -> getHeightNumber ();
788  setPlotMatrix ( columns, rows );
789  reTile ();
790  }
791 
792  if ( retval == CanvasSettings::AcceptedAndRetile ) {
793  saveSettings ();
794  }
795 
796  delete cs;
797 }
798 
799 
800 void
802 setFonts( const QFont & font )
803 {
804  const vector < const ViewBase * > & allviews = views();
805 
806  for( unsigned int i = 0; i < allviews.size(); i++ )
807  {
808  const ViewBase * curview = allviews[ i ];
809  const QtView * view = dynamic_cast < const QtView * > ( curview );
810  QtView * v = const_cast < QtView * > ( view );
811  v -> setDefaultFont( font );
812  v -> getPlotter() -> update();
813  }
814 }
815 
816 void
818 calcDefaultSize ( QtView * view, double transform_aspect_ratio )
819 {
820  double width = ( 0.95 * m_upage_w ) / m_num_width;
821  double height = ( 0.95 * m_upage_h ) / m_num_height;
822 
823  if ( transform_aspect_ratio > 0.0 )
824  {
825  width = height * transform_aspect_ratio;
826  }
827 
828  view -> setDrawRect ( 0.0, 0.0, width, height );
829 }
830 
831 
832 void
835 {
836  addPlotDisplay ( plotter, m_add_selected );
837 }
838 
839 QtView *
842 {
843  ViewFactory * factory = QtViewFactory::instance ();
844  ViewBase * view = factory -> createView ( plotter );
845  QtView * qtview = dynamic_cast< QtView * > ( view );
846  qtview -> setSize ( -1, -1 );
847 
848  return qtview;
849 }
850 
851 void CanvasView::addPlotDisplay ( PlotterBase * plotter, bool select )
852 {
853  QtView * qtview = wrapPlotter ( plotter );
854  qtview -> setPageWidth( m_upage_w );
855  qtview -> setInspector( m_inspector );
856  sizeAndPlace ( qtview );
857 
858  addView ( qtview, select );
859 }
860 
861 void
864 {
865  PlotterBase * plotter = view -> getPlotter ();
866  double transform_aspect_ratio = plotter -> getAspectRatio();
867  calcDefaultSize ( view, transform_aspect_ratio );
868  placeGraph ( view );
869 }
870 
871 static bool
872 #if QT_VERSION < 0x040000
873 sortViews ( QCanvasItem * first, QCanvasItem * second )
874 #else
875 sortViews ( Q3CanvasItem * first, Q3CanvasItem * second )
876 #endif
877 {
878  bool yes = false;
879 
880  QRect frect = first -> boundingRect ();
881  QRect srect = second -> boundingRect ();
882 
883  if ( frect.left () < srect.left () ) {
884  if ( frect.top() < srect.bottom () ) {
885  yes = true;
886  }
887  }
888  if ( frect.right () > srect.right () ) {
889  if ( frect.bottom () < srect.top () ) {
890  yes = true;
891  }
892  }
893  else {
894  yes = frect.top () < srect.top ();
895  }
896 
897  return yes;
898 }
899 
900 void
903 {
904 #if QT_VERSION < 0x040000
905  QCanvas temp_canvas;
906 #else
907  Q3Canvas temp_canvas;
908 #endif
909 #ifdef MEMFUN1_DEFECT
910  for_each ( m_items.begin(), m_items.end(),
911 #if QT_VERSION < 0x040000
912  bind2nd ( mem_fun1 ( & QCanvasItem::setCanvas ), &temp_canvas ) );
913 #else
914  bind2nd ( mem_fun1 ( & Q3CanvasItem::setCanvas ),
915  &temp_canvas ) );
916 #endif
917 #else
918  for_each ( m_items.begin(), m_items.end(),
919 #if QT_VERSION < 0x040000
920  bind2nd ( mem_fun ( & QCanvasItem::setCanvas ), &temp_canvas ) );
921 #else
922  bind2nd ( mem_fun ( & Q3CanvasItem::setCanvas ), &temp_canvas ) );
923 #endif
924 #endif
925 
926 #if QT_VERSION < 0x040000
927  vector < QCanvasItem * > items ( m_items );
928 #else
929  vector < Q3CanvasItem * > items ( m_items );
930 #endif
931  m_items.clear();
932 
933  sort ( items.begin(), items.end(), sortViews );
934 
935  placeItems ( items );
936 }
937 
938 void
939 CanvasView::
940 #if QT_VERSION < 0x040000
941 placeItems ( const std::vector < QCanvasItem * > & items )
942 {
943  vector < QCanvasItem * >:: const_iterator first = items.begin();
944 #else
945 placeItems ( const std::vector < Q3CanvasItem * > & items )
946 {
947  vector < Q3CanvasItem * >:: const_iterator first = items.begin();
948 #endif
949 
950  // Place xy plotters before text plotters.
951  vector <QtView *> textViews;
952 
953  while ( first != items.end() )
954  {
955  QtView * view = dynamic_cast < QtView * > ( *first++ );
956 
957  PlotterBase * plotter = view->getPlotter();
958  if (plotter->isTextPlotter()) {
959  // Move back to (0,0) and add to textView list.
960  double x = view -> x ();
961  double y = view -> y ();
962  view->moveBy(-x, -y);
963  textViews.push_back(view);
964  continue;
965  }
966  calcDefaultSize ( view, view -> getAspectRatio() );
967  placeGraph ( view );
968  add ( view );
969  }
970 
971  // Add text plotters to their parent plotters
972  vector <QtView *>::const_iterator it = textViews.begin();
973  while ( it != textViews.end() )
974  {
975  QtView * view = *it++;
976  moveToPlotter(view->getPlotter()->getParentPlotter(), view );
977  add ( view );
978  }
979 }
980 
981 void
984 {
985  int y = contentsY ();
986  int page = y / m_apage_h;
987  QRect rect ( 0, page * m_apage_h, m_apage_w, m_apage_h );
988 #if QT_VERSION < 0x040000
989  QCanvasItemList c_items = m_canvas -> collisions ( rect );
990 
991  // copy to STL vector and remove from item list.
992  vector < QCanvasItem * > v_items;
993  QCanvasItemList:: const_iterator first = c_items.begin();
994  while ( first != c_items.end() ) {
995  QCanvasItem * item = *first++;
996 #else
997  Q3CanvasItemList c_items = m_canvas -> collisions ( rect );
998 
999  // copy to STL vector and remove from item list.
1000  vector < Q3CanvasItem * > v_items;
1001  Q3CanvasItemList:: const_iterator first = c_items.begin();
1002  while ( first != c_items.end() ) {
1003  Q3CanvasItem * item = *first++;
1004 #endif
1005  QtView * view = dynamic_cast < QtView * > ( item );
1006 
1007  if ( view != 0 ) { // avoid page margin rect
1008  v_items.push_back ( item );
1009  removeFromItemList ( item );
1010  }
1011  }
1012 
1013  placeItems ( v_items );
1014 }
1015 
1016 void CanvasView::moveToPlotter ( const PlotterBase * plotter, QtView * view )
1017 {
1018  QtView * target = getViewFor ( plotter );
1019  QRect rect = target -> boundingRect ();
1020  double x = target -> x ();
1021  double y = target -> y ();
1022  x += 0.25 * rect.width();
1023  y += 0.25 * rect.height();
1024 
1025  view->moveBy ( x, y );
1026 }
1027 
1028 std::pair<double, double>
1030 moveToPlotterAt ( const PlotterBase * plotter,
1031  QtView * view,
1032  double xrel, double yrel )
1033 {
1034  QtView * sel_item = getViewFor ( plotter );
1035  QRect rect = sel_item->boundingRect ();
1036  double x = sel_item->x();
1037  double y = sel_item->y();
1038  x += xrel * rect.width();
1039  y += yrel * rect.height();
1040 
1041  view->moveBy ( x, y );
1042 
1043 // Find the lower left corner of the view.
1044  QRect viewRect = view->boundingRect();
1045  double xLowerLeft = view->x();
1046  double yLowerLeft = view->y() + viewRect.height();
1047 
1048 // Normalize to selectedItem coordinate system.
1049  xLowerLeft = ( xLowerLeft - sel_item->x() ) / rect.width();
1050  yLowerLeft = ( yLowerLeft - sel_item->y() ) / rect.height();
1051 
1052  return std::make_pair<double, double>(xLowerLeft, yLowerLeft);
1053 }
1054 
1055 void
1058  const std::string & s,
1059  const std::string & text )
1060 {
1061  DisplayController * display_controller = DisplayController::instance ();
1062  ViewFactory * factory = QtViewFactory::instance ();
1063 
1064  ViewBase * view
1065  = display_controller->createTextView ( factory, plotter, s, text );
1066  assert ( view != 0 );
1067 
1068  QtView * qtview = dynamic_cast < QtView * > ( view );
1069  assert ( qtview != 0 );
1070 
1071  moveToPlotter ( plotter, qtview );
1072 
1073  addView ( qtview, false );
1074 
1075  // Make sure new view on top of others
1076  double z = maximumZ ();
1077 
1078  // Make sure the new text plotter on top all other text plotters
1079  qtview->setZ(z+101.0);
1080 }
1081 
1082 std::pair<double, double>
1085  const std::string & type,
1086  const std::string & text,
1087  double x, double y )
1088 {
1089  DisplayController * display_controller = DisplayController::instance ();
1090  ViewFactory * factory = QtViewFactory::instance ();
1091 
1092  ViewBase * view
1093  = display_controller->createTextView ( factory, plotter, type, text );
1094 
1095  QtView * qtview = dynamic_cast < QtView * > ( view );
1096 
1097  std::pair<double, double> lowerLeftCorner
1098  = moveToPlotterAt ( plotter, qtview, x, y );
1099 
1100  addView ( qtview, false );
1101 
1102  return lowerLeftCorner;
1103 }
1104 
1105 void
1107 addFuncDisplay ( PlotterBase * plotter, const std::string & s)
1108 {
1110  const ViewFactory * factory = QtViewFactory::instance ();
1111 
1112  ViewBase * view
1113  = controller->createFuncView ( factory, plotter, s );
1114 
1115  QtView * qtview = dynamic_cast < QtView * > ( view );
1116  moveToPlotter ( plotter, qtview );
1117 
1118  addView (qtview, false );
1119 }
1120 
1123 void
1126 {
1127  QtView * view = getViewFor ( plotter );
1128 
1129  if ( view != 0 ) remove ( view );
1130 }
1131 
1132 void
1135 {
1136 #if QT_VERSION < 0x040000
1137  QCanvasItemList items = m_canvas->allItems ();
1138  QCanvasItemList::Iterator first = items.begin();
1139  while ( first != items.end() ) {
1140  QCanvasItem * item = *first++;
1141 #else
1142  Q3CanvasItemList items = m_canvas->allItems ();
1143  Q3CanvasItemList::Iterator first = items.begin();
1144  while ( first != items.end() ) {
1145  Q3CanvasItem * item = *first++;
1146 #endif
1147  QtView * view = dynamic_cast < QtView * > ( item );
1148  if ( view == 0 ) {
1149  item -> setVisible ( yes );
1150  }
1151  }
1152 }
1153 
1154 void
1157 {
1158  setVisibleNonViews ( false );
1160  setVisibleNonViews ( true );
1161 }
1162 
1163 void
1165 print ( const std::string & filename )
1166 {
1167  setVisibleNonViews ( false );
1168  FigureEditor::print ( filename );
1169  setVisibleNonViews ( true );
1170 }
1171 
1172 
1173 const vector < const ViewBase * > &
1176 {
1177  m_sel_views.clear ();
1178 
1179 #if QT_VERSION < 0x040000
1180  vector < QCanvasItem * > :: const_iterator first = m_selected_list.begin();
1181  while ( first != m_selected_list.end() ) {
1182  QCanvasItem * item = *first++;
1183 #else
1184  vector < Q3CanvasItem * > :: const_iterator first = m_selected_list.begin();
1185  while ( first != m_selected_list.end() ) {
1186  Q3CanvasItem * item = *first++;
1187 #endif
1188  QtView * view = dynamic_cast < QtView * > ( item );
1189  if ( view != 0 ) { // may be printer page border
1190  m_sel_views.push_back ( view );
1191  }
1192  QtGroupView * groupview = dynamic_cast < QtGroupView * > ( item );
1193  if ( groupview != 0 ){
1194  m_sel_views.push_back ( groupview );
1195  }
1196  }
1197 
1198  return m_sel_views;
1199 }
1200 
1201 const vector < const ViewBase * > & CanvasView::views () const
1202 {
1203  m_views.clear();
1204 
1205 #if QT_VERSION < 0x040000
1206  QCanvasItemList item_list = m_canvas->allItems();
1207  QCanvasItemList::Iterator it = item_list.begin();
1208 #else
1209  Q3CanvasItemList item_list = m_canvas->allItems();
1210  Q3CanvasItemList::Iterator it = item_list.begin();
1211 #endif
1212  for ( ; it != item_list.end(); ++ it ) {
1213  const QtView * view = dynamic_cast < const QtView * > ( *it );
1214  if ( view != 0 ) {
1215  m_views.push_back ( view );
1216  }
1217  }
1218 
1219  return m_views;
1220 }
1221 
1222 void
1224 fillPlotterList ( std::vector < PlotterBase * > & plotterlist )
1225 {
1226  plotterlist.clear();
1227 
1228  const vector < const ViewBase * > & view_list = views ();
1229 #ifdef ITERATOR_MEMBER_DEFECT
1230  std::
1231 #endif
1232  vector < const ViewBase * >::const_iterator first = view_list.begin ();
1233  for ( ; first != view_list.end(); ++first ) {
1234  const QtView * qtview = dynamic_cast < const QtView * > ( *first );
1235  plotterlist.push_back ( qtview->getPlotter () );
1236  }
1237 }
1238 
1239 
1240 QtView *
1242 getViewFor ( const PlotterBase * target ) const
1243 {
1244  QtView * view = 0;
1245  const vector < const ViewBase * > & all_views = views ();
1246  vector < const ViewBase * > :: const_iterator first = all_views.begin();
1247 
1248  while ( first != all_views.end() ) {
1249  const ViewBase * vb = *first++;
1250  const PlotterBase * plotter = vb->getPlotter();
1251  if ( plotter == target ) {
1252  const QtView * v = dynamic_cast < const QtView * > ( vb );
1253  view = const_cast < QtView * > ( v );
1254  break;
1255  }
1256  }
1257 
1258  return view;
1259 }
1260 
1261 void
1264 {
1265 #ifdef STRING_CLEAR_DEFECT
1266  s_image_filters.erase();
1267 #else
1268  s_image_filters.clear();
1269 #endif
1270 
1271  const string eps ( "eps" );
1272  bool eps_inserted = false;
1273 
1274 #if QT_VERSION < 0x040000
1276  QStringList::Iterator it = slist.begin();
1277 #else
1278  QList < QByteArray > slist = QImageWriter::supportedImageFormats ();
1279  QList < QByteArray > ::const_iterator it = slist.begin();
1280 #endif
1281 
1282  while ( it != slist.end() ) {
1283  QString upper = *it++;
1284  QString lower = upper.lower();
1285 #if QT_VERSION < 0x030100
1286  string low ( lower );
1287 #else
1288  string low = lower.latin1();
1289 #endif
1290 #ifdef Q_OS_MACX
1291 #else // not mac os x
1292  if ( low == "jpeg" ) low = "jpg";
1293 #endif
1294  if ( eps >= low ) {
1295 
1296 #if QT_VERSION < 0x040000
1297  s_image_filters += low +"(*." + low + ");;";
1298 #else
1299  s_image_filters += " (*." + low + ");;";
1300 #endif
1301  }
1302  else {
1303  if ( eps_inserted == false ) {
1304 #if QT_VERSION < 0x040000
1305  s_image_filters += eps + "(*." + eps + ");;";
1306 #else
1307  s_image_filters += "(*." + eps + ");;";
1308 #endif
1309  eps_inserted = true;
1310  }
1311 #if QT_VERSION < 0x040000
1312  s_image_filters += low + "(*." + low + ");;";
1313 #else
1314  s_image_filters += "(*." + low + ");;";
1315 #endif
1316  }
1317  }
1318  // Add FITS file.
1319 #if QT_VERSION < 0x040000
1320  s_image_filters += "FITS(*.fits);;";
1321 #else
1322  s_image_filters += "(*.fits);;";
1323 #endif
1324 
1325 #if QT_VERSION < 0x040000
1326  s_image_filters += "Compressed FITS(*.fits.gz)";
1327 #else
1328  s_image_filters += "(*.fits.gz)";
1329 #endif
1330 }
1331 
1332 #if QT_VERSION < 0x040000
1333 QFileDialog *
1334 #else
1335 Q3FileDialog *
1336 #endif
1339 {
1340  if ( s_image_filters.empty () ) createImageFilters ();
1341 
1342  QString filters = s_image_filters.c_str();
1343 
1344 #if QT_VERSION < 0x040000
1345  QFileDialog * dialog = new QFileDialog ( this );
1346  dialog->setFilters ( filters );
1347  dialog->setMode ( QFileDialog::AnyFile );
1348 #else
1349  Q3FileDialog * dialog = new Q3FileDialog ( this );
1350  dialog->setFilters ( filters );
1351  dialog->setMode ( Q3FileDialog::AnyFile );
1352 #endif
1353 
1354  return dialog;
1355 }
1356 
1357 /* The menu item calling this method is disabled when no plot is
1358  selected so there's no need to see if any plots are selected
1359  here.
1360 */
1361 void
1364 {
1365  setVisibleNonViews ( false );
1366 
1367 #if QT_VERSION < 0x040000
1368  const vector < QCanvasItem * > views = getSelectedItems (); // make copy
1369 #else
1370  const vector < Q3CanvasItem * > views = getSelectedItems (); // make copy
1371 #endif
1372  assert ( views.empty () == false );
1373 
1374  for ( unsigned int i = 0; i < views.size (); i++ ) {
1375  setCollidingSelected ( views[i] );
1376  }
1377 
1378  if ( s_image_filters.empty () ) createImageFilters ();
1379  QString sel_filt;
1380 #if QT_VERSION < 0x040000
1381  QString filename
1382  = QFileDialog::getSaveFileName ( QString::null, // working dir
1383  s_image_filters.c_str(),
1384  this, // parent
1385  0, // name
1386  "Save image as", // caption
1387  & sel_filt ); // selected filter
1388 #else
1389  QString filename
1390  = Q3FileDialog::getSaveFileName ( QString::null, // working dir
1391  s_image_filters.c_str(),
1392  this, // parent
1393  0, // name
1394  "Save image as", // caption
1395  & sel_filt ); // selected filter
1396 #endif
1397 
1398  if ( filename.isEmpty () ) return;
1399 
1400  filename.stripWhiteSpace ();
1401 
1402 #if QT_VERSION < 0x030100
1403  string fn ( filename );
1404 #else
1405  string fn = filename.latin1();
1406 #endif
1407 
1408  int pos = filename.findRev ( '.' );
1409  if ( pos < 0 ) {
1410  string sf = sel_filt.latin1();
1411  string::size_type pos1 = sf.find ( '(' );
1412  string::size_type pos2 = sf.find_last_of ( ')' );
1413  string::size_type len = ( pos2 ) - ( pos1 + 2 );
1414  string suffix = sf.substr ( pos1 + 2, len );
1415  fn += suffix;
1416  }
1417 
1418  saveSelectedImages ( fn, true );
1419 
1420  // Restore original selection flags.
1421  m_selected_list.clear();
1422  for ( unsigned int i = 0; i < views.size(); i++ ) {
1423  m_selected_list.push_back ( views[i] );
1424  }
1425  setSelectedFlags ();
1426  setVisibleNonViews ( true );
1427 }
1428 
1429 void
1431 saveSelectedImages (const std::string & filename)
1432 {
1433  setVisibleNonViews ( false );
1434 
1435 #if QT_VERSION < 0x040000
1436  const vector < QCanvasItem * > views = getSelectedItems (); // make copy
1437 #else
1438  const vector < Q3CanvasItem * > views = getSelectedItems (); // make copy
1439 #endif
1440  if (views.empty()) {
1441  return;
1442  }
1443 
1444  for ( unsigned int i = 0; i < views.size (); i++ ) {
1445  setCollidingSelected ( views[i] );
1446  }
1447 
1448  saveSelectedImages ( filename, false );
1449 
1450  // Restore original selection flags.
1451  m_selected_list.clear();
1452  for ( unsigned int i = 0; i < views.size(); i++ ) {
1453  m_selected_list.push_back ( views[i] );
1454  }
1455  setSelectedFlags ();
1456  setVisibleNonViews ( true );
1457 }
1458 
1463 {
1465  const vector < const ViewBase * > & view_list = views ();
1466  vector < const ViewBase * > ::const_iterator first = view_list.begin ();
1467 
1468  while ( first != view_list.end() ) {
1469  const ViewBase * view = *first++;
1470  PlotterBase * plotter = view->getPlotter();
1471  controller -> setAllIntervalEnabled ( plotter, yes );
1472  }
1473 }
1474 
1475 void
1478 {
1479 
1480  ViewFactory * factory = QtViewFactory::instance ();
1481  const vector < const ViewBase * > & targets = views ();
1482 
1483  const list < ViewBase * > & views
1484  = s_xml_controller->getFromSelectionCopy ( factory, targets );
1485 
1486  if ( views.empty() == false ) {
1487  removeSelected ();
1488  pasteViews ( views );
1489 
1490  notifyObservers ();
1491  }
1492 }
1493 
1495 {
1496 #if QT_VERSION < 0x040000
1497  QCanvasItem * selItem = m_selected_list.front ();
1498 #else
1499  Q3CanvasItem * selItem = m_selected_list.front ();
1500 #endif
1501  QtView * qtview = dynamic_cast < QtView * > ( selItem );
1502  assert ( qtview );
1503 
1504  PlotterBase * plotter = qtview->getPlotter ();
1505  assert ( plotter );
1506 
1507  plotter -> toggleActivePlot ();
1508 }
1509 
1510 void
1512 fillSelectedWithObservers ( std::vector < const ViewBase * > & view_list )
1513 {
1514  const vector < const ViewBase * > & sel_views = selectedViews ();
1515 
1516  view_list.resize ( sel_views.size() );
1517  copy ( sel_views.begin(), sel_views.end(), view_list.begin() );
1518 
1520  const vector < const ViewBase * > & all_views = views ();
1521 
1522  controller->addTextViewToList ( view_list, all_views );
1523 }
1524 
1526 {
1528  if ( (e->button() == Qt::RightButton) ||( e->state() == Qt::RightButton)) {
1529  contentsMouseMoveEvent ( e );
1530  }
1531 
1532  const vector < const ViewBase * > & sel_views = selectedViews ();
1533 
1534  if ( ! sel_views.empty () ) {
1535  vector < const ViewBase * > view_list;
1536  fillSelectedWithObservers ( view_list );
1537  s_xml_controller->saveToSelectionCopy ( view_list );
1538  }
1539 
1540  notifyObservers();
1541 }
1542 
1543 
1548 {
1549 //If right button pressed, get the position and show on the status bar.
1550  if ( (e->button() == Qt::RightButton) ||( e->state() & Qt::RightButton)) {
1551 #if QT_VERSION < 0x040000
1552  QCanvasItem * right_item=FigureEditor::getRightItem ();
1553 #else
1554  Q3CanvasItem * right_item=FigureEditor::getRightItem ();
1555 #endif
1556  if ( right_item == 0 ) return;
1557 
1558 #if QT_VERSION < 0x040000
1559  QCanvasRectangle * rect
1560  = dynamic_cast <QCanvasRectangle *> ( right_item );
1561 #else
1562  Q3CanvasRectangle * rect
1563  = dynamic_cast <Q3CanvasRectangle *> ( right_item );
1564 #endif
1565 
1566 
1567  QPoint p = inverseWorldMatrix().map(e->pos());
1568 
1569  if ( ( p.x() >= rect->x() ) &&
1570  ( p.x() <= rect->x() + rect->width() ) &&
1571  ( p.y() >= rect->y() ) &&
1572  ( p.y() <= rect->y() + rect->height() ) ) {
1573 
1574  QtView * qtview = dynamic_cast < QtView * > ( right_item );
1575  if ( qtview == 0 ) //return;
1576  {
1577  QtGroupView * gv = dynamic_cast <QtGroupView *> (right_item);
1578  const vector <ViewBase * > & views = gv->getViews();
1579  vector < ViewBase * >::const_iterator first = views.begin();
1580  for ( ; first != views.end(); ++first ) {
1581  QtView * v = dynamic_cast < QtView * > ( *first );
1582  if ( ( p.x() >= v->x() ) &&
1583  ( p.x() <= v->x() + v->width() ) &&
1584  ( p.y() >= v->y() ) &&
1585  ( p.y() <= v->y() + v->height() ) ) {
1586  qtview = v;
1587  break;
1588  }
1589  }
1590  if ( qtview == 0 ) return; // click between views
1591  }
1592 
1593 
1594  vector < double > picked;
1595  qtview -> fillPickedPoint ( p.x(), p.y(), picked );
1596  if ( picked.empty () ) return;
1597 
1598  unsigned int size = picked.size();
1599  double datax = picked[1];
1600  double datay = picked[2]; // scaled if needed
1601  double dataz = 0.0;
1602  if ( size >= 4 ) {
1603  dataz = picked[3];
1604  }
1605 
1606  double unscaledDataX = picked[1];
1607  double unscaledDataY = picked[2];
1608  if ( std::abs ( picked[0] - 1.0 ) < 0.5 ) unscaledDataY = picked[3];
1609 
1610  // Set cross cursor for fits image with transfom.
1611  BinaryTransform * tf_fits
1612  = dynamic_cast < BinaryTransform * >
1613  ( qtview->getPlotter()->getFitsTransform() );
1614 
1615  // tf_fits = 0 if the plot is not fits image with transform.
1616  if ( tf_fits ){
1617  tf_fits -> transform ( unscaledDataX, unscaledDataY );
1618  }
1619 
1620  qtview->setCrossX ( unscaledDataX );
1621  qtview->setCrossY ( unscaledDataY );
1622  qtview->setShowCrossHairs ( true );
1623  const QCursor cursor ( Qt::CrossCursor );
1624  QApplication::setOverrideCursor ( cursor, true );
1625  qtview->update(0);
1626 
1627  QString qstr = QString
1628  ( "Coordinates are : ( %1, %2, %3 )" )
1629  .arg ( datax )
1630  .arg ( datay )
1631  .arg ( dataz );
1632 
1633  CanvasWindow * cw = dynamic_cast < CanvasWindow * > ( parentWidget() );
1634  QStatusBar * sb = cw->statusBar();
1635  sb->message ( qstr );
1636 
1637 
1638  // Skip cut setting if in pick mode.
1639  // Add pick table if needed.
1640  if (m_cut_mode == 0 ){
1641  PickTable * table = 0;
1642  map < const QtView*, PickTable * > ::iterator first
1643  = m_table_map.find ( qtview );
1644  if ( first != m_table_map.end () ) {
1645  table = m_table_map [ qtview ];
1646  }
1647  else {
1648  PlotterBase * plotter = qtview->getPlotter ();
1649 
1650  table = new PickTable ( plotter );
1651  m_table_map [ qtview ] = table;
1652  }
1653  return;
1654  }
1655 
1656  // Set the cut range if the current plotter is a cut.
1657  PlotterBase * plotter = qtview->getPlotter();
1658  if ( plotter == 0 ) return;
1659  Cut1DPlotter * cut1d = dynamic_cast < Cut1DPlotter * > (plotter);
1660  Cut2DPlotter * cut2d = dynamic_cast < Cut2DPlotter * > ( plotter );
1661 
1662 
1663  // Set the cut range to be within the plotter range.
1664  // Cut1D plotter
1665  if ( cut1d ) {
1666  double cut_low = cut1d->getCutRange().low();
1667  double cut_high = cut1d->getCutRange().high();
1668  double plotter_low = cut1d->getRange( Axes::X, true ).low();
1669  double plotter_high = cut1d->getRange( Axes::X, true ).high();
1670 
1671  if (m_cut_mode == 1){
1672 
1673  if ( cut_low < plotter_low )
1674  {
1675  Range currentRange = typename Range::Range ( plotter_low, cut_high );
1676  cut1d -> setCutRangeAt ( currentRange , 0 );
1677  }
1678  if ( cut_high > plotter_high )
1679  {
1680  Range currentRange = typename Range::Range ( cut_low , plotter_high );
1681  cut1d -> setCutRangeAt ( currentRange , 0 );
1682  }
1683  }
1684 
1685  }
1686 
1687  // Cut2D plotter
1688  else if ( cut2d ) {
1689  double cut_low_x = cut2d->getCutRange().low();
1690  double cut_high_x = cut2d->getCutRange().high();
1691  double plotter_low_x = cut2d->getRange( Axes::X, true ).low();
1692  double plotter_high_x = cut2d->getRange( Axes::X, true ).high();
1693  double cut_low_y = cut2d->getCutRangeY().low();
1694  double cut_high_y = cut2d->getCutRangeY().high();
1695  double plotter_low_y = cut2d->getRange( Axes::Y, true ).low();
1696  double plotter_high_y = cut2d->getRange( Axes::Y, true ).high();
1697 
1698  if ( m_cut_mode == 1 ) {
1699 
1700  if ( cut_low_x < plotter_low_x )
1701  {
1702  Range currentRange = typename Range::Range ( plotter_low_x, cut_high_x );
1703  cut2d -> setCutRangeAt ( currentRange , 0 );
1704  }
1705  if ( cut_high_x > plotter_high_x )
1706  {
1707  Range currentRange = typename Range::Range ( cut_low_x , plotter_high_x );
1708  cut2d -> setCutRangeAt ( currentRange , 0 );
1709  }
1710 
1711  if ( cut_low_y < plotter_low_y )
1712  {
1713  Range currentRange = typename Range::Range ( plotter_low_y, cut_high_y );
1714  cut2d -> setCutRangeAt ( currentRange , 1 );
1715  }
1716  if ( cut_high_y > plotter_high_y )
1717  {
1718  Range currentRange = typename Range::Range ( cut_low_y , plotter_high_y );
1719  cut2d -> setCutRangeAt ( currentRange , 1 );
1720  }
1721  }
1722  }
1723 
1724 
1725 
1726  // Set cut according to the cut mode.
1727  switch ( m_cut_mode ){
1728  case 1:
1729  if ( cut1d ) {
1730  Range oldRange = cut1d -> getCutRange ();
1731  double old_low = oldRange.low();
1732  double old_high = oldRange.high();
1733 
1734  if ( datax < ( old_low + old_high ) / 2 ) {
1735  Range currentRange = typename Range::Range ( datax , old_high );
1736  cut1d -> setCutRangeAt ( currentRange , 0 );
1737  }
1738 
1739  else
1740  {
1741  Range currentRange = typename Range::Range ( old_low , datax );
1742  cut1d -> setCutRangeAt ( currentRange , 0 );
1743  }
1744  notifyObservers();
1745  }
1746 
1747  // Cut2D plotter
1748  else if ( cut2d ) {
1749  Range oldRangeX = cut2d -> getCutRange ();
1750  Range oldRangeY = cut2d -> getCutRangeY ();
1751  double old_low_x = oldRangeX.low();
1752  double old_high_x = oldRangeX.high();
1753  double old_low_y = oldRangeY.low();
1754  double old_high_y = oldRangeY.high();
1755 
1756  // Distances to each edge.
1757  double dis_low_x = std::abs ( datax - old_low_x );
1758  double dis_high_x = std::abs ( datax - old_high_x );
1759  double dis_low_y = std::abs ( datay - old_low_y );
1760  double dis_high_y = std::abs ( datay - old_high_y );
1761 
1762  // Left-bottom
1763  if ( ( dis_low_x <= 0.1 * (old_high_x - old_low_x)) &&
1764  ( dis_low_y <= 0.1 * (old_high_y - old_low_y)) &&
1765  ( m_edge == 0 ) || ( m_edge == 1 ) ) {
1766  Range currentRange = typename Range::Range ( datax, old_high_x );
1767  cut2d -> setCutRangeAt ( currentRange, 0 );
1768 
1769  // Handle shift drag.
1770  if ( e->state() & Qt::ShiftButton) {
1771  int view_top = qtview->toViewY(old_high_y);
1772  int view_left = qtview->toViewX(datax);
1773  int view_right = qtview->toViewX(old_high_x);
1774  int view_bottom = view_top + view_right - view_left;
1775 
1776  // Not effecient to call fillPickedPoint(), but marginToUser()
1777  // is protected.
1778  vector <double> adjusted;
1779  qtview->fillPickedPoint(view_left, view_bottom, adjusted);
1780  currentRange = typename Range::Range ( adjusted[2], old_high_y );
1781  }
1782  else
1783  currentRange = typename Range::Range ( datay, old_high_y );
1784  cut2d -> setCutRangeAt ( currentRange, 1 );
1785  m_edge = 1;
1786  }
1787 
1788  // Left-top
1789  else if ( ( dis_low_x <= 0.1 * (old_high_x - old_low_x)) &&
1790  ( dis_high_y <= 0.1 * (old_high_y - old_low_y)) &&
1791  ( m_edge == 0 ) || ( m_edge == 2 ) ) {
1792  Range currentRange = typename Range::Range ( datax, old_high_x );
1793  cut2d -> setCutRangeAt ( currentRange, 0 );
1794 
1795  // Handle shift drag
1796  if ( e->state() & Qt::ShiftButton) {
1797  int view_bottom = qtview->toViewY(old_low_y);
1798  int view_left = qtview->toViewX(datax);
1799  int view_right = qtview->toViewX(old_high_x);
1800  int view_top = view_bottom - view_right + view_left;
1801 
1802  // Not effecient to call fillPickedPoint(), but marginToUser()
1803  // is protected.
1804  vector <double> adjusted;
1805  qtview->fillPickedPoint(view_left, view_top, adjusted);
1806  currentRange = typename Range::Range ( old_low_y, adjusted[2]);
1807  }
1808  else
1809  currentRange = typename Range::Range ( old_low_y, datay );
1810  cut2d -> setCutRangeAt ( currentRange, 1 );
1811  m_edge = 2;
1812  }
1813 
1814  // Right-bottom
1815  else if ( ( dis_high_x <= 0.1 * (old_high_x - old_low_x)) &&
1816  ( dis_low_y <= 0.1 * (old_high_y - old_low_y)) &&
1817  ( m_edge == 0 ) || ( m_edge == 3 ) ) {
1818  Range currentRange = typename Range::Range ( old_low_x, datax );
1819  cut2d -> setCutRangeAt ( currentRange, 0 );
1820 
1821  // Handle shift drag.
1822  if ( e->state() & Qt::ShiftButton) {
1823  int view_top = qtview->toViewY(old_high_y);
1824  int view_left = qtview->toViewX(old_low_x);
1825  int view_right = qtview->toViewX(datax);
1826  int view_bottom = view_top + view_right - view_left;
1827 
1828  // Not effecient to call fillPickedPoint(), but marginToUser()
1829  // is protected.
1830  vector <double> adjusted;
1831  qtview->fillPickedPoint(view_right, view_bottom, adjusted);
1832  currentRange = typename Range::Range ( adjusted[2], old_high_y );
1833  }
1834  else
1835  currentRange = typename Range::Range ( datay, old_high_y );
1836  cut2d -> setCutRangeAt ( currentRange, 1 );
1837  m_edge = 3;
1838  }
1839 
1840  // Right-top
1841  else if ( ( dis_high_x <= 0.1 * (old_high_x - old_low_x)) &&
1842  ( dis_high_y <= 0.1 * (old_high_y - old_low_y)) &&
1843  ( m_edge == 0) || ( m_edge == 4 ) ) {
1844  Range currentRange = typename Range::Range ( old_low_x, datax );
1845  cut2d -> setCutRangeAt ( currentRange, 0 );
1846 
1847  // Handle shift drag.
1848  if ( e->state() & Qt::ShiftButton) {
1849  int view_bottom = qtview->toViewY(old_low_y);
1850  int view_left = qtview->toViewX(old_low_x);
1851  int view_right = qtview->toViewX(datax);
1852  int view_top = view_bottom - view_right + view_left;
1853 
1854  // Not effecient to call fillPickedPoint(), but marginToUser()
1855  // is protected.
1856  vector <double> adjusted;
1857  qtview->fillPickedPoint(view_right, view_top, adjusted);
1858  currentRange = typename Range::Range ( old_low_y, adjusted[2] );
1859  }
1860  else
1861  currentRange = typename Range::Range ( old_low_y, datay );
1862  cut2d -> setCutRangeAt ( currentRange, 1 );
1863  m_edge = 4;
1864  }
1865 
1866  // Left
1867  else if ( ( dis_low_x <= dis_high_x ) &&
1868  ( dis_low_x <= dis_low_y ) &&
1869  ( dis_low_x <= dis_high_y ) &&
1870  ( m_edge == 0 ) || ( m_edge == 5 ) ) {
1871  Range currentRange = typename Range::Range ( datax, old_high_x );
1872  cut2d -> setCutRangeAt ( currentRange, 0 );
1873  m_edge = 5;
1874  }
1875 
1876  // Right
1877  else if ( ( dis_high_x <= dis_low_x ) &&
1878  ( dis_high_x <= dis_low_y ) &&
1879  ( dis_high_x <= dis_high_y ) &&
1880  ( m_edge == 0 ) || ( m_edge == 6 ) ) {
1881  Range currentRange = typename Range::Range ( old_low_x, datax );
1882  cut2d -> setCutRangeAt ( currentRange, 0 );
1883  m_edge = 6;
1884  }
1885 
1886  // Bottom
1887  else if ( ( dis_low_y <= dis_high_x ) &&
1888  ( dis_low_y <= dis_low_x ) &&
1889  ( dis_low_y <= dis_high_y ) &&
1890  ( m_edge == 0 ) || ( m_edge == 7 ) ) {
1891  Range currentRange = typename Range::Range ( datay, old_high_y );
1892  cut2d -> setCutRangeAt ( currentRange, 1 );
1893  m_edge = 7;
1894  }
1895 
1896  // Top
1897  else
1898  {
1899  Range currentRange = typename Range::Range ( old_low_y, datay );
1900  cut2d -> setCutRangeAt ( currentRange, 1 );
1901  m_edge = 8;
1902  }
1903  notifyObservers();
1904  }
1905 
1906  break;
1907 
1908 
1909  case 2:
1910  if ( cut1d ) {
1911 
1912  if ( !m_clicked ){
1913  old_pos = datax;
1914  }
1915 
1916  else {
1917  double low, high;
1918 
1919  if ( datax > old_pos ) {
1920  low = old_pos;
1921  high = datax;
1922  }
1923 
1924  else {
1925  low = datax;
1926  high= old_pos;
1927  }
1928 
1929  Range currentRange = typename Range::Range ( low, high );
1930  cut1d -> setCutRangeAt ( currentRange , 0 );
1931  }
1932  notifyObservers();
1933  }
1934 
1935  // Cut2D plotter.
1936  else if ( cut2d ) {
1937  if ( !m_clicked ){
1938  old_pos_x = datax;
1939  old_pos_y = datay;
1940  }
1941 
1942  else {
1943  double low, high;
1944  if ( datax > old_pos_x ) {
1945  low = old_pos_x;
1946  high = datax;
1947  }
1948  else {
1949  low = datax;
1950  high = old_pos_x;
1951  }
1952  Range currentRange = typename Range::Range ( low, high );
1953  cut2d -> setCutRangeAt ( currentRange, 0 );
1954 
1955  if ( datay > old_pos_y ) {
1956  low = old_pos_y;
1957  high = datay;
1958  }
1959  else {
1960  low = datay;
1961  high = old_pos_y;
1962  }
1963  currentRange = typename Range::Range ( low, high );
1964  cut2d -> setCutRangeAt ( currentRange, 1 );
1965  }
1966  notifyObservers();
1967  }
1968 
1969  break;
1970 
1971 
1972  case 3:
1973  if ( cut1d ) {
1974 
1976  Range oldRange = cut1d -> getCutRange ();
1977  double width, low, high;
1978 
1979  // Log X axis.
1980  if ( (controller -> getLog ( plotter, Axes::X )) == true )
1981  {
1982  width = log10(oldRange.high())-log10(oldRange.low());
1983  low = pow ( 10., log10(datax) - ( width/2 ) );
1984  high = pow ( 10., log10(datax) + ( width/2 ) );
1985  }
1986 
1987  // Linear X axis.
1988  else
1989  {
1990  width = oldRange.high() - oldRange.low();
1991  low = datax - width/2;
1992  high = datax + width/2;
1993  }
1994  Range currentRange = typename Range::Range ( low, high );
1995  cut1d -> setCutRangeAt (currentRange, 0 );
1996  notifyObservers();
1997  }
1998 
1999  // Cut2D plotter.
2000  if ( cut2d ) {
2002  Range oldRangeX = cut2d -> getCutRange ();
2003  Range oldRangeY = cut2d -> getCutRangeY ();
2004  double width_x, width_y, low_x, high_x, low_y, high_y;
2005 
2006  // Log X axis.
2007  if ( (controller -> getLog ( plotter, Axes::X )) == true )
2008  {
2009  width_x = log10(oldRangeX.high())-log10(oldRangeX.low());
2010  low_x = pow ( 10., log10(datax) - ( width_x/2 ) );
2011  high_x = pow ( 10., log10(datax) + ( width_x/2 ) );
2012  }
2013 
2014  // Linear X axis.
2015  else
2016  {
2017  width_x = oldRangeX.high() - oldRangeX.low();
2018  low_x = datax - width_x/2;
2019  high_x = datax + width_x/2;
2020  }
2021 
2022  // Log Y axis.
2023  if ( (controller -> getLog ( plotter, Axes::Y )) == true )
2024  {
2025  width_y = log10(oldRangeY.high())-log10(oldRangeY.low());
2026  low_y = pow ( 10., log10(datay) - ( width_y/2 ) );
2027  high_y = pow ( 10., log10(datay) + ( width_y/2 ) );
2028  }
2029 
2030  // Linear Y axis.
2031  else
2032  {
2033  width_y = oldRangeY.high() - oldRangeY.low();
2034  low_y = datay - width_y/2;
2035  high_y = datay + width_y/2;
2036  }
2037 
2038  Range currentRange = typename Range::Range ( low_x, high_x );
2039  cut2d -> setCutRangeAt (currentRange, 0 );
2040  currentRange = typename Range::Range ( low_y, high_y );
2041  cut2d -> setCutRangeAt (currentRange, 1 );
2042  notifyObservers();
2043  }
2044 
2045  break;
2046 
2047  default:
2048  break;
2049  }
2050 
2051 
2052 
2053 
2054  }
2055  }
2056 
2057 
2058  // Left button pressed, do zoom in if in zoom mode.
2059  else{
2060 
2061  if ( isSingleItemSelected () == false )
2062  {
2064  return;
2065  }
2066 
2067 #if QT_VERSION < 0x040000
2068  QCanvasItem * item = selectedItem ();
2069 #else
2070  Q3CanvasItem * item = selectedItem ();
2071 #endif
2072 
2073  if ( item->isActive () ) return;
2074 
2075  QtView * qtview = dynamic_cast < QtView * > ( selectedItem() );
2076 
2077  if (qtview) {
2078  double aspect = qtview->getAspectRatio();
2080  }
2081  else {
2082  QtGroupView * qtgroupview =
2083  dynamic_cast < QtGroupView * > ( selectedItem());
2084  if (qtgroupview) {
2086  }
2087  }
2088 
2089 #if QT_VERSION < 0x040000
2090  QCanvasRectangle * rect
2091  = dynamic_cast <QCanvasRectangle *> ( item );
2092 #else
2093  Q3CanvasRectangle * rect
2094  = dynamic_cast <Q3CanvasRectangle *> ( item );
2095 #endif
2096 
2097  if ( getZoomMode() ){
2098  if ( (e->button() == Qt::LeftButton) ||
2099  ( e->state() & Qt::LeftButton) ) {
2100 
2101  QPoint p = inverseWorldMatrix().map ( e -> pos() );
2102  if ( ( p.x() >= rect->x() ) &&
2103  ( p.x() <= rect->x() + rect->width() ) &&
2104  ( p.y() >= rect->y() ) &&
2105  ( p.y() <= rect->y() + rect->height() ) ) {
2106 
2107 
2108  if (m_drag_rect != 0 ) {
2109  delete m_drag_rect;
2110  }
2111 
2112  QPoint top_left ( std::min ( p.x(), m_zoom_start.x() ),
2113  std::max ( p.y(), m_zoom_start.y() ) );
2114  QPoint bo_right ( std::max ( p.x(), m_zoom_start.x() ),
2115  std::min ( p.y(), m_zoom_start.y() ) );
2116 
2117  // Use square to zoom in
2118  if (e->state() & Qt::ShiftButton) {
2119  if (top_left.y() == m_zoom_start.y()) {
2120  bo_right.setY( top_left.y() - bo_right.x() + top_left.x() );
2121  }
2122 
2123  else { // if (bo_right.y() == m_zoom_start.y()){
2124  top_left.setY( bo_right.y() + bo_right.x() - top_left.x() );
2125  }
2126  }
2127 
2128 #if QT_VERSION < 0x040000
2129  m_drag_rect = new QCanvasRectangle ( QRect( top_left,bo_right ),
2130  canvas ());
2131 #else
2132  m_drag_rect = new Q3CanvasRectangle ( QRect( top_left,bo_right ),
2133  canvas ());
2134 #endif
2135  QColor color ( "black" );
2136  QPen pen ( color, 1, Qt::DotLine );
2137  m_drag_rect->setPen(pen);
2138 
2139  if ( selectedPlotter() == 0 ) {
2140  QString message ( "Can not do range zoom in a group view.\n" );
2141  message += "Please select a single plotter view.";
2142  QMessageBox::information ( this,
2143  s_app_name.c_str(),
2144  message );
2145  return;
2146  }
2147 
2148 
2149  if ( selectedPlotter()->hasAxis(Axes::Z) ){
2150  double z = selectedPlotter()->getRange(Axes::Z,true).high() ;
2151  m_drag_rect -> setZ( z ); // Why setZ? Any thing to do with text plotter?
2152  }
2153  m_drag_rect -> setVisible ( true );
2154  //canvas () -> update ();
2155  }
2156  }
2157  }
2158  }
2159 }
2160 
2161 void
2163 savePlotAsImage ( const PlotterBase * plotter,
2164  const std::string & filename )
2165 {
2166  if ( plotter == 0 ) return;
2167 
2168  string::size_type i = filename.find_last_of ( '.');
2169  if ( i != string::npos ) {
2170  string suffix ( filename.substr ( i + 1 ) );
2171  if ( suffix == "eps" ||
2172  suffix == "EPS" ) {
2173  savePlotAsEps ( plotter, filename );
2174  }
2175  else {
2176  QtView * view = getViewFor ( plotter );
2177  assert ( view != 0 );
2178 
2179  QRect rect = view -> rect ();
2180  saveAreaAsPixmap ( rect, filename );
2181  }
2182  }
2183 }
2184 
2185 void
2187 toLower ( std::string & upper )
2188 {
2189  string::size_type size = upper.size();
2190  for ( string::size_type i = 0; i < size; i++ ) {
2191  upper[i] = std::tolower ( upper[i] );
2192  }
2193 }
2194 
2195 bool
2197 isValidImageFormat ( const std::string & suffix )
2198 {
2199  // Handle gzipped suffix
2200  if (suffix=="gz" || suffix=="GZ") return true;
2201 
2202  if ( s_image_filters.empty () ) createImageFilters ();
2203 
2204  string star ( "*." + suffix );
2205  toLower ( star );
2206 
2207  // following could be 64 bit unsigned int
2208  string::size_type i = s_image_filters.find ( star );
2209 
2210  return i != string::npos;
2211 }
2212 
2213 void
2216 {
2217  QString message ( "Sorry, this installation of " );
2218  message += s_app_name.c_str();
2219  message += " was not\n"
2220  "built with the optional FITS support.";
2221  QMessageBox::information ( const_cast < CanvasView * > ( this ),
2222  s_app_name.c_str(),
2223  message );
2224 }
2225 
2226 void
2228 saveSelectedImages ( const std::string & fn, bool check_existing )
2229 {
2230  string filename = fn;
2231  string::size_type i = filename.find_last_of ( '.' );
2232 
2233  if ( i == string::npos ) { // no suffix given
2234  if ( m_image_dialog != 0 ) {
2236  string filt = s.latin1();
2237  string::size_type ipos = filt.find ( "*." ) + 1;
2238  string::size_type epos = filt.find ( ")" );
2239  string suffix ( filt.substr ( ipos, epos - ipos ) );
2240  filename += suffix;
2241  }
2242  else {
2243  filename += ".jpg";
2244  }
2245  i = filename.find_last_of ( '.' );
2246  }
2247 
2248  string suffix ( filename.substr ( i + 1 ) );
2249  if ( isValidImageFormat ( suffix ) ) {
2250  string base ( filename.substr ( 0, i - 1 ) ); //basename
2251  if ( base.empty () ) filename = "image." + suffix;
2252 
2253  if ( check_existing ) {
2254  QString fn ( filename.c_str() );
2255  bool yes = QFile::exists ( fn );
2256 
2257  if ( yes ) {
2258  yes = existingFileWarning ( filename );
2259  if ( yes == false ) return;
2260  }
2261  }
2262 
2263  setVisibleNonViews ( false );
2264  if ( suffix == "eps" ||
2265  suffix == "EPS" )
2266  {
2267  saveSelectedAsEps ( filename );
2268  }
2269  else if (suffix == "fits" ||
2270  suffix == "FITS" ||
2271  suffix == "gz" ||
2272  suffix == "GZ")
2273  {
2274 #ifdef HAVE_CFITSIO
2275  saveSelectedAsFits ( filename );
2276 #else
2277  showFitsError ();
2278 #endif
2279  }
2280  else
2281  {
2282  setUnselectedVisible ( false );
2283  saveSelectedAsPixmap ( filename );
2284  setUnselectedVisible ( true );
2285  }
2286  setVisibleNonViews ( true );
2287  }
2288  else {
2289  invalidImageFormatError ( filename );
2290  }
2291 }
2292 
2293 void
2295 savePlotAsFits ( const PlotterBase * plotter,
2296  const std::string & filename ) const
2297 {
2298 #ifdef HAVE_CFITSIO
2299  if ( plotter -> isImageConvertable () == false ) {
2300  QString message ( "The contents of this plotter is not\n"
2301  "onvertable to a FITS image." );
2302  QMessageBox::information ( const_cast < CanvasView * > ( this ),
2303  s_app_name.c_str(),
2304  message );
2305  return;
2306  }
2307 
2308  PlotterBase * p = const_cast < PlotterBase * > ( plotter );
2309 
2310  const std::vector <unsigned int> & fitsshape = p->getShape();
2311  const std::vector <double> & fitsdata = p->getZValues();
2312 
2314  ->writeImageToFile ( fitsshape[0], fitsshape[1], fitsdata, filename );
2315 
2316 #else
2317  showFitsError ();
2318 #endif
2319 }
2320 
2321 #ifdef HAVE_CFITSIO
2322 void
2324 saveSelectedAsFits ( const std::string & filename )
2325 {
2326  PlotterBase * plotter = selectedPlotter ();
2327 
2328  if ( !plotter ) {
2329  QString message ( "No plot or more than one plot selected." );
2330  QMessageBox::information ( this,
2331  s_app_name.c_str(),
2332  message );
2333  return;
2334  }
2335 
2336  else {
2337  savePlotAsFits ( plotter, filename );
2338  }
2339 }
2340 #endif
2341 
2342 
2343 void
2345 savePlotAsEps ( const PlotterBase * plotter,
2346  const std::string & filename ) const
2347 {
2348  if ( plotter != 0 ) {
2349  QtView * view = getViewFor ( plotter );
2350  assert ( view != 0 );
2351 
2352  QRect rect = view -> rect ();
2353  EpsView * eps = new EpsView ( filename,
2354  rect.x(), rect.y (),
2355  rect.width(), rect.height() );
2356  const Rect & marg_rect = view -> getMarginRect ();
2357  eps -> setMarginRect ( marg_rect );
2358 
2359  PlotterBase * p = const_cast < PlotterBase * > ( plotter );
2360  eps -> setPlotter ( p );
2361  eps -> setDrawRect ( rect.x(), rect.y(),
2362  rect.width(), rect.height() );
2363  eps -> drawSelf ();
2364  eps -> closeFile ();
2365  delete eps;
2366  }
2367 }
2368 
2369 void
2371 saveSelectedAsEps ( const std::string & filename )
2372 {
2373  QRect rect = getSelectedBounds ();
2374 
2375  EpsView * eps_view
2376  = new EpsView ( filename,
2377  rect.x(), rect.y(), rect.width(), rect.height() );
2378 
2379  const vector < const ViewBase * > & viewList = selectedViews ();
2380 #ifdef ITERATOR_MEMBER_DEFECT
2381  std::
2382 #endif
2383  vector < const ViewBase * > :: const_iterator first = viewList.begin();
2384  while ( first != viewList.end() ) {
2385  const ViewBase * vb = *first++;
2386  const QtView * view = dynamic_cast < const QtView * > ( vb );
2387  PlotterBase * plotter = view->getPlotter ();
2388  QRect rect = view->rect();
2389 
2390  eps_view -> setPlotter ( plotter );
2391  eps_view -> setDrawRect ( rect.x(), rect.y(),
2392  rect.width(), rect.height() );
2393  const Rect & marg_rect = view -> getMarginRect ();
2394  eps_view -> setMarginRect ( marg_rect );
2395 
2396  eps_view -> drawSelf ();
2397  }
2398 
2399  eps_view -> closeFile ();
2400 
2401  delete eps_view;
2402 }
2403 
2406 void
2408 saveAs ( const std::string & filename ) const
2409 {
2410  const vector < const ViewBase * > & view_list = views ();
2411  saveAs ( view_list, filename );
2412 }
2413 
2414 void
2416 saveAs ( const std::vector < PlotterBase * > & plotters,
2417  const std::string & filename )
2418 {
2419  vector < const ViewBase * > views;
2420 
2421  unsigned int size = plotters.size ();
2422  for ( unsigned int i = 0; i < size; i++ ) {
2423  PlotterBase * plotter = plotters [i];
2424  QtView * view = wrapPlotter ( plotter );
2425  views.push_back ( view );
2426  }
2427  saveAs ( views, filename );
2428 }
2429 
2430 void
2432 saveAs ( const std::vector < const ViewBase * > & views,
2433  const std::string & filename )
2434 {
2435  if ( s_xml_controller == 0 ) {
2437  }
2438 
2439  XmlController::Status status
2440  = s_xml_controller->saveToFile ( views, filename );
2441  if ( status != XmlController::Success ) {
2442  return;
2443  }
2444 }
2445 
2449 void
2451 exportTextTuple ( const std::string & data_suffix )
2452 {
2454 
2455  const vector < string > & tuples = controller->getNTupleNames();
2456 
2457  if ( tuples.empty () ) {
2458  QString message ( "There are no NTuples to be exported" );
2459  QMessageBox::information ( this,
2460  s_app_name.c_str(),
2461  message );
2462  return;
2463  }
2464 
2465  QString filename =
2466 #if QT_VERSION < 0x040000
2467  QFileDialog::getSaveFileName ( QString::null, // starting directory
2468  QString::null, // filter
2469  this,
2470  "save file dialog",
2471  "Save data source as ..." ); // caption
2472 #else
2473  Q3FileDialog::getSaveFileName ( QString::null, // starting directory
2474  QString::null, // filter
2475  this,
2476  "save file dialog",
2477  "Save data source as ..." ); // caption
2478 #endif
2479 
2480  if ( filename == QString::null ) return;
2481 
2482  QString suffix ( data_suffix.c_str() );
2483 #if QT_VERSION < 0x030300
2484  QString suffix2 ( suffix );
2485  suffix2.upper ();
2486  if ( filename.endsWith ( suffix ) == false &&
2487  filename.endsWith ( suffix2 ) == false ) {
2488  filename += data_suffix;
2489  }
2490 #else
2491  if ( filename.endsWith ( suffix, false ) == false ) {
2492  filename += data_suffix.c_str();
2493  }
2494 #endif
2495 
2496  const string tuple_name = m_inspector -> getSelectedDataSourceName ();
2497 
2498 #if defined(QT_NO_STL) || QT_VERSION < 0x030100
2499  string tuple_file( filename );
2500 #else
2501  string tuple_file ( filename.latin1() );
2502 #endif
2503 
2504  try {
2506  ->writeNTupleToFile ( tuple_name, tuple_file );
2507  controller -> changeName ( tuple_name, tuple_file );
2508  }
2509  catch ( const std::exception & e ) {
2510  QString message ( "An error occurred in writing file.\n\n" );
2511  message += e.what();
2512  QMessageBox::critical ( this, // parent
2513  QString ( "Write error" ), // caption
2514  message,
2515  QMessageBox::Ok,
2516  QMessageBox::NoButton,
2517  QMessageBox::NoButton );
2518  }
2519 
2520  notifyObservers ();
2521 }
2522 
2523 void
2526 
2528 
2529  std::vector<double> picked;
2530  fillPickedPoint(e, picked);
2531 
2532  QPoint p = inverseWorldMatrix().map(e->pos());
2533 
2534  QtView * qtview(0);
2535 
2536  // For right button, just fill m_mouseData and return...
2537  // Behave differently in different cut modes.
2538  if (e->button() == Qt::RightButton || e->state() == Qt::RightButton) {
2539 
2540 #if QT_VERSION < 0x040000
2541  QCanvasItem * right_item=FigureEditor::getRightItem ();
2542 #else
2543  Q3CanvasItem * right_item=FigureEditor::getRightItem ();
2544 #endif
2545 
2546  if ( right_item == 0 ) {
2547  return;
2548  }
2549 
2550  qtview = dynamic_cast < QtView * > ( right_item );
2551 
2552  // Select a view if a group view is selected.
2553  if ( qtview == 0 )
2554  {
2555  QtGroupView * gv = dynamic_cast <QtGroupView *> (right_item);
2556  const vector <ViewBase * > & views = gv->getViews();
2557  vector < ViewBase * >::const_iterator first = views.begin();
2558  for ( ; first != views.end(); ++first ) {
2559  QtView * v = dynamic_cast < QtView * > ( *first );
2560  if ( ( p.x() >= v->x() ) &&
2561  ( p.x() <= v->x() + v->width() ) &&
2562  ( p.y() >= v->y() ) &&
2563  ( p.y() <= v->y() + v->height() ) ) {
2564  qtview = v;
2565  break;
2566  }
2567  }
2568  if ( qtview == 0 ) return; // click between views
2569  }
2570 
2571 
2572 
2573  fillMouseData(picked);
2574 
2575  // In pick mode, update the pick table.
2576  if ( qtview && ( m_cut_mode == 0 ) ) {
2577 
2578 #if QT_VERSION < 0x040000
2579  QCanvasRectangle * rect
2580  = dynamic_cast <QCanvasRectangle *> ( qtview );
2581 #else
2582  Q3CanvasRectangle * rect
2583  = dynamic_cast <Q3CanvasRectangle *> ( qtview );
2584 #endif
2585 
2586 
2587  if ( ( p.x() >= rect->x() ) &&
2588  ( p.x() <= rect->x() + rect->width() ) &&
2589  ( p.y() >= rect->y() ) &&
2590  ( p.y() <= rect->y() + rect->height() ) ) {
2591 
2592  vector < double > picked2;
2593  qtview -> fillPickedPoint ( p.x(), p.y(), picked2 );
2594  updatePickTable ( qtview, picked2 );
2595  }
2596  }
2597 
2598  // In cut mode 2, up date m_clicked to identify first and second click.
2599  if ( qtview && ( m_cut_mode == 2 ) ) m_clicked=!m_clicked;
2600  if ( qtview && ( m_cut_mode == 1 ) ) m_edge = 0;
2601 
2602  }
2603 
2604  else { // zoom in
2605  qtview = dynamic_cast < QtView * > ( selectedItem() );
2606  if (qtview && !picked.empty() && m_whereClicked != invalid &&
2607  m_drag_rect != 0 ) { // We have a rectangle selected.
2608 
2609  std::vector <double> zoom_top_left;
2610  std::vector <double> zoom_bo_right;
2611 
2612  // Zoom in use the rect instead of the release point.
2613  qtview->fillPickedPoint(m_drag_rect->x(),
2614  m_drag_rect->y(),
2615  zoom_top_left);
2616  qtview->fillPickedPoint(m_drag_rect->x()+m_drag_rect->width(),
2617  m_drag_rect->y()+m_drag_rect->height(),
2618  zoom_bo_right);
2619  setPlotZoom(zoom_top_left, zoom_bo_right);
2620 
2621  delete m_drag_rect; // Erase the rectangle.
2622  m_drag_rect = 0;
2623  canvas()->update();
2624  } else {
2625  m_mouseData.clear();
2626  }
2627  }
2628 
2630 
2631  CanvasWindow * cw = dynamic_cast < CanvasWindow * > ( parentWidget() );
2632  QStatusBar * sb = cw->statusBar();
2633  sb->clear();
2634 
2635  if (qtview) {
2636  qtview->setShowCrossHairs ( false );
2637  qtview->update(0);
2638  }
2639 
2641  notifyObservers ();
2642 }
2643 
2644 bool
2646 fillPickedPoint(QMouseEvent * e, std::vector<double> & picked) {
2647  QPoint p = inverseWorldMatrix().map(e->pos());
2648 
2649 #if QT_VERSION < 0x040000
2651  QCanvasRectangle * rect = dynamic_cast<QCanvasRectangle *>(selItem);
2652 #else
2653  Q3CanvasItem * selItem = FigureEditor::selectedItem();
2654  Q3CanvasRectangle * rect = dynamic_cast<Q3CanvasRectangle *>(selItem);
2655 #endif
2656  if (selItem) {
2657  QtView * qtview = dynamic_cast<QtView *>(selItem);
2658  if (!qtview) return false;
2659  picked.clear();
2660  if ( ( p.x() >= rect->x() ) &&
2661  ( p.x() <= rect->x() + rect->width() ) &&
2662  ( p.y() >= rect->y() ) &&
2663  ( p.y() <= rect->y() + rect->height() ) ) {
2664  qtview -> fillPickedPoint ( p.x(), p.y(), picked );
2665  if (!picked.empty()) {
2666  return true;
2667  }
2668  }
2669  }
2670  return false;
2671 }
2672 
2673 void
2675 fillMouseData(const std::vector<double> & picked) {
2676  if (!picked.empty()) {
2677  m_mouseData.clear();
2678  m_mouseData.reserve(3);
2679  m_mouseData.push_back(picked[1]);
2680  m_mouseData.push_back(picked[2]);
2681  if (picked.size() == 4) {
2682  m_mouseData.push_back(picked[3]);
2683  } else {
2684  m_mouseData.push_back(0);
2685  }
2686  }
2687 }
2688 
2689 void
2691 updatePickTable(QtView * qtview, std::vector<double> & picked) {
2692  if (!picked.empty()){
2693  PickTable * table = 0;
2694  map < const QtView *, PickTable * > ::iterator first
2695  = m_table_map.find ( qtview );
2696  if ( first != m_table_map.end () ) {
2697  table = m_table_map [ qtview ];
2698  }
2699  if ( m_cut_mode == 0 ) {
2700  table -> addItem ( picked );
2701  }
2702  }
2703 }
2704 
2705 /* Note: indexing into the picked vector offset by one because the
2706  first entry is the type. See XyPlotter::fillPickedPointFrom().
2707  */
2708 void
2710 setPlotZoom(const std::vector<double> & start_picked,
2711  const std::vector<double> & picked) {
2712  if (getZoomMode()) {
2713  if ( !(selectedPlotter()->getCurrentRangeSaved()) ) {
2714  setCurrentRange();
2715  }
2716  PlotterBase * plotter = selectedPlotter();
2717  plotter->setRange( "x",
2718  std::min(picked[1], start_picked[1]),
2719  std::max(picked[1], start_picked[1]) );
2720  if (plotter->hasAxis(Axes::Z) || plotter->hasZoomY()) {
2721  plotter->setRange( "y",
2722  std::min(picked[2], start_picked[2]),
2723  std::max(picked[2], start_picked[2]) );
2724  }
2725  plotter -> setCurrentRangeSaved ( false );
2726  }
2727 }
2728 
2729 void
2732 {
2733  if ( ! m_current_range.empty () ){
2734  m_current_range.clear ();
2735  }
2736  PlotterBase * plotter = selectedPlotter ();
2737 
2738  m_current_range.push_back( plotter -> getRange(Axes::X,true).low());
2739  m_current_range.push_back( plotter -> getRange(Axes::X,true).high());
2740  m_current_range.push_back( plotter -> getRange(Axes::Y,true).low());
2741  m_current_range.push_back( plotter -> getRange(Axes::Y,true).high());
2742 
2743  int i = plotter -> currentView();
2744  plotter -> saveViewAtIndex( m_current_range , i + 1 );
2745  plotter -> setCurrentRangeSaved( true );
2746 }
2747 
2748 std::vector<double>&
2751 {
2752  return m_current_range;
2753 }
2754 
2755 void
2758 {
2759  m_inspector -> show ();
2760 }
2761 
2762 void
2765 {
2766 // if ( !isSingleItemSelected() ) return;
2767  if ( isSingleItemSelected () == false ) {
2768  QString message ( "One must select a single plot before showing\n"
2769  "the pick table." );
2770  QMessageBox::information ( this,
2771  s_app_name.c_str(),
2772  message );
2773  return;
2774  }
2775 
2776 #if QT_VERSION < 0x040000
2777  QCanvasItem * selItem = selectedItem();
2778 #else
2779  Q3CanvasItem * selItem = selectedItem();
2780 #endif
2781  QtView * qtview = dynamic_cast < QtView * > ( selItem );
2782  if ( qtview == 0 ) {
2783  QString message ( "Can not show pick table of a group view.\n" );
2784  message += "Please select a single plotter view.";
2785  QMessageBox::information ( this,
2786  s_app_name.c_str(),
2787  message );
2788  return;
2789  }
2790  map < const QtView *, PickTable * > ::iterator first
2791  = m_table_map.find ( qtview );
2792 
2793  if ( first == m_table_map.end() ) {
2794  PlotterBase * plotter = qtview->getPlotter ();
2795 
2796  PickTable * table = new PickTable ( plotter );
2797  m_table_map [ qtview ] = table;
2798  table->show();
2799  }
2800  else {
2801  // Show existing pick table.
2802  m_table_map[qtview]->show();
2803  }
2804 }
2805 
2806 
2807 
2808 const std::vector<double> &
2811 {
2812 #if QT_VERSION < 0x040000
2813  ::mouseEvent.wait();
2814 #else
2815  // need to learn about equivalent
2816  // ::mouseEvent.wait( mutex, time );
2817 #endif
2818  return m_mouseData;
2819 }
2820 
2821 void
2823 {
2824  const std::string & version = WindowController::version ();
2825  std::string about = "<h2>HippoDraw version: ";
2826  about += version;
2827  about += "<h3> Built on ";
2828  about += "<ul>";
2829  about += "<li> Qt ";
2830  about += QT_VERSION_STR;
2831 #ifdef HAVE_CFITSIO
2832  about += "<li> CFITSIO ";
2833  const string & fits_version = FitsController::instance () -> version ();
2834  about += fits_version.c_str();
2835 #endif
2836 
2837 #ifdef HAVE_MINUIT
2838  about += "<li> C++ Minuit";
2839 #endif
2840 
2841 #ifdef HAVE_MINUIT2
2842  about += "<li> Minuit2";
2843 #endif
2844 
2845 #ifdef HAVE_ROOT
2846  about += "<li> ROOT ";
2847  const string & root_version = RootController::instance() -> version ();
2848  about += root_version.c_str();
2849 #endif
2850 
2851 #ifdef HAVE_WCSLIB
2852  about += "<li> WCSlib ";
2853  about += PACKAGE_VERSION;
2854 #endif
2855  about += "</ul>";
2856 
2857  about += "<h3>Contributors...";
2858  about += "<ul>";
2859  about += "<li> Stephane Bonneaud";
2860  about += "<li> James Chiang";
2861  about += "<li> Johann Cohen-Tanugi";
2862  about += "<li> Xie Fang";
2863  about += "<li> Kaustuv";
2864  about += "<li> Paul F. Kunz";
2865  about += "<li> Sanket B. Malde";
2866  about += "<li> Matthew D. Langston";
2867  about += "<li> Joy Rajiv";
2868  about += "<li> Matan Shacham";
2869  about += "<li> Oded Wurman";
2870  about += "</ul>";
2871 
2872  static QMessageBox* mbox
2873  = new QMessageBox ( "HippoDraw",
2874  about.c_str(),
2875  QMessageBox::Information, 1, 0, 0, this, 0, false );
2876  mbox->setButtonText ( 1, "OK" );
2877 
2878  mbox -> exec (); // run modal
2879 }
2880 
2881 const std::string &
2884 {
2885  return s_app_name;
2886 }
2887 
2888 
2889 PlotterBase *
2892 {
2893 
2894 #if QT_VERSION < 0x040000
2895  QCanvasItem * right_item=FigureEditor::getRightItem ();
2896 #else
2897  Q3CanvasItem * right_item=FigureEditor::getRightItem ();
2898 #endif
2899 
2900  QtView * view = dynamic_cast <QtView *> (right_item);
2901 
2902  if ( view == 0 ) return 0;
2903  PlotterBase * plotter = view -> getPlotter ();
2904  return plotter;
2905 }
2906 
2907 void
2909 setCutMode ( int mode )
2910 {
2911  m_cut_mode=mode;
2912 }
2913 
2914 void
2917 {
2919 
2920  const vector < string > & tuples = controller->getNTupleNames();
2921 
2922  if ( tuples.empty () ) {
2923  QString message ( "There are no NTuples to be used as source" );
2924  QMessageBox::information ( this,
2925  s_app_name.c_str(),
2926  message );
2927  return;
2928  }
2929 
2930  CreateNTuple * cnt = new CreateNTuple ();
2931  cnt-> show ();
2932 }
2933 
2934 NTuple *
2937 {
2938 
2939  const ViewBase * selview;
2940  if (m_sel_views.size()==1) selview = m_sel_views[0];
2941  else return NULL;
2942 
2943  const QtView * view = dynamic_cast < const QtView * > ( selview );
2944 
2945  PickTable * table=0;
2946  map < const QtView *, PickTable * > ::iterator first
2947  = m_table_map.find ( view );
2948  if ( first != m_table_map.end () ) {
2949  table = m_table_map [ view ];
2950  }
2951  if ( table ) {
2952  return table->getPickTable();
2953  }
2954 
2955  return NULL;
2956 
2957 }
2958 
2959 NTuple *
2961 getPickTable ( const PlotterBase * plotter )
2962 {
2963 
2964  const QtView * view = getViewFor ( plotter );
2965 
2966  PickTable * table = 0;
2967  map < const QtView *, PickTable * > :: iterator first
2968  = m_table_map.find (view);
2969  if ( first !=m_table_map.end() ) {
2970  table = m_table_map [view];
2971  }
2972  if ( table ) {
2973  return table->getPickTable();
2974  }
2975 
2976  return NULL;
2977 }
2978 
2979 void
2982 {
2983  const vector < const ViewBase * > & selViews = selectedViews();
2984  if ( selViews.empty () ) return;
2985 
2986  QRect groupRect = QRect(0,0,0,0);
2987 
2988  QtGroupView * groupView = new QtGroupView ();
2989 
2990  vector < const ViewBase * >::const_iterator it = selViews.begin();
2991  for ( ; it != selViews.end(); ++it ) {
2992  ViewBase * view = const_cast < ViewBase * > ( *it );
2993 
2994  QtView * qtview = dynamic_cast < QtView * > ( view );
2995  if (!qtview) continue; // don't include groupview in groupview
2996 
2997  groupView->addView (view);
2998  removeFromItemList (qtview);
2999  QRect temp = qtview->boundingRect();
3000  groupRect|=temp; // get a rect to contain all QtViews
3001  }
3002 
3003  groupView->setDrawRect(groupRect);
3004  groupView->setPositions(); // set relative position
3005  add(groupView);
3007  addSelectedItem ( groupView );
3008 }
3009 
3010 void
3013 {
3014  const vector < const ViewBase * > & selViews = selectedViews();
3015  if ( selViews.size() != 1 ) return;
3016 
3017  const QtGroupView * groupView =
3018  dynamic_cast < const QtGroupView * > ( selViews[0] );
3019  if (!groupView) return;
3020 
3021  QtGroupView * gv = const_cast < QtGroupView * > ( groupView );
3022  clearSelectedList ();
3023  const vector < ViewBase * > & views = gv->getViews();
3024 
3025  vector < ViewBase * >::const_iterator first = views.begin();
3026  for ( ; first != views.end(); ++first ) {
3027  QtView * qtview = dynamic_cast < QtView * > ( *first );
3028  add (qtview);
3029  gv->removeView(*first);
3030  --first; // a view is removed, decrease the iterator
3031  addSelectedItem (qtview );
3032  }
3033  remove ( gv );
3034 }
3035 
3037 {
3038  const vector < const ViewBase * > & views = selectedViews ();
3039 #ifdef ITERATOR_MEMBER_DEFECT
3040  std::
3041 #endif
3042  vector < const ViewBase * > ::const_iterator first = views.begin();
3043  while ( first != views.end() ) {
3044  const QtView * view = dynamic_cast < const QtView * > ( *first++ );
3045  QtView * v = const_cast < QtView * > ( view );
3046  hide(v);
3047  }
3048 }
3049 
3050 void
3052 addRecentFile (const QString & filename, QActionGroup * ag )
3053 {
3054  #if QT_VERSION < 0x040000
3055 #else
3056  QObject * parent = ag -> parent ();
3057 #endif
3058 
3059  // Avoid duplicate recently opened files.
3060  // Remove old item with same name if needed.
3061  std::list<QAction *>::iterator it=m_recent_list.begin();
3062 
3063  for (; it!=m_recent_list.end(); ++it){
3064  if (((*it)->menuText())==filename){
3065  delete *it; // need removeFrom(ag) ?
3066  it=m_recent_list.erase(it);
3067  break;
3068  }
3069  }
3070 
3071  // Add new item.
3072 #if QT_VERSION < 0x040000
3073  QAction * action = new QAction ( "", // text
3074  QIconSet(),
3075  filename, // menu test
3076  0, // accel
3077  ag ); // parent
3078 #else
3079  QAction * action = new QAction ( filename, parent );
3080  ag -> addAction ( action );
3081 #endif
3082  action -> setToggleAction ( true );
3083  m_recent_list.push_back(action);
3084 
3085  // Remove the first element if size is more than 5.
3086  if (m_recent_list.size() > 5) {
3087  it=m_recent_list.begin();
3088  delete *it; //need removeFrom(ag) ?
3089  m_recent_list.pop_front();
3090  }
3091 }
3092 
3093 void
3094 CanvasView::
3095 #if QT_VERSION < 0x040000
3097 #else
3098 autosaveSettings (Q3MainWindow * mw)
3099 #endif
3100 {
3101  QSettings settings;
3102  settings.insertSearchPath ( QSettings::Windows, s_registry );
3103  QString fn;
3104  list<QAction *>::iterator it;
3105  unsigned int i=0;
3106 
3107 
3108  // Save recently opened files
3109  for ( it=m_recent_list.begin();
3110  it!=m_recent_list.end(); i++, it++ )
3111  {
3112  fn = (*it)->menuText();
3113  QString number=QString::number(i);
3114  settings.writeEntry ( s_app_key + "Files/File"+number, fn );
3115  }
3116 
3117  // Save dock window positions.
3118  QString dockSetting;
3119  QTextStream stream( &dockSetting, IO_WriteOnly );
3120  stream << *mw;
3121  settings.writeEntry(s_app_key+"DockWindow/Position", dockSetting);
3122 }
3123 
3124 void
3127 {
3128  moveDockWindow(toolBar);
3129  moveDockWindow(Toolbar_2);
3130  moveDockWindow(Toolbar);
3131  moveDockWindow(Toolbar_4);
3132 
3133  lineUpDockWindows();
3134 }

Generated for HippoDraw Class Library by doxygen