#include "GraphDisplay.h" #include #include #include #include #include #include #include #include #include #include #include "ElementProperties.h" #include "PadProperties.h" #define PAD_SIZE 8 #define PAD_SIZE_ACTION 16 GraphDisplay::GraphDisplay(QWidget *parent, Qt::WindowFlags f): QWidget(parent, f) { setFocusPolicy(Qt::WheelFocus); setMouseTracking(true); } ElementInfo* GraphDisplay::getElement(std::size_t elementId) { ElementInfo* element = NULL; std::size_t i=0; for(; im_pads.size(); j++) if(element->m_pads[j].m_id == padId) { pad = &element->m_pads[j]; break; } return pad; } void GraphDisplay::updateDisplayInfoIds() { for(std::size_t i=0; i &info) { bool needUpdate = false; if(m_info.size() != info.size()) needUpdate = true; if(!needUpdate) { for(std::size_t i=0; i= 1) height += (std::max(numInPads, numOutPads) - 1) * 25; int curX, curY; curX = curY = 10; QRect rect(curX, curY, width, height); while(true) { rect = QRect(curX, curY, width, height); QRect rectTest(curX, curY - 15, width + 15, height + 15); bool noIntersects = true; for(std::size_t i=0; i= m_displayInfo.size()) break; } std::size_t i=0; for(; i reorderedDisplayInfo(m_info.size()); for(std::size_t i=0; i pos(), elementId, padId); if(event -> buttons() & Qt::RightButton) { showContextMenu(event); } else { if(padId != ((size_t)-1)) { m_moveInfo.m_padId = padId; m_moveInfo.m_elementId = elementId; m_moveInfo.m_position = event -> pos(); m_moveInfo.m_action = MakeConnect; m_moveInfo.m_startPosition = event -> pos(); } else if(elementId != ((size_t)-1)) { m_moveInfo.m_elementId = elementId; m_moveInfo.m_padId = -1; m_moveInfo.m_position = event -> pos(); m_moveInfo.m_action = MoveComponent; m_moveInfo.m_startPosition = event -> pos(); } else { m_moveInfo.m_startPosition = event -> pos(); m_moveInfo.m_action = Select; m_moveInfo.m_position = QPoint(); } } for(std::size_t i=0; i pos(), elementId, padId); if(elementId != ((size_t)-1) && padId != ((size_t)-1)) { ElementInfo infoSrc, infoDst; const char *srcPad, *dstPad; srcPad = NULL; dstPad = NULL; for(std::size_t i=0; i Connect(infoSrc.m_name.c_str(), srcPad, infoDst.m_name.c_str(), dstPad)) { QString msg; msg = "Connection "; msg += QString(infoSrc.m_name.c_str()) + ":" + srcPad; msg += " => "; msg += QString(infoDst.m_name.c_str()) + ":" + dstPad; msg += " was FAILED"; QMessageBox::warning(this, "Coonection failed", msg); } m_info = m_pGraph -> GetInfo(); updateDisplayInfoIds(); if(g_str_has_prefix(infoDst.m_name.c_str(),"decodebin")) { m_pGraph->Play(); qDebug() << "Launch play to discover the new pad"; } } } else if(m_moveInfo.m_action == Select) { std::size_t width = std::abs(m_moveInfo.m_position.x() - m_moveInfo.m_startPosition.x()); std::size_t height = std::abs(m_moveInfo.m_position.y() - m_moveInfo.m_startPosition.y()); if(!m_moveInfo.m_position.isNull() && width * height > 5) { QRect selectionRect(m_moveInfo.m_startPosition, m_moveInfo.m_position); for(std::size_t i=0; i x() - m_moveInfo.m_startPosition.x(); int dy = event -> y() - m_moveInfo.m_startPosition.y(); if(dx == dy && dy == 0) { for(std::size_t i=0; i x() - m_moveInfo.m_position.x(); int dy = event -> y() - m_moveInfo.m_position.y(); for(std::size_t i=0; i pos(); repaint(); } else { std::size_t elementId, padId; getIdByPosition(event -> pos(), elementId, padId); if (padId != ((size_t)-1)) { ElementInfo* element = getElement(elementId); PadInfo* pad = getPad(element, padId); QString caps = m_pGraph->getPadCaps(element,pad,PAD_CAPS_ALL,true); setToolTip(caps); } else setToolTip(""); } } void GraphDisplay::keyPressEvent(QKeyEvent* event) { if(event -> key() == Qt::Key_Delete) removeSelected(); return QWidget::keyPressEvent(event); } void GraphDisplay::showContextMenu(QMouseEvent *event) { QMenu menu; std::size_t elementId, padId; getIdByPosition(event -> pos(), elementId, padId); GstState state; GstStateChangeReturn res = gst_element_get_state (m_pGraph -> m_pGraph, &state, NULL, GST_MSECOND); bool isActive = false; if(res != GST_STATE_CHANGE_SUCCESS || state == GST_STATE_PAUSED || state == GST_STATE_PLAYING) isActive = true; int selectedCount = 0; for(std::size_t i=0; i 1) { QAction *pact = menu.addAction("Remove selected"); if(isActive) pact -> setDisabled(true); } else if(padId != ((size_t)-1)) menu.addAction("Pad properties"); else if(elementId != ((size_t)-1)) { menu.addAction("Element properties"); QAction *pact = menu.addAction("Remove"); if(isActive) pact -> setDisabled(true); pact = menu.addAction("Request pad..."); } else { for(std::size_t i=0; i pos().x(); double y0 = event -> pos().y(); double distance = std::abs((int)(dy * x0 - dx * y0 + x2 * y1 - y2 * x1)); distance = distance / sqrt(dy * dy + dx * dx); if(distance < 5) { elementId = m_info[i].m_id; padId = m_info[i].m_pads[j].m_id; QAction *pact = menu.addAction("Disconnect"); if(isActive) pact -> setDisabled(true); break; } } } if(!menu.isEmpty()) break; } } if(!menu.isEmpty()) { QAction *pact = menu.exec(event -> globalPos()); if(pact) { if(pact -> text() == "Remove") removePlugin(elementId); else if(pact -> text() == "Element properties") showElementProperties(elementId); else if(pact -> text() == "Pad properties") showPadProperties(elementId, padId); else if(pact -> text() == "Disconnect") disconnect(elementId, padId); else if(pact -> text() == "Request pad...") requestPad(elementId); else if(pact -> text() == "Remove selected") removeSelected(); } } } void GraphDisplay::removeSelected() { GstState state; GstStateChangeReturn res = gst_element_get_state (m_pGraph -> m_pGraph, &state, NULL, GST_MSECOND); if(res != GST_STATE_CHANGE_SUCCESS || state == GST_STATE_PAUSED || state == GST_STATE_PLAYING) return; while(true) { std::size_t i=0; for(; i RemovePlugin(m_info[i].m_name.c_str())) { std::vector info = m_pGraph -> GetInfo(); update(info); } else QMessageBox::warning(this, "Element removing problem", "Element `" + QString(m_info[i].m_name.c_str()) + "` remowing was FAILED"); } } void GraphDisplay::showElementProperties(std::size_t id) { std::size_t i=0; for(; i setAttribute(Qt::WA_QuitOnClose, false); pprops -> show(); } } void GraphDisplay::showPadProperties(std::size_t elementId, std::size_t padId) { std::size_t i=0; for(; i setAttribute(Qt::WA_QuitOnClose, false); pprops -> show(); } } } void GraphDisplay::disconnect(size_t elementId, size_t padId) { std::string src, dst, srcPad, dstPad; for(std::size_t i=0; i " << dst.c_str() << ":" << dstPad.c_str(); if(src.empty() || dst.empty() || srcPad.empty() || dstPad.empty()) return; m_pGraph -> Disconnect(src.c_str(), srcPad.c_str(), dst.c_str(), dstPad.c_str()); m_info = m_pGraph -> GetInfo(); updateDisplayInfoIds(); repaint(); } void GraphDisplay::requestPad(std::size_t elementId) { QStringList labels; labels.push_back("Template name"); labels.push_back("Caps"); labels.push_back("Direction"); QTableWidget *ptwgt = new QTableWidget(); ptwgt -> setColumnCount(3); ptwgt -> setHorizontalHeaderLabels(labels); ptwgt -> setSelectionBehavior(QAbstractItemView::SelectRows); ptwgt -> setEditTriggers(QAbstractItemView::NoEditTriggers); GstElement *element = NULL; for(std::size_t i=0; i m_pGraph), m_info[i].m_name.c_str()); break; } } if(!element) { QMessageBox::warning(this, "Request pad failed", "Request pad list obtaining was failed"); return; } GstElementClass *klass; klass = GST_ELEMENT_GET_CLASS(element); GList *lst = gst_element_class_get_pad_template_list(klass); std::size_t k = 0; while (lst != NULL) { GstPadTemplate *templ; templ = (GstPadTemplate *) lst -> data; if(GST_PAD_TEMPLATE_PRESENCE(templ) == GST_PAD_REQUEST) { ptwgt -> setRowCount(k + 1); ptwgt -> setItem(k, 0, new QTableWidgetItem(GST_PAD_TEMPLATE_NAME_TEMPLATE(templ))); GstCaps *caps = gst_pad_template_get_caps(templ); gchar *capsStr = gst_caps_to_string(caps); ptwgt -> setItem(k, 1, new QTableWidgetItem(capsStr)); g_free(capsStr); gst_caps_unref(caps); const char *directionSrc = "SRC"; const char *directionSink = "SINK"; const char *directionUnknown = "UNKNOWN"; QString direction; switch(GST_PAD_TEMPLATE_DIRECTION(templ)) { case GST_PAD_UNKNOWN: direction = directionUnknown; break; case GST_PAD_SRC: direction = directionSrc; break; case GST_PAD_SINK: direction = directionSink; break; }; ptwgt -> setItem(k, 2, new QTableWidgetItem(direction)); k++; } lst = g_list_next(lst); } qulonglong v((qulonglong)element); ptwgt -> setProperty("element", v); connect(ptwgt, SIGNAL(cellActivated(int, int)), SLOT(addRequestPad(int, int))); ptwgt -> setAttribute(Qt::WA_QuitOnClose, false); ptwgt -> show(); } void GraphDisplay::addRequestPad(int row, int collumn) { QTableWidget *ptwgt = dynamic_cast (QObject::sender()); qulonglong v = ptwgt -> property("element").toULongLong(); GstElement *element = (GstElement *) v; GstElementClass *klass = GST_ELEMENT_GET_CLASS(element); GstPadTemplate *templ = gst_element_class_get_pad_template(klass, ptwgt -> itemAt(row, 0) -> text().toStdString().c_str()); gst_element_request_pad(element, templ, NULL, NULL); gst_object_unref(element); ptwgt -> close(); std::vector info = m_pGraph -> GetInfo(); update(info); } void GraphDisplay::getIdByPosition(const QPoint &pos, std::size_t &elementId, std::size_t &padId) { std::size_t i=0; elementId = padId = -1; for(; i