diff --git a/src/App/PropertyLinks.h b/src/App/PropertyLinks.h index e69b874d8b..5d9dfac110 100644 --- a/src/App/PropertyLinks.h +++ b/src/App/PropertyLinks.h @@ -217,6 +217,8 @@ public: virtual void Paste(const Property &from); virtual unsigned int getMemSize(void) const; + virtual const char* getEditorName(void) const + { return "Gui::PropertyEditor::PropertyLinkListItem"; } private: std::vector _lValueList; diff --git a/src/Gui/DlgPropertyLink.cpp b/src/Gui/DlgPropertyLink.cpp index 6021595a39..f3a7aaab40 100644 --- a/src/Gui/DlgPropertyLink.cpp +++ b/src/Gui/DlgPropertyLink.cpp @@ -59,19 +59,28 @@ DlgPropertyLink::DlgPropertyLink(const QStringList& list, QWidget* parent, Qt::W */ DlgPropertyLink::~DlgPropertyLink() { - // no need to delete child widgets, Qt does it all for us + // no need to delete child widgets, Qt does it all for us delete ui; } +void DlgPropertyLink::setSelectionMode(QAbstractItemView::SelectionMode mode) +{ + ui->listWidget->setSelectionMode(mode); + ui->listWidget->clear(); + findObjects(ui->checkObjectType->isChecked()); +} + void DlgPropertyLink::accept() { - QList items = ui->listWidget->selectedItems(); - if (items.isEmpty()) { - QMessageBox::warning(this, tr("No selection"), tr("Please select an object from the list")); - } - else { - QDialog::accept(); + if (ui->listWidget->selectionMode() == QAbstractItemView::SingleSelection) { + QList items = ui->listWidget->selectedItems(); + if (items.isEmpty()) { + QMessageBox::warning(this, tr("No selection"), tr("Please select an object from the list")); + return; + } } + + QDialog::accept(); } QStringList DlgPropertyLink::propertyLink() const @@ -90,6 +99,27 @@ QStringList DlgPropertyLink::propertyLink() const } } +QVariantList DlgPropertyLink::propertyLinkList() const +{ + QVariantList varList; + QList items = ui->listWidget->selectedItems(); + if (items.isEmpty()) { + varList << link; + } + else { + for (QList::iterator it = items.begin(); it != items.end(); ++it) { + QStringList list = link; + list[1] = (*it)->data(Qt::UserRole).toString(); + list[2] = (*it)->text(); + if (list[1].isEmpty()) + list[2] = QString::fromUtf8(""); + varList << list; + } + } + + return varList; +} + void DlgPropertyLink::findObjects(bool on) { QString docName = link[0]; @@ -129,10 +159,12 @@ void DlgPropertyLink::findObjects(bool on) } // Add a "None" entry on top - QListWidgetItem* item = new QListWidgetItem(ui->listWidget); - item->setText(tr("None (Remove link)")); - QByteArray ba(""); - item->setData(Qt::UserRole, ba); + if (ui->listWidget->selectionMode() == QAbstractItemView::SingleSelection) { + QListWidgetItem* item = new QListWidgetItem(ui->listWidget); + item->setText(tr("None (Remove link)")); + QByteArray ba(""); + item->setData(Qt::UserRole, ba); + } std::vector obj = doc->getObjectsOfType(baseType); for (std::vector::iterator it = obj.begin(); it != obj.end(); ++it) { diff --git a/src/Gui/DlgPropertyLink.h b/src/Gui/DlgPropertyLink.h index a9bd36015e..41705847dd 100644 --- a/src/Gui/DlgPropertyLink.h +++ b/src/Gui/DlgPropertyLink.h @@ -25,6 +25,7 @@ #define GUI_DIALOG_DLGPROPERTYLINK_H #include +#include namespace Gui { namespace Dialog { @@ -37,8 +38,10 @@ public: DlgPropertyLink(const QStringList& list, QWidget* parent = 0, Qt::WindowFlags fl = 0); ~DlgPropertyLink(); + void setSelectionMode(QAbstractItemView::SelectionMode mode); void accept(); QStringList propertyLink() const; + QVariantList propertyLinkList() const; private Q_SLOTS: void on_checkObjectType_toggled(bool); diff --git a/src/Gui/SoFCDB.cpp b/src/Gui/SoFCDB.cpp index c8aed2114c..65d988d189 100644 --- a/src/Gui/SoFCDB.cpp +++ b/src/Gui/SoFCDB.cpp @@ -151,6 +151,7 @@ void Gui::SoFCDB::init() PropertyPathItem ::init(); PropertyTransientFileItem ::init(); PropertyLinkItem ::init(); + PropertyLinkListItem ::init(); NavigationStyle ::init(); UserNavigationStyle ::init(); diff --git a/src/Gui/propertyeditor/PropertyItem.cpp b/src/Gui/propertyeditor/PropertyItem.cpp index d802b41a8e..22a6276094 100644 --- a/src/Gui/propertyeditor/PropertyItem.cpp +++ b/src/Gui/propertyeditor/PropertyItem.cpp @@ -3462,6 +3462,7 @@ QVariant PropertyLinkItem::value(const App::Property* prop) const const App::PropertyLink* prop_link = static_cast(prop); App::PropertyContainer* c = prop_link->getContainer(); + // the list has four elements: [document name, internal name, label, internal name of container] App::DocumentObject* obj = prop_link->getValue(); QStringList list; if (obj) { @@ -3539,6 +3540,188 @@ QVariant PropertyLinkItem::editorData(QWidget *editor) const // -------------------------------------------------------------------- +LinkListLabel::LinkListLabel (QWidget * parent) : QWidget(parent) +{ + QHBoxLayout *layout = new QHBoxLayout(this); + layout->setMargin(0); + layout->setSpacing(1); + + label = new QLabel(this); + label->setAutoFillBackground(true); + layout->addWidget(label); + + editButton = new QPushButton(QLatin1String("..."), this); + editButton->setToolTip(tr("Change the linked objects")); + layout->addWidget(editButton); + + // setLayout(layout); + connect(editButton, SIGNAL(clicked()), + this, SLOT(onEditClicked())); +} + +LinkListLabel::~LinkListLabel() +{ +} + +void LinkListLabel::setPropertyLinkList(const QVariantList& o) +{ + links = o; + if (links.isEmpty()) { + label->clear(); + } + else if (links.size() == 1) { + QStringList s = links.front().toStringList(); + label->setText(s[2]); + } + else { + QStringList obj; + for (QVariantList::iterator it = links.begin(); it != links.end(); ++it) + obj << it->toStringList()[2]; + label->setText(QString::fromLatin1("[%1]").arg(obj.join(QString::fromLatin1(", ")))); + } +} + +QVariantList LinkListLabel::propertyLinkList() const +{ + return links; +} + +void LinkListLabel::onEditClicked () +{ + QStringList list = links.front().toStringList(); + Gui::Dialog::DlgPropertyLink dlg(list, this); + dlg.setSelectionMode(QAbstractItemView::ExtendedSelection); + if (dlg.exec() == QDialog::Accepted) { + setPropertyLinkList(dlg.propertyLinkList()); + Q_EMIT linkChanged(links); + } +} + +void LinkListLabel::resizeEvent(QResizeEvent* e) +{ + editButton->setFixedWidth(e->size().height()); +} + + +PROPERTYITEM_SOURCE(Gui::PropertyEditor::PropertyLinkListItem) + +PropertyLinkListItem::PropertyLinkListItem() +{ +} + +QVariant PropertyLinkListItem::toString(const QVariant& prop) const +{ + QVariantList list = prop.toList(); + if (list.empty()) { + return QString(); + } + else if (list.size() == 1) { + QStringList item = list.front().toStringList(); + return QString::fromLatin1("%1").arg(item[2]); + } + else { + QStringList obj; + for (QVariantList::iterator it = list.begin(); it != list.end(); ++it) + obj << it->toStringList()[2]; + return QString::fromLatin1("[%1]").arg(obj.join(QString::fromLatin1(", "))); + } +} + +QVariant PropertyLinkListItem::value(const App::Property* prop) const +{ + assert(prop && prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())); + + const App::PropertyLinkList* prop_link = static_cast(prop); + App::PropertyContainer* c = prop_link->getContainer(); + + // the name of this object + QString objName; + if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { + App::DocumentObject* obj = static_cast(c); + objName = QString::fromLatin1(obj->getNameInDocument()); + } + else { + objName = QString::fromLatin1("Null"); + } + + // each item is a list of four elements: [document name, internal name, label, internal name of container] + // the variant list contains at least one item + std::vector obj = prop_link->getValues(); + QVariantList varList; + if (!obj.empty()) { + for (std::vector::iterator it = obj.begin(); it != obj.end(); ++it) { + QStringList list; + list << QString::fromLatin1((*it)->getDocument()->getName()); + list << QString::fromLatin1((*it)->getNameInDocument()); + list << QString::fromUtf8((*it)->Label.getValue()); + list << objName; + varList << list; + } + } + else { + QStringList list; + // no object assigned + // the document name + if (c->getTypeId().isDerivedFrom(App::DocumentObject::getClassTypeId())) { + App::DocumentObject* obj = static_cast(c); + list << QString::fromLatin1(obj->getDocument()->getName()); + } + else { + list << QString::fromLatin1(""); + } + + // the internal object name + list << QString::fromLatin1("Null"); + // the object label + list << QString::fromLatin1(""); + list << objName; + varList << list; + } + + return QVariant(varList); +} + +void PropertyLinkListItem::setValue(const QVariant& value) +{ + if (!value.canConvert(QVariant::List)) + return; + QVariantList items = value.toList(); + QStringList data; + for (QVariantList::iterator it = items.begin(); it != items.end(); ++it) { + QStringList list = it->toStringList(); + QString d = list[0]; + QString o = list[1]; + if (!o.isEmpty()) + data << QString::fromLatin1("App.getDocument('%1').getObject('%2')").arg(d).arg(o); + } + + setPropertyValue(QString::fromLatin1("[%1]").arg(data.join(QString::fromLatin1(", ")))); +} + +QWidget* PropertyLinkListItem::createEditor(QWidget* parent, const QObject* receiver, const char* method) const +{ + LinkListLabel *ll = new LinkListLabel(parent); + ll->setAutoFillBackground(true); + ll->setDisabled(isReadOnly()); + QObject::connect(ll, SIGNAL(linkChanged(const QVariantList&)), receiver, method); + return ll; +} + +void PropertyLinkListItem::setEditorData(QWidget *editor, const QVariant& data) const +{ + QVariantList list = data.toList(); + LinkListLabel *ll = static_cast(editor); + ll->setPropertyLinkList(list); +} + +QVariant PropertyLinkListItem::editorData(QWidget *editor) const +{ + LinkListLabel *ll = static_cast(editor); + return QVariant(ll->propertyLinkList()); +} + +// -------------------------------------------------------------------- + PropertyItemEditorFactory::PropertyItemEditorFactory() { } diff --git a/src/Gui/propertyeditor/PropertyItem.h b/src/Gui/propertyeditor/PropertyItem.h index a425981a02..0929cdf735 100644 --- a/src/Gui/propertyeditor/PropertyItem.h +++ b/src/Gui/propertyeditor/PropertyItem.h @@ -968,6 +968,52 @@ protected: PropertyLinkItem(); }; +class LinkListLabel : public QWidget +{ + Q_OBJECT + +public: + LinkListLabel (QWidget * parent = 0); + virtual ~LinkListLabel(); + void setPropertyLinkList(const QVariantList& o); + QVariantList propertyLinkList() const; + +protected: + void resizeEvent(QResizeEvent*); + +protected Q_SLOTS: + void onEditClicked(); + +Q_SIGNALS: + void linkChanged(const QVariantList&); + +private: + QLabel* label; + QPushButton* editButton; + QVariantList links; +}; + +/** + * Edit properties of link list type. + * \author Werner Mayer + */ +class GuiExport PropertyLinkListItem: public PropertyItem +{ + PROPERTYITEM_HEADER + + virtual QWidget* createEditor(QWidget* parent, const QObject* receiver, const char* method) const; + virtual void setEditorData(QWidget *editor, const QVariant& data) const; + virtual QVariant editorData(QWidget *editor) const; + +protected: + virtual QVariant toString(const QVariant&) const; + virtual QVariant value(const App::Property*) const; + virtual void setValue(const QVariant&); + +protected: + PropertyLinkListItem(); +}; + class PropertyItemEditorFactory : public QItemEditorFactory { public: