File indexing completed on 2024-04-28 04:42:12

0001 /* This file is part of the KDE project
0002  * Copyright (C) 2001-2007 by OpenMFG, LLC (info@openmfg.com)
0003  * Copyright (C) 2007-2008 by Adam Pigg (adam@piggz.co.uk)
0004  * Copyright (C) 2012 by Friedrich W. H. Kossebau (kossebau@kde.org)
0005  *
0006  * This library is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Lesser General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2.1 of the License, or (at your option) any later version.
0010  *
0011  * This library is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014  * Lesser General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Lesser General Public
0017  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0018  */
0019 
0020 #include "KReportSectionEditor.h"
0021 
0022 #include "KReportDesigner.h"
0023 #include "KReportSection.h"
0024 #include "KReportDesignerSectionDetail.h"
0025 #include "KReportDetailGroupSectionDialog.h"
0026 #include "KReportDesignerSectionDetailGroup.h"
0027 
0028 #include <QIcon>
0029 #include <QDialogButtonBox>
0030 #include <QVBoxLayout>
0031 #include <QPushButton>
0032 
0033 enum {
0034     KeyRole = Qt::UserRole
0035 };
0036 
0037 // KReportDesigner currently prepends an empty key/fieldname pair to the list
0038 // of fields, possibly to offer the option to have report elements not yet
0039 // bound to fields
0040 static inline bool isEditorHelperField(const QString &key)
0041 {
0042     return key.isEmpty();
0043 }
0044 
0045 /*
0046  *  Constructs a SectionEditor as a child of 'parent'.
0047  *
0048  *  The dialog will by default be modeless, unless you set 'modal' to
0049  *  true to construct a modal dialog.
0050  */
0051 KReportSectionEditor::KReportSectionEditor(KReportDesigner* designer)
0052   : QDialog(designer)
0053 {
0054     Q_ASSERT(designer);
0055     m_reportDesigner = designer;
0056     m_reportSectionDetail = m_reportDesigner->detailSection();
0057 
0058     //! @todo check section editor
0059     //setButtons(Close);
0060     //setCaption(tr("Section Editor"));
0061 
0062     QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
0063     QVBoxLayout* mainLayout = new QVBoxLayout(this);
0064     QPushButton* closeButton = buttonBox->button(QDialogButtonBox::Close);
0065 
0066     closeButton->setDefault(true);
0067     closeButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0068     connect(buttonBox, SIGNAL(rejected()), this, SLOT(accept()));
0069 
0070     QWidget *widget = new QWidget(this);
0071     m_ui.setupUi(widget);
0072     m_btnAdd = new QPushButton(QIcon::fromTheme(QLatin1String("list-add")), tr("Add..."), this);
0073     m_ui.lGroupSectionsButtons->addWidget(m_btnAdd);
0074     m_btnEdit = new QPushButton(QIcon::fromTheme(QLatin1String("document-edit")), tr("Edit..."), this);
0075     m_ui.lGroupSectionsButtons->addWidget(m_btnEdit);
0076     m_btnRemove = new QPushButton(QIcon::fromTheme(QLatin1String("list-remove")), tr("Delete"), this);
0077     m_ui.lGroupSectionsButtons->addWidget(m_btnRemove);
0078     m_btnMoveUp = new QPushButton(QIcon::fromTheme(QLatin1String("arrow-up")), tr("Move Up"), this);
0079     m_ui.lGroupSectionsButtons->addWidget(m_btnMoveUp);
0080     m_btnMoveDown = new QPushButton(QIcon::fromTheme(QLatin1String("arrow-down")), tr("Move Down"), this);
0081     m_ui.lGroupSectionsButtons->addWidget(m_btnMoveDown);
0082     m_ui.lGroupSectionsButtons->addStretch();
0083 
0084     mainLayout->addWidget(widget);
0085     mainLayout->addWidget(buttonBox);
0086 
0087     //setMainWidget(widget);
0088 
0089     // signals and slots connections
0090     connect(m_ui.cbReportHeader, SIGNAL(toggled(bool)), this, SLOT(cbReportHeader_toggled(bool)));
0091     connect(m_ui.cbReportFooter, SIGNAL(toggled(bool)), this, SLOT(cbReportFooter_toggled(bool)));
0092     connect(m_ui.cbHeadFirst, SIGNAL(toggled(bool)), this, SLOT(cbHeadFirst_toggled(bool)));
0093     connect(m_ui.cbHeadLast, SIGNAL(toggled(bool)), this, SLOT(cbHeadLast_toggled(bool)));
0094     connect(m_ui.cbHeadEven, SIGNAL(toggled(bool)), this, SLOT(cbHeadEven_toggled(bool)));
0095     connect(m_ui.cbHeadOdd, SIGNAL(toggled(bool)), this, SLOT(cbHeadOdd_toggled(bool)));
0096     connect(m_ui.cbFootFirst, SIGNAL(toggled(bool)), this, SLOT(cbFootFirst_toggled(bool)));
0097     connect(m_ui.cbFootLast, SIGNAL(toggled(bool)), this, SLOT(cbFootLast_toggled(bool)));
0098     connect(m_ui.cbFootEven, SIGNAL(toggled(bool)), this, SLOT(cbFootEven_toggled(bool)));
0099     connect(m_ui.cbFootOdd, SIGNAL(toggled(bool)), this, SLOT(cbFootOdd_toggled(bool)));
0100     connect(m_ui.cbHeadAny, SIGNAL(toggled(bool)), this, SLOT(cbHeadAny_toggled(bool)));
0101     connect(m_ui.cbFootAny, SIGNAL(toggled(bool)), this, SLOT(cbFootAny_toggled(bool)));
0102     connect(m_ui.lbGroups, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
0103             this, SLOT(updateButtonsForItem(QListWidgetItem*)));
0104     connect(m_ui.lbGroups, SIGNAL(currentRowChanged(int)),
0105             this, SLOT(updateButtonsForRow(int)));
0106 
0107     connect(m_btnAdd, SIGNAL(clicked(bool)), this, SLOT(btnAdd_clicked()));
0108     connect(m_btnEdit, SIGNAL(clicked(bool)), this, SLOT(btnEdit_clicked()));
0109     connect(m_btnRemove, SIGNAL(clicked(bool)), this, SLOT(btnRemove_clicked()));
0110     connect(m_btnMoveUp, SIGNAL(clicked(bool)), this, SLOT(btnMoveUp_clicked()));
0111     connect(m_btnMoveDown, SIGNAL(clicked(bool)), this, SLOT(brnMoveDown_clicked()));
0112 
0113     // set all the properties
0114 
0115     m_ui.cbReportHeader->setChecked(m_reportDesigner->section(KReportSectionData::Type::ReportHeader));
0116     m_ui.cbReportFooter->setChecked(m_reportDesigner->section(KReportSectionData::Type::ReportFooter));
0117 
0118     m_ui.cbHeadFirst->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderFirst));
0119     m_ui.cbHeadOdd->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderOdd));
0120     m_ui.cbHeadEven->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderEven));
0121     m_ui.cbHeadLast->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderLast));
0122     m_ui.cbHeadAny->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageHeaderAny));
0123 
0124     m_ui.cbFootFirst->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterFirst));
0125     m_ui.cbFootOdd->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterOdd));
0126     m_ui.cbFootEven->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterEven));
0127     m_ui.cbFootLast->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterLast));
0128     m_ui.cbFootAny->setChecked(m_reportDesigner->section(KReportSectionData::Type::PageFooterAny));
0129 
0130     // now set the rw value
0131     if (m_reportSectionDetail) {
0132         const QStringList columnNames = m_reportDesigner->fieldNames();
0133         const QStringList keys = m_reportDesigner->fieldKeys();
0134         for (int i = 0; i < m_reportSectionDetail->groupSectionCount(); ++i) {
0135             const QString key = m_reportSectionDetail->groupSection(i)->column();
0136             const int idx = keys.indexOf(key);
0137             const QString columnName = columnNames.value(idx);
0138             QListWidgetItem *item = new QListWidgetItem(columnName);
0139             item->setData(KeyRole, key);
0140             m_ui.lbGroups->addItem(item);
0141         }
0142     }
0143     if (m_ui.lbGroups->count() == 0) {
0144     } else {
0145         m_ui.lbGroups->setCurrentItem(m_ui.lbGroups->item(0));
0146     }
0147     updateButtonsForItem(m_ui.lbGroups->currentItem());
0148     updateAddButton();
0149     updateButtonsForRow(m_ui.lbGroups->currentRow());
0150 }
0151 
0152 /*
0153  *  Destroys the object and frees any allocated resources
0154  */
0155 KReportSectionEditor::~KReportSectionEditor()
0156 {
0157     // no need to delete child widgets, Qt does it all for us
0158 }
0159 
0160 void KReportSectionEditor::cbReportHeader_toggled(bool yes)
0161 {
0162     if (m_reportDesigner) {
0163         if (yes) {
0164             m_reportDesigner->insertSection(KReportSectionData::Type::ReportHeader);
0165         } else {
0166             m_reportDesigner->removeSection(KReportSectionData::Type::ReportHeader);
0167         }
0168     }
0169 
0170 }
0171 
0172 void KReportSectionEditor::cbReportFooter_toggled(bool yes)
0173 {
0174     if (m_reportDesigner) {
0175         if (yes) {
0176             m_reportDesigner->insertSection(KReportSectionData::Type::ReportFooter);
0177         } else {
0178             m_reportDesigner->removeSection(KReportSectionData::Type::ReportFooter);
0179         }
0180     }
0181 
0182 }
0183 
0184 void KReportSectionEditor::cbHeadFirst_toggled(bool yes)
0185 {
0186     if (m_reportDesigner) {
0187         if (yes) {
0188             m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderFirst);
0189         } else {
0190             m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderFirst);
0191         }
0192     }
0193 
0194 }
0195 
0196 void KReportSectionEditor::cbHeadLast_toggled(bool yes)
0197 {
0198     if (m_reportDesigner) {
0199         if (yes) {
0200             m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderLast);
0201         } else {
0202             m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderLast);
0203         }
0204     }
0205 
0206 }
0207 
0208 void KReportSectionEditor::cbHeadEven_toggled(bool yes)
0209 {
0210     if (m_reportDesigner) {
0211         if (yes) {
0212             m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderEven);
0213         } else {
0214             m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderEven);
0215         }
0216     }
0217 
0218 }
0219 
0220 void KReportSectionEditor::cbHeadOdd_toggled(bool yes)
0221 {
0222     if (m_reportDesigner) {
0223         if (yes) {
0224             m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderOdd);
0225         } else {
0226             m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderOdd);
0227         }
0228     }
0229 
0230 }
0231 
0232 void KReportSectionEditor::cbFootFirst_toggled(bool yes)
0233 {
0234     if (m_reportDesigner) {
0235         if (yes) {
0236             m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterFirst);
0237         } else {
0238             m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterFirst);
0239         }
0240     }
0241 
0242 }
0243 
0244 void KReportSectionEditor::cbFootLast_toggled(bool yes)
0245 {
0246     if (m_reportDesigner) {
0247         if (yes) {
0248             m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterLast);
0249         } else {
0250             m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterLast);
0251         }
0252     }
0253 
0254 }
0255 
0256 void KReportSectionEditor::cbFootEven_toggled(bool yes)
0257 {
0258     if (m_reportDesigner) {
0259         if (yes) {
0260             m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterEven);
0261         } else {
0262             m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterEven);
0263         }
0264     }
0265 
0266 }
0267 
0268 void KReportSectionEditor::cbFootOdd_toggled(bool yes)
0269 {
0270     if (m_reportDesigner) {
0271         if (yes) {
0272             m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterOdd);
0273         } else {
0274             m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterOdd);
0275         }
0276     }
0277 
0278 }
0279 
0280 bool KReportSectionEditor::editDetailGroup(KReportDesignerSectionDetailGroup * rsdg)
0281 {
0282     KReportDetailGroupSectionDialog * dgsd = new KReportDetailGroupSectionDialog(this);
0283 
0284     // add the current column and all columns not yet used for groups
0285     const QStringList keys = m_reportDesigner->fieldKeys();
0286     const QStringList columnNames = m_reportDesigner->fieldNames();
0287     // in case of to-be-added group that column needs to be added to the used
0288     const QSet<QString> usedColumns = groupingColumns() << rsdg->column();
0289     // if the current column is not among the keys, something is broken.
0290     // for now just simply select no column in the combobox, achieved by -1
0291     int indexOfCurrentColumn = -1;
0292     for (int i = 0; i < keys.count(); ++i) {
0293         const QString &key = keys.at(i);
0294         // skip any editor helper fields
0295         if (isEditorHelperField(key)) {
0296             continue;
0297         }
0298         // already used?
0299         if (usedColumns.contains(key)) {
0300             // and not the one of the group?
0301             if (key != rsdg->column()) {
0302                 continue;
0303             }
0304             // remember index
0305             indexOfCurrentColumn = dgsd->cbColumn->count();
0306         }
0307         dgsd->cbColumn->insertItem( i, columnNames.value(i), key);
0308     }
0309     dgsd->cbColumn->setCurrentIndex(indexOfCurrentColumn);
0310 
0311     dgsd->cbSort->addItem(tr("Ascending"), Qt::AscendingOrder);
0312     dgsd->cbSort->addItem(tr("Descending"), Qt::DescendingOrder);
0313     dgsd->cbSort->setCurrentIndex(dgsd->cbSort->findData(rsdg->sort()));
0314 
0315     dgsd->breakAfterFooter->setChecked(rsdg->pageBreak() == KReportDesignerSectionDetailGroup::PageBreak::AfterGroupFooter);
0316     dgsd->cbHead->setChecked(rsdg->groupHeaderVisible());
0317     dgsd->cbFoot->setChecked(rsdg->groupFooterVisible());
0318 
0319     const bool isOkayed = (dgsd->exec() == QDialog::Accepted);
0320 
0321     if (isOkayed) {
0322         const QString newColumn =
0323             dgsd->cbColumn->itemData(dgsd->cbColumn->currentIndex()).toString();
0324         const QString oldColumn = rsdg->column();
0325         if (newColumn != oldColumn) {
0326             rsdg->setColumn(newColumn);
0327         }
0328 
0329         rsdg->setGroupHeaderVisible(dgsd->cbHead->isChecked());
0330         rsdg->setGroupFooterVisible(dgsd->cbFoot->isChecked());
0331 
0332         const KReportDesignerSectionDetailGroup::PageBreak pageBreak
0333             = dgsd->breakAfterFooter->isChecked()
0334             ? KReportDesignerSectionDetailGroup::PageBreak::AfterGroupFooter
0335             : KReportDesignerSectionDetailGroup::PageBreak::None;
0336         rsdg->setPageBreak(pageBreak);
0337 
0338         const Qt::SortOrder sortOrder =
0339             static_cast<Qt::SortOrder>(dgsd->cbSort->itemData(dgsd->cbSort->currentIndex()).toInt());
0340         rsdg->setSort(sortOrder);
0341     }
0342 
0343     delete dgsd;
0344 
0345     return isOkayed;
0346 }
0347 
0348 QString KReportSectionEditor::columnName(const QString &column) const
0349 {
0350     const QStringList keys = m_reportDesigner->fieldKeys();
0351     const QStringList columnNames = m_reportDesigner->fieldNames();
0352     return columnNames.at(keys.indexOf(column));
0353 }
0354 
0355 QSet<QString> KReportSectionEditor::groupingColumns() const
0356 {
0357     QSet<QString> result;
0358     for (int i = 0; i < m_ui.lbGroups->count(); ++i) {
0359         result.insert(m_ui.lbGroups->item(i)->data(KeyRole).toString());
0360     }
0361     return result;
0362 }
0363 
0364 void KReportSectionEditor::cbHeadAny_toggled(bool yes)
0365 {
0366     if (m_reportDesigner) {
0367         if (yes) {
0368             m_reportDesigner->insertSection(KReportSectionData::Type::PageHeaderAny);
0369         } else {
0370             m_reportDesigner->removeSection(KReportSectionData::Type::PageHeaderAny);
0371         }
0372     }
0373 }
0374 
0375 void KReportSectionEditor::cbFootAny_toggled(bool yes)
0376 {
0377     if (m_reportDesigner) {
0378         if (yes) {
0379             m_reportDesigner->insertSection(KReportSectionData::Type::PageFooterAny);
0380         } else {
0381             m_reportDesigner->removeSection(KReportSectionData::Type::PageFooterAny);
0382         }
0383     }
0384 }
0385 
0386 void KReportSectionEditor::btnEdit_clicked()
0387 {
0388     if (m_reportSectionDetail) {
0389         const int idx = m_ui.lbGroups->currentRow();
0390         if (idx < 0) {
0391             return;
0392         }
0393         KReportDesignerSectionDetailGroup * rsdg = m_reportSectionDetail->groupSection(idx);
0394         if (editDetailGroup(rsdg)) {
0395             // update name in list
0396             m_ui.lbGroups->item(idx)->setText(columnName(rsdg->column()));
0397         }
0398     }
0399 }
0400 
0401 void KReportSectionEditor::btnAdd_clicked()
0402 {
0403     if (m_reportSectionDetail) {
0404         // lets add a new section
0405         // search for unused column
0406         QString column;
0407         const QStringList keys = m_reportDesigner->fieldKeys();
0408         const QSet<QString> columns = groupingColumns();
0409         foreach(const QString &key, keys) {
0410             // skip any editor helper fields
0411             if (isEditorHelperField(key)) {
0412                 continue;
0413             }
0414             if (! columns.contains(key)) {
0415                 column = key;
0416                 break;
0417             }
0418         }
0419         // should not happen, but we do not really know if m_reportDesigner is in sync
0420         if (column.isEmpty()) {
0421             return;
0422         }
0423 
0424         // create new group, have it edited and add it, if not cancelled
0425         KReportDesignerSectionDetailGroup * rsdg =
0426             new KReportDesignerSectionDetailGroup(column, m_reportSectionDetail, m_reportSectionDetail);
0427         if (editDetailGroup(rsdg)) {
0428             // append to group sections
0429             m_reportSectionDetail->insertGroupSection(m_reportSectionDetail->groupSectionCount(), rsdg);
0430             // add to combobox
0431             const QString column = rsdg->column();
0432             QListWidgetItem *item = new QListWidgetItem(columnName(column));
0433             item->setData(KeyRole, column);
0434             m_ui.lbGroups->addItem(item);
0435             m_ui.lbGroups->setCurrentRow(m_ui.lbGroups->count() - 1);
0436             updateAddButton();
0437         } else {
0438             delete rsdg;
0439         }
0440     }
0441 }
0442 
0443 
0444 void KReportSectionEditor::btnRemove_clicked()
0445 {
0446     if (m_reportSectionDetail) {
0447         const int index = m_ui.lbGroups->currentRow();
0448         if (index != -1) {
0449             QListWidgetItem *item = m_ui.lbGroups->takeItem(index);
0450             delete item;
0451             m_reportSectionDetail->removeGroupSection(index, true);
0452             // a field got usable, so make sure add button is available again
0453             m_btnAdd->setEnabled(true);
0454             // workaround for at least Qt 4.8.1, which does not emit the proper
0455             // currentRowChanged signal on deletion of the first element
0456             updateButtonsForRow(m_ui.lbGroups->currentRow());
0457         }
0458     }
0459 }
0460 
0461 
0462 void KReportSectionEditor::btnMoveUp_clicked()
0463 {
0464     if (m_reportSectionDetail) {
0465         int idx = m_ui.lbGroups->currentRow();
0466         if (idx <= 0) return;
0467         QString s = m_ui.lbGroups->currentItem()->text();
0468         m_ui.lbGroups->takeItem(idx);
0469         m_ui.lbGroups->insertItem(idx - 1, s);
0470         m_ui.lbGroups->setCurrentRow(idx - 1, QItemSelectionModel::ClearAndSelect);
0471         KReportDesignerSectionDetailGroup * rsdg = m_reportSectionDetail->groupSection(idx);
0472         bool showgh = rsdg->groupHeaderVisible();
0473         bool showgf = rsdg->groupFooterVisible();
0474         m_reportSectionDetail->removeGroupSection(idx);
0475         m_reportSectionDetail->insertGroupSection(idx - 1, rsdg);
0476         rsdg->setGroupHeaderVisible(showgh);
0477         rsdg->setGroupFooterVisible(showgf);
0478     }
0479 }
0480 
0481 
0482 void KReportSectionEditor::brnMoveDown_clicked()
0483 {
0484     if (m_reportSectionDetail) {
0485         int idx = m_ui.lbGroups->currentRow();
0486         if (idx == (int)(m_ui.lbGroups->count() - 1)) return;
0487         QString s = m_ui.lbGroups->currentItem()->text();
0488         m_ui.lbGroups->takeItem(idx);
0489         m_ui.lbGroups->insertItem (idx + 1, s);
0490         m_ui.lbGroups->setCurrentRow(idx + 1, QItemSelectionModel::ClearAndSelect);
0491         KReportDesignerSectionDetailGroup * rsdg = m_reportSectionDetail->groupSection(idx);
0492         bool showgh = rsdg->groupHeaderVisible();
0493         bool showgf = rsdg->groupFooterVisible();
0494         m_reportSectionDetail->removeGroupSection(idx);
0495         m_reportSectionDetail->insertGroupSection(idx + 1, rsdg);
0496         rsdg->setGroupHeaderVisible(showgh);
0497         rsdg->setGroupFooterVisible(showgf);
0498     }
0499 }
0500 
0501 void KReportSectionEditor::updateButtonsForItem(QListWidgetItem* currentItem)
0502 {
0503     const bool isItemSelected = currentItem;
0504 
0505     m_btnEdit->setEnabled(isItemSelected);
0506     m_btnRemove->setEnabled(isItemSelected);
0507 }
0508 
0509 void KReportSectionEditor::updateButtonsForRow(int row)
0510 {
0511     const bool enableMoveUpButton = (row > 0);
0512     const bool enableMoveDownButton = (0 <= row) && (row+1 < m_ui.lbGroups->count());
0513 
0514     m_btnMoveUp->setEnabled(enableMoveUpButton);
0515     m_btnMoveDown->setEnabled(enableMoveDownButton);
0516 }
0517 
0518 void KReportSectionEditor::updateAddButton()
0519 {
0520     // search for unused column
0521     bool foundUnusedColumn = false;
0522     const QStringList keys = m_reportDesigner->fieldKeys();
0523     const QSet<QString> columns = groupingColumns();
0524     foreach(const QString &key, keys) {
0525         // skip any editor helper fields
0526         if (isEditorHelperField(key)) {
0527             continue;
0528         }
0529         if (! columns.contains(key)) {
0530             foundUnusedColumn = true;
0531             break;
0532         }
0533     }
0534     m_btnAdd->setEnabled(foundUnusedColumn);
0535 }