/**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of the Qt Mobility Components. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://qt.digia.com/licensing. For further information ** use the contact form at http://qt.digia.com/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3.0 as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU General Public License version 3.0 requirements will be ** met: http://www.gnu.org/copyleft/gpl.html. ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "interfacewidget.h" #include "mandatorylineedit.h" #include "errorcollector.h" #include #include #include #include #include #include #include #include #include #include #include #include QTM_USE_NAMESPACE class EditableListWidgetGroup : public QWidget { Q_OBJECT public: EditableListWidgetGroup(QWidget *parent = 0); signals: void dataChanged(); protected: virtual int addItem() = 0; virtual bool removeItemAt(int index) = 0; virtual QStringList listValues() const = 0; void initLayout(QLayout *addItemLayout, const QString &buttonAddText); void refreshView(); void setAddButtonEnabled(bool enabled); private slots: void clickedAdd(); void clickedRemove(); void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous); private: QString defaultValue() const; QStringListModel *m_model; QListView *m_listView; QPushButton *m_buttonAdd; QPushButton *m_buttonDel; QGridLayout *m_grid; }; EditableListWidgetGroup::EditableListWidgetGroup(QWidget *parent) : QWidget(parent), m_model(new QStringListModel(this)), m_listView(new QListView), m_buttonAdd(new QPushButton), m_buttonDel(new QPushButton(tr("Delete"))), m_grid(new QGridLayout) { m_listView->setEditTriggers(QAbstractItemView::NoEditTriggers); } void EditableListWidgetGroup::initLayout(QLayout *addItemLayout, const QString &buttonAddText) { m_buttonAdd->setText(buttonAddText); m_grid->setContentsMargins(0, 0, 0, 0); m_grid->addWidget(m_listView, 0, 0); m_grid->addWidget(m_buttonDel, 0, 1, Qt::AlignTop); m_grid->addWidget(m_buttonAdd, 1, 1); if (addItemLayout) m_grid->addLayout(addItemLayout, 1, 0); m_model->setStringList(QStringList(defaultValue())); m_listView->setModel(m_model); m_buttonAdd->setEnabled(false); m_buttonDel->setEnabled(false); connect(m_buttonAdd, SIGNAL(clicked()), SLOT(clickedAdd())); connect(m_buttonDel, SIGNAL(clicked()), SLOT(clickedRemove())); connect(m_listView->selectionModel(), SIGNAL(currentRowChanged(QModelIndex,QModelIndex)), SLOT(currentRowChanged(QModelIndex,QModelIndex))); setLayout(m_grid); } void EditableListWidgetGroup::refreshView() { QStringList values = listValues(); if (values.isEmpty()) m_model->setStringList(QStringList(defaultValue())); else m_model->setStringList(values); } void EditableListWidgetGroup::setAddButtonEnabled(bool enabled) { m_buttonAdd->setEnabled(enabled); } void EditableListWidgetGroup::clickedAdd() { int index = addItem(); if (index >= 0) { refreshView(); m_listView->setCurrentIndex(m_model->index(index)); emit dataChanged(); } } void EditableListWidgetGroup::clickedRemove() { QModelIndex index = m_listView->currentIndex(); if (index.isValid() && removeItemAt(index.row())) { refreshView(); m_listView->setCurrentIndex(m_model->index(index.row() == 0 ? 0 : index.row()-1)); emit dataChanged(); } } void EditableListWidgetGroup::currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous) { Q_UNUSED(previous); m_buttonDel->setEnabled(current.isValid() && listValues().count() > 0); } QString EditableListWidgetGroup::defaultValue() const { return tr("(None)"); } class CapabilitiesWidget : public EditableListWidgetGroup { Q_OBJECT public: CapabilitiesWidget(QWidget *parent = 0); void setCapabilities(const QStringList &values); const QStringList &capabilities() const { return m_values; } protected: virtual int addItem(); virtual bool removeItemAt(int index); virtual QStringList listValues() const; private slots: void valueToAddChanged(const QString &text); private: QStringList m_values; QLineEdit *m_newValueEdit; }; CapabilitiesWidget::CapabilitiesWidget(QWidget *parent) : EditableListWidgetGroup(parent), m_newValueEdit(new QLineEdit) { connect(m_newValueEdit, SIGNAL(textChanged(QString)), SLOT(valueToAddChanged(QString))); QHBoxLayout *box = new QHBoxLayout; box->addWidget(m_newValueEdit); initLayout(box, tr("Add")); } void CapabilitiesWidget::setCapabilities(const QStringList &values) { m_values = values; refreshView(); } int CapabilitiesWidget::addItem() { if (!m_newValueEdit->text().isEmpty()) { m_values << m_newValueEdit->text(); m_newValueEdit->clear(); return m_values.count() - 1; } return -1; } bool CapabilitiesWidget::removeItemAt(int index) { if (index >= 0 && index < m_values.count()) { m_values.removeAt(index); return true; } return false; } QStringList CapabilitiesWidget::listValues() const { return m_values; } void CapabilitiesWidget::valueToAddChanged(const QString &text) { setAddButtonEnabled(!text.isEmpty()); } class CustomPropertiesWidget : public EditableListWidgetGroup { Q_OBJECT public: CustomPropertiesWidget(QWidget *parent = 0); void setProperties(const QHash &values); const QStringList &propertyKeys() const { return m_keys; } const QHash &properties() const { return m_pairs; } protected: virtual int addItem(); virtual bool removeItemAt(int index); virtual QStringList listValues() const; private slots: void keyToAddChanged(const QString &text); private: QStringList m_keys; QHash m_pairs; QLineEdit *m_newKeyEdit; QLineEdit *m_newValueEdit; }; CustomPropertiesWidget::CustomPropertiesWidget(QWidget *parent) : EditableListWidgetGroup(parent), m_newKeyEdit(new QLineEdit), m_newValueEdit(new QLineEdit) { connect(m_newKeyEdit, SIGNAL(textChanged(QString)), SLOT(keyToAddChanged(QString))); QHBoxLayout *box = new QHBoxLayout; box->addWidget(m_newKeyEdit); box->addWidget(new QLabel(QLatin1String("=>"))); box->addWidget(m_newValueEdit); initLayout(box, tr("Add / Modify")); } void CustomPropertiesWidget::setProperties(const QHash &values) { m_pairs = values; m_keys = m_pairs.keys(); refreshView(); } int CustomPropertiesWidget::addItem() { int index = -1; QString key = m_newKeyEdit->text(); if (!key.isEmpty()) { index = m_keys.indexOf(key); if (index < 0) { m_keys << key; index = m_keys.count() - 1; } m_pairs[key] = m_newValueEdit->text(); m_newKeyEdit->clear(); m_newValueEdit->clear(); } return index; } bool CustomPropertiesWidget::removeItemAt(int index) { if (index >= 0 && index < m_keys.count()) { m_pairs.remove(m_keys.takeAt(index)); return true; } return false; } QStringList CustomPropertiesWidget::listValues() const { QStringList values; for (int i=0; i " + m_pairs[m_keys[i]]); return values; } void CustomPropertiesWidget::keyToAddChanged(const QString &text) { setAddButtonEnabled(!text.isEmpty()); } InterfaceWidget::InterfaceWidget(QWidget *parent) : QWidget(parent), m_name(new MandatoryLineEdit(tr("(Name required)"))), m_verMajor(new QSpinBox), m_verMinor(new QSpinBox), m_desc(new QLineEdit), m_capWidget(new CapabilitiesWidget), m_customPropWidget(new CustomPropertiesWidget) { m_verMajor->setMinimum(1); // min version as documented for interfaces QHBoxLayout *versions = new QHBoxLayout; versions->addWidget(m_verMajor); versions->addWidget(new QLabel(tr("(Major)"))); versions->addWidget(m_verMinor); versions->addWidget(new QLabel(tr("(Minor)"))); QFormLayout *form = new QFormLayout; form->addRow(tr("* Name"), m_name); form->addRow(tr("* Version"), versions); form->addRow(tr("Description"), m_desc); form->addRow(tr("Capabilities"), m_capWidget); form->addRow(tr("Custom attributes"), m_customPropWidget); setLayout(form); connect(m_name, SIGNAL(textEdited(QString)), SLOT(changedNameOrVersion())); connect(m_verMajor, SIGNAL(valueChanged(int)), SLOT(changedNameOrVersion())); connect(m_verMinor, SIGNAL(valueChanged(int)), SLOT(changedNameOrVersion())); connect(m_desc, SIGNAL(textEdited(QString)), SIGNAL(dataChanged())); connect(m_capWidget, SIGNAL(dataChanged()), SIGNAL(dataChanged())); connect(m_customPropWidget, SIGNAL(dataChanged()), SIGNAL(dataChanged())); } void InterfaceWidget::init() { m_name->setFocus(); } void InterfaceWidget::load(const QServiceInterfaceDescriptor &info) { const QServiceInterfaceDescriptorPrivate *p = QServiceInterfaceDescriptorPrivate::getPrivate(&info); if (!p) return; m_name->setText(p->interfaceName); m_verMajor->setValue(p->major); m_verMinor->setValue(p->minor); if (p->attributes.contains(QServiceInterfaceDescriptor::InterfaceDescription)) m_desc->setText(p->attributes[QServiceInterfaceDescriptor::InterfaceDescription].toString()); if (p->attributes.contains(QServiceInterfaceDescriptor::Capabilities)) m_capWidget->setCapabilities(p->attributes[QServiceInterfaceDescriptor::Capabilities].toStringList()); if (!p->customAttributes.isEmpty()) m_customPropWidget->setProperties(p->customAttributes); } void InterfaceWidget::validate(ErrorCollector *errors) { m_name->validate(errors); } void InterfaceWidget::writeXml(QXmlStreamWriter *writer) const { writer->writeTextElement(QLatin1String("name"), !m_name->hasText() ? QString() : m_name->text()); writer->writeTextElement(QLatin1String("version"), QString("%1.%2").arg(m_verMajor->value()).arg(m_verMinor->value())); writer->writeTextElement(QLatin1String("description"), m_desc->text()); writer->writeTextElement(QLatin1String("capabilities"), m_capWidget->capabilities().join(QLatin1String(","))); const QStringList &customPropKeys = m_customPropWidget->propertyKeys(); const QHash &customProps = m_customPropWidget->properties(); for (int i=0; iwriteStartElement(QLatin1String("customproperty")); writer->writeAttribute(QLatin1String("key"), customPropKeys[i]); writer->writeCharacters(customProps[customPropKeys[i]]); writer->writeEndElement(); } } QString InterfaceWidget::title() const { QString name = m_name->text().isEmpty() ? tr("[New Interface]") : m_name->text(); return QString("%1 %2.%3").arg(name).arg(m_verMajor->value()).arg(m_verMinor->value()); } void InterfaceWidget::changedNameOrVersion() { emit titleChanged(title()); emit dataChanged(); } #include "interfacewidget.moc"