KReport

KReportDesignerSection.cpp
1 /* This file is part of the KDE project
2  * Copyright (C) 2001-2007 by OpenMFG, LLC ([email protected])
3  * Copyright (C) 2007-2008 by Adam Pigg ([email protected])
4  * Copyright (C) 2014 JarosÅ‚aw Staniek <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "KReportDesignerSection.h"
21 
22 #include "KReportDesignerSectionScene.h"
23 #include "KReportDesignerSectionView.h"
24 #include "KReportDesigner.h"
25 #include "KReportDesignerItemBase.h"
26 #include "KReportUtils.h"
27 #include "KReportPluginInterface.h"
28 #include "KReportPluginManager.h"
29 #include "KReportDesignerItemRectBase.h"
30 #include "KReportDesignerItemLine.h"
31 #include "KReportRuler_p.h"
32 #include "KReportZoomHandler_p.h"
33 #include "KReportUtils_p.h"
34 #include "KReportPluginMetaData.h"
35 #include "kreport_debug.h"
36 
37 #include <QLabel>
38 #include <QFrame>
39 #include <QDomDocument>
40 #include <QLayout>
41 #include <QGridLayout>
42 #include <QMouseEvent>
43 #include <QApplication>
44 #include <QApplication>
45 #include <QIcon>
46 
47 
48 //! @internal
49 class ReportResizeBar : public QFrame
50 {
51  Q_OBJECT
52 public:
53  explicit ReportResizeBar(QWidget * parent = nullptr, Qt::WindowFlags f = nullptr);
54 
55 Q_SIGNALS:
56  void barDragged(int delta);
57 
58 protected:
59  void mouseMoveEvent(QMouseEvent * e) override;
60 };
61 
62 //! @internal
63 class KReportDesignerSectionTitle : public QLabel
64 {
65  Q_OBJECT
66 public:
67  explicit KReportDesignerSectionTitle(QWidget *parent = nullptr);
68  ~KReportDesignerSectionTitle() override;
69 
70 Q_SIGNALS:
71  void clicked();
72 
73 protected:
74  void paintEvent(QPaintEvent* event) override;
75  void mousePressEvent(QMouseEvent *event) override;
76 };
77 
78 //! @internal
79 class Q_DECL_HIDDEN KReportDesignerSection::Private
80 {
81 public:
82  explicit Private()
83  {}
84 
85  ~Private()
86  {}
87 
88  KReportDesignerSectionTitle *title;
89  KReportDesignerSectionScene *scene;
90  ReportResizeBar *resizeBar;
91  KReportDesignerSectionView *sceneView;
92  KReportDesigner*reportDesigner;
93  KReportRuler *sectionRuler;
94 
95  KReportSectionData *sectionData;
96  int dpiY;
97  bool slotPropertyChangedEnabled = true;
98 };
99 
100 
101 KReportDesignerSection::KReportDesignerSection(KReportDesigner * rptdes,
102  const KReportZoomHandler &zoomHandler)
103  : QWidget(rptdes)
104  , d(new Private())
105 {
106  Q_ASSERT(rptdes);
107  d->sectionData = new KReportSectionData(this);
108  connect(d->sectionData->propertySet(), SIGNAL(propertyChanged(KPropertySet&,KProperty&)),
109  this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&)));
110 
111  d->dpiY = KReportPrivate::dpiY();
112 
113  d->reportDesigner = rptdes;
114  setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
115 
116  QGridLayout * glayout = new QGridLayout(this);
117  glayout->setSpacing(0);
118  glayout->setMargin(0);
119  glayout->setColumnStretch(1, 1);
120  glayout->setRowStretch(1, 1);
122 
123  // ok create the base interface
124  d->title = new KReportDesignerSectionTitle(this);
125  d->title->setObjectName(QLatin1String("detail"));
126  d->title->setText(tr("Detail"));
127 
128  d->sectionRuler = new KReportRuler(this, Qt::Vertical, zoomHandler);
129  d->sectionRuler->setUnit(d->reportDesigner->pageUnit());
130  d->scene = new KReportDesignerSectionScene(d->reportDesigner->pageWidthPx(), d->dpiY, rptdes);
131  d->scene->setBackgroundBrush(d->sectionData->backgroundColor());
132 
133  d->sceneView = new KReportDesignerSectionView(rptdes, d->scene, this);
134  d->sceneView->setObjectName(QLatin1String("scene view"));
135  d->sceneView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
136 
137  d->resizeBar = new ReportResizeBar(this);
138 
139  connect(d->resizeBar, SIGNAL(barDragged(int)), this, SLOT(slotResizeBarDragged(int)));
140  connect(d->reportDesigner, &KReportDesigner::pagePropertyChanged,
141  this, &KReportDesignerSection::slotPageOptionsChanged);
142  connect(d->scene, &KReportDesignerSectionScene::clicked, this, &KReportDesignerSection::slotSceneClicked);
143  connect(d->scene, SIGNAL(lostFocus()), d->title, SLOT(update()));
144  connect(d->title, &KReportDesignerSectionTitle::clicked, this, &KReportDesignerSection::slotSceneClicked);
145 
146  glayout->addWidget(d->title, 0, 0, 1, 2);
147  glayout->addWidget(d->sectionRuler, 1, 0);
148  glayout->addWidget(d->sceneView , 1, 1);
149  glayout->addWidget(d->resizeBar, 2, 0, 1, 2);
150  d->sectionRuler->setFixedWidth(d->sectionRuler->sizeHint().width());
151 
152  setLayout(glayout);
153  slotResizeBarDragged(0);
154 }
155 
156 KReportDesignerSection::~KReportDesignerSection()
157 {
158  delete d;
159 }
160 
161 void KReportDesignerSection::setTitle(const QString & s)
162 {
163  d->title->setText(s);
164 }
165 
166 void KReportDesignerSection::slotResizeBarDragged(int delta, bool changeSet)
167 {
168  if (d->sceneView->designer() && d->sceneView->designer()->propertySet()->property("page-size").value().toString() == QLatin1String("Labels")) {
169  return; // we don't want to allow this on reports that are for labels
170  }
171 
172  if (changeSet) {
173  slotSceneClicked(); // switches property set to this section
174  }
175 
176  qreal h = d->scene->height() + delta;
177 
178  if (h < 1) h = 1;
179 
180  h = d->scene->gridPoint(QPointF(0, h)).y();
181  d->slotPropertyChangedEnabled = false; // reduce updates
182  d->sectionData->setHeight(INCH_TO_POINT(h / d->dpiY),
185  d->slotPropertyChangedEnabled = true;
186  d->sectionRuler->setRulerLength(h);
187 
188  const QRect newSceneRect(0, 0, d->scene->width(), h);
189  if (d->scene->sceneRect() != newSceneRect) {
190  d->scene->setSceneRect(newSceneRect);
191  }
192  d->sceneView->resizeContents(newSceneRect.size());
193 
194  if (delta != 0) {
195  d->reportDesigner->setModified(true);
196  }
197 }
198 
199 void KReportDesignerSection::buildXML(QDomDocument *doc, QDomElement *section)
200 {
201  KReportUtils::setAttribute(section, QLatin1String("svg:height"), d->sectionData->height());
202  section->setAttribute(QLatin1String("fo:background-color"), d->sectionData->backgroundColor().name());
203 
204  // now get a list of all the QGraphicsItems on this scene and output them.
205  QGraphicsItemList list = d->scene->items();
207  it != list.end(); ++it) {
208  KReportDesignerItemBase::buildXML((*it), doc, section);
209  }
210 }
211 
213 {
214  QDomNodeList nl = section.childNodes();
215  QDomNode node;
216  QString n;
217 
218  qreal ptHeight = KReportUtils::readSizeAttributes(section.toElement(), QSizeF(DEFAULT_SECTION_SIZE_PT, DEFAULT_SECTION_SIZE_PT)).height();
219  d->sectionData->setHeight(ptHeight);
220 
221  qreal h = POINT_TO_INCH(ptHeight) * d->dpiY;
222  //kreportDebug() << "Section Height: " << h;
223  d->scene->setSceneRect(0, 0, d->scene->width(), h);
224  slotResizeBarDragged(0);
225  d->sectionData->setBackgroundColor(KReportUtils::attr(
226  section.toElement(), QLatin1String("fo:background-color"), QColor(Qt::white)));
227  d->sectionData->propertySet()->clearModifiedFlags();
228 
229  KReportPluginManager* manager = KReportPluginManager::self();
230  for (int i = 0; i < nl.count(); ++i) {
231  node = nl.item(i);
232  n = node.nodeName();
233  QObject *obj = nullptr;
234  if (n.startsWith(QLatin1String("report:"))) {
235  //Load objects
236  //report:line is a special case as it is not a plugin
237  KReportPluginInterface *plugin = nullptr;
238  QString reportItemName = n.mid(qstrlen("report:"));
239  if (reportItemName == QLatin1String("line")) {
240  obj = new KReportDesignerItemLine(node, d->sceneView->designer(), d->scene);
241  } else {
242  plugin = manager->plugin(reportItemName);
243  if (plugin) {
244  obj = plugin->createDesignerInstance(node, d->reportDesigner, d->scene);
245  }
246  }
247  if (obj) {
248  KReportDesignerItemRectBase *entity = dynamic_cast<KReportDesignerItemRectBase*>(obj);
249  if (entity) {
250  entity->setVisible(true);
251  }
252  KReportItemBase *item = dynamic_cast<KReportItemBase*>(obj);
253  if (item) {
254  item->setUnit(d->reportDesigner->pageUnit());
255  if (plugin) {
256  KReportDesigner::addMetaProperties(item->propertySet(),
257  plugin->metaData()->name(),
258  plugin->metaData()->iconName());
259  }
260  item->propertySet()->clearModifiedFlags();
261  }
262  }
263  }
264  if (!obj) {
265  kreportWarning() << "Unknown element" << n << "while parsing section"
266  << section.toElement().tagName();
267  }
268  }
269 }
270 
271 QSize KReportDesignerSection::sizeHint() const
272 {
273  return QSize(d->scene->width() + d->sectionRuler->frameSize().width(), d->title->frameSize().height() + d->sceneView->sizeHint().height() + d->resizeBar->frameSize().height());
274 }
275 
276 void KReportDesignerSection::slotPageOptionsChanged(KPropertySet &set)
277 {
278  Q_UNUSED(set)
279 
280  KReportUnit unit = d->reportDesigner->pageUnit();
281  d->sectionData->setUnit(unit);
282 
283  //update items position with unit
284  QList<QGraphicsItem*> itms = d->scene->items();
285  for (int i = 0; i < itms.size(); ++i) {
286  KReportItemBase *obj = dynamic_cast<KReportItemBase*>(itms[i]);
287  if (obj) {
288  obj->setUnit(unit);
289  }
290  }
291 
292  d->scene->setSceneRect(0, 0, d->reportDesigner->pageWidthPx(), d->scene->height());
293  d->title->setMinimumWidth(d->reportDesigner->pageWidthPx() + d->sectionRuler->frameSize().width());
294  d->sectionRuler->setUnit(d->reportDesigner->pageUnit());
295 
296  //Trigger a redraw of the background
297  d->sceneView->resizeContents(QSize(d->scene->width(), d->scene->height()));
298 
299  d->sceneView->resetCachedContent();
300  d->sceneView->update();
301 
302  d->reportDesigner->adjustSize();
303  d->reportDesigner->repaint();
304 }
305 
306 void KReportDesignerSection::slotSceneClicked()
307 {
308  d->reportDesigner->setActiveScene(d->scene);
309  d->reportDesigner->changeSet(d->sectionData->propertySet());
310 }
311 
312 void KReportDesignerSection::slotPropertyChanged(KPropertySet &s, KProperty &p)
313 {
314  Q_UNUSED(s)
315  if (!d->slotPropertyChangedEnabled) {
316  return;
317  }
318  //kreportDebug() << p.name();
319 
320  //Handle Background Color
321  if (p.name() == "background-color") {
322  d->scene->setBackgroundBrush(p.value().value<QColor>());
323  }
324 
325  if (p.name() == "height") {
326  const QRect newSceneRect(0, 0, d->scene->width(), POINT_TO_INCH(d->sectionData->height()) * d->dpiY);
327  if (d->scene->sceneRect() != newSceneRect) {
328  d->scene->setSceneRect(newSceneRect);
329  }
330  d->sceneView->resizeContents(newSceneRect.size());
331  }
332 
333  if (d->reportDesigner)
334  d->reportDesigner->setModified(true);
335 
336  d->sceneView->resetCachedContent();
337  d->scene->update();
338 }
339 
340 void KReportDesignerSection::setSectionCursor(const QCursor& c)
341 {
342  if (d->sceneView)
343  d->sceneView->setCursor(c);
344 }
345 
346 void KReportDesignerSection::unsetSectionCursor()
347 {
348  if (d->sceneView)
349  d->sceneView->unsetCursor();
350 }
351 
353 {
355 
356  if (d->scene) {
357  foreach (QGraphicsItem *itm, d->scene->items()) {
358  if (itm->parentItem() == nullptr) {
359  items << itm;
360  }
361  }
362  }
363 
364  return items;
365 }
366 
367 
368 //
369 // class ReportResizeBar
370 //
371 ReportResizeBar::ReportResizeBar(QWidget * parent, Qt::WindowFlags f)
372  : QFrame(parent, f)
373 {
375  setFrameStyle(QFrame::HLine);
377 }
378 
379 void ReportResizeBar::mouseMoveEvent(QMouseEvent * e)
380 {
381  e->accept();
382  emit barDragged(e->y());
383 }
384 
385 //=============================================================================
386 
387 KReportDesignerSectionTitle::KReportDesignerSectionTitle(QWidget*parent) : QLabel(parent)
388 {
390  setAlignment(Qt::AlignLeft | Qt::AlignTop);
391  setMinimumHeight(qMax(fontMetrics().lineSpacing(),16 + 2)); //16 = Small icon size
392 }
393 
394 KReportDesignerSectionTitle::~KReportDesignerSectionTitle()
395 {
396 }
397 
398 //! \return true if \a o has parent \a par.
399 static bool hasParent(QObject* par, QObject* o)
400 {
401  if (!o || !par)
402  return false;
403  while (o && o != par)
404  o = o->parent();
405  return o == par;
406 }
407 
408 static void replaceColors(QPixmap* original, const QColor& color)
409 {
410  QImage dest(original->toImage());
411  QPainter p(&dest);
412  p.setCompositionMode(QPainter::CompositionMode_SourceIn);
413  p.fillRect(dest.rect(), color);
414  *original = QPixmap::fromImage(dest);
415 }
416 
417 void KReportDesignerSectionTitle::paintEvent(QPaintEvent * event)
418 {
419  QPainter painter(this);
420  KReportDesignerSection* section = dynamic_cast<KReportDesignerSection*>(parent());
421  if (section) {
422  const bool current = section->d->scene == section->d->reportDesigner->activeScene();
424  QWidget *activeWindow = QApplication::activeWindow();
425  if (activeWindow) {
426  QWidget *par = activeWindow->focusWidget();
427  if (qobject_cast<KReportDesignerSectionView*>(par)) {
428  par = par->parentWidget(); // we're close, pick common parent
429  }
430  if (hasParent(par, this)) {
431  cg = QPalette::Active;
432  }
433  }
434  if (current) {
435  painter.fillRect(rect(), palette().brush(cg, QPalette::Highlight));
436  }
437  painter.setPen(palette().color(cg, current ? QPalette::HighlightedText : QPalette::WindowText));
438  QPixmap pixmap(QIcon::fromTheme(QLatin1String("arrow-down")).pixmap(16,16));
439  replaceColors(&pixmap, painter.pen().color());
440  const int left = 25;
441  painter.drawPixmap(QPoint(left, (height() - pixmap.height()) / 2), pixmap);
442 
443  painter.drawText(rect().adjusted(left + pixmap.width() + 4, 0, 0, 0), Qt::AlignLeft | Qt::AlignVCenter, text());
444  }
445  QFrame::paintEvent(event);
446 }
447 
448 void KReportDesignerSectionTitle::mousePressEvent(QMouseEvent *event)
449 {
451  if (event->button() == Qt::LeftButton) {
452  emit clicked();
453  }
454 }
455 
456 #include "KReportDesignerSection.moc"
Q_OBJECTQ_OBJECT
QByteArray name() const
Base class for items that are drawn syncronously.
QGraphicsItem * parentItem() const const
This class is the base to all Report Section's visual representation.
AlignLeft
int count() const const
qreal height() const const
Converts between different units.
Definition: KReportUnit.h:70
QGraphicsItemList items() const
Return the items in the section Only return top-level items ...
QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags)
QDomElement toElement() const const
QFontMetrics fontMetrics() const const
void setSizePolicy(QSizePolicy)
virtual void setUnit(const KReportUnit &u)
Sets unit to a and converts values of position and size property from the old unit to new if needed.
QString tagName() const const
void update(const QRectF &rect)
void setMargin(int margin)
T value() const const
QTextStream & left(QTextStream &stream)
static void addMetaProperties(KPropertySet *set, const QString &classString, const QString &iconName)
Adds meta-properties to the property set set for consumption by property editor.
QIcon fromTheme(const QString &name)
QWidget * activeWindow()
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
LeftButton
KReportSectionData is used to store the information about a specific report section.
Manager class for finding and loading available plugins.
QWidget * focusWidget() const const
QString iconName() const
void setRowStretch(int row, int stretch)
void setAttribute(const QString &name, const QString &value)
typedef WindowFlags
int size() const const
void setColumnStretch(int column, int stretch)
QDomNode item(int index) const const
virtual void mousePressEvent(QMouseEvent *ev) override
const KReportPluginMetaData * metaData() const
void initFromXML(const QDomNode &section)
QString name() const
Vertical
SizeVerCursor
int y() const const
void setSpacing(int spacing)
QDomNodeList childNodes() const const
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
virtual void paintEvent(QPaintEvent *) override
QImage toImage() const const
QString nodeName() const const
Q_SIGNALSQ_SIGNALS
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
void setMinimumHeight(int minh)
void setSizeConstraint(QLayout::SizeConstraint)
void setVisible(bool visible)
virtual void paintEvent(QPaintEvent *) override
Base class for rectangular report items used within the designer GUI.
QVariant value() const
void addWidget(QWidget *widget, int row, int column, Qt::Alignment alignment)
QList::iterator begin()
void clearModifiedFlags()
The ReportDesigner is the main widget for designing a report.
QList::iterator end()
CompositionMode_SourceIn
virtual void mouseMoveEvent(QMouseEvent *event)
QString mid(int position, int n) const const
QWidget * parentWidget() const const
QObject * parent() const const
void setCursor(const QCursor &)
void accept()
An interface for plugins delivering KReport elements.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:04:11 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.