ui: optimized widget signals for selecting clips/nodes
Decent performance optimization when working with the UI.
This commit is contained in:
+2
-61
@@ -29,7 +29,8 @@ NodePanel::NodePanel(QWidget *parent) :
|
||||
node_view_ = new NodeView(this);
|
||||
|
||||
// Connect node view signals to this panel
|
||||
connect(node_view_, SIGNAL(SelectionChanged(QList<Node*>)), this, SIGNAL(SelectionChanged(QList<Node*>)));
|
||||
connect(node_view_, &NodeView::NodesSelected, this, &NodePanel::NodesSelected);
|
||||
connect(node_view_, &NodeView::NodesDeselected, this, &NodePanel::NodesDeselected);
|
||||
|
||||
// Set it as the main widget of this panel
|
||||
SetWidgetWithPadding(node_view_);
|
||||
@@ -38,64 +39,4 @@ NodePanel::NodePanel(QWidget *parent) :
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void NodePanel::SetGraph(NodeGraph *graph)
|
||||
{
|
||||
node_view_->SetGraph(graph);
|
||||
}
|
||||
|
||||
void NodePanel::SelectAll()
|
||||
{
|
||||
node_view_->SelectAll();
|
||||
}
|
||||
|
||||
void NodePanel::DeselectAll()
|
||||
{
|
||||
node_view_->DeselectAll();
|
||||
}
|
||||
|
||||
void NodePanel::DeleteSelected()
|
||||
{
|
||||
node_view_->DeleteSelected();
|
||||
}
|
||||
|
||||
void NodePanel::CutSelected()
|
||||
{
|
||||
node_view_->CopySelected(true);
|
||||
}
|
||||
|
||||
void NodePanel::CopySelected()
|
||||
{
|
||||
node_view_->CopySelected(false);
|
||||
}
|
||||
|
||||
void NodePanel::Paste()
|
||||
{
|
||||
node_view_->Paste();
|
||||
}
|
||||
|
||||
void NodePanel::Duplicate()
|
||||
{
|
||||
node_view_->Duplicate();
|
||||
}
|
||||
|
||||
void NodePanel::Select(const QList<Node *> &nodes)
|
||||
{
|
||||
node_view_->Select(nodes);
|
||||
}
|
||||
|
||||
void NodePanel::SelectWithDependencies(const QList<Node *> &nodes)
|
||||
{
|
||||
node_view_->SelectWithDependencies(nodes);
|
||||
}
|
||||
|
||||
void NodePanel::SelectBlocks(const QList<Block *> &nodes)
|
||||
{
|
||||
node_view_->SelectBlocks(nodes);
|
||||
}
|
||||
|
||||
void NodePanel::Retranslate()
|
||||
{
|
||||
SetTitle(tr("Node Editor"));
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
+59
-16
@@ -35,34 +35,77 @@ class NodePanel : public PanelWidget
|
||||
public:
|
||||
NodePanel(QWidget* parent);
|
||||
|
||||
void SetGraph(NodeGraph* graph);
|
||||
void SetGraph(NodeGraph *graph)
|
||||
{
|
||||
node_view_->SetGraph(graph);
|
||||
}
|
||||
|
||||
virtual void SelectAll() override;
|
||||
virtual void DeselectAll() override;
|
||||
virtual void SelectAll() override
|
||||
{
|
||||
node_view_->SelectAll();
|
||||
}
|
||||
|
||||
virtual void DeleteSelected() override;
|
||||
virtual void DeselectAll() override
|
||||
{
|
||||
node_view_->DeselectAll();
|
||||
}
|
||||
|
||||
virtual void CutSelected() override;
|
||||
virtual void CopySelected() override;
|
||||
virtual void DeleteSelected() override
|
||||
{
|
||||
node_view_->DeleteSelected();
|
||||
}
|
||||
|
||||
virtual void Paste() override;
|
||||
virtual void CutSelected() override
|
||||
{
|
||||
node_view_->CopySelected(true);
|
||||
}
|
||||
|
||||
virtual void Duplicate() override;
|
||||
virtual void CopySelected() override
|
||||
{
|
||||
node_view_->CopySelected(false);
|
||||
}
|
||||
|
||||
virtual void Paste() override
|
||||
{
|
||||
node_view_->Paste();
|
||||
}
|
||||
|
||||
virtual void Duplicate() override
|
||||
{
|
||||
node_view_->Duplicate();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void Select(const QList<Node*>& nodes);
|
||||
void SelectWithDependencies(const QList<Node*>& nodes);
|
||||
void Select(const QList<Node*>& nodes)
|
||||
{
|
||||
node_view_->Select(nodes);
|
||||
}
|
||||
|
||||
void SelectBlocks(const QList<Block*>& nodes);
|
||||
void SelectWithDependencies(const QList<Node*>& nodes)
|
||||
{
|
||||
node_view_->SelectWithDependencies(nodes);
|
||||
}
|
||||
|
||||
void SelectBlocks(const QList<Block*>& nodes)
|
||||
{
|
||||
node_view_->SelectBlocks(nodes);
|
||||
}
|
||||
|
||||
void DeselectBlocks(const QList<Block*>& nodes)
|
||||
{
|
||||
node_view_->DeselectBlocks(nodes);
|
||||
}
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Wrapper for NodeView::SelectionChanged()
|
||||
*/
|
||||
void SelectionChanged(QList<Node*> selected_nodes);
|
||||
void NodesSelected(const QList<Node*>& nodes);
|
||||
|
||||
void NodesDeselected(const QList<Node*>& nodes);
|
||||
|
||||
private:
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override
|
||||
{
|
||||
SetTitle(tr("Node Editor"));
|
||||
}
|
||||
|
||||
NodeView* node_view_;
|
||||
|
||||
|
||||
@@ -30,15 +30,22 @@ ParamPanel::ParamPanel(QWidget* parent) :
|
||||
NodeParamView* view = new NodeParamView();
|
||||
connect(view, &NodeParamView::InputDoubleClicked, this, &ParamPanel::CreateCurvePanel);
|
||||
connect(view, &NodeParamView::RequestSelectNode, this, &ParamPanel::RequestSelectNode);
|
||||
connect(view, &NodeParamView::FoundGizmos, this, &ParamPanel::FoundGizmos);
|
||||
//connect(view, &NodeParamView::FoundGizmos, this, &ParamPanel::FoundGizmos);
|
||||
SetTimeBasedWidget(view);
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void ParamPanel::SetNodes(QList<Node *> nodes)
|
||||
void ParamPanel::SelectNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
static_cast<NodeParamView*>(GetTimeBasedWidget())->SetNodes(nodes);
|
||||
static_cast<NodeParamView*>(GetTimeBasedWidget())->SelectNodes(nodes);
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void ParamPanel::DeselectNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
static_cast<NodeParamView*>(GetTimeBasedWidget())->DeselectNodes(nodes);
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
@@ -62,10 +69,10 @@ void ParamPanel::Retranslate()
|
||||
|
||||
NodeParamView* view = static_cast<NodeParamView*>(GetTimeBasedWidget());
|
||||
|
||||
if (view->nodes().isEmpty()) {
|
||||
if (view->GetItemMap().isEmpty()) {
|
||||
SetSubtitle(tr("(none)"));
|
||||
} else if (view->nodes().size() == 1) {
|
||||
SetSubtitle(view->nodes().first()->Name());
|
||||
} else if (view->GetItemMap().size() == 1) {
|
||||
SetSubtitle(view->GetItemMap().firstKey()->Name());
|
||||
} else {
|
||||
SetSubtitle(tr("(multiple)"));
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ public:
|
||||
ParamPanel(QWidget* parent);
|
||||
|
||||
public slots:
|
||||
void SetNodes(QList<Node*> nodes);
|
||||
void SelectNodes(const QList<Node*>& nodes);
|
||||
void DeselectNodes(const QList<Node*>& nodes);
|
||||
|
||||
virtual void SetTimestamp(const int64_t& timestamp) override;
|
||||
|
||||
|
||||
@@ -25,17 +25,11 @@ OLIVE_NAMESPACE_ENTER
|
||||
NodeTablePanel::NodeTablePanel(QWidget* parent) :
|
||||
TimeBasedPanel(QStringLiteral("NodeTablePanel"), parent)
|
||||
{
|
||||
view_ = new NodeTableWidget();
|
||||
SetTimeBasedWidget(view_);
|
||||
SetTimeBasedWidget(new NodeTableWidget());
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void NodeTablePanel::SetNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
view_->SetNodes(nodes);
|
||||
}
|
||||
|
||||
void NodeTablePanel::Retranslate()
|
||||
{
|
||||
SetTitle(tr("Table View"));
|
||||
|
||||
@@ -33,12 +33,19 @@ public:
|
||||
NodeTablePanel(QWidget* parent);
|
||||
|
||||
public slots:
|
||||
void SetNodes(const QList<Node*>& nodes);
|
||||
void SelectNodes(const QList<Node*>& nodes)
|
||||
{
|
||||
static_cast<NodeTableWidget*>(GetTimeBasedWidget())->SelectNodes(nodes);
|
||||
}
|
||||
|
||||
void DeselectNodes(const QList<Node*>& nodes)
|
||||
{
|
||||
static_cast<NodeTableWidget*>(GetTimeBasedWidget())->DeselectNodes(nodes);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
NodeTableWidget* view_;
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -33,7 +33,8 @@ TimelinePanel::TimelinePanel(QWidget *parent) :
|
||||
|
||||
Retranslate();
|
||||
|
||||
connect(tw, &TimelineWidget::SelectionChanged, this, &TimelinePanel::SelectionChanged);
|
||||
connect(tw, &TimelineWidget::BlocksSelected, this, &TimelinePanel::BlocksSelected);
|
||||
connect(tw, &TimelineWidget::BlocksDeselected, this, &TimelinePanel::BlocksDeselected);
|
||||
}
|
||||
|
||||
void TimelinePanel::Clear()
|
||||
|
||||
@@ -91,7 +91,9 @@ protected:
|
||||
virtual void Retranslate() override;
|
||||
|
||||
signals:
|
||||
void SelectionChanged(const QList<Block*>& selected_blocks);
|
||||
void BlocksSelected(const QList<Block*>& selected_blocks);
|
||||
|
||||
void BlocksDeselected(const QList<Block*>& deselected_blocks);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -74,6 +74,19 @@ void KeyframeViewBase::DeleteSelected()
|
||||
Core::instance()->undo_stack()->pushIfHasChildren(command);
|
||||
}
|
||||
|
||||
void KeyframeViewBase::RemoveKeyframesOfNode(Node *n)
|
||||
{
|
||||
QList<NodeInput*> inputs = n->GetInputsIncludingArrays();
|
||||
|
||||
foreach (NodeInput* i, inputs) {
|
||||
foreach (const NodeInput::KeyframeTrack& track, i->keyframe_tracks()) {
|
||||
foreach (NodeKeyframePtr key, track) {
|
||||
RemoveKeyframe(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewBase::RemoveKeyframe(NodeKeyframePtr key)
|
||||
{
|
||||
KeyframeAboutToBeRemoved(key.get());
|
||||
|
||||
@@ -40,6 +40,8 @@ public:
|
||||
|
||||
void DeleteSelected();
|
||||
|
||||
void RemoveKeyframesOfNode(Node* n);
|
||||
|
||||
public slots:
|
||||
void RemoveKeyframe(NodeKeyframePtr key);
|
||||
|
||||
|
||||
@@ -122,52 +122,41 @@ NodeParamView::NodeParamView(QWidget *parent) :
|
||||
SetMaximumScale(TimelineViewBase::kMaximumScale);
|
||||
}
|
||||
|
||||
void NodeParamView::SetNodes(QList<Node *> nodes)
|
||||
void NodeParamView::SelectNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
// If we already have item widgets, delete them all now
|
||||
foreach (NodeParamViewItem* item, items_) {
|
||||
emit ClosedNode(item->GetNode());
|
||||
emit FoundGizmos(nullptr);
|
||||
item->deleteLater();
|
||||
foreach (Node* n, nodes) {
|
||||
NodeParamViewItem* item = new NodeParamViewItem(n);
|
||||
|
||||
// Insert the widget before the stretch
|
||||
param_layout_->insertWidget(param_layout_->count() - 1, item);
|
||||
|
||||
connect(item, &NodeParamViewItem::KeyframeAdded, keyframe_view_, &KeyframeView::AddKeyframe);
|
||||
connect(item, &NodeParamViewItem::KeyframeRemoved, keyframe_view_, &KeyframeView::RemoveKeyframe);
|
||||
connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::ItemRequestedTimeChanged);
|
||||
connect(item, &NodeParamViewItem::InputDoubleClicked, this, &NodeParamView::InputDoubleClicked);
|
||||
connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::RequestSelectNode);
|
||||
|
||||
items_.insert(n, item);
|
||||
}
|
||||
items_.clear();
|
||||
|
||||
// Reset keyframe view
|
||||
keyframe_view_->Clear();
|
||||
UpdateItemTime(GetTimestamp());
|
||||
|
||||
// Set the internal list to the one we've received
|
||||
nodes_ = nodes;
|
||||
// Re-arrange keyframes
|
||||
QMetaObject::invokeMethod(this, "PlaceKeyframesOnView", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
if (!nodes_.isEmpty()) {
|
||||
// For each node, create a widget
|
||||
bool found_gizmos = false;
|
||||
void NodeParamView::DeselectNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
// Remove item from map and delete the widget
|
||||
foreach (Node* n, nodes) {
|
||||
// Remove all keyframes from this node
|
||||
keyframe_view_->RemoveKeyframesOfNode(n);
|
||||
|
||||
foreach (Node* node, nodes_) {
|
||||
NodeParamViewItem* item = new NodeParamViewItem(node);
|
||||
|
||||
// Insert the widget before the stretch
|
||||
param_layout_->insertWidget(param_layout_->count() - 1, item);
|
||||
|
||||
connect(item, &NodeParamViewItem::KeyframeAdded, keyframe_view_, &KeyframeView::AddKeyframe);
|
||||
connect(item, &NodeParamViewItem::KeyframeRemoved, keyframe_view_, &KeyframeView::RemoveKeyframe);
|
||||
connect(item, &NodeParamViewItem::RequestSetTime, this, &NodeParamView::ItemRequestedTimeChanged);
|
||||
connect(item, &NodeParamViewItem::InputDoubleClicked, this, &NodeParamView::InputDoubleClicked);
|
||||
connect(item, &NodeParamViewItem::RequestSelectNode, this, &NodeParamView::RequestSelectNode);
|
||||
|
||||
items_.append(item);
|
||||
|
||||
emit OpenedNode(node);
|
||||
|
||||
if (!found_gizmos && node->HasGizmos()) {
|
||||
emit FoundGizmos(node);
|
||||
found_gizmos = true;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateItemTime(GetTimestamp());
|
||||
|
||||
QMetaObject::invokeMethod(this, "PlaceKeyframesOnView", Qt::QueuedConnection);
|
||||
delete items_.take(n);
|
||||
}
|
||||
|
||||
// Re-arrange keyframes
|
||||
QMetaObject::invokeMethod(this, "PlaceKeyframesOnView", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void NodeParamView::resizeEvent(QResizeEvent *event)
|
||||
@@ -212,11 +201,6 @@ void NodeParamView::ConnectedNodeChanged(ViewerOutput *n)
|
||||
}
|
||||
}
|
||||
|
||||
const QList<Node *> &NodeParamView::nodes()
|
||||
{
|
||||
return nodes_;
|
||||
}
|
||||
|
||||
Node *NodeParamView::GetTimeTarget() const
|
||||
{
|
||||
return keyframe_view_->GetTimeTarget();
|
||||
|
||||
@@ -37,8 +37,13 @@ class NodeParamView : public TimeBasedWidget
|
||||
public:
|
||||
NodeParamView(QWidget* parent = nullptr);
|
||||
|
||||
void SetNodes(QList<Node*> nodes);
|
||||
const QList<Node*>& nodes();
|
||||
void SelectNodes(const QList<Node*>& nodes);
|
||||
void DeselectNodes(const QList<Node*>& nodes);
|
||||
|
||||
const QMap<Node*, NodeParamViewItem*>& GetItemMap() const
|
||||
{
|
||||
return items_;
|
||||
}
|
||||
|
||||
Node* GetTimeTarget() const;
|
||||
|
||||
@@ -49,12 +54,6 @@ signals:
|
||||
|
||||
void RequestSelectNode(const QList<Node*>& target);
|
||||
|
||||
void OpenedNode(Node* n);
|
||||
|
||||
void ClosedNode(Node* n);
|
||||
|
||||
void FoundGizmos(Node* n);
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
@@ -71,9 +70,7 @@ private:
|
||||
|
||||
KeyframeView* keyframe_view_;
|
||||
|
||||
QList<Node*> nodes_;
|
||||
|
||||
QList<NodeParamViewItem*> items_;
|
||||
QMap<Node*, NodeParamViewItem*> items_;
|
||||
|
||||
QScrollBar* vertical_scrollbar_;
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
NodeTableView::NodeTableView(QWidget* parent) :
|
||||
QTreeWidget(parent),
|
||||
last_set_node_(nullptr)
|
||||
QTreeWidget(parent)
|
||||
{
|
||||
setColumnCount(3);
|
||||
setHeaderLabels({tr("Type"),
|
||||
@@ -41,14 +40,135 @@ NodeTableView::NodeTableView(QWidget* parent) :
|
||||
tr("A/W")});
|
||||
}
|
||||
|
||||
void NodeTableView::SelectNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
foreach (Node* n, nodes) {
|
||||
QTreeWidgetItem* top_item = new QTreeWidgetItem();
|
||||
top_item->setText(0, n->Name());
|
||||
top_item->setFirstColumnSpanned(true);
|
||||
this->addTopLevelItem(top_item);
|
||||
top_level_item_map_.insert(n, top_item);
|
||||
}
|
||||
|
||||
SetTime(last_time_);
|
||||
}
|
||||
|
||||
void NodeTableView::DeselectNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
foreach (Node* n, nodes) {
|
||||
delete top_level_item_map_.take(n);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTableView::SetTime(const rational &time)
|
||||
{
|
||||
last_time_ = time;
|
||||
|
||||
NodeTableTraverser traverser;
|
||||
|
||||
QMap<Node*, QTreeWidgetItem*>::const_iterator i;
|
||||
for (i=top_level_item_map_.constBegin(); i!=top_level_item_map_.constEnd(); i++) {
|
||||
Node* node = i.key();
|
||||
QTreeWidgetItem* item = i.value();
|
||||
|
||||
// Generate a value database for this node at this time
|
||||
NodeValueDatabase db = traverser.GenerateDatabase(node, TimeRange(time, time));
|
||||
|
||||
// Delete any children of this item that aren't in this database
|
||||
for (int j=0; j<item->childCount(); j++) {
|
||||
if (!db.contains(item->child(j)->data(0, Qt::UserRole).toString())) {
|
||||
delete item->takeChild(j);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
// Update all inputs
|
||||
NodeValueDatabase::const_iterator l;
|
||||
|
||||
for (l=db.begin(); l!=db.end(); l++) {
|
||||
const NodeValueTable& table = l.value();
|
||||
|
||||
NodeInput* input = node->GetInputWithID(l.key());
|
||||
if (!input) {
|
||||
// Filters out table entries that aren't inputs (like "global")
|
||||
continue;
|
||||
}
|
||||
|
||||
QTreeWidgetItem* input_item = nullptr;
|
||||
|
||||
for (int j=0; j<item->childCount(); j++) {
|
||||
QTreeWidgetItem* compare = item->child(j);
|
||||
|
||||
if (compare->data(0, Qt::UserRole).toString() == input->id()) {
|
||||
input_item = compare;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!input_item) {
|
||||
input_item = new QTreeWidgetItem();
|
||||
input_item->setText(0, input->name());
|
||||
input_item->setData(0, Qt::UserRole, input->id());
|
||||
input_item->setFirstColumnSpanned(true);
|
||||
item->addChild(input_item);
|
||||
}
|
||||
|
||||
// Create children if necessary
|
||||
while (input_item->childCount() < table.Count()) {
|
||||
input_item->addChild(new QTreeWidgetItem());
|
||||
}
|
||||
|
||||
// Remove children if necessary
|
||||
while (input_item->childCount() > table.Count()) {
|
||||
delete input_item->takeChild(input_item->childCount() - 1);
|
||||
}
|
||||
|
||||
for (int j=0;j<table.Count();j++) {
|
||||
const NodeValue& value = table.at(table.Count() - 1 - j);
|
||||
|
||||
// Create item
|
||||
QTreeWidgetItem* sub_item = input_item->child(j);
|
||||
|
||||
// Set data type name
|
||||
sub_item->setText(0, NodeParam::GetPrettyDataTypeName(value.type()));
|
||||
|
||||
// Determine source
|
||||
QString source_name;
|
||||
if (value.source()) {
|
||||
source_name = value.source()->Name();
|
||||
} else {
|
||||
source_name = tr("(unknown)");
|
||||
}
|
||||
sub_item->setText(1, source_name);
|
||||
|
||||
switch (value.type()) {
|
||||
case NodeParam::kTexture:
|
||||
{
|
||||
// NodeTableTraverser puts video params in here
|
||||
VideoParams p = value.data().value<VideoParams>();
|
||||
int channel_count = PixelFormat::ChannelCount(p.format());
|
||||
|
||||
for (int k=0;k<channel_count;k++) {
|
||||
this->setItemWidget(sub_item, 2 + k, new QCheckBox());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
QVector<QVariant> split_values = input->split_normal_value_into_track_values(value.data());
|
||||
for (int k=0;k<split_values.size();k++) {
|
||||
sub_item->setText(2 + k, NodeInput::ValueToString(value.type(), split_values.at(k)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
void NodeTableView::SetNode(Node *n, const rational &time)
|
||||
{
|
||||
if (last_set_node_ != n) {
|
||||
// Clear everything if the node has changed
|
||||
clear();
|
||||
}
|
||||
last_set_node_ = n;
|
||||
|
||||
NodeTableTraverser traverser;
|
||||
NodeValueDatabase db = traverser.GenerateDatabase(n, TimeRange(time, time));
|
||||
|
||||
@@ -141,15 +261,6 @@ void NodeTableView::SetNode(Node *n, const rational &time)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTableView::SetMultipleNodeMessage()
|
||||
{
|
||||
this->clear();
|
||||
|
||||
QTreeWidgetItem* item = new QTreeWidgetItem();
|
||||
item->setText(0, tr("Multiple nodes selected"));
|
||||
item->setFirstColumnSpanned(true);
|
||||
this->addTopLevelItem(item);
|
||||
}
|
||||
*/
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -32,12 +32,16 @@ class NodeTableView : public QTreeWidget
|
||||
public:
|
||||
NodeTableView(QWidget* parent = nullptr);
|
||||
|
||||
void SetNode(Node* n, const rational& time);
|
||||
void SelectNodes(const QList<Node*>& nodes);
|
||||
|
||||
void SetMultipleNodeMessage();
|
||||
void DeselectNodes(const QList<Node*>& nodes);
|
||||
|
||||
void SetTime(const rational& time);
|
||||
|
||||
private:
|
||||
Node* last_set_node_;
|
||||
QMap<Node*, QTreeWidgetItem*> top_level_item_map_;
|
||||
|
||||
rational last_time_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
OLIVE_NAMESPACE_ENTER
|
||||
|
||||
NodeTableWidget::NodeTableWidget(QWidget* parent) :
|
||||
TimeBasedWidget(parent),
|
||||
node_(nullptr)
|
||||
TimeBasedWidget(parent)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
@@ -36,37 +35,4 @@ NodeTableWidget::NodeTableWidget(QWidget* parent) :
|
||||
layout->addWidget(view_);
|
||||
}
|
||||
|
||||
void NodeTableWidget::SetNodes(const QList<Node *> &nodes)
|
||||
{
|
||||
node_ = nullptr;
|
||||
|
||||
if (nodes.isEmpty()) {
|
||||
view_->clear();
|
||||
} else if (nodes.size() == 1) {
|
||||
node_ = nodes.first();
|
||||
|
||||
ViewerOutput* viewer = node_->FindOutputNode<ViewerOutput>();
|
||||
if (viewer) {
|
||||
qDebug() << "Found timebase";
|
||||
SetTimebase(viewer->video_params().time_base());
|
||||
}
|
||||
|
||||
UpdateView();
|
||||
} else {
|
||||
view_->SetMultipleNodeMessage();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTableWidget::TimeChangedEvent(const int64_t &)
|
||||
{
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
void NodeTableWidget::UpdateView()
|
||||
{
|
||||
if (node_) {
|
||||
view_->SetNode(node_, GetTime());
|
||||
}
|
||||
}
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -31,18 +31,30 @@ class NodeTableWidget : public TimeBasedWidget
|
||||
public:
|
||||
NodeTableWidget(QWidget* parent = nullptr);
|
||||
|
||||
void SetNodes(const QList<Node*>& nodes);
|
||||
void SelectNodes(const QList<Node*>& nodes)
|
||||
{
|
||||
view_->SelectNodes(nodes);
|
||||
}
|
||||
|
||||
void DeselectNodes(const QList<Node*>& nodes)
|
||||
{
|
||||
view_->DeselectNodes(nodes);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void TimeChangedEvent(const int64_t& ts) override;
|
||||
virtual void TimeChangedEvent(const int64_t& ts) override
|
||||
{
|
||||
UpdateView();
|
||||
}
|
||||
|
||||
private:
|
||||
void UpdateView();
|
||||
void UpdateView()
|
||||
{
|
||||
view_->SetTime(GetTime());
|
||||
}
|
||||
|
||||
NodeTableView* view_;
|
||||
|
||||
Node* node_;
|
||||
|
||||
};
|
||||
|
||||
OLIVE_NAMESPACE_EXIT
|
||||
|
||||
@@ -144,7 +144,8 @@ void NodeView::SelectAll()
|
||||
|
||||
scene_.SelectAll();
|
||||
|
||||
ReconnectSelectionChangedSignal();
|
||||
ConnectSelectionChangedSignal();
|
||||
SceneSelectionChangedSlot();
|
||||
}
|
||||
|
||||
void NodeView::DeselectAll()
|
||||
@@ -155,7 +156,8 @@ void NodeView::DeselectAll()
|
||||
|
||||
scene_.DeselectAll();
|
||||
|
||||
ReconnectSelectionChangedSignal();
|
||||
ConnectSelectionChangedSignal();
|
||||
SceneSelectionChangedSlot();
|
||||
}
|
||||
|
||||
void NodeView::Select(const QList<Node *> &nodes)
|
||||
@@ -176,7 +178,8 @@ void NodeView::Select(const QList<Node *> &nodes)
|
||||
item->setSelected(true);
|
||||
}
|
||||
|
||||
ReconnectSelectionChangedSignal();
|
||||
ConnectSelectionChangedSignal();
|
||||
SceneSelectionChangedSlot();
|
||||
}
|
||||
|
||||
void NodeView::SelectWithDependencies(QList<Node *> nodes)
|
||||
@@ -195,10 +198,13 @@ void NodeView::SelectWithDependencies(QList<Node *> nodes)
|
||||
|
||||
void NodeView::SelectBlocks(const QList<Block *> &blocks)
|
||||
{
|
||||
if (selected_blocks_ == blocks) {
|
||||
return;
|
||||
}
|
||||
selected_blocks_.append(blocks);
|
||||
|
||||
SelectBlocksInternal();
|
||||
}
|
||||
|
||||
void NodeView::DeselectBlocks(const QList<Block *> &blocks)
|
||||
{
|
||||
// Remove temporary associations
|
||||
foreach (Block* b, selected_blocks_) {
|
||||
if (!blocks.contains(b)) {
|
||||
@@ -206,35 +212,12 @@ void NodeView::SelectBlocks(const QList<Block *> &blocks)
|
||||
}
|
||||
}
|
||||
|
||||
selected_blocks_ = blocks;
|
||||
|
||||
// Block scene signals while our selection is changing a lot
|
||||
scene_.blockSignals(true);
|
||||
|
||||
if (filter_mode_ == kFilterShowSelectedBlocks) {
|
||||
UpdateBlockFilter();
|
||||
}
|
||||
|
||||
QList<Node*> nodes;
|
||||
nodes.reserve(blocks.size());
|
||||
|
||||
// Remove blocks from selected array
|
||||
foreach (Block* b, blocks) {
|
||||
nodes.append(b);
|
||||
nodes.append(b->GetDependencies());
|
||||
selected_blocks_.removeOne(b);
|
||||
}
|
||||
|
||||
SelectWithDependencies(nodes);
|
||||
|
||||
// Stop blocking signals and send a change signal now that all of our processing is done
|
||||
scene_.blockSignals(false);
|
||||
SceneSelectionChangedSlot();
|
||||
|
||||
if (!blocks.isEmpty()) {
|
||||
NodeViewItem* item = scene_.NodeToUIObject(blocks.first());
|
||||
if (item) {
|
||||
centerOn(item);
|
||||
}
|
||||
}
|
||||
SelectBlocksInternal();
|
||||
}
|
||||
|
||||
void NodeView::CopySelected(bool cut)
|
||||
@@ -478,7 +461,44 @@ void NodeView::wheelEvent(QWheelEvent *event)
|
||||
|
||||
void NodeView::SceneSelectionChangedSlot()
|
||||
{
|
||||
emit SelectionChanged(scene_.GetSelectedNodes());
|
||||
QList<Node*> current_selection = scene_.GetSelectedNodes();
|
||||
|
||||
QList<Node*> selected;
|
||||
QList<Node*> deselected;
|
||||
|
||||
// Determine which nodes are newly selected
|
||||
if (selected_nodes_.isEmpty()) {
|
||||
// All nodes in the current selection have just been selected
|
||||
selected = current_selection;
|
||||
} else {
|
||||
foreach (Node* n, current_selection) {
|
||||
if (!selected_nodes_.contains(n)) {
|
||||
selected.append(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine which nodes are newly deselected
|
||||
if (current_selection.isEmpty()) {
|
||||
// All nodes that were selected have been deselected
|
||||
deselected = selected_nodes_;
|
||||
} else {
|
||||
foreach (Node* n, selected_nodes_) {
|
||||
if (!current_selection.contains(n)) {
|
||||
deselected.append(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
selected_nodes_ = current_selection;
|
||||
|
||||
if (!selected.isEmpty()) {
|
||||
emit NodesSelected(selected);
|
||||
}
|
||||
|
||||
if (!deselected.isEmpty()) {
|
||||
emit NodesDeselected(deselected);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::ShowContextMenu(const QPoint &pos)
|
||||
@@ -803,12 +823,6 @@ void NodeView::ConnectSelectionChangedSignal()
|
||||
connect(&scene_, &QGraphicsScene::selectionChanged, this, &NodeView::SceneSelectionChangedSlot);
|
||||
}
|
||||
|
||||
void NodeView::ReconnectSelectionChangedSignal()
|
||||
{
|
||||
ConnectSelectionChangedSignal();
|
||||
SceneSelectionChangedSlot();
|
||||
}
|
||||
|
||||
void NodeView::DisconnectSelectionChangedSignal()
|
||||
{
|
||||
disconnect(&scene_, &QGraphicsScene::selectionChanged, this, &NodeView::SceneSelectionChangedSlot);
|
||||
@@ -913,6 +927,37 @@ void NodeView::DisassociateNode(Node *n, bool remove_from_map)
|
||||
disconnect(n, &Node::destroyed, this, &NodeView::AssociatedNodeDestroyed);
|
||||
}
|
||||
|
||||
void NodeView::SelectBlocksInternal()
|
||||
{
|
||||
// Block scene signals while our selection is changing a lot
|
||||
scene_.blockSignals(true);
|
||||
|
||||
if (filter_mode_ == kFilterShowSelectedBlocks) {
|
||||
UpdateBlockFilter();
|
||||
}
|
||||
|
||||
QList<Node*> nodes;
|
||||
nodes.reserve(selected_blocks_.size());
|
||||
|
||||
foreach (Block* b, selected_blocks_) {
|
||||
nodes.append(b);
|
||||
nodes.append(b->GetDependencies());
|
||||
}
|
||||
|
||||
SelectWithDependencies(nodes);
|
||||
|
||||
// Stop blocking signals and send a change signal now that all of our processing is done
|
||||
scene_.blockSignals(false);
|
||||
SceneSelectionChangedSlot();
|
||||
|
||||
if (!selected_blocks_.isEmpty()) {
|
||||
NodeViewItem* item = scene_.NodeToUIObject(selected_blocks_.first());
|
||||
if (item) {
|
||||
centerOn(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeView::ValidateFilter()
|
||||
{
|
||||
// Force auto-positioning
|
||||
|
||||
@@ -61,18 +61,19 @@ public:
|
||||
void Select(const QList<Node*>& nodes);
|
||||
void SelectWithDependencies(QList<Node *> nodes);
|
||||
|
||||
void SelectBlocks(const QList<Block*>& blocks);
|
||||
|
||||
void CopySelected(bool cut);
|
||||
void Paste();
|
||||
|
||||
void Duplicate();
|
||||
|
||||
void SelectBlocks(const QList<Block*>& blocks);
|
||||
|
||||
void DeselectBlocks(const QList<Block*>& blocks);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted when the selected nodes have changed
|
||||
*/
|
||||
void SelectionChanged(QList<Node*> selected_nodes);
|
||||
void NodesSelected(const QList<Node*>& nodes);
|
||||
|
||||
void NodesDeselected(const QList<Node*>& nodes);
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
@@ -83,6 +84,8 @@ protected:
|
||||
|
||||
virtual void wheelEvent(QWheelEvent* event) override;
|
||||
|
||||
//virtual void scrollContentsBy(int dx, int dy) override;
|
||||
|
||||
private:
|
||||
void PlaceNode(NodeViewItem* n, const QPointF& pos);
|
||||
|
||||
@@ -97,7 +100,6 @@ private:
|
||||
void MoveAttachedNodesToCursor(const QPoint &p);
|
||||
|
||||
void ConnectSelectionChangedSignal();
|
||||
void ReconnectSelectionChangedSignal();
|
||||
void DisconnectSelectionChangedSignal();
|
||||
|
||||
void UpdateBlockFilter();
|
||||
@@ -105,6 +107,8 @@ private:
|
||||
void AssociateNodeWithSelectedBlocks(Node* n);
|
||||
void DisassociateNode(Node* n, bool remove_from_map);
|
||||
|
||||
void SelectBlocksInternal();
|
||||
|
||||
NodeGraph* graph_;
|
||||
|
||||
struct AttachedItem {
|
||||
@@ -119,6 +123,8 @@ private:
|
||||
|
||||
NodeViewScene scene_;
|
||||
|
||||
QList<Node*> selected_nodes_;
|
||||
|
||||
QList<Block*> selected_blocks_;
|
||||
|
||||
QHash<Node*, QList<Block*> > association_map_;
|
||||
|
||||
@@ -129,7 +129,6 @@ TimelineWidget::TimelineWidget(QWidget *parent) :
|
||||
connect(view, &TimelineView::DragMoved, this, &TimelineWidget::ViewDragMoved);
|
||||
connect(view, &TimelineView::DragLeft, this, &TimelineWidget::ViewDragLeft);
|
||||
connect(view, &TimelineView::DragDropped, this, &TimelineWidget::ViewDragDropped);
|
||||
ConnectViewSelectionSignal(view);
|
||||
|
||||
connect(tview->splitter(), &QSplitter::splitterMoved, this, &TimelineWidget::UpdateHorizontalSplitters);
|
||||
|
||||
@@ -163,21 +162,19 @@ TimelineWidget::~TimelineWidget()
|
||||
|
||||
void TimelineWidget::Clear()
|
||||
{
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
DisconnectViewSelectionSignal(tview->view());
|
||||
}
|
||||
QList<Block*> deselected_blocks;
|
||||
|
||||
QMap<Block*, TimelineViewBlockItem*>::const_iterator iterator;
|
||||
for (iterator=block_items_.begin(); iterator!=block_items_.end(); iterator++) {
|
||||
if (iterator.value()->isSelected()) {
|
||||
deselected_blocks.append(iterator.key());
|
||||
}
|
||||
|
||||
delete iterator.value();
|
||||
}
|
||||
block_items_.clear();
|
||||
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
ConnectViewSelectionSignal(tview->view());
|
||||
}
|
||||
|
||||
emit SelectionChanged(QList<Block*>());
|
||||
emit BlocksDeselected(deselected_blocks);
|
||||
|
||||
SetTimebase(0);
|
||||
}
|
||||
@@ -379,24 +376,34 @@ rational TimelineWidget::GetToolTipTimebase() const
|
||||
|
||||
void TimelineWidget::SelectAll()
|
||||
{
|
||||
foreach (TimelineAndTrackView* view, views_) {
|
||||
DisconnectViewSelectionSignal(view->view());
|
||||
view->view()->SelectAll();
|
||||
ConnectViewSelectionSignal(view->view());
|
||||
QList<Block*> blocks_selected;
|
||||
|
||||
QMap<Block*, TimelineViewBlockItem*>::const_iterator i;
|
||||
|
||||
for (i=block_items_.constBegin(); i!=block_items_.end(); i++) {
|
||||
if (!i.value()->isSelected()) {
|
||||
i.value()->setSelected(true);
|
||||
blocks_selected.append(i.key());
|
||||
}
|
||||
}
|
||||
|
||||
ViewSelectionChanged();
|
||||
emit BlocksSelected(blocks_selected);
|
||||
}
|
||||
|
||||
void TimelineWidget::DeselectAll()
|
||||
{
|
||||
foreach (TimelineAndTrackView* view, views_) {
|
||||
DisconnectViewSelectionSignal(view->view());
|
||||
view->view()->DeselectAll();
|
||||
ConnectViewSelectionSignal(view->view());
|
||||
QList<Block*> blocks_deselected;
|
||||
|
||||
QMap<Block*, TimelineViewBlockItem*>::const_iterator i;
|
||||
|
||||
for (i=block_items_.constBegin(); i!=block_items_.end(); i++) {
|
||||
if (i.value()->isSelected()) {
|
||||
i.value()->setSelected(false);
|
||||
blocks_deselected.append(i.key());
|
||||
}
|
||||
}
|
||||
|
||||
emit SelectionChanged(QList<Block*>());
|
||||
emit BlocksDeselected(blocks_deselected);
|
||||
}
|
||||
|
||||
void TimelineWidget::RippleToIn()
|
||||
@@ -803,16 +810,6 @@ TrackOutput *TimelineWidget::GetTrackFromReference(const TrackReference &ref)
|
||||
return GetConnectedNode()->track_list(ref.type())->GetTrackAt(ref.index());
|
||||
}
|
||||
|
||||
void TimelineWidget::ConnectViewSelectionSignal(TimelineView *view)
|
||||
{
|
||||
connect(view, &TimelineView::SelectionChanged, this, &TimelineWidget::ViewSelectionChanged);
|
||||
}
|
||||
|
||||
void TimelineWidget::DisconnectViewSelectionSignal(TimelineView *view)
|
||||
{
|
||||
disconnect(view, &TimelineView::SelectionChanged, this, &TimelineWidget::ViewSelectionChanged);
|
||||
}
|
||||
|
||||
int TimelineWidget::GetTrackY(const TrackReference &ref)
|
||||
{
|
||||
return views_.at(ref.type())->view()->GetTrackY(ref.index());
|
||||
@@ -983,22 +980,6 @@ void TimelineWidget::TrackIndexChanged()
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineWidget::ViewSelectionChanged()
|
||||
{
|
||||
if (rubberband_.isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QList<TimelineViewBlockItem*> selected_items = GetSelectedBlocks();
|
||||
QList<Block*> selected_blocks;
|
||||
|
||||
foreach (TimelineViewBlockItem* item, selected_items) {
|
||||
selected_blocks.append(item->block());
|
||||
}
|
||||
|
||||
emit SelectionChanged(selected_blocks);
|
||||
}
|
||||
|
||||
void TimelineWidget::BlockRefreshed()
|
||||
{
|
||||
TimelineViewRect* rect = block_items_.value(static_cast<Block*>(sender()));
|
||||
@@ -1393,6 +1374,14 @@ void TimelineWidget::StartRubberBandSelect(bool enable_selecting, bool select_li
|
||||
drag_origin_ = QCursor::pos();
|
||||
rubberband_.show();
|
||||
|
||||
// We don't touch any blocks that are already selected. If you want these to be deselected by
|
||||
// default, call DeselectAll() befoer calling StartRubberBandSelect()
|
||||
foreach (TimelineViewBlockItem* block, block_items_) {
|
||||
if (block->isSelected()) {
|
||||
rubberband_already_selected_.append(block);
|
||||
}
|
||||
}
|
||||
|
||||
MoveRubberBandSelect(enable_selecting, select_links);
|
||||
}
|
||||
|
||||
@@ -1408,10 +1397,11 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
|
||||
QList<QGraphicsItem*> new_selected_list;
|
||||
|
||||
// Determine all items in the rubberband
|
||||
foreach (TimelineAndTrackView* tview, views_) {
|
||||
// Map global mouse coordinates to viewport
|
||||
TimelineView* view = tview->view();
|
||||
|
||||
// Map global mouse coordinates to viewport
|
||||
QRect mapped_rect(view->viewport()->mapFromGlobal(drag_origin_),
|
||||
view->viewport()->mapFromGlobal(rubberband_now));
|
||||
|
||||
@@ -1421,13 +1411,25 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
new_selected_list.append(rubberband_items);
|
||||
}
|
||||
|
||||
// Filter out any items that were already selected
|
||||
if (!rubberband_already_selected_.isEmpty()) {
|
||||
for (int i=0; i<new_selected_list.size(); i++) {
|
||||
if (rubberband_already_selected_.contains(new_selected_list.at(i))) {
|
||||
new_selected_list.removeAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (QGraphicsItem* item, rubberband_now_selected_) {
|
||||
item->setSelected(false);
|
||||
}
|
||||
|
||||
foreach (QGraphicsItem* item, new_selected_list) {
|
||||
TimelineViewBlockItem* block_item = dynamic_cast<TimelineViewBlockItem*>(item);
|
||||
if (!block_item || block_item->block()->type() == Block::kGap) {
|
||||
// Cache limit because we append to this array in this loop and don't need to process those
|
||||
int lim = new_selected_list.size();
|
||||
for (int i=0;i<lim;i++) {
|
||||
TimelineViewBlockItem* block_item = static_cast<TimelineViewBlockItem*>(new_selected_list.at(i));
|
||||
if (block_item->block()->type() == Block::kGap) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1436,18 +1438,22 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
continue;
|
||||
}
|
||||
|
||||
// Since new_selected_list is filtered by rubberband_already_selected_, this should certainly
|
||||
// be deselected by now
|
||||
block_item->setSelected(true);
|
||||
|
||||
if (select_links) {
|
||||
// Select the block's links
|
||||
Block* b = block_item->block();
|
||||
SetBlockLinksSelected(b, true);
|
||||
|
||||
// Add its links to the list
|
||||
TimelineViewBlockItem* link_item;
|
||||
foreach (Block* link, b->linked_clips()) {
|
||||
if ((link_item = block_items_[link]) != nullptr) {
|
||||
if (!new_selected_list.contains(link_item)) {
|
||||
link_item->setSelected(true);
|
||||
|
||||
if (!new_selected_list.contains(link_item)
|
||||
&& !rubberband_already_selected_.contains(link_item)) {
|
||||
new_selected_list.append(link_item);
|
||||
}
|
||||
}
|
||||
@@ -1458,13 +1464,19 @@ void TimelineWidget::MoveRubberBandSelect(bool enable_selecting, bool select_lin
|
||||
rubberband_now_selected_ = new_selected_list;
|
||||
}
|
||||
|
||||
void TimelineWidget::EndRubberBandSelect(bool enable_selecting, bool select_links)
|
||||
void TimelineWidget::EndRubberBandSelect()
|
||||
{
|
||||
MoveRubberBandSelect(enable_selecting, select_links);
|
||||
rubberband_.hide();
|
||||
rubberband_now_selected_.clear();
|
||||
|
||||
ViewSelectionChanged();
|
||||
// Emit any blocks that were newly selected
|
||||
QList<Block*> selected_blocks;
|
||||
foreach (QGraphicsItem* item, rubberband_now_selected_) {
|
||||
selected_blocks.append(static_cast<TimelineViewBlockItem*>(item)->block());
|
||||
}
|
||||
emit BlocksSelected(selected_blocks);
|
||||
|
||||
rubberband_now_selected_.clear();
|
||||
rubberband_already_selected_.clear();
|
||||
}
|
||||
|
||||
struct SnapData {
|
||||
|
||||
@@ -104,7 +104,9 @@ public:
|
||||
void RestoreSplitterState(const QByteArray& state);
|
||||
|
||||
signals:
|
||||
void SelectionChanged(const QList<Block*>& selected_blocks);
|
||||
void BlocksSelected(const QList<Block*>& selected_blocks);
|
||||
|
||||
void BlocksDeselected(const QList<Block*>& deselected_blocks);
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
@@ -474,8 +476,9 @@ private:
|
||||
|
||||
void StartRubberBandSelect(bool enable_selecting, bool select_links);
|
||||
void MoveRubberBandSelect(bool enable_selecting, bool select_links);
|
||||
void EndRubberBandSelect(bool enable_selecting, bool select_links);
|
||||
void EndRubberBandSelect();
|
||||
QRubberBand rubberband_;
|
||||
QList<QGraphicsItem*> rubberband_already_selected_;
|
||||
QList<QGraphicsItem*> rubberband_now_selected_;
|
||||
|
||||
Tool* GetActiveTool();
|
||||
@@ -496,10 +499,6 @@ private:
|
||||
|
||||
TrackOutput* GetTrackFromReference(const TrackReference& ref);
|
||||
|
||||
void ConnectViewSelectionSignal(TimelineView* view);
|
||||
|
||||
void DisconnectViewSelectionSignal(TimelineView* view);
|
||||
|
||||
QList<TimelineAndTrackView*> views_;
|
||||
|
||||
TimeSlider* timecode_label_;
|
||||
@@ -539,8 +538,6 @@ private slots:
|
||||
void RemoveTrack(TrackOutput* track);
|
||||
void TrackIndexChanged();
|
||||
|
||||
void ViewSelectionChanged();
|
||||
|
||||
/**
|
||||
* @brief Slot for when a Block node changes its parameters and the graphics need to update
|
||||
*
|
||||
|
||||
@@ -78,16 +78,23 @@ void TimelineWidget::PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
// If this item is already selected, no further selection needs to be made
|
||||
if (clicked_item_->isSelected()) {
|
||||
|
||||
// Collect item deselections
|
||||
QList<Block*> deselected_blocks;
|
||||
|
||||
// If shift is held, deselect it
|
||||
if (event->GetModifiers() & Qt::ShiftModifier) {
|
||||
clicked_item_->setSelected(false);
|
||||
deselected_blocks.append(clicked_item_->block());
|
||||
|
||||
// If not holding alt, deselect all links as well
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
parent()->SetBlockLinksSelected(clicked_item_->block(), false);
|
||||
deselected_blocks.append(clicked_item_->block()->linked_clips().toList());
|
||||
}
|
||||
}
|
||||
|
||||
emit parent()->BlocksDeselected(deselected_blocks);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -98,18 +105,29 @@ void TimelineWidget::PointerTool::MousePress(TimelineViewMouseEvent *event)
|
||||
}
|
||||
|
||||
if (selectable_item) {
|
||||
|
||||
// Collect item selections
|
||||
QList<Block*> selected_blocks;
|
||||
|
||||
// Select this item
|
||||
clicked_item_->setSelected(true);
|
||||
selected_blocks.append(clicked_item_->block());
|
||||
|
||||
// If not holding alt, select all links as well
|
||||
if (!(event->GetModifiers() & Qt::AltModifier)) {
|
||||
parent()->SetBlockLinksSelected(clicked_item_->block(), true);
|
||||
selected_blocks.append(clicked_item_->block()->linked_clips().toList());
|
||||
}
|
||||
|
||||
emit parent()->BlocksSelected(selected_blocks);
|
||||
|
||||
} else if (event->GetButton() == Qt::LeftButton) {
|
||||
|
||||
// Start rubberband drag
|
||||
parent()->StartRubberBandSelect(true, !(event->GetModifiers() & Qt::AltModifier));
|
||||
|
||||
rubberband_selecting_ = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +168,7 @@ void TimelineWidget::PointerTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
{
|
||||
if (rubberband_selecting_) {
|
||||
// Finish rubberband select
|
||||
parent()->EndRubberBandSelect(true, !(event->GetModifiers() & Qt::AltModifier));
|
||||
parent()->EndRubberBandSelect();
|
||||
rubberband_selecting_ = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ void TimelineWidget::ZoomTool::MouseRelease(TimelineViewMouseEvent *event)
|
||||
// Zoom into the rubberband selection
|
||||
QRect screen_coords = parent()->rubberband_.geometry();
|
||||
|
||||
parent()->EndRubberBandSelect(false, false);
|
||||
parent()->EndRubberBandSelect();
|
||||
|
||||
TimelineView* reference_view = parent()->views_.first()->view();
|
||||
QPointF scene_topleft = reference_view->mapToScene(reference_view->mapFrom(parent(), screen_coords.topLeft()));
|
||||
|
||||
@@ -47,26 +47,6 @@ TimelineView::TimelineView(Qt::Alignment vertical_alignment, QWidget *parent) :
|
||||
setBackgroundRole(QPalette::Window);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
viewport()->setMouseTracking(true);
|
||||
|
||||
connect(scene(), &QGraphicsScene::selectionChanged, this, &TimelineView::SelectionChanged);
|
||||
}
|
||||
|
||||
void TimelineView::SelectAll()
|
||||
{
|
||||
QList<QGraphicsItem*> all_items = items();
|
||||
|
||||
foreach (QGraphicsItem* i, all_items) {
|
||||
i->setSelected(true);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineView::DeselectAll()
|
||||
{
|
||||
QList<QGraphicsItem*> all_items = items();
|
||||
|
||||
foreach (QGraphicsItem* i, all_items) {
|
||||
i->setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineView::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
@@ -49,10 +49,6 @@ public:
|
||||
TimelineView(Qt::Alignment vertical_alignment = Qt::AlignTop,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
void SelectAll();
|
||||
|
||||
void DeselectAll();
|
||||
|
||||
int GetTrackY(int track_index) const;
|
||||
int GetTrackHeight(int track_index) const;
|
||||
|
||||
@@ -74,8 +70,6 @@ signals:
|
||||
void DragLeft(QDragLeaveEvent* event);
|
||||
void DragDropped(TimelineViewMouseEvent* event);
|
||||
|
||||
void SelectionChanged();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
|
||||
@@ -82,8 +82,10 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
audio_monitor_panel_ = PanelManager::instance()->CreatePanel<AudioMonitorPanel>(this);
|
||||
|
||||
// Make connections to sequence viewer
|
||||
connect(node_panel_, &NodePanel::SelectionChanged, param_panel_, &ParamPanel::SetNodes);
|
||||
connect(node_panel_, &NodePanel::SelectionChanged, table_panel_, &NodeTablePanel::SetNodes);
|
||||
connect(node_panel_, &NodePanel::NodesSelected, param_panel_, &ParamPanel::SelectNodes);
|
||||
connect(node_panel_, &NodePanel::NodesDeselected, param_panel_, &ParamPanel::DeselectNodes);
|
||||
connect(node_panel_, &NodePanel::NodesSelected, table_panel_, &NodeTablePanel::SelectNodes);
|
||||
connect(node_panel_, &NodePanel::NodesDeselected, table_panel_, &NodeTablePanel::DeselectNodes);
|
||||
connect(param_panel_, &ParamPanel::RequestSelectNode, node_panel_, &NodePanel::Select);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, param_panel_, &ParamPanel::SetTimestamp);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, table_panel_, &NodeTablePanel::SetTimestamp);
|
||||
@@ -480,7 +482,8 @@ TimelinePanel* MainWindow::AppendTimelinePanel()
|
||||
connect(panel, &TimelinePanel::TimeChanged, param_panel_, &ParamPanel::SetTimestamp);
|
||||
connect(panel, &TimelinePanel::TimeChanged, table_panel_, &NodeTablePanel::SetTimestamp);
|
||||
connect(panel, &TimelinePanel::TimeChanged, sequence_viewer_panel_, &SequenceViewerPanel::SetTimestamp);
|
||||
connect(panel, &TimelinePanel::SelectionChanged, node_panel_, &NodePanel::SelectBlocks);
|
||||
connect(panel, &TimelinePanel::BlocksSelected, node_panel_, &NodePanel::SelectBlocks);
|
||||
connect(panel, &TimelinePanel::BlocksDeselected, node_panel_, &NodePanel::DeselectBlocks);
|
||||
connect(param_panel_, &ParamPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
|
||||
connect(sequence_viewer_panel_, &SequenceViewerPanel::TimeChanged, panel, &TimelinePanel::SetTimestamp);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user