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();
206 for (QGraphicsItemList::iterator it = list.begin();
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
352QGraphicsItemList KReportDesignerSection::items() const
353{
354 QGraphicsItemList items;
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();
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
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.
QGraphicsScene * activeScene() 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.
void update(Part *part, const QByteArray &data, qint64 dataSize)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QWidget * activeWindow()
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
QGraphicsScene * scene() const const
void setVisible(bool visible)
QList< QGraphicsItem * > items(Qt::SortOrder order) const const
qreal width() const const
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 void mousePressEvent(QMouseEvent *ev) override
void setSizeConstraint(SizeConstraint)
iterator begin()
iterator end()
qsizetype size() const const
int y() const const
QObject(QObject *parent)
Q_OBJECTQ_OBJECT
Q_SIGNALSQ_SIGNALS
virtual bool event(QEvent *e)
QObject * parent() const const
T qobject_cast(QObject *object)
CompositionMode_SourceIn
QPixmap fromImage(QImage &&image, Qt::ImageConversionFlags flags)
QImage toImage() const const
int 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)
T value() const const
QWidget(QWidget *parent, Qt::WindowFlags f)
void setCursor(const QCursor &)
QWidget * focusWidget() const const
QFontMetrics fontMetrics() const const
void setMinimumHeight(int minh)
QWidget * parentWidget() const const
void setSizePolicy(QSizePolicy)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Jan 24 2025 11:54:26 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.