KReport

KReportDesignerSection.cpp
1/* This file is part of the KDE project
2 * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
3 * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
4 * Copyright (C) 2014 Jarosław Staniek <staniek@kde.org>
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
49class ReportResizeBar : public QFrame
50{
52public:
53 explicit ReportResizeBar(QWidget * parent = nullptr, Qt::WindowFlags f = nullptr);
54
56 void barDragged(int delta);
57
58protected:
59 void mouseMoveEvent(QMouseEvent * e) override;
60};
61
62//! @internal
63class KReportDesignerSectionTitle : public QLabel
64{
66public:
67 explicit KReportDesignerSectionTitle(QWidget *parent = nullptr);
68 ~KReportDesignerSectionTitle() override;
69
71 void clicked();
72
73protected:
74 void paintEvent(QPaintEvent* event) override;
75 void mousePressEvent(QMouseEvent *event) override;
76};
77
78//! @internal
79class Q_DECL_HIDDEN KReportDesignerSection::Private
80{
81public:
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
101KReportDesignerSection::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;
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
156KReportDesignerSection::~KReportDesignerSection()
157{
158 delete d;
159}
160
161void KReportDesignerSection::setTitle(const QString & s)
162{
163 d->title->setText(s);
164}
165
166void 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),
183 delta == 0 ? KProperty::ValueOption::IgnoreOld
184 : KProperty::ValueOption::None);
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
199void 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
271QSize 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
276void 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
306void KReportDesignerSection::slotSceneClicked()
307{
308 d->reportDesigner->setActiveScene(d->scene);
309 d->reportDesigner->changeSet(d->sectionData->propertySet());
310}
311
312void 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
340void KReportDesignerSection::setSectionCursor(const QCursor& c)
341{
342 if (d->sceneView)
343 d->sceneView->setCursor(c);
344}
345
346void 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//
371ReportResizeBar::ReportResizeBar(QWidget * parent, Qt::WindowFlags f)
372 : QFrame(parent, f)
373{
375 setFrameStyle(QFrame::HLine);
377}
378
379void ReportResizeBar::mouseMoveEvent(QMouseEvent * e)
380{
381 e->accept();
382 emit barDragged(e->y());
383}
384
385//=============================================================================
386
387KReportDesignerSectionTitle::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
394KReportDesignerSectionTitle::~KReportDesignerSectionTitle()
395{
396}
397
398//! \return true if \a o has parent \a par.
399static 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
408static 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
417void 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 }
446}
447
448void KReportDesignerSectionTitle::mousePressEvent(QMouseEvent *event)
449{
451 if (event->button() == Qt::LeftButton) {
452 emit clicked();
453 }
454}
455
456#include "KReportDesignerSection.moc"
QString iconName() const
QString name() const
KProperty & property(const QByteArray &name) const
void clearModifiedFlags()
QVariant value() const
QByteArray name() const
Base class for rectangular report items used within the designer GUI.
This class is the base to all Report Section's visual representation.
void initFromXML(const QDomNode &section)
QGraphicsItemList items() const
Return the items in the section Only return top-level items ... ie, items with no parent item because...
The ReportDesigner is the main widget for designing a report.
KReportUnit pageUnit() const
Return the current unit assigned to the report.
int pageWidthPx() const
Calculate the width of the page in pixels given the paper size, orientation, dpi and margin.
void setActiveScene(QGraphicsScene *scene)
Sets the active Scene.
void setModified(bool modified)
Sets the modified status, defaulting to true for modified.
QGraphicsScene * activeScene() const
void changeSet(KPropertySet *set)
Sets the property set for the currently selected item.
KPropertySet * propertySet() const
static void addMetaProperties(KPropertySet *set, const QString &classString, const QString &iconName)
Adds meta-properties to the property set set for consumption by property editor.
Base class for items that are drawn syncronously.
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.
An interface for plugins delivering KReport elements.
const KReportPluginMetaData * metaData() const
Manager class for finding and loading available plugins.
KReportSectionData is used to store the information about a specific report section.
KPropertySet * propertySet()
Returns property set for this section.
Converts between different units.
Definition KReportUnit.h:71
void update(Part *part, const QByteArray &data, qint64 dataSize)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QWidget * activeWindow()
QString name(NameFormat format) const const
void setAttribute(const QString &name, const QString &value)
QString tagName() const const
QDomNodeList childNodes() const const
QString nodeName() const const
QDomElement toElement() const const
int count() const const
QDomNode item(int index) const const
void accept()
virtual void paintEvent(QPaintEvent *) override
QGraphicsItem * parentItem() const const
void setVisible(bool visible)
void setBackgroundBrush(const QBrush &brush)
qreal height() const const
QList< QGraphicsItem * > items(Qt::SortOrder order) const const
void update(const QRectF &rect)
qreal width() const const
void resetCachedContent()
void addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment)
void setColumnStretch(int column, int stretch)
void setRowStretch(int row, int stretch)
virtual void setSpacing(int spacing) override
QIcon fromTheme(const QString &name)
virtual bool event(QEvent *e) override
virtual void mousePressEvent(QMouseEvent *ev) override
void setText(const QString &)
void setSizeConstraint(SizeConstraint)
iterator begin()
iterator end()
qsizetype size() const const
int y() const const
Q_OBJECTQ_OBJECT
Q_SIGNALSQ_SIGNALS
QObject * parent() const const
CompositionMode_SourceIn
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
QImage toImage() const const
qreal y() const const
int height() const const
qreal height() const const
QString mid(qsizetype position, qsizetype n) const const
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
AlignLeft
SizeVerCursor
LeftButton
Vertical
typedef WindowFlags
QTextStream & left(QTextStream &stream)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString() const const
T value() const const
void adjustSize()
void setCursor(const QCursor &)
QWidget * focusWidget() const const
QFontMetrics fontMetrics() const const
void setMinimumHeight(int minh)
void setMinimumWidth(int minw)
QWidget * parentWidget() const const
void repaint()
void setSizePolicy(QSizePolicy)
void update()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:21:31 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.