KReport

KReportSectionEditor.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) 2012 by Friedrich W. H. Kossebau (kossebau@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 "KReportSectionEditor.h"
21
22#include "KReportDesigner.h"
23#include "KReportSection.h"
24#include "KReportDesignerSectionDetail.h"
25#include "KReportDetailGroupSectionDialog.h"
26#include "KReportDesignerSectionDetailGroup.h"
27
28#include <QIcon>
29#include <QDialogButtonBox>
30#include <QVBoxLayout>
31#include <QPushButton>
32
33enum {
34 KeyRole = Qt::UserRole
35};
36
37// KReportDesigner currently prepends an empty key/fieldname pair to the list
38// of fields, possibly to offer the option to have report elements not yet
39// bound to fields
40static inline bool isEditorHelperField(const QString &key)
41{
42 return key.isEmpty();
43}
44
45/*
46 * Constructs a SectionEditor as a child of 'parent'.
47 *
48 * The dialog will by default be modeless, unless you set 'modal' to
49 * true to construct a modal dialog.
50 */
51KReportSectionEditor::KReportSectionEditor(KReportDesigner* designer)
52 : QDialog(designer)
53{
54 Q_ASSERT(designer);
55 m_reportDesigner = designer;
56 m_reportSectionDetail = m_reportDesigner->detailSection();
57
58 //! @todo check section editor
59 //setButtons(Close);
60 //setCaption(tr("Section Editor"));
61
63 QVBoxLayout* mainLayout = new QVBoxLayout(this);
64 QPushButton* closeButton = buttonBox->button(QDialogButtonBox::Close);
65
66 closeButton->setDefault(true);
67 closeButton->setShortcut(Qt::CTRL | Qt::Key_Return);
68 connect(buttonBox, SIGNAL(rejected()), this, SLOT(accept()));
69
70 QWidget *widget = new QWidget(this);
71 m_ui.setupUi(widget);
72 m_btnAdd = new QPushButton(QIcon::fromTheme(QLatin1String("list-add")), tr("Add..."), this);
73 m_ui.lGroupSectionsButtons->addWidget(m_btnAdd);
74 m_btnEdit = new QPushButton(QIcon::fromTheme(QLatin1String("document-edit")), tr("Edit..."), this);
75 m_ui.lGroupSectionsButtons->addWidget(m_btnEdit);
76 m_btnRemove = new QPushButton(QIcon::fromTheme(QLatin1String("list-remove")), tr("Delete"), this);
77 m_ui.lGroupSectionsButtons->addWidget(m_btnRemove);
78 m_btnMoveUp = new QPushButton(QIcon::fromTheme(QLatin1String("arrow-up")), tr("Move Up"), this);
79 m_ui.lGroupSectionsButtons->addWidget(m_btnMoveUp);
80 m_btnMoveDown = new QPushButton(QIcon::fromTheme(QLatin1String("arrow-down")), tr("Move Down"), this);
81 m_ui.lGroupSectionsButtons->addWidget(m_btnMoveDown);
82 m_ui.lGroupSectionsButtons->addStretch();
83
84 mainLayout->addWidget(widget);
85 mainLayout->addWidget(buttonBox);
86
87 //setMainWidget(widget);
88
89 // signals and slots connections
90 connect(m_ui.cbReportHeader, SIGNAL(toggled(bool)), this, SLOT(cbReportHeader_toggled(bool)));
91 connect(m_ui.cbReportFooter, SIGNAL(toggled(bool)), this, SLOT(cbReportFooter_toggled(bool)));
92 connect(m_ui.cbHeadFirst, SIGNAL(toggled(bool)), this, SLOT(cbHeadFirst_toggled(bool)));
93 connect(m_ui.cbHeadLast, SIGNAL(toggled(bool)), this, SLOT(cbHeadLast_toggled(bool)));
94 connect(m_ui.cbHeadEven, SIGNAL(toggled(bool)), this, SLOT(cbHeadEven_toggled(bool)));
95 connect(m_ui.cbHeadOdd, SIGNAL(toggled(bool)), this, SLOT(cbHeadOdd_toggled(bool)));
96 connect(m_ui.cbFootFirst, SIGNAL(toggled(bool)), this, SLOT(cbFootFirst_toggled(bool)));
97 connect(m_ui.cbFootLast, SIGNAL(toggled(bool)), this, SLOT(cbFootLast_toggled(bool)));
98 connect(m_ui.cbFootEven, SIGNAL(toggled(bool)), this, SLOT(cbFootEven_toggled(bool)));
99 connect(m_ui.cbFootOdd, SIGNAL(toggled(bool)), this, SLOT(cbFootOdd_toggled(bool)));
100 connect(m_ui.cbHeadAny, SIGNAL(toggled(bool)), this, SLOT(cbHeadAny_toggled(bool)));
101 connect(m_ui.cbFootAny, SIGNAL(toggled(bool)), this, SLOT(cbFootAny_toggled(bool)));
102 connect(m_ui.lbGroups, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
103 this, SLOT(updateButtonsForItem(QListWidgetItem*)));
104 connect(m_ui.lbGroups, SIGNAL(currentRowChanged(int)),
105 this, SLOT(updateButtonsForRow(int)));
106
107 connect(m_btnAdd, SIGNAL(clicked(bool)), this, SLOT(btnAdd_clicked()));
108 connect(m_btnEdit, SIGNAL(clicked(bool)), this, SLOT(btnEdit_clicked()));
109 connect(m_btnRemove, SIGNAL(clicked(bool)), this, SLOT(btnRemove_clicked()));
110 connect(m_btnMoveUp, SIGNAL(clicked(bool)), this, SLOT(btnMoveUp_clicked()));
111 connect(m_btnMoveDown, SIGNAL(clicked(bool)), this, SLOT(brnMoveDown_clicked()));
112
113 // set all the properties
114
115 m_ui.cbReportHeader->setChecked(m_reportDesigner->section(KReportSectionData::Type::ReportHeader));
116 m_ui.cbReportFooter->setChecked(m_reportDesigner->section(KReportSectionData::Type::ReportFooter));
117
118 m_ui.cbHeadFirst->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderFirst));
119 m_ui.cbHeadOdd->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderOdd));
120 m_ui.cbHeadEven->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderEven));
121 m_ui.cbHeadLast->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderLast));
122 m_ui.cbHeadAny->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderAny));
123
124 m_ui.cbFootFirst->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterFirst));
125 m_ui.cbFootOdd->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterOdd));
126 m_ui.cbFootEven->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterEven));
127 m_ui.cbFootLast->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterLast));
128 m_ui.cbFootAny->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterAny));
129
130 // now set the rw value
131 if (m_reportSectionDetail) {
132 const QStringList columnNames = m_reportDesigner->fieldNames();
133 const QStringList keys = m_reportDesigner->fieldKeys();
134 for (int i = 0; i < m_reportSectionDetail->groupSectionCount(); ++i) {
135 const QString key = m_reportSectionDetail->groupSection(i)->column();
136 const int idx = keys.indexOf(key);
137 const QString columnName = columnNames.value(idx);
138 QListWidgetItem *item = new QListWidgetItem(columnName);
139 item->setData(KeyRole, key);
140 m_ui.lbGroups->addItem(item);
141 }
142 }
143 if (m_ui.lbGroups->count() == 0) {
144 } else {
145 m_ui.lbGroups->setCurrentItem(m_ui.lbGroups->item(0));
146 }
147 updateButtonsForItem(m_ui.lbGroups->currentItem());
148 updateAddButton();
149 updateButtonsForRow(m_ui.lbGroups->currentRow());
150}
151
152/*
153 * Destroys the object and frees any allocated resources
154 */
155KReportSectionEditor::~KReportSectionEditor()
156{
157 // no need to delete child widgets, Qt does it all for us
158}
159
160void KReportSectionEditor::cbReportHeader_toggled(bool yes)
161{
162 if (m_reportDesigner) {
163 if (yes) {
164 m_reportDesigner->insertSection(KReportSectionData::Type::ReportHeader);
165 } else {
166 m_reportDesigner->removeSection(KReportSectionData::Type::ReportHeader);
167 }
168 }
169
170}
171
172void KReportSectionEditor::cbReportFooter_toggled(bool yes)
173{
174 if (m_reportDesigner) {
175 if (yes) {
176 m_reportDesigner->insertSection(KReportSectionData::Type::ReportFooter);
177 } else {
178 m_reportDesigner->removeSection(KReportSectionData::Type::ReportFooter);
179 }
180 }
181
182}
183
184void KReportSectionEditor::cbHeadFirst_toggled(bool yes)
185{
186 if (m_reportDesigner) {
187 if (yes) {
188 m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderFirst);
189 } else {
190 m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderFirst);
191 }
192 }
193
194}
195
196void KReportSectionEditor::cbHeadLast_toggled(bool yes)
197{
198 if (m_reportDesigner) {
199 if (yes) {
200 m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderLast);
201 } else {
202 m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderLast);
203 }
204 }
205
206}
207
208void KReportSectionEditor::cbHeadEven_toggled(bool yes)
209{
210 if (m_reportDesigner) {
211 if (yes) {
212 m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderEven);
213 } else {
214 m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderEven);
215 }
216 }
217
218}
219
220void KReportSectionEditor::cbHeadOdd_toggled(bool yes)
221{
222 if (m_reportDesigner) {
223 if (yes) {
224 m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderOdd);
225 } else {
226 m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderOdd);
227 }
228 }
229
230}
231
232void KReportSectionEditor::cbFootFirst_toggled(bool yes)
233{
234 if (m_reportDesigner) {
235 if (yes) {
236 m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterFirst);
237 } else {
238 m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterFirst);
239 }
240 }
241
242}
243
244void KReportSectionEditor::cbFootLast_toggled(bool yes)
245{
246 if (m_reportDesigner) {
247 if (yes) {
248 m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterLast);
249 } else {
250 m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterLast);
251 }
252 }
253
254}
255
256void KReportSectionEditor::cbFootEven_toggled(bool yes)
257{
258 if (m_reportDesigner) {
259 if (yes) {
260 m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterEven);
261 } else {
262 m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterEven);
263 }
264 }
265
266}
267
268void KReportSectionEditor::cbFootOdd_toggled(bool yes)
269{
270 if (m_reportDesigner) {
271 if (yes) {
272 m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterOdd);
273 } else {
274 m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterOdd);
275 }
276 }
277
278}
279
280bool KReportSectionEditor::editDetailGroup(KReportDesignerSectionDetailGroup * rsdg)
281{
282 KReportDetailGroupSectionDialog * dgsd = new KReportDetailGroupSectionDialog(this);
283
284 // add the current column and all columns not yet used for groups
285 const QStringList keys = m_reportDesigner->fieldKeys();
286 const QStringList columnNames = m_reportDesigner->fieldNames();
287 // in case of to-be-added group that column needs to be added to the used
288 const QSet<QString> usedColumns = groupingColumns() << rsdg->column();
289 // if the current column is not among the keys, something is broken.
290 // for now just simply select no column in the combobox, achieved by -1
291 int indexOfCurrentColumn = -1;
292 for (int i = 0; i < keys.count(); ++i) {
293 const QString &key = keys.at(i);
294 // skip any editor helper fields
295 if (isEditorHelperField(key)) {
296 continue;
297 }
298 // already used?
299 if (usedColumns.contains(key)) {
300 // and not the one of the group?
301 if (key != rsdg->column()) {
302 continue;
303 }
304 // remember index
305 indexOfCurrentColumn = dgsd->cbColumn->count();
306 }
307 dgsd->cbColumn->insertItem( i, columnNames.value(i), key);
308 }
309 dgsd->cbColumn->setCurrentIndex(indexOfCurrentColumn);
310
311 dgsd->cbSort->addItem(tr("Ascending"), Qt::AscendingOrder);
312 dgsd->cbSort->addItem(tr("Descending"), Qt::DescendingOrder);
313 dgsd->cbSort->setCurrentIndex(dgsd->cbSort->findData(rsdg->sort()));
314
315 dgsd->breakAfterFooter->setChecked(rsdg->pageBreak() == KReportDesignerSectionDetailGroup::PageBreak::AfterGroupFooter);
316 dgsd->cbHead->setChecked(rsdg->groupHeaderVisible());
317 dgsd->cbFoot->setChecked(rsdg->groupFooterVisible());
318
319 const bool isOkayed = (dgsd->exec() == QDialog::Accepted);
320
321 if (isOkayed) {
322 const QString newColumn =
323 dgsd->cbColumn->itemData(dgsd->cbColumn->currentIndex()).toString();
324 const QString oldColumn = rsdg->column();
325 if (newColumn != oldColumn) {
326 rsdg->setColumn(newColumn);
327 }
328
329 rsdg->setGroupHeaderVisible(dgsd->cbHead->isChecked());
330 rsdg->setGroupFooterVisible(dgsd->cbFoot->isChecked());
331
332 const KReportDesignerSectionDetailGroup::PageBreak pageBreak
333 = dgsd->breakAfterFooter->isChecked()
334 ? KReportDesignerSectionDetailGroup::PageBreak::AfterGroupFooter
335 : KReportDesignerSectionDetailGroup::PageBreak::None;
336 rsdg->setPageBreak(pageBreak);
337
338 const Qt::SortOrder sortOrder =
339 static_cast<Qt::SortOrder>(dgsd->cbSort->itemData(dgsd->cbSort->currentIndex()).toInt());
340 rsdg->setSort(sortOrder);
341 }
342
343 delete dgsd;
344
345 return isOkayed;
346}
347
348QString KReportSectionEditor::columnName(const QString &column) const
349{
350 const QStringList keys = m_reportDesigner->fieldKeys();
351 const QStringList columnNames = m_reportDesigner->fieldNames();
352 return columnNames.at(keys.indexOf(column));
353}
354
355QSet<QString> KReportSectionEditor::groupingColumns() const
356{
358 for (int i = 0; i < m_ui.lbGroups->count(); ++i) {
359 result.insert(m_ui.lbGroups->item(i)->data(KeyRole).toString());
360 }
361 return result;
362}
363
364void KReportSectionEditor::cbHeadAny_toggled(bool yes)
365{
366 if (m_reportDesigner) {
367 if (yes) {
368 m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderAny);
369 } else {
370 m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderAny);
371 }
372 }
373}
374
375void KReportSectionEditor::cbFootAny_toggled(bool yes)
376{
377 if (m_reportDesigner) {
378 if (yes) {
379 m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterAny);
380 } else {
381 m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterAny);
382 }
383 }
384}
385
386void KReportSectionEditor::btnEdit_clicked()
387{
388 if (m_reportSectionDetail) {
389 const int idx = m_ui.lbGroups->currentRow();
390 if (idx < 0) {
391 return;
392 }
393 KReportDesignerSectionDetailGroup * rsdg = m_reportSectionDetail->groupSection(idx);
394 if (editDetailGroup(rsdg)) {
395 // update name in list
396 m_ui.lbGroups->item(idx)->setText(columnName(rsdg->column()));
397 }
398 }
399}
400
401void KReportSectionEditor::btnAdd_clicked()
402{
403 if (m_reportSectionDetail) {
404 // lets add a new section
405 // search for unused column
406 QString column;
407 const QStringList keys = m_reportDesigner->fieldKeys();
408 const QSet<QString> columns = groupingColumns();
409 foreach(const QString &key, keys) {
410 // skip any editor helper fields
411 if (isEditorHelperField(key)) {
412 continue;
413 }
414 if (! columns.contains(key)) {
415 column = key;
416 break;
417 }
418 }
419 // should not happen, but we do not really know if m_reportDesigner is in sync
420 if (column.isEmpty()) {
421 return;
422 }
423
424 // create new group, have it edited and add it, if not cancelled
426 new KReportDesignerSectionDetailGroup(column, m_reportSectionDetail, m_reportSectionDetail);
427 if (editDetailGroup(rsdg)) {
428 // append to group sections
429 m_reportSectionDetail->insertGroupSection(m_reportSectionDetail->groupSectionCount(), rsdg);
430 // add to combobox
431 const QString column = rsdg->column();
432 QListWidgetItem *item = new QListWidgetItem(columnName(column));
433 item->setData(KeyRole, column);
434 m_ui.lbGroups->addItem(item);
435 m_ui.lbGroups->setCurrentRow(m_ui.lbGroups->count() - 1);
436 updateAddButton();
437 } else {
438 delete rsdg;
439 }
440 }
441}
442
443
444void KReportSectionEditor::btnRemove_clicked()
445{
446 if (m_reportSectionDetail) {
447 const int index = m_ui.lbGroups->currentRow();
448 if (index != -1) {
449 QListWidgetItem *item = m_ui.lbGroups->takeItem(index);
450 delete item;
451 m_reportSectionDetail->removeGroupSection(index, true);
452 // a field got usable, so make sure add button is available again
453 m_btnAdd->setEnabled(true);
454 // workaround for at least Qt 4.8.1, which does not emit the proper
455 // currentRowChanged signal on deletion of the first element
456 updateButtonsForRow(m_ui.lbGroups->currentRow());
457 }
458 }
459}
460
461
462void KReportSectionEditor::btnMoveUp_clicked()
463{
464 if (m_reportSectionDetail) {
465 int idx = m_ui.lbGroups->currentRow();
466 if (idx <= 0) return;
467 QString s = m_ui.lbGroups->currentItem()->text();
468 m_ui.lbGroups->takeItem(idx);
469 m_ui.lbGroups->insertItem(idx - 1, s);
470 m_ui.lbGroups->setCurrentRow(idx - 1, QItemSelectionModel::ClearAndSelect);
471 KReportDesignerSectionDetailGroup * rsdg = m_reportSectionDetail->groupSection(idx);
472 bool showgh = rsdg->groupHeaderVisible();
473 bool showgf = rsdg->groupFooterVisible();
474 m_reportSectionDetail->removeGroupSection(idx);
475 m_reportSectionDetail->insertGroupSection(idx - 1, rsdg);
476 rsdg->setGroupHeaderVisible(showgh);
477 rsdg->setGroupFooterVisible(showgf);
478 }
479}
480
481
482void KReportSectionEditor::brnMoveDown_clicked()
483{
484 if (m_reportSectionDetail) {
485 int idx = m_ui.lbGroups->currentRow();
486 if (idx == (int)(m_ui.lbGroups->count() - 1)) return;
487 QString s = m_ui.lbGroups->currentItem()->text();
488 m_ui.lbGroups->takeItem(idx);
489 m_ui.lbGroups->insertItem (idx + 1, s);
490 m_ui.lbGroups->setCurrentRow(idx + 1, QItemSelectionModel::ClearAndSelect);
491 KReportDesignerSectionDetailGroup * rsdg = m_reportSectionDetail->groupSection(idx);
492 bool showgh = rsdg->groupHeaderVisible();
493 bool showgf = rsdg->groupFooterVisible();
494 m_reportSectionDetail->removeGroupSection(idx);
495 m_reportSectionDetail->insertGroupSection(idx + 1, rsdg);
496 rsdg->setGroupHeaderVisible(showgh);
497 rsdg->setGroupFooterVisible(showgf);
498 }
499}
500
501void KReportSectionEditor::updateButtonsForItem(QListWidgetItem* currentItem)
502{
503 const bool isItemSelected = currentItem;
504
505 m_btnEdit->setEnabled(isItemSelected);
506 m_btnRemove->setEnabled(isItemSelected);
507}
508
509void KReportSectionEditor::updateButtonsForRow(int row)
510{
511 const bool enableMoveUpButton = (row > 0);
512 const bool enableMoveDownButton = (0 <= row) && (row+1 < m_ui.lbGroups->count());
513
514 m_btnMoveUp->setEnabled(enableMoveUpButton);
515 m_btnMoveDown->setEnabled(enableMoveDownButton);
516}
517
518void KReportSectionEditor::updateAddButton()
519{
520 // search for unused column
521 bool foundUnusedColumn = false;
522 const QStringList keys = m_reportDesigner->fieldKeys();
523 const QSet<QString> columns = groupingColumns();
524 foreach(const QString &key, keys) {
525 // skip any editor helper fields
526 if (isEditorHelperField(key)) {
527 continue;
528 }
529 if (! columns.contains(key)) {
530 foundUnusedColumn = true;
531 break;
532 }
533 }
534 m_btnAdd->setEnabled(foundUnusedColumn);
535}
A section group allows a header and footer to be used for a particular report field.
The ReportDesigner is the main widget for designing a report.
KReportDesignerSectionDetail * detailSection() const
Return a pointer to the detail section.
void insertSection(KReportSectionData::Type type)
Create a new section and insert it into the report.
QStringList fieldKeys() const
void removeSection(KReportSectionData::Type type)
Deletes the section specified.
QStringList fieldNames() const
char * toString(const EngineQuery &query)
void setShortcut(const QKeySequence &key)
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
virtual int exec()
int result() const const
QPushButton * button(StandardButton which) const const
QIcon fromTheme(const QString &name)
const_reference at(qsizetype i) const const
qsizetype count() const const
T value(qsizetype i) const const
virtual void setData(int role, const QVariant &value)
QString tr(const char *sourceText, const char *disambiguation, int n)
void setDefault(bool)
bool contains(const QSet< T > &other) const const
bool isEmpty() const const
qsizetype indexOf(const QRegularExpression &re, qsizetype from) const const
UserRole
Key_Return
AscendingOrder
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
void setEnabled(bool)
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.