1 /***************************************************************************
2     File                 : MultiLayer.h
3     Project              : QtiPlot
4     --------------------------------------------------------------------
5     Copyright            : (C) 2006 - 2009 by Ion Vasilief, Knut Franke
6     Email (use @ for *)  : ion_vasilief*yahoo.fr, knut.franke*gmx.de
7     Description          : Multi layer widget
8 
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *  This program is free software; you can redistribute it and/or modify   *
14  *  it under the terms of the GNU General Public License as published by   *
15  *  the Free Software Foundation; either version 2 of the License, or      *
16  *  (at your option) any later version.                                    *
17  *                                                                         *
18  *  This program is distributed in the hope that it will be useful,        *
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
21  *  GNU General Public License for more details.                           *
22  *                                                                         *
23  *   You should have received a copy of the GNU General Public License     *
24  *   along with this program; if not, write to the Free Software           *
25  *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
26  *   Boston, MA  02110-1301  USA                                           *
27  *                                                                         *
28  ***************************************************************************/
29 #ifndef MULTILAYER_H
30 #define MULTILAYER_H
31 
32 #include <MdiSubWindow.h>
33 #include <FrameWidget.h>
34 #include <QPushButton>
35 #include <QLayout>
36 #include <QPointer>
37 
38 class QTextDocument;
39 class QLabel;
40 class LayerButton;
41 class SelectionMoveResizer;
42 class LegendWidget;
43 class Graph;
44 class QwtPlotCurve;
45 class Matrix;
46 
47 /**
48  * \brief An MDI window (MdiSubWindow) managing one or more Graph objects.
49  *
50  * %Note that several parts of the code, as well as the user interface, refer to MultiLayer as "graph" or "plot",
51  * practically guaranteeing confusion with the classes Graph and Plot.
52  *
53  * \section future Future Plans
54  * Manage any QWidget instead of only Graph.
55  * This would allow 3D graphs to be added as well, so you could produce mixed 2D/3D arrangements.
56  * It would also allow text labels to be added directly instead of having to complicate things by wrapping them
57  * up in a Graph (see documentation of ImageMarker for details) (see documentation of ImageMarker for details).
58  *
59  * The main problem to be figured out for this is how Graph would interface with the rest of the project.
60  * A possible solution is outlined in the documentation of ApplicationWindow:
61  * If MultiLayer exposes its parent Project to the widgets it manages, they could handle things like creating
62  * tables by calling methods of Project instead of sending signals.
63  */
64 class MultiLayer: public MdiSubWindow
65 {
66 	Q_OBJECT
67 
68 public:
69     MultiLayer (ApplicationWindow* parent = 0, int layers = 1, int rows = 1, int cols = 1, const QString& label = "", const char* name=0, Qt::WFlags f=0);
70 	~MultiLayer();
71 
layersList()72 	QList<Graph *> layersList(){return graphsList;};
73 	QList<Graph*> stackOrderedLayersList();
74 	Graph *layer(int num);
layerIndex(Graph * g)75 	int layerIndex(Graph *g){return graphsList.indexOf(g);};
76 
numLayers()77     int numLayers(){return graphsList.size();};
78     void setNumLayers(int n);
79 
80 	void copy(MultiLayer* ml);
81 
82 	enum HorAlignement{HCenter, Left, Right};
83 	enum VertAlignement{VCenter, Top, Bottom};
84 	enum AlignPolicy{AlignLayers = 0, AlignCanvases};
85 	enum SizePolicy{Expanding = 0, UserSize};
86 
scaleLayersOnPrint()87 	bool scaleLayersOnPrint(){return d_scale_on_print;};
setScaleLayersOnPrint(bool on)88 	void setScaleLayersOnPrint(bool on){d_scale_on_print = on;};
89 
printCropmarksEnabled()90 	bool printCropmarksEnabled(){return d_print_cropmarks;};
printCropmarks(bool on)91 	void printCropmarks(bool on){d_print_cropmarks = on;};
92 
scaleLayersOnResize()93 	bool scaleLayersOnResize(){return d_scale_layers;};
setScaleLayersOnResize(bool ok)94 	void setScaleLayersOnResize(bool ok){d_scale_layers = ok;};
95 
canvas()96 	QWidget *canvas(){return d_canvas;};
canvasRect()97 	QRect canvasRect(){return d_canvas->rect();};
98 	QRect canvasChildrenRect();
99 	virtual QString sizeToString();
100 
101 	void setWaterfallLayout(bool on = true);
102 
103 	void setEqualSizedLayers();
104 
105 	void plotProfiles(Matrix* m);
106 
toolBox()107 	QHBoxLayout *toolBox(){return toolbuttonsBox;};
108 
alignPolicy()109 	AlignPolicy alignPolicy(){return d_align_policy;};
setAlignPolicy(const AlignPolicy & policy)110 	void setAlignPolicy(const AlignPolicy& policy){d_align_policy = policy;};
111 
sizePolicy()112 	SizePolicy sizePolicy(){return d_size_policy;};
setSizePolicy(const SizePolicy & policy)113 	void setSizePolicy(const SizePolicy& policy){d_size_policy = policy;};
114 
115 	void setCommonLayerAxes(bool verticalAxis = true, bool horizontalAxis = true);
116 	void linkXLayerAxes(bool link = true);
hasLinkedXLayerAxes()117 	bool hasLinkedXLayerAxes(){return d_link_x_axes;};
hasCommonAxes()118 	bool hasCommonAxes(){return d_common_axes_layout;};
119 	void setCommonAxesLayout(bool on = true){d_common_axes_layout = on;};
120 
121 	void deselect();
122 	bool hasSelectedLayers();
123 	bool isLayerSelected(Graph*);
124 
125 	void adjustLayersToCanvasSize();
126 
127 public slots:
128 	Graph* addLayer(int x = 0, int y = 0, int width = 0, int height = 0, bool = false);
129 
130 	bool isEmpty();
131     bool removeLayer(Graph *g);
132     bool removeActiveLayer();
133 	void confirmRemoveLayer();
134 
activeLayer()135 	Graph* activeLayer(){return active_graph;};
136 	void setActiveLayer(Graph* g);
137 	void activateGraph(LayerButton* button);
138 	void selectLayerCanvas(Graph* g);
139 
140     //! Returns the layer at the given position; returns 0 if there is no such layer.
141 	Graph* layerAt(const QPoint& pos);
142 	void setGraphGeometry(int x, int y, int w, int h);
143 
144 	void findBestLayout(int &rows, int &cols);
145 
146 	QSize arrangeLayers(bool userSize);
147 	bool arrangeLayers(bool fit, bool userSize);
148 	bool swapLayers(int src, int dest);
149 	void updateLayersLayout(Graph *);
150 
getRows()151 	int getRows(){return d_rows;};
152 	void setRows(int r);
153 
getCols()154 	int getCols(){return d_cols;};
155 	void setCols(int c);
156 
colsSpacing()157 	int colsSpacing(){return colsSpace;};
rowsSpacing()158 	int rowsSpacing(){return rowsSpace;};
159 	void setSpacing (int rgap, int cgap);
160 
leftMargin()161 	int leftMargin(){return left_margin;};
rightMargin()162 	int rightMargin(){return right_margin;};
topMargin()163 	int topMargin(){return top_margin;};
bottomMargin()164 	int bottomMargin(){return bottom_margin;};
165 	void setMargins (int lm, int rm, int tm, int bm);
166 
layerCanvasSize()167 	QSize layerCanvasSize(){return QSize(l_canvas_width, l_canvas_height);};
168 	void setLayerCanvasSize (int w, int h);
169 
horizontalAlignement()170 	int horizontalAlignement(){return hor_align;};
verticalAlignement()171 	int verticalAlignement(){return vert_align;};
172 	void setAlignement (int ha, int va);
173 
174 	//! \name Print and Export
175 	//@{
176 	QPixmap canvasPixmap(const QSize& size = QSize(), double scaleFontsFactor = 1.0, bool transparent = false);
177 	void exportToFile(const QString& fileName);
178 #if QT_VERSION >= 0x040500
179 	void exportImage(QTextDocument *document, int quality = 100, bool transparent = false,
180 		int dpi = 0, const QSizeF& customSize = QSizeF (), int unit = FrameWidget::Pixel, double fontsFactor = 1.0);
181 #endif
182 	void exportImage(const QString& fileName, int quality = 100, bool transparent = false, int dpi = 0,
183 		const QSizeF& customSize = QSizeF (), int unit = FrameWidget::Pixel, double fontsFactor = 1.0, int compression = 0);
184 	void exportSVG(const QString& fname, const QSizeF& customSize = QSizeF(), int unit = FrameWidget::Pixel, double fontsFactor = 1.0);
185     void exportPDF(const QString& fname);
186 	void exportVector(const QString& fileName, int res = 0, bool color = true,
187 		const QSizeF& customSize = QSizeF (), int unit = FrameWidget::Pixel, double fontsFactor = 1.0);
188 	void exportVector(QPrinter *printer, int res = 0, bool color = true,
189 		const QSizeF& customSize = QSizeF (), int unit = FrameWidget::Pixel, double fontsFactor = 1.0);
190 
191 	void draw(QPaintDevice *, const QSizeF& customSize, int unit, int res, double fontsFactor = 1.0);
192 
193 	void exportEMF(const QString& fname, const QSizeF& customSize = QSizeF(), int unit = FrameWidget::Pixel, double fontsFactor = 1.0);
194 	void exportTeX(const QString& fname, bool color = true, bool escapeStrings = true, bool fontSizes = true,
195 					const QSizeF& customSize = QSizeF(), int unit = FrameWidget::Pixel, double fontsFactor = 1.0);
196 
197 	void copyAllLayers();
198 	void print();
199 	void print(QPrinter *);
200 	void printAllLayers(QPainter *painter);
201 	void printActiveLayer();
202 	//@}
203 
204 	void setFonts(const QFont& titleFnt, const QFont& scaleFnt,
205 							const QFont& numbersFnt, const QFont& legendFnt);
206 
207 	void connectLayer(Graph *g);
208 
209 	void save(const QString& fn, const QString& geometry, bool = false);
210 
211     //! \name Waterfall Plots
212 	//@{
213     void showWaterfallOffsetDialog();
214     void reverseWaterfallOrder();
215     void showWaterfallFillDialog();
216 	void updateWaterfalls();
isWaterfallPlot()217 	bool isWaterfallPlot(){return d_is_waterfall_plot;}
waterfallFillColor()218 	QColor waterfallFillColor(){return d_waterfall_fill_color;}
219 	void setWaterfallFillColor(const QColor& c);
220     //@}
221 
222 	void updateLayerAxes(Graph *g, int axis);
223 
224 signals:
225 	void showEnrichementDialog();
226 	void showCurvesDialog();
227 	void drawLineEnded(bool);
228 	void showMarkerPopupMenu();
229 	void modifiedPlot();
230 	void cursorInfo(const QString&);
231 	void showLineDialog();
232 	void pasteMarker();
233 	void setPointerCursor();
234 	void currentFontChanged(const QFont&);
235 	void currentColorChanged(const QColor&);
236 
237 private:
238 	//! \name Event Handlers
239 	//@{
240 	void mouseReleaseEvent(QMouseEvent *);
241 	void showEvent(QShowEvent *);
242 	void dropEvent(QDropEvent*);
243 	void dragEnterEvent(QDragEnterEvent*);
244 	void wheelEvent(QWheelEvent *);
245 	void keyPressEvent(QKeyEvent *);
246 	bool eventFilter(QObject *object, QEvent *);
247 	void releaseLayer();
248 	void resizeLayers(QResizeEvent *);
249 	//! Try to guess on which layer the user clicked if the layers are superposed
250 	Graph* clickedLayer(Graph*);
251 	//@}
252 
253 	LayerButton* addLayerButton();
254 	void createWaterfallBox();
255 
256 	Graph* active_graph;
257 	//! Used for resizing of layers.
258 	int d_cols, d_rows, graph_width, graph_height, colsSpace, rowsSpace;
259 	int left_margin, right_margin, top_margin, bottom_margin;
260 	int l_canvas_width, l_canvas_height, hor_align, vert_align;
261 	bool d_scale_on_print, d_print_cropmarks;
262     //! Flag telling if layers should be rescaled on the plot window is resized by the user.
263 	bool d_scale_layers;
264 
265     QList<LayerButton *> buttonsList;
266     QList<Graph *> graphsList;
267 	QHBoxLayout *layerButtonsBox, *waterfallBox, *toolbuttonsBox;
268     QWidget *d_canvas;
269 
270 	QPointer<SelectionMoveResizer> d_layers_selector;
271 
272 	bool d_is_waterfall_plot;
273 	QColor d_waterfall_fill_color;
274 
275 	QPushButton *d_add_layer_btn, *d_remove_layer_btn;
276 
277 	QSize d_canvas_size;
278 
279 	AlignPolicy d_align_policy;
280 	SizePolicy d_size_policy;
281 	bool d_link_x_axes;
282 	bool d_common_axes_layout;
283 
284 	QVector<QRectF> d_layer_coordinates;
285 };
286 
287 //! Button with layer number
288 class LayerButton: public QPushButton
289 {
290 	Q_OBJECT
291 
292 public:
293     LayerButton (const QString& text = QString::null, QWidget* parent = 0);
btnSize()294 	static int btnSize(){return 20;};
295 
296 protected:
297 	void mousePressEvent( QMouseEvent * );
298 	void mouseDoubleClickEvent ( QMouseEvent * );
299 
300 signals:
301 	void showCurvesDialog();
302 	void clicked(LayerButton*);
303 	void showLayerContextMenu();
304 };
305 
306 #endif
307