Fixed text file permissions
[snark14.git] / tools / Display / displaylines.cpp
1 /** @file displaylines.cpp
2     @package snark14Display
3     @author Bruno M. Carvalho and Deniz Sarioz
4     licensed under (open-source) QPL v1.0
5     which accompanies this distribution in the file QPL
6         
7     modification: Joanna Klukowska 1/13/2009
8             added choice of grayScale display for plot
9             in addition to color display
10 */
11
12 #include "displaylines.hpp"
13 #include "verbosity.hpp"
14
15 #include <cstdio>
16 #include <cstdlib>
17 #include <iostream>
18
19 #include <qwidget.h>
20 #include <qpushbutton.h>
21 #include <qlayout.h>
22 #include <qvariant.h>
23 #include <qtooltip.h>
24 #include <qwhatsthis.h>
25 #include <qimage.h>
26 #include <qpixmap.h>
27 #include <qmessagebox.h>
28 #include <qfiledialog.h>
29 #include <qstring.h>
30 #include <qregexp.h>
31
32 /* 
33  *  Constructs a displaylineswindow which is a child of 'parent', with the 
34  *  name 'name' and widget flags set to 'f' 
35  *
36  *  The dialog will by default be modeless, unless you set 'modal' to
37  *  TRUE to construct a modal dialog.
38  */
39 displaylineswindow::displaylineswindow( QWidget* parent,  const char* name, QPixmap* pixmap, bool modal, WFlags fl , int x, int y )
40     : QDialog( parent, name, modal, fl )
41 {
42   QPoint topleft;
43   
44   if ( !name ) 
45     setName( "Column/Line Profile" );
46   imagename=name;
47   int outerXPAD = 10;
48   int outerTopYPad = 10;
49   int outerBotYPad = 90;
50   int WID = pixmap->width();
51   int WINWIDTH  = 2*outerXPAD + WID;
52   int HEI = pixmap->height();
53   int WINHEIGHT = HEI + outerTopYPad + outerBotYPad;
54   resize( WINWIDTH, WINHEIGHT );
55   setMinimumSize( QSize( WINWIDTH, WINHEIGHT ) );
56   setMaximumSize( QSize( WINWIDTH, WINHEIGHT ) );
57   //    setCaption( tr( "Column/Line Profile" ) );
58   setCaption( name );
59   topleft.setX(x);
60   topleft.setY(y);
61   this->move(topleft);
62   localpixmap=pixmap;
63   pixmapwidget = new QWidget( this, "pixmapwidget" );
64   pixmapwidget->setGeometry( QRect( outerXPAD, outerTopYPad, WID, HEI ) );
65   pixmapwidget->setBackgroundPixmap( *pixmap );
66   int BUTTONWID = 100;
67   int BUTTONHEI = 40;
68   int BUTXPAD = 40;
69   int BUTBOTPAD = 20;
70   savebutton = new QPushButton( this, "savebutton" );
71   savebutton->setGeometry( QRect( BUTXPAD, WINHEIGHT-BUTTONHEI-BUTBOTPAD, BUTTONWID, BUTTONHEI ) ); 
72   savebutton->setCaption( tr( "" ) );
73   savebutton->setText( tr( "Save" ) );
74   QObject::connect(savebutton,SIGNAL(clicked()),this,SLOT(saveImage()));
75   
76   closebutton = new QPushButton( this, "closebutton" );
77   closebutton->setGeometry( QRect( WINWIDTH-BUTTONWID-BUTXPAD, WINHEIGHT-BUTTONHEI-BUTBOTPAD, BUTTONWID, BUTTONHEI ) ); 
78   closebutton->setCaption( tr( "" ) );
79   closebutton->setText( tr( "Close" ) );
80   QObject::connect(closebutton,SIGNAL(clicked()),this,SLOT(accept()));
81 } // displaylineswindow ctor
82
83 /*
84  *  Destroys the object and frees any allocated resources
85  */
86 displaylineswindow::~displaylineswindow()
87 {
88   // no need to delete child widgets, Qt does it all for us
89 }
90
91 /** Saves the profile graph image
92     @param void
93     @author Bruno M. Carvalho, changes by Deniz
94     @version 1.2 */ 
95 void displaylineswindow::saveImage()
96
97   if(std::verbose >=2) std::cout << "++displaylineswindow::saveImage()" << std::endl;
98   QString prefixForSaving = (imagename.simplifyWhiteSpace());
99   if(std::verbose >=2) std::cout << "My prefix is originally: \"" << prefixForSaving << "\"" << std::endl;
100   // beware weird characters in save file name!
101   // these might be intentionally meaningful
102   prefixForSaving.replace( QRegExp("\\="), "_EQ_");
103   prefixForSaving.replace( QRegExp("\\+"), "_PLUS_");
104   prefixForSaving.replace( QRegExp("\\@"), "_AT_");
105   //  prefixForSaving.replace( QRegExp("-"), "_MINUS_"); // maybe
106   // convert everything non-alphanumeric to underscore
107   prefixForSaving.replace( QRegExp("[^a-zA-Z0-9]"), "_");
108   // allow maximum of 2 consecutive underscores  
109   prefixForSaving.replace( QRegExp("__+") , "__"); 
110   // chuck underscore from beginning and end
111   prefixForSaving.replace( QRegExp("^_+"), "");
112   prefixForSaving.replace( QRegExp("_+$"), "");
113   if(std::verbose >=2) std::cout << "My prefix became: \"" << prefixForSaving << "\"" << std::endl;
114   // this is how the filter ought to be according to manual for version 3.3.
115   QString myExtensionFilter =   // delimiter is double-semicolon, NOT '\n'
116     "png (PNG file);;"
117     "bmp (BMP file);;"
118     "pbm (PBM file);;"
119     "pgm (PGM file);;"
120     "ppm (PPM file);;"
121     "xbm (XBM file);;"
122     "xpm (XPM file)"   ;
123   QString mySaveAs = "Save Image as";
124   QString startInDir = "./";
125   QFileDialog fd(startInDir, myExtensionFilter, this, mySaveAs, true);
126   fd.setMode(QFileDialog::AnyFile);
127   fd.setSelection(prefixForSaving);
128   if (QDialog::Accepted != fd.exec()) {
129     if(std::verbose >=2) std::cout << "--displaylineswindow::saveImage() in a hurry" << std::endl;
130     return; // happens, say, when cancel is pressed.  just leave, no harm.
131   }
132   QString userFileSavePrefix = fd.selectedFile();
133   QString userFileSaveExtension = fd.selectedFilter();
134   if (userFileSavePrefix.isEmpty()) {
135     if(std::verbose >=2) std::cout << "--displaylineswindow::saveImage() in a hurry" << std::endl;
136     return; // happens, say, when cancel is pressed.  just leave, no harm.
137   }
138   if(std::verbose >=2) std::cout << "Got file name as: \"" << userFileSavePrefix << "\"" << std::endl;
139   if(std::verbose >=2) std::cout << "Got selected ext: \"" << userFileSaveExtension << "\"" << std::endl;
140   /* NB: userFileSavePrefix now contains directory info as well.
141    * if user entered additional forward-slashes without
142    * knowing that it signified directory, that's NOT our problem.
143    * (the user MAY legitimately enter "a/myImage" as file name if there is a directory "a" 
144    *   within the currently open directory in the save dialog window)
145    * do part only after last forward-slash (i.e., what user entered)...
146    * don't want to burn ourselves if path in fact had legit non-alphanumericounderscore chars
147    */
148   QString justFilePrefix, justPath;
149   // funnylooking because written to work with Qt BOTH 2.3 and 3.3
150   int posLastSlash = userFileSavePrefix.findRev('/'); // returns pos if found, -1 if not.
151   if (-1 != posLastSlash) {
152     justPath = userFileSavePrefix.left(posLastSlash+1); // +1 to include last '/'
153     justFilePrefix = userFileSavePrefix;
154     QRegExp fakeRegex("^" + justPath); // it just *looks* fake...
155     justFilePrefix.replace( fakeRegex, "" ); // chuck away including last '/' for justFilePrefix
156     if(std::verbose >=2) std::cout << "just after regex replace, justFilePrefix: \"" << justFilePrefix << "\"" << std::endl;
157   } else {  // if for some reason no forwardslash, handle that gracefully too.
158     justFilePrefix = userFileSavePrefix;
159     justPath = "";
160   }
161   if(std::verbose >=2) std::cout << "justPath is: \"" << justPath << "\"" << std::endl;
162   if(std::verbose >=2) std::cout << "justFilePrefix is first: \"" << justFilePrefix << "\"" << std::endl;
163   // remove justFilePrefix from ONLY the end of 'userFileSavePrefix'.
164   justFilePrefix.replace( QRegExp("="), "_EQ_");
165   justFilePrefix.replace( QRegExp("+"), "_PLUS_");
166   justFilePrefix.replace( QRegExp("[^a-zA-Z0-9]"), "_"); // no forward slash in regex
167   // allow maximum of 2 consecutive underscores  
168   justFilePrefix.replace( QRegExp("__+") , "__"); 
169   // chuck underscore from beginning and end
170   justFilePrefix.replace( QRegExp("^_+"), "");
171   justFilePrefix.replace( QRegExp("_+$"), "");
172   if(std::verbose >=2) std::cout << "justFilePrefix is later: \"" << justFilePrefix << "\"" << std::endl;
173   // reset userFileSavePrefix by putting back together justPath and the refined justFilePrefix
174   userFileSavePrefix = justPath + justFilePrefix;
175   userFileSaveExtension.truncate(3);
176   if(std::verbose >=2) std::cout << "My userFileSavePrefix is \"" << userFileSavePrefix << "\"" << std::endl;
177   if(std::verbose >=2) std::cout << "My userFileSaveExtension is \"" << userFileSaveExtension << "\"" << std::endl;
178   QString extensionUpper = userFileSaveExtension.upper();
179   QString saveFullNameWithPath = userFileSavePrefix + "." + extensionUpper;
180   if(std::verbose >=2) std::cout << "extensionUpper is now \"" << extensionUpper << "\"" << std::endl;
181   if(std::verbose >=2) std::cout << "saveFullNameWithPath is now \"" << saveFullNameWithPath << "\"" << std::endl;
182   QImage prof=localpixmap->convertToImage();
183   QImageIO recio;
184   recio.setImage(prof);
185   recio.setFormat(extensionUpper);
186   recio.setFileName(saveFullNameWithPath);
187   if ( recio.write() ) {
188     if(std::verbose>=1) {
189       std::cout << "successfully saved: \"" << saveFullNameWithPath << "\"" << std::endl;
190     }
191   } else {
192     std::cerr << "UNsuccessfully tried to save as: \"" << saveFullNameWithPath << "\"" << std::endl;
193   }
194   if(std::verbose >=2) std::cout << "--displaylineswindow::saveImage()" << std::endl;
195 } // --displaylineswindow::saveImage()