File indexing completed on 2024-05-12 16:39:46

0001 /* This file is part of the KDE project
0002    Copyright (C) 2004 Cedric Pasteur <cedric.pasteur@free.fr>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017  * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include <QHeader>
0021 #include <QVBoxLayout>
0022 #include <QHBoxLayout>
0023 #include <QDebug>
0024 
0025 #include <KLocalizedString>
0026 
0027 #include <KexiIcon.h>
0028 #include <KPropertyEditorView>
0029 #include <KPropertySet>
0030 #include <KProperty>
0031 
0032 #include "editlistviewdialog.h"
0033 
0034 namespace KFormDesigner
0035 {
0036 
0037 //////////////////////////////////////////////////////////////////////////////////
0038 /// A Dialog to edit the contents of a listview /////////////////////
0039 /////////////////////////////////////////////////////////////////////////////////
0040 
0041 EditListViewDialog::EditListViewDialog(QWidget *parent)
0042         : KPageDialog(parent)
0043 {
0044     setObjectName("editlistview_dialog");
0045     setModal(true);
0046     setFaceType(Tabbed);
0047     setWindowTitle(xi18nc("@title:window", "Edit Listview Contents"));
0048 
0049     ///////// Setup the "Contents" page /////////////////////////////
0050     m_columnsPageItem = addPage(new QWidget(this), xi18n("Columns"));
0051     QHBoxLayout *layout = new QHBoxLayout(m_contentsPageItem->widget(), 0, 6);
0052 
0053     //// Setup the icon toolbar /////////////////
0054     QVBoxLayout *vlayout = new QVBoxLayout(layout, 3);
0055     QToolButton *newRow = new QToolButton(m_contentsPageItem->widget());
0056     newRow->setIconSet(koIcon("list-add"));
0057     newRow->setTextLabel(xi18n("&Add Item"), true);
0058     vlayout->addWidget(newRow);
0059     m_buttons.insert(BNewRow, newRow);
0060     connect(newRow, SIGNAL(clicked()), this, SLOT(newRow()));
0061 
0062     QToolButton *newChild = new QToolButton(m_contentsPageItem->widget());
0063     newChild->setIconSet(koIcon("arrow-right"));
0064     newChild->setTextLabel(xi18n("New &Subitem"), true);
0065     vlayout->addWidget(newChild);
0066     m_buttons.insert(BNewChild, newChild);
0067     connect(newChild, SIGNAL(clicked()), this, SLOT(newChildRow()));
0068 
0069     QToolButton *delRow = new QToolButton(m_contentsPageItem->widget());
0070     delRow->setIconSet(koIcon("list-remove"));
0071     delRow->setTextLabel(xi18n("&Delete Item"), true);
0072     vlayout->addWidget(delRow);
0073     m_buttons.insert(BRemRow, delRow);
0074     connect(delRow, SIGNAL(clicked()), this, SLOT(removeRow()));
0075 
0076     QToolButton *rowUp = new QToolButton(m_contentsPageItem->widget());
0077     rowUp->setIconSet(koIcon("arrow-up"));
0078     rowUp->setTextLabel(xi18n("Move Item &Up"), true);
0079     vlayout->addWidget(rowUp);
0080     m_buttons.insert(BRowUp, rowUp);
0081     connect(rowUp, SIGNAL(clicked()), this, SLOT(MoveRowUp()));
0082 
0083     QToolButton *rowDown = new QToolButton(m_contentsPageItem->widget());
0084     rowDown->setIconSet(koIcon("arrow-down"));
0085     rowDown->setTextLabel(xi18n("Move Item &Down"), true);
0086     vlayout->addWidget(rowDown);
0087     m_buttons.insert(BRowDown, rowDown);
0088     connect(rowDown, SIGNAL(clicked()), this, SLOT(MoveRowDown()));
0089     vlayout->addStretch();
0090 
0091     //// The listview ///////////
0092     m_listview = new KListView(m_contentsPageItem->widget());
0093     m_listview->setObjectName("editlistview_listview");
0094     m_listview->setItemsRenameable(true);
0095     m_listview->setItemsMovable(true);
0096     m_listview->setDragEnabled(true);
0097     m_listview->setAllColumnsShowFocus(true);
0098     m_listview->setRootIsDecorated(true);
0099     m_listview->setDropVisualizer(true);
0100     m_listview->setAcceptDrops(true);
0101     m_listview->setSorting(-1);
0102     layout->addWidget(m_listview);
0103     m_listview->setFocus();
0104     connect(m_listview, SIGNAL(currentChanged(QListViewItem*)), this, SLOT(updateButtons(QListViewItem*)));
0105     connect(m_listview, SIGNAL(moved(QListViewItem*,QListViewItem*,QListViewItem*)), this, SLOT(updateButtons(QListViewItem*)));
0106 
0107     /////////////////// Setup the columns page ////////////////
0108     m_contentsPageItem = addPage(new QWidget(this), xi18n("Contents"));
0109     QHBoxLayout *hbox = new QHBoxLayout(m_columnsPageItem->widget(), 0, 6);
0110 
0111     // The "item properties" field
0112     m_editor = new KPropertyEditorView(m_columnsPageItem->widget());
0113     m_editor->setObjectName("editcolumn_propeditor");
0114     m_propSet = new KPropertySet(this);
0115     m_propSet->addProperty(
0116         new KProperty("caption", "Caption", xi18n("Caption"), xi18n("Caption")));
0117     m_propSet->addProperty(
0118         new KProperty("width", 100, xi18n("Width"), xi18n("Width")));
0119     m_propSet->addProperty(
0120         new KProperty("clickable", QVariant(true), xi18n("Clickable"), xi18n("Clickable")));
0121     m_propSet->addProperty(
0122         new KProperty("resizable", QVariant(true), xi18n("Resizable"), xi18n("Resizable")));
0123     m_propSet->addProperty(
0124         new KProperty("fullwidth", QVariant(false), xi18n("Full Width"), xi18n("Full Width")));
0125     m_editor->changeSet(m_propSet);
0126     connect(m_propSet, SIGNAL(propertyChanged(KPropertySet&,KProperty&)),
0127             this, SLOT(changeProperty(KPropertySet&,KProperty&)));
0128 
0129     // Setup the icon toolbar //////////
0130     QVBoxLayout *vbox = new QVBoxLayout(hbox, 3);
0131     QToolButton *add = new QToolButton(m_columnsPageItem->widget());
0132     add->setIconSet(koIcon("list-add"));
0133     add->setTextLabel(xi18n("&Add Item"), true);
0134     vbox->addWidget(add);
0135     m_buttons.insert(BColAdd, add);
0136     connect(add, SIGNAL(clicked()), this, SLOT(newItem()));
0137 
0138     QToolButton *remove = new QToolButton(m_columnsPageItem->widget());
0139     remove->setIconSet(koIcon("list-remove"));
0140     remove->setTextLabel(xi18n("&Delete Item"), true);
0141     vbox->addWidget(remove);
0142     m_buttons.insert(BColRem, remove);
0143     connect(remove, SIGNAL(clicked()), this, SLOT(removeItem()));
0144 
0145     QToolButton *up = new QToolButton(m_columnsPageItem->widget());
0146     up->setIconSet(koIcon("arrow-up"));
0147     up->setTextLabel(xi18n("Move Item &Up"), true);
0148     vbox->addWidget(up);
0149     m_buttons.insert(BColUp, up);
0150     connect(up, SIGNAL(clicked()), this, SLOT(MoveItemUp()));
0151 
0152     QToolButton *down = new QToolButton(m_columnsPageItem->widget());
0153     down->setIconSet(koIcon("arrow-down"));
0154     down->setTextLabel(xi18n("Move Item &Down"), true);
0155     vbox->addWidget(down);
0156     m_buttons.insert(BColDown, down);
0157     connect(down, SIGNAL(clicked()), this, SLOT(MoveItemDown()));
0158     vbox->addStretch();
0159 
0160     // The listbox with columns name /////
0161     m_listbox = new KListBox(m_columnsPageItem->widget(), "editlistview_columns");
0162     m_listbox->setFocus();
0163     hbox->insertWidget(0, m_listbox);
0164     hbox->addWidget(m_editor);
0165     connect(m_listbox, SIGNAL(currentChanged(QListBoxItem*)), this, SLOT(updateItemProperties(QListBoxItem*)));
0166 
0167     //// Init dialog and display it ////////////////////////
0168 //! @todo KEXI3 not available in kdelibs4: setInitialSize(QSize(500, 300), true);
0169 }
0170 
0171 int
0172 EditListViewDialog::exec(QListView *listview)
0173 {
0174     if (!listview) {
0175         qWarning() << "EditListViewDialog ERROR: no listview ";
0176         return 0;
0177     }
0178 
0179     // We copy the contents of the listview into our listview
0180     for (int i = 0; i < listview->columns(); i++) {
0181         m_listview->addColumn(listview->columnText(i), listview->columnWidth(i));
0182         m_listview->header()->setClickEnabled(listview->header()->isClickEnabled(i), i);
0183         m_listview->header()->setResizeEnabled(listview->header()->isResizeEnabled(i), i);
0184         m_listview->header()->setStretchEnabled(listview->header()->isStretchEnabled(i), i);
0185         m_listview->setRenameable(i, true);
0186     }
0187     QListViewItem *item = listview->firstChild();
0188     while (item)  {
0189         loadChildNodes(m_listview, item, 0);
0190         item = item->nextSibling();
0191     }
0192 
0193     m_listview->setSelected(m_listview->firstChild(), true);
0194     if (!m_listview->firstChild())
0195         updateButtons(0);
0196 
0197     for (int i = 0; i < listview->columns(); i++)
0198         m_listbox->insertItem(listview->columnText(i));
0199     m_listbox->setSelected(0, true);
0200 
0201     // and we exec the dialog
0202     int r =  KPageDialog::exec();
0203     if (r == QDialog::Accepted) {
0204         listview->clear();
0205         // We copy the contents of our listview back in the listview
0206         for (int i = 0; i < m_listview->columns(); i++) {
0207             if (listview->columns() <= i)
0208                 listview->addColumn(m_listview->columnText(i), m_listview->columnWidth(i));
0209             else {
0210                 listview->setColumnText(i, m_listview->columnText(i));
0211                 listview->setColumnWidth(i, m_listview->columnWidth(i));
0212             }
0213             listview->header()->setClickEnabled(m_listview->header()->isClickEnabled(i), i);
0214             listview->header()->setResizeEnabled(m_listview->header()->isResizeEnabled(i), i);
0215             listview->header()->setStretchEnabled(m_listview->header()->isStretchEnabled(i), i);
0216         }
0217 
0218         QListViewItem *item = m_listview->firstChild();
0219         while (item) {
0220             loadChildNodes(listview, item, 0);
0221             item = item->nextSibling();
0222         }
0223     }
0224     return r;
0225 }
0226 
0227 /// Columns page slots ///////
0228 void
0229 EditListViewDialog::changeProperty(KPropertySet& set, KProperty& property)
0230 {
0231     if (&set != m_propSet)
0232         return;
0233 
0234     QString name = property.name();
0235     QVariant value = property.value();
0236     if (name == "caption") {
0237         m_propSet->blockSignals(true); // we need to block signals because changeItem will modify selection, and call updateItemProperties
0238         m_listbox->changeItem(value.toString(), m_listbox->currentItem());
0239         m_listview->setColumnText(m_listbox->currentItem(), value.toString());
0240         m_propSet->blockSignals(false);
0241     } else if (name == "width")
0242         m_listview->setColumnWidth(m_listbox->currentItem(), value.toInt());
0243     else if (name == "resizable")
0244         m_listview->header()->setResizeEnabled(value.toBool(), m_listbox->currentItem());
0245     else if (name == "clickable")
0246         m_listview->header()->setClickEnabled(value.toBool(), m_listbox->currentItem());
0247     else if (name == "fullwidth")
0248         m_listview->header()->setStretchEnabled(value.toBool(), m_listbox->currentItem());
0249 }
0250 
0251 void
0252 EditListViewDialog::updateItemProperties(QListBoxItem *item)
0253 {
0254     if (!item)
0255         return;
0256 
0257     int id = m_listbox->index(item);
0258     if (m_propSet) {
0259         m_propSet->blockSignals(true); // we don't want changeProperty to be called
0260         (*m_propSet)["caption"].setValue(m_listview->columnText(id), false);
0261         (*m_propSet)["width"].setValue(m_listview->columnWidth(id), false);
0262         (*m_propSet)["clickable"].setValue(QVariant(m_listview->header()->isClickEnabled(id)), false);
0263         (*m_propSet)["resizable"].setValue(QVariant(m_listview->header()->isResizeEnabled(id)), false);
0264         (*m_propSet)["fullwidth"].setValue(QVariant(m_listview->header()->isStretchEnabled(id)), false);
0265         m_propSet->blockSignals(false);
0266         m_editor->changeSet(m_propSet);
0267     }
0268 
0269     m_buttons[BColUp]->setEnabled(item->prev());
0270     m_buttons[BColDown]->setEnabled(item->next());
0271 }
0272 
0273 void
0274 EditListViewDialog::newItem()
0275 {
0276     m_listbox->insertItem(xi18n("New Column"));
0277     m_listview->addColumn(xi18n("New Column"));
0278     m_listview->setRenameable(m_listview->columns() - 1, true);
0279     m_listbox->setCurrentItem(m_listbox->count() - 1);
0280     m_buttons[BColRem]->setEnabled(true);
0281 }
0282 
0283 void
0284 EditListViewDialog::removeItem()
0285 {
0286     int current = m_listbox->currentItem();
0287     if (m_listbox->item(current + 1))
0288         m_listbox->setCurrentItem(current + 1);
0289     else
0290         m_listbox->setCurrentItem(current - 1);
0291 
0292     m_listview->removeColumn(current);
0293     m_listbox->removeItem(current);
0294     if (m_listbox->count() == 0)
0295         m_buttons[BColRem]->setEnabled(false);
0296 }
0297 
0298 void
0299 EditListViewDialog::MoveItemUp()
0300 {
0301     int current = m_listbox->currentItem();
0302     QString text = m_listbox->text(current);
0303     m_listbox->blockSignals(true);
0304 
0305     m_listbox->changeItem(m_listbox->text(current - 1), current);
0306     m_listview->setColumnText(current, m_listview->columnText(current - 1));
0307     m_listview->setColumnWidth(current, m_listview->columnWidth(current - 1));
0308     m_listview->header()->setClickEnabled(m_listview->header()->isClickEnabled(current - 1), current);
0309     m_listview->header()->setResizeEnabled(m_listview->header()->isResizeEnabled(current - 1), current);
0310     m_listview->header()->setStretchEnabled(m_listview->header()->isStretchEnabled(current - 1), current);
0311 
0312     m_listbox->changeItem(text, current - 1);
0313     m_listview->setColumnText(current - 1, (*m_propSet)["caption"].value().toString());
0314     m_listview->setColumnWidth(current - 1, (*m_propSet)["width"].value().toBool());
0315     m_listview->header()->setClickEnabled((*m_propSet)["clickable"].value().toBool(), current - 1);
0316     m_listview->header()->setResizeEnabled((*m_propSet)["resizable"].value().toBool(), current - 1);
0317     m_listview->header()->setStretchEnabled((*m_propSet)["fullwidth"].value().toBool(), current - 1);
0318 
0319     m_listbox->blockSignals(false);
0320     m_listbox->setCurrentItem(current - 1);
0321 }
0322 
0323 void
0324 EditListViewDialog::MoveItemDown()
0325 {
0326     int current = m_listbox->currentItem();
0327     QString text = m_listbox->text(current);
0328     m_listbox->blockSignals(true);
0329 
0330     m_listbox->changeItem(m_listbox->text(current + 1), current);
0331     m_listview->setColumnText(current, m_listview->columnText(current + 1));
0332     m_listview->setColumnWidth(current, m_listview->columnWidth(current + 1));
0333     m_listview->header()->setClickEnabled(m_listview->header()->isClickEnabled(current + 1), current);
0334     m_listview->header()->setResizeEnabled(m_listview->header()->isResizeEnabled(current + 1), current);
0335     m_listview->header()->setStretchEnabled(m_listview->header()->isStretchEnabled(current + 1), current);
0336 
0337     m_listbox->changeItem(text, current + 1);
0338     m_listview->setColumnText(current + 1, (*m_propSet)["caption"].value().toString());
0339     m_listview->setColumnWidth(current + 1, (*m_propSet)["width"].value().toBool());
0340     m_listview->header()->setClickEnabled((*m_propSet)["clickable"].value().toBool(), current + 1);
0341     m_listview->header()->setResizeEnabled((*m_propSet)["resizable"].value().toBool(), current + 1);
0342     m_listview->header()->setStretchEnabled((*m_propSet)["fullwidth"].value().toBool(), current + 1);
0343 
0344     m_listbox->blockSignals(false);
0345     m_listbox->setCurrentItem(current + 1);
0346 }
0347 
0348 
0349 /// Contents page slots ////////
0350 void
0351 EditListViewDialog::updateButtons(QListViewItem *item)
0352 {
0353     if (!item) {
0354         foreach (QToolButton *button, m_buttons) {
0355             button->setEnabled(false);
0356         }
0357         return;
0358     }
0359 
0360     m_buttons[BNewChild]->setEnabled(true);
0361     m_buttons[BRemRow]->setEnabled(true);
0362     m_buttons[BRowUp]->setEnabled((item->itemAbove() && (item->itemAbove()->parent() == item->parent())));
0363     m_buttons[BRowDown]->setEnabled(item->nextSibling());
0364 }
0365 
0366 void
0367 EditListViewDialog::loadChildNodes(QListView *listview, QListViewItem *item, QListViewItem *parent)
0368 {
0369     QListViewItem *newItem;
0370     if (listview->inherits("KListView")) {
0371         if (parent)
0372             newItem = new KListViewItem(parent);
0373         else
0374             newItem = new KListViewItem(listview);
0375     } else {
0376         if (parent)
0377             newItem = new QListViewItem(parent);
0378         else
0379             newItem = new QListViewItem(listview);
0380     }
0381 
0382     // We need to move the item at the end, which is the expected behaviour (by default it is inserted at the beginning)
0383     QListViewItem *last;
0384     if (parent)
0385         last = parent->firstChild();
0386     else
0387         last = listview->firstChild();
0388 
0389     while (last->nextSibling())
0390         last = last->nextSibling();
0391     newItem->moveItem(last);
0392 
0393     // We copy the text of all the columns
0394     for (int i = 0; i < listview->columns(); i++)
0395         newItem->setText(i, item->text(i));
0396 
0397     QListViewItem *child = item->firstChild();
0398     if (child)
0399         newItem->setOpen(true);
0400     while (child)  {
0401         loadChildNodes(listview, child, newItem);
0402         child = child->nextSibling();
0403     }
0404 }
0405 
0406 void
0407 EditListViewDialog::newRow()
0408 {
0409     KListViewItem *parent = (KListViewItem*)m_listview->selectedItem();
0410     if (parent)
0411         parent = (KListViewItem*)parent->parent();
0412     KListViewItem *item;
0413     if (parent)
0414         item = new KListViewItem(parent, m_listview->selectedItem());
0415     else
0416         item = new KListViewItem(m_listview, m_listview->selectedItem());
0417     item->setText(0, xi18n("New Item"));
0418     m_listview->setCurrentItem(item);
0419 }
0420 
0421 void
0422 EditListViewDialog::newChildRow()
0423 {
0424     KListViewItem *parent = (KListViewItem*)m_listview->currentItem();
0425     KListViewItem *item;
0426     if (parent)
0427         item = new KListViewItem(parent);
0428     else
0429         item = new KListViewItem(m_listview, m_listview->currentItem());
0430     item->setText(0, xi18n("Sub Item"));
0431 
0432     m_listview->setCurrentItem(item);
0433     if (parent)
0434         parent->setOpen(true);
0435 }
0436 
0437 void
0438 EditListViewDialog::removeRow()
0439 {
0440     delete m_listview->currentItem();
0441 }
0442 
0443 void
0444 EditListViewDialog::MoveRowUp()
0445 {
0446     QListViewItem *item = m_listview->currentItem()->itemAbove();
0447     item->moveItem(m_listview->currentItem());
0448     updateButtons(m_listview->currentItem());
0449 }
0450 
0451 void
0452 EditListViewDialog::MoveRowDown()
0453 {
0454     QListViewItem *before = m_listview->currentItem();
0455     before->moveItem(before->nextSibling());
0456     updateButtons(before);
0457 }
0458 
0459 }
0460 
0461 //! @todo KEXI3 noi18n # added to disable message extraction in Messages.sh