nodecombobox: implemented node combobox widget
This commit is contained in:
+44
-5
@@ -62,7 +62,7 @@ void NodeFactory::Destroy()
|
||||
library_.clear();
|
||||
}
|
||||
|
||||
Menu *NodeFactory::CreateMenu(QWidget* parent)
|
||||
Menu *NodeFactory::CreateMenu(QWidget* parent, bool create_none_item)
|
||||
{
|
||||
Menu* menu = new Menu(parent);
|
||||
menu->setToolTipsVisible(true);
|
||||
@@ -100,18 +100,57 @@ Menu *NodeFactory::CreateMenu(QWidget* parent)
|
||||
a->setToolTip(n->Description());
|
||||
}
|
||||
|
||||
if (create_none_item) {
|
||||
|
||||
QAction* none_item = new QAction(QCoreApplication::translate("NodeFactory", "None"),
|
||||
menu);
|
||||
|
||||
none_item->setData(-1);
|
||||
|
||||
if (menu->actions().isEmpty()) {
|
||||
menu->addAction(none_item);
|
||||
} else {
|
||||
QAction* separator = menu->insertSeparator(menu->actions().first());
|
||||
menu->insertAction(separator, none_item);
|
||||
}
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
Node* NodeFactory::CreateFromMenuAction(QAction *action)
|
||||
{
|
||||
int library_index = action->data().toInt();
|
||||
int index = action->data().toInt();
|
||||
|
||||
if (library_index >= 0 && library_index < library_.size()) {
|
||||
return library_.at(library_index)->copy();
|
||||
if (index == -1) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return library_.at(index)->copy();
|
||||
}
|
||||
|
||||
QString NodeFactory::GetIDFromMenuAction(QAction *action)
|
||||
{
|
||||
int index = action->data().toInt();
|
||||
|
||||
if (index == -1) {
|
||||
return QString();
|
||||
}
|
||||
|
||||
return library_.at(action->data().toInt())->id();
|
||||
}
|
||||
|
||||
QString NodeFactory::GetNameFromID(const QString &id)
|
||||
{
|
||||
if (!id.isEmpty()) {
|
||||
foreach (Node* n, library_) {
|
||||
if (n->id() == id) {
|
||||
return n->Name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
Node *NodeFactory::CreateFromID(const QString &id)
|
||||
|
||||
+5
-1
@@ -60,10 +60,14 @@ public:
|
||||
|
||||
static void Destroy();
|
||||
|
||||
static Menu* CreateMenu(QWidget *parent);
|
||||
static Menu* CreateMenu(QWidget *parent, bool create_none_item = false);
|
||||
|
||||
static Node* CreateFromMenuAction(QAction* action);
|
||||
|
||||
static QString GetIDFromMenuAction(QAction* action);
|
||||
|
||||
static QString GetNameFromID(const QString& id);
|
||||
|
||||
static Node* CreateFromID(const QString& id);
|
||||
|
||||
private:
|
||||
|
||||
+68
-9
@@ -371,7 +371,7 @@ void Node::Hash(QCryptographicHash &hash, const rational& time) const
|
||||
// Footage timestamp
|
||||
if (stream->type() == Stream::kVideo) {
|
||||
hash.addData(QStringLiteral("%1/%2").arg(QString::number(input_time.numerator()),
|
||||
QString::number(input_time.denominator())).toUtf8());
|
||||
QString::number(input_time.denominator())).toUtf8());
|
||||
|
||||
hash.addData(QString::number(static_cast<VideoStream*>(stream.get())->start_time()).toUtf8());
|
||||
|
||||
@@ -532,16 +532,75 @@ NodeOutput *Node::GetOutputWithID(const QString &id) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool Node::OutputsTo(Node *n) const
|
||||
bool Node::OutputsTo(Node *n, bool recursively) const
|
||||
{
|
||||
foreach (NodeParam* param, params_) {
|
||||
if (param->type() == NodeParam::kOutput) {
|
||||
QVector<NodeEdgePtr> edges = param->edges();
|
||||
QList<NodeOutput*> outputs = GetOutputs();
|
||||
|
||||
foreach (NodeEdgePtr edge, edges) {
|
||||
if (edge->input()->parent() == n) {
|
||||
return true;
|
||||
}
|
||||
foreach (NodeOutput* output, outputs) {
|
||||
foreach (NodeEdgePtr edge, output->edges()) {
|
||||
Node* connected = edge->input()->parentNode();
|
||||
|
||||
if (connected == n) {
|
||||
return true;
|
||||
} else if (recursively && connected->OutputsTo(n, recursively)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Node::OutputsTo(const QString &id, bool recursively) const
|
||||
{
|
||||
QList<NodeOutput*> outputs = GetOutputs();
|
||||
|
||||
foreach (NodeOutput* output, outputs) {
|
||||
foreach (NodeEdgePtr edge, output->edges()) {
|
||||
Node* connected = edge->input()->parentNode();
|
||||
|
||||
if (connected->id() == id) {
|
||||
return true;
|
||||
} else if (recursively && connected->OutputsTo(id, recursively)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Node::InputsFrom(Node *n, bool recursively) const
|
||||
{
|
||||
QList<NodeInput*> inputs = GetInputsIncludingArrays();
|
||||
|
||||
foreach (NodeInput* input, inputs) {
|
||||
foreach (NodeEdgePtr edge, input->edges()) {
|
||||
Node* connected = edge->output()->parentNode();
|
||||
|
||||
if (connected == n) {
|
||||
return true;
|
||||
} else if (recursively && connected->InputsFrom(n, recursively)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Node::InputsFrom(const QString &id, bool recursively) const
|
||||
{
|
||||
QList<NodeInput*> inputs = GetInputsIncludingArrays();
|
||||
|
||||
foreach (NodeInput* input, inputs) {
|
||||
foreach (NodeEdgePtr edge, input->edges()) {
|
||||
Node* connected = edge->output()->parentNode();
|
||||
|
||||
if (connected->id() == id) {
|
||||
return true;
|
||||
} else if (recursively && connected->InputsFrom(id, recursively)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-2
@@ -229,9 +229,33 @@ public:
|
||||
NodeOutput* GetOutputWithID(const QString& id) const;
|
||||
|
||||
/**
|
||||
* @brief Returns whether this Node outputs directly to `n`
|
||||
* @brief Returns whether this Node outputs to `n`
|
||||
*
|
||||
* @param n
|
||||
*
|
||||
* The node instance to check.
|
||||
*
|
||||
* @param recursively
|
||||
*
|
||||
* Whether to keep traversing down outputs to find this node (TRUE) or stick to immediate outputs
|
||||
* (FALSE).
|
||||
*/
|
||||
bool OutputsTo(Node* n) const;
|
||||
bool OutputsTo(Node* n, bool recursively) const;
|
||||
|
||||
/**
|
||||
* @brief Same as OutputsTo(Node*), but for a node ID rather than a specific instance.
|
||||
*/
|
||||
bool OutputsTo(const QString& id, bool recursively) const;
|
||||
|
||||
/**
|
||||
* @brief Returns whether this node ever receives an input from a particular node instance
|
||||
*/
|
||||
bool InputsFrom(Node* n, bool recursively) const;
|
||||
|
||||
/**
|
||||
* @brief Returns whether this node ever receives an input from a node with a particular ID
|
||||
*/
|
||||
bool InputsFrom(const QString& id, bool recursively) const;
|
||||
|
||||
/**
|
||||
* @brief Determines how many paths go from this node out to another node
|
||||
|
||||
@@ -27,6 +27,7 @@ add_subdirectory(footagecombobox)
|
||||
add_subdirectory(keyframeview)
|
||||
add_subdirectory(manageddisplay)
|
||||
add_subdirectory(menu)
|
||||
add_subdirectory(nodecombobox)
|
||||
add_subdirectory(nodecopypaste)
|
||||
add_subdirectory(nodeview)
|
||||
add_subdirectory(nodeparamview)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# Olive - Non-Linear Video Editor
|
||||
# Copyright (C) 2019 Olive Team
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
widget/nodecombobox/nodecombobox.h
|
||||
widget/nodecombobox/nodecombobox.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,93 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "nodecombobox.h"
|
||||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
|
||||
#include "node/factory.h"
|
||||
#include "ui/icons/icons.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
NodeComboBox::NodeComboBox(QWidget *parent) :
|
||||
QComboBox(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeComboBox::showPopup()
|
||||
{
|
||||
Menu* m = NodeFactory::CreateMenu(this, true);
|
||||
|
||||
QAction* selected = m->exec(parentWidget()->mapToGlobal(pos()));
|
||||
|
||||
if (selected) {
|
||||
QString new_id = NodeFactory::GetIDFromMenuAction(selected);
|
||||
|
||||
SetNodeInternal(new_id, true);
|
||||
}
|
||||
|
||||
delete m;
|
||||
}
|
||||
|
||||
const QString &NodeComboBox::GetSelectedNode() const
|
||||
{
|
||||
return selected_id_;
|
||||
}
|
||||
|
||||
void NodeComboBox::SetNode(const QString &id)
|
||||
{
|
||||
SetNodeInternal(id, false);
|
||||
}
|
||||
|
||||
void NodeComboBox::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
UpdateText();
|
||||
}
|
||||
|
||||
QComboBox::changeEvent(e);
|
||||
}
|
||||
|
||||
void NodeComboBox::UpdateText()
|
||||
{
|
||||
clear();
|
||||
|
||||
if (!selected_id_.isEmpty()) {
|
||||
addItem(NodeFactory::GetNameFromID(selected_id_));
|
||||
}
|
||||
}
|
||||
|
||||
void NodeComboBox::SetNodeInternal(const QString &id, bool emit_signal)
|
||||
{
|
||||
if (selected_id_ != id) {
|
||||
selected_id_ = id;
|
||||
|
||||
UpdateText();
|
||||
|
||||
if (emit_signal) {
|
||||
emit NodeChanged(selected_id_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
@@ -0,0 +1,60 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef NODECOMBOBOX_H
|
||||
#define NODECOMBOBOX_H
|
||||
|
||||
#include <QComboBox>
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
class NodeComboBox : public QComboBox
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeComboBox(QWidget* parent = nullptr);
|
||||
|
||||
virtual void showPopup() override;
|
||||
|
||||
const QString& GetSelectedNode() const;
|
||||
|
||||
public slots:
|
||||
void SetNode(const QString& id);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
signals:
|
||||
void NodeChanged(const QString& id);
|
||||
|
||||
private:
|
||||
void UpdateText();
|
||||
|
||||
void SetNodeInternal(const QString& id, bool emit_signal);
|
||||
|
||||
QString selected_id_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
#endif // FOOTAGECOMBOBOX_H
|
||||
@@ -467,7 +467,7 @@ void NodeViewItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
||||
if (cached_drop_item_->GetInputRect(i).contains(cached_drop_item_->mapFromScene(event->scenePos()))) { // See if we're dragging inside the hitbox
|
||||
|
||||
// Attempt to prevent circular dependency - ensure the receiving node doesn't output to the outputting node
|
||||
if (!cached_drop_item_->GetNode()->OutputsTo(node_)) {
|
||||
if (!cached_drop_item_->GetNode()->OutputsTo(node_, true)) {
|
||||
drag_dest_param_ = comp_param;
|
||||
highlight_their_index = i;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user