BlockTreeDock::BlockTreeDock(QWidget *parent): QDockWidget(parent), _searchBox(new QLineEdit(this)) { this->setObjectName("BlockTreeDock"); this->setWindowTitle(tr("Block Tree")); this->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); this->setWidget(new QWidget(this)); auto layout = new QVBoxLayout(this->widget()); this->widget()->setLayout(layout); _searchBox->setPlaceholderText(tr("Search blocks")); #if QT_VERSION > 0x050200 _searchBox->setClearButtonEnabled(true); #endif layout->addWidget(_searchBox); _blockTree = new BlockTreeWidget(this->widget()); connect(getObjectMap()["blockCache"], SIGNAL(blockDescUpdate(const Poco::JSON::Array::Ptr &)), _blockTree, SLOT(handleBlockDescUpdate(const Poco::JSON::Array::Ptr &))); connect(_blockTree, SIGNAL(blockDescEvent(const Poco::JSON::Object::Ptr &, bool)), this, SLOT(handleBlockDescEvent(const Poco::JSON::Object::Ptr &, bool))); connect(_searchBox, SIGNAL(textChanged(const QString &)), _blockTree, SLOT(handleFilter(const QString &))); layout->addWidget(_blockTree); _addButton = new QPushButton(makeIconFromTheme("list-add"), "Add Block", this->widget()); layout->addWidget(_addButton); connect(_addButton, SIGNAL(released(void)), this, SLOT(handleAdd(void))); _addButton->setEnabled(false); //default disabled }
AffinityZonesDock::AffinityZonesDock(QWidget *parent): QDockWidget(parent), _mapper(new QSignalMapper(this)), _zoneEntry(new QLineEdit(this)), _createButton(new QPushButton(makeIconFromTheme("list-add"), tr("Create zone"), this)), _editorsTabs(new QTabWidget(this)) { this->setObjectName("AffinityZonesDock"); this->setWindowTitle(tr("Affinity Zones")); this->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); this->setWidget(new QWidget(this)); //layout setup auto mainLayout = new QVBoxLayout(this->widget()); this->widget()->setLayout(mainLayout); //editors area { mainLayout->addWidget(_editorsTabs); _editorsTabs->setTabsClosable(true); _editorsTabs->setMovable(true); _editorsTabs->setUsesScrollButtons(true); _editorsTabs->setTabPosition(QTabWidget::North); _editorsTabs->setStyleSheet( QString("QTabBar::close-button {image: url(%1);}").arg(makeIconPath("standardbutton-closetab-16.png"))+ QString("QTabBar::close-button:hover {image: url(%1);}").arg(makeIconPath("standardbutton-closetab-hover-16.png"))+ QString("QTabBar::close-button:pressed {image: url(%1);}").arg(makeIconPath("standardbutton-closetab-down-16.png"))); connect(_mapper, SIGNAL(mapped(const QString &)), this, SIGNAL(zoneChanged(const QString &))); } //zone creation area { auto hbox = new QHBoxLayout(); mainLayout->addLayout(hbox); hbox->addWidget(_zoneEntry); hbox->addWidget(_createButton); _zoneEntry->setPlaceholderText(tr("Enter a new zone name...")); _createButton->setToolTip(tr("Create a new affinity zone editor panel.")); connect(_zoneEntry, SIGNAL(returnPressed(void)), this, SLOT(handleCreateZone(void))); connect(_createButton, SIGNAL(pressed(void)), this, SLOT(handleCreateZone(void))); } this->initAffinityZoneEditors(); }
BlockPropertiesPanel::BlockPropertiesPanel(GraphBlock *block, QWidget *parent): QWidget(parent), _ignoreChanges(true), _idLabel(new QLabel(this)), _idLineEdit(new QLineEdit(this)), _affinityZoneLabel(new QLabel(this)), _affinityZoneBox(nullptr), _blockErrorLabel(new QLabel(this)), _updateTimer(new QTimer(this)), _formLayout(nullptr), _block(block) { auto blockDesc = block->getBlockDesc(); //master layout for this widget auto layout = new QVBoxLayout(this); //create a scroller and a form layout auto scroll = new QScrollArea(this); scroll->setWidgetResizable(true); scroll->setWidget(new QWidget(scroll)); _formLayout = new QFormLayout(scroll); scroll->widget()->setLayout(_formLayout); layout->addWidget(scroll); //title { auto label = new QLabel(QString("<h1>%1</h1>").arg(_block->getTitle().toHtmlEscaped()), this); label->setAlignment(Qt::AlignCenter); _formLayout->addRow(label); } //errors { _formLayout->addRow(_blockErrorLabel); } //id { _idOriginal = _block->getId(); _formLayout->addRow(_idLabel, _idLineEdit); connect(_idLineEdit, SIGNAL(textEdited(const QString &)), this, SLOT(handleEditWidgetChanged(const QString &))); connect(_idLineEdit, SIGNAL(returnPressed(void)), this, SLOT(handleCommitButton(void))); } //properties for (const auto &prop : _block->getProperties()) { _propIdToOriginal[prop.getKey()] = _block->getPropertyValue(prop.getKey()); auto paramDesc = _block->getParamDesc(prop.getKey()); assert(paramDesc); //create editable widget auto editWidget = new BlockPropertyEditWidget(paramDesc, this); connect(editWidget, SIGNAL(valueChanged(void)), this, SLOT(handleEditWidgetChanged(void))); connect(editWidget, SIGNAL(commitRequested(void)), this, SLOT(handleCommitButton(void))); _propIdToEditWidget[prop.getKey()] = editWidget; //create labels _propIdToFormLabel[prop.getKey()] = new QLabel(this); _propIdToErrorLabel[prop.getKey()] = new QLabel(this); editWidget->setToolTip(this->getParamDocString(_block->getParamDesc(prop.getKey()))); //layout stuff auto editLayout = new QVBoxLayout(); editLayout->addWidget(editWidget); editLayout->addWidget(_propIdToErrorLabel[prop.getKey()]); _formLayout->addRow(_propIdToFormLabel[prop.getKey()], editLayout); } //affinity zone { _affinityZoneOriginal = _block->getAffinityZone(); auto dock = dynamic_cast<AffinityZonesDock *>(getObjectMap()["affinityZonesDock"]); assert(dock != nullptr); _affinityZoneBox = dock->makeComboBox(this); _formLayout->addRow(_affinityZoneLabel, _affinityZoneBox); connect(_affinityZoneBox, SIGNAL(activated(const QString &)), this, SLOT(handleEditWidgetChanged(const QString &))); } //draw the block's preview onto a mini pixmap //this is cool, maybe useful, but its big, where can we put it? /* { const auto bounds = _block->getBoundingRect(); QPixmap pixmap(bounds.size().toSize()+QSize(2,2)); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.translate(-bounds.topLeft()+QPoint(1,1)); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); _block->render(painter); painter.end(); auto label = new QLabel(this); label->setPixmap(pixmap); _formLayout->addRow(label); _formLayout->setAlignment(label, Qt::AlignHCenter); } */ //block level description if (blockDesc->isArray("docs")) { QString output; output += QString("<h1>%1</h1>").arg(QString::fromStdString(blockDesc->get("name").convert<std::string>())); output += QString("<p>%1</p>").arg(QString::fromStdString(block->getBlockDescPath())); output += "<p>"; for (const auto &lineObj : *blockDesc->getArray("docs")) { const auto line = lineObj.extract<std::string>(); if (line.empty()) output += "<p /><p>"; else output += QString::fromStdString(line)+"\n"; } output += "</p>"; //enumerate properties if (not _block->getProperties().empty()) { output += QString("<h2>%1</h2>").arg(tr("Properties")); for (const auto &prop : _block->getProperties()) { output += this->getParamDocString(_block->getParamDesc(prop.getKey())); } } //enumerate slots if (not block->getSlotPorts().empty()) { output += QString("<h2>%1</h2>").arg(tr("Slots")); output += "<ul>"; for (const auto &port : block->getSlotPorts()) { output += QString("<li>%1(...)</li>").arg(port.getName()); } output += "</ul>"; } //enumerate signals if (not block->getSignalPorts().empty()) { output += QString("<h2>%1</h2>").arg(tr("Signals")); output += "<ul>"; for (const auto &port : block->getSignalPorts()) { output += QString("<li>%1(...)</li>").arg(port.getName()); } output += "</ul>"; } auto text = new QLabel(output, this); text->setStyleSheet("QLabel{background:white;margin:1px;}"); text->setWordWrap(true); _formLayout->addRow(text); } //buttons { auto buttonLayout = new QHBoxLayout(); layout->addLayout(buttonLayout); auto commitButton = new QPushButton(makeIconFromTheme("dialog-ok-apply"), tr("Commit"), this); connect(commitButton, SIGNAL(pressed(void)), this, SLOT(handleCommitButton(void))); buttonLayout->addWidget(commitButton); auto cancelButton = new QPushButton(makeIconFromTheme("dialog-cancel"), tr("Cancel"), this); connect(cancelButton, SIGNAL(pressed(void)), this, SLOT(handleCancelButton(void))); buttonLayout->addWidget(cancelButton); } //update timer _updateTimer->setSingleShot(true); _updateTimer->setInterval(UPDATE_TIMER_MS); connect(_updateTimer, SIGNAL(timeout(void)), this, SLOT(handleUpdateTimerExpired(void))); //connect state change to the graph editor auto draw = dynamic_cast<GraphDraw *>(_block->parent()); auto editor = draw->getGraphEditor(); connect(this, SIGNAL(stateChanged(const GraphState &)), editor, SLOT(handleStateChange(const GraphState &))); connect(_block, SIGNAL(destroyed(QObject*)), this, SLOT(handleBlockDestroyed(QObject*))); this->updateAllForms(); _ignoreChanges = false; }
ConnectionPropertiesPanel::ConnectionPropertiesPanel(GraphConnection *conn, QWidget *parent): QWidget(parent), _conn(conn), _isSlot(_conn->getInputEndpoint().getConnectableAttrs().direction == GRAPH_CONN_SLOT), _isSignal(_conn->getOutputEndpoint().getConnectableAttrs().direction == GRAPH_CONN_SIGNAL), _removeButton(nullptr), _inputListWidget(nullptr), _outputListWidget(nullptr), _connectionsListWidget(nullptr) { //master layout for this widget auto layout = new QVBoxLayout(this); auto inputEp = _conn->getInputEndpoint(); auto outputEp = _conn->getOutputEndpoint(); //title { auto label = new QLabel(tr("<h1>%1</h1>").arg(tr("Connection")), this); label->setAlignment(Qt::AlignCenter); layout->addWidget(label); } //signal/slots selection boxes { auto listWidgetLayout = new QHBoxLayout(); layout->addLayout(listWidgetLayout); //output list _outputListWidget = this->makePortListWidget(this, outputEp, _outputItemToKey); connect(_outputListWidget, SIGNAL(itemSelectionChanged(void)), this, SLOT(handleItemSelectionChanged(void))); listWidgetLayout->addWidget(_outputListWidget); //input list _inputListWidget = this->makePortListWidget(this, inputEp, _inputItemToKey); connect(_inputListWidget, SIGNAL(itemSelectionChanged(void)), this, SLOT(handleItemSelectionChanged(void))); listWidgetLayout->addWidget(_inputListWidget); } //existing connections { _connectionsListWidget = new QTreeWidget(this); layout->addWidget(_connectionsListWidget); _connectionsListWidget->setColumnCount(1); _connectionsListWidget->setHeaderLabels(QStringList(tr("Signal slot connections"))); connect(_connectionsListWidget, SIGNAL(itemSelectionChanged(void)), this, SLOT(handleItemSelectionChanged(void))); //save pre-edit settings _originalKeyPairs = _conn->getSigSlotPairs(); } //remove button { _removeButton = new QPushButton(makeIconFromTheme("list-remove"), tr("Remove connection"), this); connect(_removeButton, SIGNAL(pressed(void)), this, SLOT(handleRemoveConnection(void))); layout->addWidget(_removeButton); } connect(_conn, SIGNAL(destroyed(QObject*)), this, SLOT(handleConnectionDestroyed(QObject*))); this->handleItemSelectionChanged(); //init state this->populateConnectionsList(); //init state }