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)  

WorksheetElementContainer.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  File : WorksheetElementContainer.cpp
3  Project : LabPlot
4  Description : Worksheet element container - parent of multiple elements
5  --------------------------------------------------------------------
6  Copyright : (C) 2009 Tilman Benkert (thzs@gmx.net)
7  Copyright : (C) 2012-2015 by Alexander Semke (alexander.semke@web.de)
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  * This program is distributed in the hope that it will be useful, *
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
20  * GNU General Public License for more details. *
21  * *
22  * You should have received a copy of the GNU General Public License *
23  * along with this program; if not, write to the Free Software *
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
25  * Boston, MA 02110-1301 USA *
26  * *
27  ***************************************************************************/
28 
34 #include "backend/lib/macros.h"
35 #include "backend/lib/trace.h"
36 
37 #include <QGraphicsScene>
38 #include <QGraphicsSceneContextMenuEvent>
39 #include <QMenu>
40 #include <QPainter>
41 
42 #include <KLocalizedString>
43 
44 /**
45  * \class WorksheetElementContainer
46  * \ingroup worksheet
47  * \brief Worksheet element container - parent of multiple elements
48  * This class provides the functionality for a containers of multiple
49  * worksheet elements. Such a container can be a plot or group of elements.
50  */
51 
53  : WorksheetElement(name, type), d_ptr(new WorksheetElementContainerPrivate(this)) {
54 
56 }
57 
59  : WorksheetElement(name, type), d_ptr(dd) {
60 
62 }
63 
64 //no need to delete the d-pointer here - it inherits from QGraphicsItem
65 //and is deleted during the cleanup in QGraphicsScene
67 
69  return const_cast<QGraphicsItem*>(static_cast<const QGraphicsItem*>(d_ptr));
70 }
71 
73  Q_D(const WorksheetElementContainer);
74  return d->rect;
75 }
76 
77 STD_SWAP_METHOD_SETTER_CMD_IMPL(WorksheetElementContainer, SetVisible, bool, swapVisible)
78 void WorksheetElementContainer::setVisible(bool on) {
80 
81  //take care of proper ordering on the undo-stack,
82  //when making the container and all its children visible/invisible.
83  //if visible is set true, change the visibility of the container first
84  if (on) {
85  beginMacro( i18n("%1: set visible", name()) );
86  exec( new WorksheetElementContainerSetVisibleCmd(d, on, ki18n("%1: set visible")) );
87  } else
88  beginMacro( i18n("%1: set invisible", name()) );
89 
90  //change the visibility of all children
92  for (auto* elem : childList) {
93  auto* curve = dynamic_cast<XYCurve*>(elem);
94  if (curve) {
95  //making curves invisible triggers the recalculation of plot ranges if auto-scale is active.
96  //this needs to avoided by supressing the retransformation in the curves.
97  curve->suppressRetransform(true);
98  elem->setVisible(on);
99  curve->suppressRetransform(false);
100  } else if (elem)
101  elem->setVisible(on);
102  }
103 
104  //if visible is set false, change the visibility of the container last
105  if (!on)
106  exec(new WorksheetElementContainerSetVisibleCmd(d, false, ki18n("%1: set invisible")));
107 
108  endMacro();
109 }
110 
112  Q_D(const WorksheetElementContainer);
113  return d->isVisible();
114 }
115 
118  for (const auto* elem : childList) {
119  if (!elem->isVisible())
120  return false;
121  }
122  return true;
123 }
124 
127  d->m_printing = on;
128 }
129 
131 // if (isLoading())
132 // return;
133 
134  PERFTRACE("WorksheetElementContainer::retransform()");
136 
138  for (auto* child : childList)
139  child->retransform();
140 
141  d->recalcShapeAndBoundingRect();
142 }
143 
144 /*!
145  * called if the size of the worksheet page was changed and the content has to be adjusted/resized (\c pageResize = true)
146  * or if a new rectangular for the element container was set (\c pageResize = false).
147  * In the second case, \c WorksheetElement::handleResize() is called for every worksheet child to adjuste the content to the new size.
148  * In the first case, a new rectangular for the container is calculated and set first, which on the other hand, triggers the content adjustments
149  * in the container children.
150  */
151 void WorksheetElementContainer::handleResize(double horizontalRatio, double verticalRatio, bool pageResize) {
152  DEBUG("WorksheetElementContainer::handleResize()");
153  Q_D(const WorksheetElementContainer);
154  if (pageResize) {
155  QRectF rect(d->rect);
156  rect.setWidth(d->rect.width()*horizontalRatio);
157  rect.setHeight(d->rect.height()*verticalRatio);
158  setRect(rect);
159  } else {
160 // for (auto* elem : children<WorksheetElement>(IncludeHidden))
161 // elem->handleResize(horizontalRatio, verticalRatio);
162  }
163 }
164 
167 
168  const auto* element = qobject_cast<const WorksheetElement*>(aspect);
169  if (element && (aspect->parentAspect() == this)) {
172  element->graphicsItem()->setParentItem(d);
173 
174  qreal zVal = 0;
175  for (auto* child : children<WorksheetElement>(ChildIndexFlag::IncludeHidden))
176  child->setZValue(zVal++);
177  }
178 
179  if (!isLoading())
180  d->recalcShapeAndBoundingRect();
181 }
182 
185  if (!d->isSelected()) {
186  if (d->m_hovered)
187  d->m_hovered = false;
188  d->update();
189  }
190 }
191 
194  if (!d->isSelected()) {
195  d->m_hovered = true;
196  d->update();
197  }
198 }
199 
202  d->prepareGeometryChangeRequested();
203 }
204 
205 //################################################################
206 //################### Private implementation ##########################
207 //################################################################
209  setAcceptHoverEvents(true);
210 }
211 
213  return q->name();
214 }
215 
216 void WorksheetElementContainerPrivate::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
217  scene()->clearSelection();
218  setSelected(true);
219  QMenu* menu = q->createContextMenu();
220  menu->exec(event->screenPos());
221 }
222 
223 void WorksheetElementContainerPrivate::hoverEnterEvent(QGraphicsSceneHoverEvent*) {
224  if (!isSelected()) {
225  m_hovered = true;
226  update();
227  }
228 }
229 
230 void WorksheetElementContainerPrivate::hoverLeaveEvent(QGraphicsSceneHoverEvent*) {
231  if (m_hovered) {
232  m_hovered = false;
233  update();
234  }
235 }
236 
238  bool oldValue = isVisible();
239 
240  //When making a graphics item invisible, it gets deselected in the scene.
241  //In this case we don't want to deselect the item in the project explorer.
242  //We need to supress the deselection in the view.
243  auto* worksheet = static_cast<Worksheet*>(q->parent(AspectType::Worksheet));
244  worksheet->suppressSelectionChangedEvent(true);
245  setVisible(on);
246  emit q->visibleChanged(on);
247  worksheet->suppressSelectionChangedEvent(false);
248 
249  return oldValue;
250 }
251 
253  prepareGeometryChange();
255 }
256 
258 // if (q->isLoading())
259 // return;
260 
261  //old logic calculating the bounding box as as the box covering all children.
262  //we might need this logic later once we implement something like selection of multiple plots, etc.
263 // boundingRectangle = QRectF();
264 // QVector<WorksheetElement*> childList = q->children<WorksheetElement>(AbstractAspect::IncludeHidden | AbstractAspect::Compress);
265 // foreach (const WorksheetElement* elem, childList)
266 // boundingRectangle |= elem->graphicsItem()->mapRectToParent(elem->graphicsItem()->boundingRect());
267 //
268  float penWidth = 2.;
269  boundingRectangle = q->rect();
270  boundingRectangle = QRectF(-boundingRectangle.width()/2 - penWidth / 2, -boundingRectangle.height()/2 - penWidth / 2,
271  boundingRectangle.width() + penWidth, boundingRectangle.height() + penWidth);
272 
273  QPainterPath path;
274  path.addRect(boundingRectangle);
275 
276  //make the shape somewhat thicker then the hoveredPen to make the selection/hovering box more visible
277  containerShape = QPainterPath();
278  containerShape.addPath(WorksheetElement::shapeFromPath(path, QPen(QBrush(), penWidth)));
279 }
280 
281 // Inherited from QGraphicsItem
283  return boundingRectangle;
284 }
285 
286 // Inherited from QGraphicsItem
287 void WorksheetElementContainerPrivate::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) {
288  Q_UNUSED(option)
289  Q_UNUSED(widget)
290 
291  if (!isVisible())
292  return;
293 
294  if (m_hovered && !isSelected() && !m_printing) {
295  painter->setPen(QPen(QApplication::palette().color(QPalette::Shadow), 2, Qt::SolidLine));
296  painter->drawPath(containerShape);
297  }
298 
299  if (isSelected() && !m_printing) {
300  painter->setPen(QPen(QApplication::palette().color(QPalette::Highlight), 2, Qt::SolidLine));
301  painter->drawPath(containerShape);
302  }
303 }
AspectType
Base class of all persistent objects in a Project.
void aspectAdded(const AbstractAspect *)
Emitted after a new Aspect has been added to the tree.
@ IncludeHidden
Include aspects marked as "hidden" in numbering or listing children.
@ Compress
Remove all null pointers from the result list.
AbstractAspect * parent(AspectType type) const
In the parent-child hierarchy, return the first parent of type.
QString name() const
T * child(int index, ChildIndexFlags flags={}) const
AbstractAspect * parentAspect() const
Return my parent Aspect or 0 if I currently don't have one.
bool isLoading() const
AbstractAspectPrivate * d
WorksheetElementContainerPrivate(WorksheetElementContainer *)
void hoverEnterEvent(QGraphicsSceneHoverEvent *) override
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *widget=nullptr) override
void hoverLeaveEvent(QGraphicsSceneHoverEvent *) override
void contextMenuEvent(QGraphicsSceneContextMenuEvent *) override
Worksheet element container - parent of multiple elements This class provides the functionality for a...
virtual void handleAspectAdded(const AbstractAspect *)
WorksheetElementContainerPrivate *const d_ptr
bool isVisible() const override
Return whether the element is (at least) partially visible.
void handleResize(double horizontalRatio, double verticalRatio, bool pageResize=false) override
WorksheetElementContainer(const QString &, AspectType)
void setPrinting(bool) override
Switches the printing mode on/off.
bool isFullyVisible() const override
Return whether the element is fully visible (i.e., including all child elements).
~WorksheetElementContainer() override
virtual void setRect(const QRectF &)=0
QGraphicsItem * graphicsItem() const override
Return the graphics item representing this element.
Base class for all Worksheet children.
static QPainterPath shapeFromPath(const QPainterPath &, const QPen &)
QMenu * createContextMenu() override
Return a new context menu.
Top-level container for worksheet elements like plot, labels, etc.
Definition: Worksheet.h:46
void suppressSelectionChangedEvent(bool)
Definition: Worksheet.cpp:408
A 2D-curve, provides an interface for editing many properties of the curve.
Definition: XYCurve.h:46
void suppressRetransform(bool)
Definition: XYCurve.cpp:752
#define DEBUG(x)
Definition: macros.h:50
#define STD_SWAP_METHOD_SETTER_CMD_IMPL(class_name, cmd_name, value_type, method_name)
Definition: macros.h:250
@ Shadow
Definition: OriginObj.h:71
#define i18n(m)
Definition: nsl_common.h:38
#define PERFTRACE(msg)
Definition: trace.h:57