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