labplot  2.8.2
About: LabPlot is an application for plotting and analysis of 2D and 3D functions and data. It is a complete rewrite of LabPlot1 and lacks in the first release a lot of features available in the predecessor. On the other hand, the GUI and the usability is more superior.
  Fossies Dox: labplot-2.8.2.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

WorksheetElement.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : WorksheetElement.cpp
3  Project : LabPlot
4  Description : Base class for all Worksheet children.
5  --------------------------------------------------------------------
6  Copyright : (C) 2009 Tilman Benkert (thzs@gmx.net)
7  Copyright : (C) 2012-2017 by Alexander Semke (alexander.semke@web.de)
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 
33 
34 #include <QGraphicsItem>
35 #include <QMenu>
36 #include <QPen>
37 #include <KLocalizedString>
38 
39 /**
40  * \class WorksheetElement
41  * \brief Base class for all Worksheet children.
42  *
43  */
45  : AbstractAspect(name, type) {
46 
47  m_drawingOrderMenu = new QMenu(i18n("Drawing &order"));
48  m_drawingOrderMenu->setIcon(QIcon::fromTheme("layer-bottom"));
49  m_moveBehindMenu = new QMenu(i18n("Move &behind"));
50  m_moveBehindMenu->setIcon(QIcon::fromTheme("draw-arrow-down"));
51  m_moveInFrontOfMenu = new QMenu(i18n("Move in &front of"));
52  m_moveInFrontOfMenu->setIcon(QIcon::fromTheme("draw-arrow-up"));
55 
56  connect(m_moveBehindMenu, &QMenu::aboutToShow, this, &WorksheetElement::prepareMoveBehindMenu);
57  connect(m_moveInFrontOfMenu, &QMenu::aboutToShow, this, &WorksheetElement::prepareMoveInFrontOfMenu);
58  connect(m_moveBehindMenu, &QMenu::triggered, this, &WorksheetElement::execMoveBehind);
59  connect(m_moveInFrontOfMenu, &QMenu::triggered, this, &WorksheetElement::execMoveInFrontOf);
60 }
61 
63  delete m_moveBehindMenu;
64  delete m_moveInFrontOfMenu;
65  delete m_drawingOrderMenu;
66 }
67 
68 /**
69  * \fn QGraphicsItem *WorksheetElement::graphicsItem() const
70  * \brief Return the graphics item representing this element.
71  *
72  */
73 
74 /**
75  * \fn void WorksheetElement::setVisible(bool on)
76  * \brief Show/hide the element.
77  *
78  */
79 
80 /**
81  * \fn bool WorksheetElement::isVisible() const
82  * \brief Return whether the element is (at least) partially visible.
83  *
84  */
85 
86 /**
87  * \brief Return whether the element is fully visible (i.e., including all child elements).
88  *
89  * The standard implementation returns isVisible().
90  */
92  return isVisible();
93 }
94 
95 /**
96  * \fn void WorksheetElement::setPrinting(bool on)
97  * \brief Switches the printing mode on/off
98  *
99  */
100 
101 /**
102  * \fn void WorksheetElement::retransform()
103  * \brief Tell the element to newly transform its graphics item into its coordinate system.
104  *
105  * This method must not change the undo-aware data of the element, only
106  * the graphics item which represents the item is to be updated.
107  */
108 
109 void WorksheetElement::setZValue(qreal value) {
110  graphicsItem()->setZValue(value);
111 }
112 
113 /**
114  This does exactly what Qt internally does to creates a shape from a painter path.
115 */
116 QPainterPath WorksheetElement::shapeFromPath(const QPainterPath &path, const QPen &pen) {
117  if (path == QPainterPath())
118  return path;
119 
120 // PERFTRACE("WorksheetElement::shapeFromPath()");
121 
122  // TODO: We unfortunately need this hack as QPainterPathStroker will set a width of 1.0
123  // if we pass a value of 0.0 to QPainterPathStroker::setWidth()
124  const qreal penWidthZero = qreal(1.e-8);
125 
126  QPainterPathStroker ps;
127  ps.setCapStyle(pen.capStyle());
128  if (pen.widthF() <= 0.0)
129  ps.setWidth(penWidthZero);
130  else
131  ps.setWidth(pen.widthF());
132  ps.setJoinStyle(pen.joinStyle());
133  ps.setMiterLimit(pen.miterLimit());
134 
135  QPainterPath p = ps.createStroke(path);
136  p.addPath(path);
137 
138  return p;
139 }
140 
142  QMenu* menu = AbstractAspect::createContextMenu();
143 
144  //add the sub-menu for the drawing order
145 
146  //don't add the drawing order menu for axes and legends, they're always drawn on top of each other elements
148  return menu;
149 
150  //for plots in a worksheet with an active layout the Z-factor is not relevant but we still
151  //want to use the "Drawing order" menu to be able to change the position/order of the plot in the layout.
152  //Since the order of the child in the list of children is opposite to the Z-factor, we change
153  //the names of the menus to adapt to the reversed logic.
154  if (dynamic_cast<AbstractPlot*>(this) ) {
155  const Worksheet* w = dynamic_cast<const Worksheet*>(this->parentAspect());
156  if (!w)
157  return menu;
158 
159  if (w->layout() != Worksheet::Layout::NoLayout) {
160  m_moveBehindMenu->setTitle(i18n("Move in &front of"));
161  m_moveBehindMenu->setIcon(QIcon::fromTheme("draw-arrow-up"));
162  m_moveInFrontOfMenu->setTitle(i18n("Move &behind"));
163  m_moveInFrontOfMenu->setIcon(QIcon::fromTheme("draw-arrow-down"));
164  } else {
165  m_moveBehindMenu->setTitle(i18n("Move &behind"));
166  m_moveBehindMenu->setIcon(QIcon::fromTheme("draw-arrow-down"));
167  m_moveInFrontOfMenu->setTitle(i18n("Move in &front of"));
168  m_moveInFrontOfMenu->setIcon(QIcon::fromTheme("draw-arrow-up"));
169  }
170  }
171 
172  //don't add the drawing order menu if the parent element has no other children
173  int children = 0;
174  for (auto* child : parentAspect()->children<WorksheetElement>()) {
175  if (child->type() != AspectType::Axis && child->type() != AspectType::CartesianPlotLegend)
176  children++;
177  }
178 
179  if (children > 1) {
180  menu->addSeparator();
181  menu->addMenu(m_drawingOrderMenu);
182  }
183 
184  return menu;
185 }
186 
188  m_moveBehindMenu->clear();
190  int index = parent->indexOfChild<WorksheetElement>(this);
192 
193  for (int i = 0; i < index; ++i) {
194  const WorksheetElement* elem = children.at(i);
195  //axes and legends are always drawn on top of other elements, don't add them to the menu
196  if (elem->type() != AspectType::Axis && elem->type() != AspectType::CartesianPlotLegend) {
197  QAction* action = m_moveBehindMenu->addAction(elem->icon(), elem->name());
198  action->setData(i);
199  }
200  }
201 
202  //TODO: doesn't always work properly
203  //hide the "move behind" menu if it doesn't have any entries, show if not shown yet otherwise
204  //m_moveBehindMenu->menuAction()->setVisible(!m_moveBehindMenu->isEmpty());
205 }
206 
208  m_moveInFrontOfMenu->clear();
210  int index = parent->indexOfChild<WorksheetElement>(this);
212 
213  for (int i = index + 1; i < children.size(); ++i) {
214  const WorksheetElement* elem = children.at(i);
215  //axes and legends are always drawn on top of other elements, don't add them to the menu
216  if (elem->type() != AspectType::Axis && elem->type() != AspectType::CartesianPlotLegend) {
217  QAction* action = m_moveInFrontOfMenu->addAction(elem->icon(), elem->name());
218  action->setData(i);
219  }
220  }
221 
222  //TODO: doesn't alway work properly
223  //hide the "move in front" menu if it doesn't have any entries, show if not shown yet otherwise
224  //m_moveInFrontOfMenu->menuAction()->setVisible(!m_moveInFrontOfMenu->isEmpty());
225 }
226 
229  int index = action->data().toInt();
230  AbstractAspect* sibling1 = parent->child<WorksheetElement>(index);
231  AbstractAspect* sibling2 = parent->child<WorksheetElement>(index + 1);
232  beginMacro(i18n("%1: move behind %2.", name(), sibling1->name()));
233  remove();
234  parent->insertChildBefore(this, sibling2);
235  endMacro();
236 }
237 
240  int index = action->data().toInt();
241  AbstractAspect* sibling = parent->child<WorksheetElement>(index);
242  beginMacro(i18n("%1: move in front of %2.", name(), sibling->name()));
243  remove();
244  parent->insertChildBefore(this, sibling);
245  endMacro();
246 }
247 
248 void WorksheetElement::loadThemeConfig(const KConfig &) {
249 }
250 
251 void WorksheetElement::saveThemeConfig(const KConfig &) {
252 }
AspectType
@ CartesianPlotLegend
Base class of all persistent objects in a Project.
virtual QIcon icon() const
Return an icon to be used for decorating my views.
AspectType type() const
int indexOfChild(const AbstractAspect *child, ChildIndexFlags flags={}) const
Return (0 based) index of child in the list of children inheriting from class T.
AbstractAspect * parent(AspectType type) const
In the parent-child hierarchy, return the first parent of type.
void remove()
Remove me from my parent's list of children.
QString name() const
const QVector< AbstractAspect * > & children() const
virtual QMenu * createContextMenu()
Return a new context menu.
T * child(int index, ChildIndexFlags flags={}) const
AbstractAspect * parentAspect() const
Return my parent Aspect or 0 if I currently don't have one.
void beginMacro(const QString &text)
Begin an undo stack macro (series of commands)
virtual QString path() const
Return the path that leads from the top-most Aspect (usually a Project) to me.
QVector< AbstractAspect * > children(AspectType type, ChildIndexFlags flags={}) const
void insertChildBefore(AbstractAspect *child, AbstractAspect *before)
Insert the given Aspect at a specific position in my list of children.
void endMacro()
End the current undo stack macro.
Second level container in a Worksheet for logical grouping.
Definition: AbstractPlot.h:41
Base class for all Worksheet children.
WorksheetElement(const QString &, AspectType)
static QPainterPath shapeFromPath(const QPainterPath &, const QPen &)
virtual bool isVisible() const =0
Return whether the element is (at least) partially visible.
void execMoveInFrontOf(QAction *)
virtual void setZValue(qreal)
virtual void loadThemeConfig(const KConfig &)
QMenu * m_moveInFrontOfMenu
QMenu * createContextMenu() override
Return a new context menu.
void execMoveBehind(QAction *)
virtual bool isFullyVisible() const
Return whether the element is fully visible (i.e., including all child elements).
virtual QGraphicsItem * graphicsItem() const =0
Return the graphics item representing this element.
~WorksheetElement() override
virtual void saveThemeConfig(const KConfig &)
QMenu * m_drawingOrderMenu
Top-level container for worksheet elements like plot, labels, etc.
Definition: Worksheet.h:46
#define i18n(m)
Definition: nsl_common.h:38