GraphEditor::GraphEditor(QWidget *parent): QTabWidget(parent), _parentTabWidget(dynamic_cast<QTabWidget *>(parent)), _moveGraphObjectsMapper(new QSignalMapper(this)), _insertGraphWidgetsMapper(new QSignalMapper(this)), _stateManager(new GraphStateManager(this)), _evalEngine(new EvalEngine(this)), _isTopologyActive(false) { this->setMovable(true); this->setUsesScrollButtons(true); this->setTabPosition(QTabWidget::West); this->makeDefaultPage(); this->tabBar()->setStyleSheet("font-size:8pt;"); //connect handlers that work at the page-level of control connect(QApplication::clipboard(), SIGNAL(dataChanged(void)), this, SLOT(handleClipboardDataChange(void))); connect(this, SIGNAL(currentChanged(int)), this, SLOT(handleCurrentChanged(int))); connect(_stateManager, SIGNAL(newStateSelected(int)), this, SLOT(handleResetState(int))); connect(getActionMap()["createGraphPage"], SIGNAL(triggered(void)), this, SLOT(handleCreateGraphPage(void))); connect(getActionMap()["renameGraphPage"], SIGNAL(triggered(void)), this, SLOT(handleRenameGraphPage(void))); connect(getActionMap()["deleteGraphPage"], SIGNAL(triggered(void)), this, SLOT(handleDeleteGraphPage(void))); connect(getActionMap()["inputBreaker"], SIGNAL(triggered(void)), this, SLOT(handleCreateInputBreaker(void))); connect(getActionMap()["outputBreaker"], SIGNAL(triggered(void)), this, SLOT(handleCreateOutputBreaker(void))); connect(getActionMap()["cut"], SIGNAL(triggered(void)), this, SLOT(handleCut(void))); connect(getActionMap()["copy"], SIGNAL(triggered(void)), this, SLOT(handleCopy(void))); connect(getActionMap()["paste"], SIGNAL(triggered(void)), this, SLOT(handlePaste(void))); connect(getObjectMap()["blockTreeDock"], SIGNAL(addBlockEvent(const Poco::JSON::Object::Ptr &)), this, SLOT(handleAddBlock(const Poco::JSON::Object::Ptr &))); connect(getActionMap()["selectAll"], SIGNAL(triggered(void)), this, SLOT(handleSelectAll(void))); connect(getActionMap()["delete"], SIGNAL(triggered(void)), this, SLOT(handleDelete(void))); connect(getActionMap()["rotateLeft"], SIGNAL(triggered(void)), this, SLOT(handleRotateLeft(void))); connect(getActionMap()["rotateRight"], SIGNAL(triggered(void)), this, SLOT(handleRotateRight(void))); connect(getActionMap()["objectProperties"], SIGNAL(triggered(void)), this, SLOT(handleObjectProperties(void))); connect(getActionMap()["graphProperties"], SIGNAL(triggered(void)), this, SLOT(handleGraphProperties(void))); connect(getActionMap()["zoomIn"], SIGNAL(triggered(void)), this, SLOT(handleZoomIn(void))); connect(getActionMap()["zoomOut"], SIGNAL(triggered(void)), this, SLOT(handleZoomOut(void))); connect(getActionMap()["zoomOriginal"], SIGNAL(triggered(void)), this, SLOT(handleZoomOriginal(void))); connect(getActionMap()["undo"], SIGNAL(triggered(void)), this, SLOT(handleUndo(void))); connect(getActionMap()["redo"], SIGNAL(triggered(void)), this, SLOT(handleRedo(void))); connect(getActionMap()["enable"], SIGNAL(triggered(void)), this, SLOT(handleEnable(void))); connect(getActionMap()["disable"], SIGNAL(triggered(void)), this, SLOT(handleDisable(void))); connect(getActionMap()["reeval"], SIGNAL(triggered(void)), this, SLOT(handleReeval(void))); connect(getMenuMap()["setAffinityZone"], SIGNAL(zoneClicked(const QString &)), this, SLOT(handleAffinityZoneClicked(const QString &))); connect(getObjectMap()["affinityZonesDock"], SIGNAL(zoneChanged(const QString &)), this, SLOT(handleAffinityZoneChanged(const QString &))); connect(getActionMap()["showRenderedGraph"], SIGNAL(triggered(void)), this, SLOT(handleShowRenderedGraphDialog(void))); connect(getActionMap()["showTopologyStats"], SIGNAL(triggered(void)), this, SLOT(handleShowTopologyStatsDialog(void))); connect(getActionMap()["activateTopology"], SIGNAL(toggled(bool)), this, SLOT(handleToggleActivateTopology(bool))); connect(getActionMap()["showPortNames"], SIGNAL(changed(void)), this, SLOT(handleShowPortNames(void))); connect(getActionMap()["increment"], SIGNAL(triggered(void)), this, SLOT(handleBlockIncrement(void))); connect(getActionMap()["decrement"], SIGNAL(triggered(void)), this, SLOT(handleBlockDecrement(void))); connect(_moveGraphObjectsMapper, SIGNAL(mapped(int)), this, SLOT(handleMoveGraphObjects(int))); connect(_insertGraphWidgetsMapper, SIGNAL(mapped(QObject *)), this, SLOT(handleInsertGraphWidget(QObject *))); connect(_evalEngine, SIGNAL(deactivateDesign(void)), this, SLOT(handleEvalEngineDeactivate(void))); connect(this, SIGNAL(newTitleSubtext(const QString &)), getObjectMap()["mainWindow"], SLOT(handleNewTitleSubtext(const QString &))); }
void GraphEditor::showEvent(QShowEvent *event) { //load our state monitor into the actions dock auto actionsDock = dynamic_cast<GraphActionsDock *>(getObjectMap()["graphActionsDock"]); assert(actionsDock != nullptr); actionsDock->setActiveWidget(_stateManager); this->updateGraphEditorMenus(); this->updateEnabledActions(); QWidget::showEvent(event); }
void LLPathfindingCharacterList::parseCharacterListData(const LLSD& pCharacterListData) { LLPathfindingObjectMap &objectMap = getObjectMap(); for (LLSD::map_const_iterator characterDataIter = pCharacterListData.beginMap(); characterDataIter != pCharacterListData.endMap(); ++characterDataIter) { const std::string& uuid(characterDataIter->first); const LLSD& characterData = characterDataIter->second; LLPathfindingObjectPtr character(new LLPathfindingCharacter(uuid, characterData)); objectMap.insert(std::pair<std::string, LLPathfindingObjectPtr>(uuid, character)); } }
GraphEditorTabs::GraphEditorTabs(QWidget *parent): QTabWidget(parent) { this->setTabsClosable(true); this->setMovable(true); this->setUsesScrollButtons(true); this->setTabPosition(QTabWidget::North); this->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(getObjectMap()["mainWindow"], SIGNAL(initDone(void)), this, SLOT(handleInit(void))); connect(getObjectMap()["mainWindow"], SIGNAL(exitBegin(QCloseEvent *)), this, SLOT(handleExit(QCloseEvent *))); connect(getActionMap()["new"], SIGNAL(triggered(void)), this, SLOT(handleNew(void))); connect(getActionMap()["open"], SIGNAL(triggered(void)), this, SLOT(handleOpen(void))); connect(getActionMap()["save"], SIGNAL(triggered(void)), this, SLOT(handleSave(void))); connect(getActionMap()["saveAs"], SIGNAL(triggered(void)), this, SLOT(handleSaveAs(void))); connect(getActionMap()["saveAll"], SIGNAL(triggered(void)), this, SLOT(handleSaveAll(void))); connect(getActionMap()["reload"], SIGNAL(triggered(void)), this, SLOT(handleReload(void))); connect(getActionMap()["close"], SIGNAL(triggered(void)), this, SLOT(handleClose(void))); connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(handleClose(int))); }
void BlockTreeWidget::mouseMoveEvent(QMouseEvent *event) { if(!(event->buttons() & Qt::LeftButton)) { QTreeWidget::mouseMoveEvent(event); return; } if((event->pos() - _dragStartPos).manhattanLength() < QApplication::startDragDistance()) { QTreeWidget::mouseMoveEvent(event); return; } //get the block data auto blockItem = dynamic_cast<BlockTreeWidgetItem *>(itemAt(_dragStartPos)); if (not blockItem->getBlockDesc()) return; //create a block object to render the image auto draw = dynamic_cast<GraphEditorTabs *>(getObjectMap()["editorTabs"])->getCurrentGraphEditor()->getCurrentGraphDraw(); std::shared_ptr<GraphBlock> renderBlock(new GraphBlock(draw)); renderBlock->setBlockDesc(blockItem->getBlockDesc()); renderBlock->prerender(); //precalculate so we can get bounds const auto bounds = renderBlock->boundingRect(); //draw the block's preview onto a mini pixmap QPixmap pixmap(bounds.size().toSize()+QSize(2,2)); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.translate(-bounds.topLeft()+QPoint(1,1)); //painter.scale(zoomScale, zoomScale); //TODO get zoomscale from draw painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::HighQualityAntialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); renderBlock->render(painter); renderBlock.reset(); painter.end(); //create the drag object auto mimeData = new QMimeData(); std::ostringstream oss; blockItem->getBlockDesc()->stringify(oss); QByteArray byteArray(oss.str().c_str(), oss.str().size()); mimeData->setData("text/json/pothos_block", byteArray); auto drag = new QDrag(this); drag->setMimeData(mimeData); drag->setPixmap(pixmap); drag->setHotSpot(-bounds.topLeft().toPoint()); drag->exec(Qt::CopyAction | Qt::MoveAction); }
AffinityZoneEditor::AffinityZoneEditor(QWidget *parent): QWidget(parent), _hostExplorerDock(dynamic_cast<HostExplorerDock *>(getObjectMap()["hostExplorerDock"])), _colorPicker(new QtColorPicker(this)), _hostsBox(new QComboBox(this)), _processNameEdit(new QLineEdit(this)), _numThreadsSpin(new QSpinBox(this)), _prioritySpin(new QSpinBox(this)), _cpuSelection(nullptr), _cpuSelectionContainer(new QVBoxLayout()), _yieldModeBox(new QComboBox(this)) { assert(_hostExplorerDock != nullptr); //bold title this->setStyleSheet("QGroupBox{font-weight: bold;}"); //setup layout auto formLayout = new QFormLayout(this); this->setLayout(formLayout); //color picker { formLayout->addRow(tr("Affinity color"), _colorPicker); //https://en.wikipedia.org/wiki/List_of_colors_%28compact%29 _colorPicker->insertColor(QColor(119,158,203), tr("Dark pastel blue")); _colorPicker->insertColor(QColor(3,192,60), tr("Dark pastel green")); _colorPicker->insertColor(QColor(150,111,214), tr("Dark pastel purple")); _colorPicker->insertColor(QColor(194,59,34), tr("Dark pastel red")); _colorPicker->insertColor(QColor(177,156,217), tr("Light pastel purple")); _colorPicker->insertColor(QColor(174,198,207), tr("Pastel blue")); _colorPicker->insertColor(QColor(130,105,83), tr("Pastel brown")); _colorPicker->insertColor(QColor(207,207,196), tr("Pastel gray")); _colorPicker->insertColor(QColor(119,221,119), tr("Pastel green")); _colorPicker->insertColor(QColor(244,154,194), tr("Pastel magenta")); _colorPicker->insertColor(QColor(255,179,71), tr("Pastel orange")); _colorPicker->insertColor(QColor(222,165,164), tr("Pastel pink")); _colorPicker->insertColor(QColor(179,158,181), tr("Pastel purple")); _colorPicker->insertColor(QColor(255,105,97), tr("Pastel red")); _colorPicker->insertColor(QColor(203,153,201), tr("Pastel violet")); _colorPicker->insertColor(QColor(253,253,150), tr("Pastel yellow")); _colorPicker->setCurrentColor(QColor(253,253,150)); //Pastel yellow _colorPicker->setToolTip(tr("Select a color to associate affinities in the graph editor")); connect(_colorPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(handleColorChanged(const QColor &))); } //host selection { formLayout->addRow(tr("Host URI"), _hostsBox); _hostsBox->setEditable(true); _hostsBox->setToolTip(tr("Select the URI for a local or remote host")); connect(_hostsBox, SIGNAL(activated(int)), this, SLOT(handleUriChanged(int))); connect(_hostExplorerDock, SIGNAL(hostUriListChanged(void)), this, SLOT(handleHostListChanged(void))); this->handleHostListChanged(); } //process id { formLayout->addRow(tr("Process name"), _processNameEdit); _processNameEdit->setPlaceholderText(tr("The string name of a process")); _processNameEdit->setToolTip(tr("An arbitrary name to identify a process on a node")); connect(_processNameEdit, SIGNAL(editingFinished(void)), this, SLOT(handleProcessNameChanged(void))); } //num threads { formLayout->addRow(tr("Thread count"), _numThreadsSpin); _numThreadsSpin->setRange(0, ARBITRARY_MAX_THREADS); _numThreadsSpin->setToolTip(tr("Number of threads to allocate, 0 means automatic")); connect(_numThreadsSpin, SIGNAL(editingFinished(void)), this, SLOT(handleSpinSelChanged())); } //priority selection { formLayout->addRow(tr("Process priority %"), _prioritySpin); _prioritySpin->setRange(-100, +100); _prioritySpin->setToolTip(tr("A priority percentage between -100% and 100%")); connect(_prioritySpin, SIGNAL(editingFinished(void)), this, SLOT(handleSpinSelChanged())); } //cpu/node selection { formLayout->addRow(tr("CPU selection"), _cpuSelectionContainer); this->updateCpuSelection(); } //yield mode { formLayout->addRow(tr("Yield mode"), _yieldModeBox); _yieldModeBox->addItem(tr("Default"), ""); _yieldModeBox->addItem(tr("Condition"), "CONDITION"); _yieldModeBox->addItem(tr("Hybrid"), "HYBRID"); _yieldModeBox->addItem(tr("Spin"), "SPIN"); _yieldModeBox->setToolTip(tr("Yield mode specifies the internal threading mechanisms")); connect(_yieldModeBox, SIGNAL(activated(int)), this, SLOT(handleComboChanged(int))); } }
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; }