change: change code style to Linux style except indent.
This commit is contained in:
@@ -28,456 +28,478 @@
|
||||
#include "common/decibel.h"
|
||||
#include "common/qtutils.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const int kDecibelStep = 6;
|
||||
const int kDecibelMinimum = -198; // Must be divisible by kDecibelStep for infinity to appear
|
||||
const int kDecibelMinimum =
|
||||
-198; // Must be divisible by kDecibelStep for infinity to appear
|
||||
const int kMaximumSmoothness = 8;
|
||||
|
||||
QVector<AudioMonitor*> AudioMonitor::instances_;
|
||||
QVector<AudioMonitor *> AudioMonitor::instances_;
|
||||
|
||||
AudioMonitor::AudioMonitor(QWidget *parent) :
|
||||
QOpenGLWidget(parent),
|
||||
waveform_(nullptr),
|
||||
cached_channels_(0)
|
||||
AudioMonitor::AudioMonitor(QWidget *parent)
|
||||
: QOpenGLWidget(parent)
|
||||
, waveform_(nullptr)
|
||||
, cached_channels_(0)
|
||||
{
|
||||
instances_.append(this);
|
||||
instances_.append(this);
|
||||
|
||||
values_.resize(kMaximumSmoothness);
|
||||
values_.resize(kMaximumSmoothness);
|
||||
|
||||
this->setMinimumWidth(this->fontMetrics().height());
|
||||
this->setMinimumWidth(this->fontMetrics().height());
|
||||
}
|
||||
|
||||
AudioMonitor::~AudioMonitor()
|
||||
{
|
||||
instances_.removeOne(this);
|
||||
instances_.removeOne(this);
|
||||
}
|
||||
|
||||
void AudioMonitor::SetParams(const AudioParams ¶ms)
|
||||
{
|
||||
if (params_ != params) {
|
||||
params_ = params;
|
||||
if (params_ != params) {
|
||||
params_ = params;
|
||||
|
||||
for (int i=0;i<values_.size();i++) {
|
||||
values_[i].resize(params_.channel_count());
|
||||
values_[i].fill(0);
|
||||
}
|
||||
for (int i = 0; i < values_.size(); i++) {
|
||||
values_[i].resize(params_.channel_count());
|
||||
values_[i].fill(0);
|
||||
}
|
||||
|
||||
peaked_.resize(params_.channel_count());
|
||||
peaked_.fill(false);
|
||||
peaked_.resize(params_.channel_count());
|
||||
peaked_.fill(false);
|
||||
|
||||
update();
|
||||
}
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioMonitor::Stop()
|
||||
{
|
||||
waveform_ = nullptr;
|
||||
waveform_ = nullptr;
|
||||
|
||||
// We don't stop the update loop here so that the monitor can show a smooth fade out. The update
|
||||
// loop will stop itself since file_ and waveform_ are null.
|
||||
// We don't stop the update loop here so that the monitor can show a smooth fade out. The update
|
||||
// loop will stop itself since file_ and waveform_ are null.
|
||||
}
|
||||
|
||||
void AudioMonitor::PushSampleBuffer(const SampleBuffer &d)
|
||||
{
|
||||
if (!params_.channel_count()) {
|
||||
return;
|
||||
}
|
||||
if (!params_.channel_count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QVector<double> v(params_.channel_count(), 0);
|
||||
QVector<double> v(params_.channel_count(), 0);
|
||||
|
||||
AudioVisualWaveform::Sample summed = AudioVisualWaveform::SumSamples(d, 0, d.sample_count());
|
||||
AudioVisualWaveform::Sample summed =
|
||||
AudioVisualWaveform::SumSamples(d, 0, d.sample_count());
|
||||
|
||||
AudioVisualWaveformSampleToInternalValues(summed, v);
|
||||
AudioVisualWaveformSampleToInternalValues(summed, v);
|
||||
|
||||
// Fill values because they get averaged out for smoothing
|
||||
values_.fill(v);
|
||||
// Fill values because they get averaged out for smoothing
|
||||
values_.fill(v);
|
||||
|
||||
SetUpdateLoop(true);
|
||||
SetUpdateLoop(true);
|
||||
}
|
||||
|
||||
void AudioMonitor::StartWaveform(const AudioWaveformCache *waveform, const rational &start, int playback_speed)
|
||||
void AudioMonitor::StartWaveform(const AudioWaveformCache *waveform,
|
||||
const rational &start, int playback_speed)
|
||||
{
|
||||
Stop();
|
||||
Stop();
|
||||
|
||||
waveform_length_ = waveform->length();
|
||||
if (start >= waveform_length_) {
|
||||
return;
|
||||
}
|
||||
waveform_length_ = waveform->length();
|
||||
if (start >= waveform_length_) {
|
||||
return;
|
||||
}
|
||||
|
||||
waveform_ = waveform;
|
||||
waveform_time_ = start;
|
||||
waveform_ = waveform;
|
||||
waveform_time_ = start;
|
||||
|
||||
playback_speed_ = playback_speed;
|
||||
playback_speed_ = playback_speed;
|
||||
|
||||
last_time_ = QDateTime::currentMSecsSinceEpoch();
|
||||
last_time_ = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
SetUpdateLoop(true);
|
||||
SetUpdateLoop(true);
|
||||
}
|
||||
|
||||
void AudioMonitor::SetUpdateLoop(bool e)
|
||||
{
|
||||
if (e) {
|
||||
connect(this, &AudioMonitor::frameSwapped, this, static_cast<void(AudioMonitor::*)()>(&AudioMonitor::update));
|
||||
if (e) {
|
||||
connect(this, &AudioMonitor::frameSwapped, this,
|
||||
static_cast<void (AudioMonitor::*)()>(&AudioMonitor::update));
|
||||
|
||||
update();
|
||||
} else {
|
||||
disconnect(this, &AudioMonitor::frameSwapped, this, static_cast<void(AudioMonitor::*)()>(&AudioMonitor::update));
|
||||
}
|
||||
update();
|
||||
} else {
|
||||
disconnect(
|
||||
this, &AudioMonitor::frameSwapped, this,
|
||||
static_cast<void (AudioMonitor::*)()>(&AudioMonitor::update));
|
||||
}
|
||||
}
|
||||
|
||||
void AudioMonitor::paintGL()
|
||||
{
|
||||
QPainter p(this);
|
||||
QPalette palette = qApp->palette();
|
||||
QRect geometry(0, 0, width(), height());
|
||||
QPainter p(this);
|
||||
QPalette palette = qApp->palette();
|
||||
QRect geometry(0, 0, width(), height());
|
||||
|
||||
p.fillRect(geometry, palette.window().color());
|
||||
p.fillRect(geometry, palette.window().color());
|
||||
|
||||
if (!params_.channel_count()) {
|
||||
return;
|
||||
}
|
||||
if (!params_.channel_count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFont f = p.font();
|
||||
f.setPointSizeF(f.pointSizeF() * 0.75);
|
||||
p.setFont(f);
|
||||
QFont f = p.font();
|
||||
f.setPointSizeF(f.pointSizeF() * 0.75);
|
||||
p.setFont(f);
|
||||
|
||||
QFontMetrics fm = p.fontMetrics();
|
||||
QFontMetrics fm = p.fontMetrics();
|
||||
|
||||
int font_height = fm.height();
|
||||
int font_height = fm.height();
|
||||
|
||||
bool horizontal = this->width() > this->height();
|
||||
bool horizontal = this->width() > this->height();
|
||||
|
||||
int minimum_width = this->fontMetrics().height() * 3;
|
||||
int minimum_width = this->fontMetrics().height() * 3;
|
||||
|
||||
// Determine rect where the main meter will go
|
||||
QRect full_meter_rect = geometry;
|
||||
// Determine rect where the main meter will go
|
||||
QRect full_meter_rect = geometry;
|
||||
|
||||
// Create rect where decibel markings will go on the side
|
||||
QRect db_labels_rect;
|
||||
bool draw_text;
|
||||
// Create rect where decibel markings will go on the side
|
||||
QRect db_labels_rect;
|
||||
bool draw_text;
|
||||
|
||||
// Width of each channel in the meter
|
||||
int peaks_pos;
|
||||
int channel_size;
|
||||
int db_line_length = fm.horizontalAdvance(QStringLiteral("-"));
|
||||
int db_width = QtUtils::QFontMetricsWidth(p.fontMetrics(), "-00 ");
|
||||
if (horizontal) {
|
||||
// Insert peaks area
|
||||
full_meter_rect.adjust(0, 0, -font_height, 0);
|
||||
// Width of each channel in the meter
|
||||
int peaks_pos;
|
||||
int channel_size;
|
||||
int db_line_length = fm.horizontalAdvance(QStringLiteral("-"));
|
||||
int db_width = QtUtils::QFontMetricsWidth(p.fontMetrics(), "-00 ");
|
||||
if (horizontal) {
|
||||
// Insert peaks area
|
||||
full_meter_rect.adjust(0, 0, -font_height, 0);
|
||||
|
||||
draw_text = (height() >= minimum_width);
|
||||
draw_text = (height() >= minimum_width);
|
||||
|
||||
// Derive dB label rect
|
||||
if (draw_text) {
|
||||
// Insert meter rect
|
||||
full_meter_rect.adjust(db_width/2, 0, 0, -font_height);
|
||||
// Derive dB label rect
|
||||
if (draw_text) {
|
||||
// Insert meter rect
|
||||
full_meter_rect.adjust(db_width / 2, 0, 0, -font_height);
|
||||
|
||||
db_labels_rect = full_meter_rect;
|
||||
db_labels_rect.setTop(db_labels_rect.bottom());
|
||||
db_labels_rect.setHeight(font_height + db_line_length);
|
||||
}
|
||||
db_labels_rect = full_meter_rect;
|
||||
db_labels_rect.setTop(db_labels_rect.bottom());
|
||||
db_labels_rect.setHeight(font_height + db_line_length);
|
||||
}
|
||||
|
||||
// Divide height by channel count
|
||||
channel_size = full_meter_rect.height() / params_.channel_count();
|
||||
// Divide height by channel count
|
||||
channel_size = full_meter_rect.height() / params_.channel_count();
|
||||
|
||||
// Set peaks Y to right-most
|
||||
peaks_pos = full_meter_rect.right();
|
||||
} else {
|
||||
// Insert peaks rect
|
||||
full_meter_rect.adjust(0, font_height, 0, 0);
|
||||
// Set peaks Y to right-most
|
||||
peaks_pos = full_meter_rect.right();
|
||||
} else {
|
||||
// Insert peaks rect
|
||||
full_meter_rect.adjust(0, font_height, 0, 0);
|
||||
|
||||
draw_text = (width() >= minimum_width);
|
||||
draw_text = (width() >= minimum_width);
|
||||
|
||||
// Derive dB label rect
|
||||
if (draw_text) {
|
||||
int db_width_and_line = db_width + db_line_length;
|
||||
// Derive dB label rect
|
||||
if (draw_text) {
|
||||
int db_width_and_line = db_width + db_line_length;
|
||||
|
||||
// Insert meter rect
|
||||
full_meter_rect.adjust(db_width_and_line, 0, 0, -font_height / 2);
|
||||
|
||||
db_labels_rect = full_meter_rect;
|
||||
db_labels_rect.setX(0);
|
||||
db_labels_rect.setWidth(db_width_and_line);
|
||||
}
|
||||
|
||||
// Divide width by channel count
|
||||
channel_size = full_meter_rect.width() / params_.channel_count();
|
||||
|
||||
// Set peaks Y to very top
|
||||
peaks_pos = 0;
|
||||
}
|
||||
|
||||
if (cached_background_.size() != size() ||
|
||||
cached_channels_ != params_.channel_count()) {
|
||||
cached_channels_ = params_.channel_count();
|
||||
|
||||
// Insert meter rect
|
||||
full_meter_rect.adjust(db_width_and_line, 0, 0, -font_height/2);
|
||||
// Generate new background
|
||||
cached_background_ = QPixmap(size());
|
||||
cached_background_.fill(Qt::transparent);
|
||||
|
||||
QPainter cached_painter(&cached_background_);
|
||||
|
||||
db_labels_rect = full_meter_rect;
|
||||
db_labels_rect.setX(0);
|
||||
db_labels_rect.setWidth(db_width_and_line);
|
||||
}
|
||||
if (draw_text) {
|
||||
cached_painter.setFont(f);
|
||||
|
||||
// Divide width by channel count
|
||||
channel_size = full_meter_rect.width() / params_.channel_count();
|
||||
// Draw decibel markings
|
||||
QRect last_db_marking_rect;
|
||||
|
||||
cached_painter.setPen(palette.text().color());
|
||||
|
||||
// Set peaks Y to very top
|
||||
peaks_pos = 0;
|
||||
}
|
||||
for (int i = 0; i >= kDecibelMinimum; i -= kDecibelStep) {
|
||||
QString db_label;
|
||||
qreal log_val;
|
||||
|
||||
if (cached_background_.size() != size()
|
||||
|| cached_channels_ != params_.channel_count()) {
|
||||
if (i == kDecibelMinimum) {
|
||||
db_label = QStringLiteral("-∞ ");
|
||||
log_val = 0;
|
||||
} else {
|
||||
db_label = QStringLiteral("%1 ").arg(i);
|
||||
log_val = Decibel::toLogarithmic(i);
|
||||
}
|
||||
|
||||
QLine db_line;
|
||||
QRect db_marking_rect;
|
||||
bool overlaps_infinity = false;
|
||||
|
||||
cached_channels_ = params_.channel_count();
|
||||
if (horizontal) {
|
||||
int x = db_labels_rect.x() +
|
||||
qRound(log_val * db_labels_rect.width());
|
||||
|
||||
db_marking_rect = QRect(
|
||||
x - db_width / 2, db_labels_rect.top() + db_line_length,
|
||||
db_width, db_labels_rect.height() - db_line_length);
|
||||
db_line = QLine(x, db_labels_rect.top(), x,
|
||||
db_labels_rect.top() + db_line_length);
|
||||
|
||||
overlaps_infinity = db_marking_rect.left() <
|
||||
db_labels_rect.left() + db_width / 2;
|
||||
} else {
|
||||
int y = db_labels_rect.y() + db_labels_rect.height() -
|
||||
qRound(log_val * db_labels_rect.height());
|
||||
|
||||
db_marking_rect = QRect(
|
||||
db_labels_rect.x(), y - font_height / 2,
|
||||
db_labels_rect.width() - db_line_length, font_height);
|
||||
db_line = QLine(db_marking_rect.right() + 1, y,
|
||||
db_labels_rect.width(), y);
|
||||
|
||||
overlaps_infinity = db_marking_rect.bottom() >=
|
||||
db_labels_rect.bottom() - font_height;
|
||||
}
|
||||
|
||||
if (overlaps_infinity && i == kDecibelMinimum) {
|
||||
overlaps_infinity = false;
|
||||
}
|
||||
|
||||
// Generate new background
|
||||
cached_background_ = QPixmap(size());
|
||||
cached_background_.fill(Qt::transparent);
|
||||
// Prevent any dB markings overlapping
|
||||
if (i == 0 ||
|
||||
(!db_marking_rect.intersects(last_db_marking_rect) &&
|
||||
!overlaps_infinity)) {
|
||||
cached_painter.drawText(db_marking_rect, Qt::AlignCenter,
|
||||
db_label);
|
||||
cached_painter.drawLine(db_line);
|
||||
|
||||
last_db_marking_rect = db_marking_rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Draw bars
|
||||
QLinearGradient g;
|
||||
|
||||
QPainter cached_painter(&cached_background_);
|
||||
if (horizontal) {
|
||||
g.setStart(full_meter_rect.topRight());
|
||||
g.setFinalStop(full_meter_rect.topLeft());
|
||||
} else {
|
||||
g.setStart(full_meter_rect.topLeft());
|
||||
g.setFinalStop(full_meter_rect.bottomLeft());
|
||||
}
|
||||
|
||||
g.setStops({ QGradientStop(0.0, Qt::red),
|
||||
QGradientStop(0.25, Qt::yellow),
|
||||
QGradientStop(1.0, Qt::green) });
|
||||
|
||||
if (draw_text) {
|
||||
cached_painter.setFont(f);
|
||||
cached_painter.setPen(Qt::black);
|
||||
|
||||
// Draw decibel markings
|
||||
QRect last_db_marking_rect;
|
||||
for (int i = 0; i < params_.channel_count(); i++) {
|
||||
QRect peaks_rect, meter_rect;
|
||||
|
||||
if (horizontal) {
|
||||
int channel_y = full_meter_rect.y() + channel_size * i;
|
||||
|
||||
peaks_rect =
|
||||
QRect(peaks_pos, channel_y, font_height, channel_size);
|
||||
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setY(channel_y);
|
||||
meter_rect.setHeight(channel_size);
|
||||
} else {
|
||||
int channel_x = full_meter_rect.x() + channel_size * i;
|
||||
|
||||
peaks_rect =
|
||||
QRect(channel_x, peaks_pos, channel_size, font_height);
|
||||
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setX(channel_x);
|
||||
meter_rect.setWidth(channel_size);
|
||||
}
|
||||
|
||||
// Draw peak rects
|
||||
cached_painter.setBrush(Qt::red);
|
||||
cached_painter.drawRect(peaks_rect);
|
||||
|
||||
// Draw gradient meter
|
||||
cached_painter.setBrush(g);
|
||||
cached_painter.drawRect(meter_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.drawPixmap(0, 0, cached_background_);
|
||||
|
||||
QVector<double> v(params_.channel_count(), 0);
|
||||
|
||||
if (IsPlaying()) {
|
||||
// Determines how many milliseconds have passed since last update
|
||||
qint64 current_time = QDateTime::currentMSecsSinceEpoch();
|
||||
qint64 delta_time = current_time - last_time_;
|
||||
int abs_speed = qAbs(playback_speed_);
|
||||
|
||||
// Multiply by speed if the speed is not 1
|
||||
if (abs_speed != 1) {
|
||||
delta_time *= abs_speed;
|
||||
}
|
||||
|
||||
if (waveform_) {
|
||||
UpdateValuesFromWaveform(v, delta_time);
|
||||
|
||||
if (waveform_time_ >= waveform_length_) {
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
last_time_ = current_time;
|
||||
}
|
||||
|
||||
PushValue(v);
|
||||
|
||||
QVector<double> vals = GetAverages();
|
||||
|
||||
p.setBrush(QColor(0, 0, 0, 128));
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
bool all_zeroes = true;
|
||||
|
||||
cached_painter.setPen(palette.text().color());
|
||||
for (int i = 0; i < params_.channel_count(); i++) {
|
||||
// Validate value and whether it peaked
|
||||
double vol = vals.at(i);
|
||||
if (vol > 1.0) {
|
||||
peaked_[i] = true;
|
||||
}
|
||||
|
||||
for (int i=0;i>=kDecibelMinimum;i-=kDecibelStep) {
|
||||
QString db_label;
|
||||
qreal log_val;
|
||||
if (all_zeroes && !qIsNull(vol)) {
|
||||
all_zeroes = false;
|
||||
}
|
||||
|
||||
if (i == kDecibelMinimum) {
|
||||
db_label = QStringLiteral("-∞ ");
|
||||
log_val = 0;
|
||||
} else {
|
||||
db_label = QStringLiteral("%1 ").arg(i);
|
||||
log_val = Decibel::toLogarithmic(i);
|
||||
}
|
||||
// Convert val to logarithmic scale
|
||||
vol = Decibel::LinearToLogarithmic(vol);
|
||||
|
||||
QLine db_line;
|
||||
QRect db_marking_rect;
|
||||
bool overlaps_infinity = false;
|
||||
QRect peaks_rect, meter_rect;
|
||||
|
||||
if (horizontal) {
|
||||
int x = db_labels_rect.x() + qRound(log_val * db_labels_rect.width());
|
||||
if (horizontal) {
|
||||
int channel_y = full_meter_rect.y() + channel_size * i;
|
||||
|
||||
db_marking_rect = QRect(x - db_width/2, db_labels_rect.top() + db_line_length, db_width, db_labels_rect.height() - db_line_length);
|
||||
db_line = QLine(x, db_labels_rect.top(), x, db_labels_rect.top() + db_line_length);
|
||||
peaks_rect = QRect(peaks_pos, channel_y, font_height, channel_size);
|
||||
|
||||
overlaps_infinity = db_marking_rect.left() < db_labels_rect.left() + db_width/2;
|
||||
} else {
|
||||
int y = db_labels_rect.y() + db_labels_rect.height() - qRound(log_val * db_labels_rect.height());
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setY(channel_y);
|
||||
meter_rect.setHeight(channel_size);
|
||||
meter_rect.adjust(qRound(meter_rect.width() * vol), 0, 0, 0);
|
||||
} else {
|
||||
int channel_x = full_meter_rect.x() + channel_size * i;
|
||||
|
||||
db_marking_rect = QRect(db_labels_rect.x(), y - font_height/2, db_labels_rect.width() - db_line_length, font_height);
|
||||
db_line = QLine(db_marking_rect.right()+1, y, db_labels_rect.width(), y);
|
||||
peaks_rect = QRect(channel_x, peaks_pos, channel_size, font_height);
|
||||
|
||||
overlaps_infinity = db_marking_rect.bottom() >= db_labels_rect.bottom()-font_height;
|
||||
}
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setX(channel_x);
|
||||
meter_rect.setWidth(channel_size);
|
||||
meter_rect.adjust(0, 0, 0, -qRound(meter_rect.height() * vol));
|
||||
}
|
||||
p.drawRect(meter_rect);
|
||||
|
||||
if (overlaps_infinity && i == kDecibelMinimum) {
|
||||
overlaps_infinity = false;
|
||||
}
|
||||
if (!peaked_.at(i)) {
|
||||
p.drawRect(peaks_rect);
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent any dB markings overlapping
|
||||
if (i == 0 || (!db_marking_rect.intersects(last_db_marking_rect) && !overlaps_infinity)) {
|
||||
cached_painter.drawText(db_marking_rect, Qt::AlignCenter, db_label);
|
||||
cached_painter.drawLine(db_line);
|
||||
|
||||
last_db_marking_rect = db_marking_rect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// Draw bars
|
||||
QLinearGradient g;
|
||||
|
||||
if (horizontal) {
|
||||
g.setStart(full_meter_rect.topRight());
|
||||
g.setFinalStop(full_meter_rect.topLeft());
|
||||
} else {
|
||||
g.setStart(full_meter_rect.topLeft());
|
||||
g.setFinalStop(full_meter_rect.bottomLeft());
|
||||
}
|
||||
|
||||
g.setStops({
|
||||
QGradientStop(0.0, Qt::red),
|
||||
QGradientStop(0.25, Qt::yellow),
|
||||
QGradientStop(1.0, Qt::green)
|
||||
});
|
||||
|
||||
cached_painter.setPen(Qt::black);
|
||||
|
||||
for (int i=0;i<params_.channel_count();i++) {
|
||||
QRect peaks_rect, meter_rect;
|
||||
|
||||
if (horizontal) {
|
||||
int channel_y = full_meter_rect.y() + channel_size * i;
|
||||
|
||||
peaks_rect = QRect(peaks_pos, channel_y, font_height, channel_size);
|
||||
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setY(channel_y);
|
||||
meter_rect.setHeight(channel_size);
|
||||
} else {
|
||||
int channel_x = full_meter_rect.x() + channel_size * i;
|
||||
|
||||
peaks_rect = QRect(channel_x, peaks_pos, channel_size, font_height);
|
||||
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setX(channel_x);
|
||||
meter_rect.setWidth(channel_size);
|
||||
}
|
||||
|
||||
// Draw peak rects
|
||||
cached_painter.setBrush(Qt::red);
|
||||
cached_painter.drawRect(peaks_rect);
|
||||
|
||||
// Draw gradient meter
|
||||
cached_painter.setBrush(g);
|
||||
cached_painter.drawRect(meter_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.drawPixmap(0, 0, cached_background_);
|
||||
|
||||
QVector<double> v(params_.channel_count(), 0);
|
||||
|
||||
if (IsPlaying()) {
|
||||
// Determines how many milliseconds have passed since last update
|
||||
qint64 current_time = QDateTime::currentMSecsSinceEpoch();
|
||||
qint64 delta_time = current_time - last_time_;
|
||||
int abs_speed = qAbs(playback_speed_);
|
||||
|
||||
// Multiply by speed if the speed is not 1
|
||||
if (abs_speed != 1) {
|
||||
delta_time *= abs_speed;
|
||||
}
|
||||
|
||||
if (waveform_) {
|
||||
UpdateValuesFromWaveform(v, delta_time);
|
||||
|
||||
if (waveform_time_ >= waveform_length_) {
|
||||
Stop();
|
||||
}
|
||||
}
|
||||
|
||||
last_time_ = current_time;
|
||||
}
|
||||
|
||||
PushValue(v);
|
||||
|
||||
QVector<double> vals = GetAverages();
|
||||
|
||||
p.setBrush(QColor(0, 0, 0, 128));
|
||||
p.setPen(Qt::NoPen);
|
||||
|
||||
bool all_zeroes = true;
|
||||
|
||||
for (int i=0;i<params_.channel_count();i++) {
|
||||
// Validate value and whether it peaked
|
||||
double vol = vals.at(i);
|
||||
if (vol > 1.0) {
|
||||
peaked_[i] = true;
|
||||
}
|
||||
|
||||
if (all_zeroes && !qIsNull(vol)) {
|
||||
all_zeroes = false;
|
||||
}
|
||||
|
||||
// Convert val to logarithmic scale
|
||||
vol = Decibel::LinearToLogarithmic(vol);
|
||||
|
||||
QRect peaks_rect, meter_rect;
|
||||
|
||||
if (horizontal) {
|
||||
int channel_y = full_meter_rect.y() + channel_size * i;
|
||||
|
||||
peaks_rect = QRect(peaks_pos, channel_y, font_height, channel_size);
|
||||
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setY(channel_y);
|
||||
meter_rect.setHeight(channel_size);
|
||||
meter_rect.adjust(qRound(meter_rect.width() * vol), 0, 0, 0);
|
||||
} else {
|
||||
int channel_x = full_meter_rect.x() + channel_size * i;
|
||||
|
||||
peaks_rect = QRect(channel_x, peaks_pos, channel_size, font_height);
|
||||
|
||||
meter_rect = full_meter_rect;
|
||||
meter_rect.setX(channel_x);
|
||||
meter_rect.setWidth(channel_size);
|
||||
meter_rect.adjust(0, 0, 0, -qRound(meter_rect.height() * vol));
|
||||
}
|
||||
p.drawRect(meter_rect);
|
||||
|
||||
if (!peaked_.at(i)) {
|
||||
p.drawRect(peaks_rect);
|
||||
}
|
||||
}
|
||||
|
||||
if (all_zeroes && !IsPlaying()) {
|
||||
// Optimize by disabling the update loop
|
||||
SetUpdateLoop(false);
|
||||
}
|
||||
if (all_zeroes && !IsPlaying()) {
|
||||
// Optimize by disabling the update loop
|
||||
SetUpdateLoop(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioMonitor::mousePressEvent(QMouseEvent *)
|
||||
{
|
||||
peaked_.fill(false);
|
||||
update();
|
||||
peaked_.fill(false);
|
||||
update();
|
||||
}
|
||||
|
||||
void AudioMonitor::UpdateValuesFromWaveform(QVector<double> &v, qint64 delta_time)
|
||||
void AudioMonitor::UpdateValuesFromWaveform(QVector<double> &v,
|
||||
qint64 delta_time)
|
||||
{
|
||||
// Delta time is provided in milliseconds, so we convert to seconds in rational
|
||||
rational length(delta_time, 1000);
|
||||
// Delta time is provided in milliseconds, so we convert to seconds in rational
|
||||
rational length(delta_time, 1000);
|
||||
|
||||
AudioVisualWaveform::Sample sum = waveform_->GetSummaryFromTime(waveform_time_, length);
|
||||
AudioVisualWaveform::Sample sum =
|
||||
waveform_->GetSummaryFromTime(waveform_time_, length);
|
||||
|
||||
AudioVisualWaveformSampleToInternalValues(sum, v);
|
||||
AudioVisualWaveformSampleToInternalValues(sum, v);
|
||||
|
||||
waveform_time_ += length;
|
||||
waveform_time_ += length;
|
||||
}
|
||||
|
||||
void AudioMonitor::AudioVisualWaveformSampleToInternalValues(const AudioVisualWaveform::Sample &in, QVector<double> &out)
|
||||
void AudioMonitor::AudioVisualWaveformSampleToInternalValues(
|
||||
const AudioVisualWaveform::Sample &in, QVector<double> &out)
|
||||
{
|
||||
for (size_t i=0; i<in.size(); i++) {
|
||||
float max = qMax(qAbs(in.at(i).min), qAbs(in.at(i).max));
|
||||
for (size_t i = 0; i < in.size(); i++) {
|
||||
float max = qMax(qAbs(in.at(i).min), qAbs(in.at(i).max));
|
||||
|
||||
int output_index = i%out.size();
|
||||
if (max > out.at(output_index)) {
|
||||
out[output_index] = max;
|
||||
}
|
||||
}
|
||||
int output_index = i % out.size();
|
||||
if (max > out.at(output_index)) {
|
||||
out[output_index] = max;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioMonitor::PushValue(const QVector<double> &v)
|
||||
{
|
||||
int lim = values_.size()-1;
|
||||
for (int i=0; i<lim; i++) {
|
||||
values_[i] = values_[i+1];
|
||||
}
|
||||
values_[lim] = v;
|
||||
int lim = values_.size() - 1;
|
||||
for (int i = 0; i < lim; i++) {
|
||||
values_[i] = values_[i + 1];
|
||||
}
|
||||
values_[lim] = v;
|
||||
}
|
||||
|
||||
void AudioMonitor::BytesToSampleSummary(const QByteArray &b, QVector<double> &v)
|
||||
{
|
||||
const float* samples = reinterpret_cast<const float*>(b.constData());
|
||||
int nb_samples = b.size() / sizeof(float);
|
||||
const float *samples = reinterpret_cast<const float *>(b.constData());
|
||||
int nb_samples = b.size() / sizeof(float);
|
||||
|
||||
for (int i=0;i<nb_samples;i++) {
|
||||
int channel = i % params_.channel_count();
|
||||
for (int i = 0; i < nb_samples; i++) {
|
||||
int channel = i % params_.channel_count();
|
||||
|
||||
float abs_sample = samples[i];
|
||||
float abs_sample = samples[i];
|
||||
|
||||
if (abs_sample > v.at(channel)) {
|
||||
v.replace(channel, abs_sample);
|
||||
}
|
||||
}
|
||||
if (abs_sample > v.at(channel)) {
|
||||
v.replace(channel, abs_sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<double> AudioMonitor::GetAverages() const
|
||||
{
|
||||
QVector<double> v(params_.channel_count(), 0);
|
||||
QVector<double> v(params_.channel_count(), 0);
|
||||
|
||||
for (int i=0;i<values_.size();i++) {
|
||||
for (int j=0;j<v.size();j++) {
|
||||
v[j] += values_.at(i).at(j);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < values_.size(); i++) {
|
||||
for (int j = 0; j < v.size(); j++) {
|
||||
v[j] += values_.at(i).at(j);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0;i<v.size();i++) {
|
||||
v[i] /= static_cast<double>(values_.size());
|
||||
}
|
||||
for (int i = 0; i < v.size(); i++) {
|
||||
v[i] /= static_cast<double>(values_.size());
|
||||
}
|
||||
|
||||
return v;
|
||||
return v;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,87 +29,89 @@
|
||||
#include "common/define.h"
|
||||
#include "render/audiowaveformcache.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class AudioMonitor : public QOpenGLWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class AudioMonitor : public QOpenGLWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioMonitor(QWidget *parent = nullptr);
|
||||
AudioMonitor(QWidget *parent = nullptr);
|
||||
|
||||
virtual ~AudioMonitor() override;
|
||||
virtual ~AudioMonitor() override;
|
||||
|
||||
bool IsPlaying() const
|
||||
{
|
||||
return waveform_;
|
||||
}
|
||||
bool IsPlaying() const
|
||||
{
|
||||
return waveform_;
|
||||
}
|
||||
|
||||
static void StartWaveformOnAll(const AudioWaveformCache *waveform, const rational& start, int playback_speed)
|
||||
{
|
||||
foreach (AudioMonitor *m, instances_) {
|
||||
m->StartWaveform(waveform, start, playback_speed);
|
||||
}
|
||||
}
|
||||
static void StartWaveformOnAll(const AudioWaveformCache *waveform,
|
||||
const rational &start, int playback_speed)
|
||||
{
|
||||
foreach (AudioMonitor *m, instances_) {
|
||||
m->StartWaveform(waveform, start, playback_speed);
|
||||
}
|
||||
}
|
||||
|
||||
static void StopOnAll()
|
||||
{
|
||||
foreach (AudioMonitor *m, instances_) {
|
||||
m->Stop();
|
||||
}
|
||||
}
|
||||
static void StopOnAll()
|
||||
{
|
||||
foreach (AudioMonitor *m, instances_) {
|
||||
m->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
static void PushSampleBufferOnAll(const SampleBuffer &d)
|
||||
{
|
||||
foreach (AudioMonitor *m, instances_) {
|
||||
m->PushSampleBuffer(d);
|
||||
}
|
||||
}
|
||||
static void PushSampleBufferOnAll(const SampleBuffer &d)
|
||||
{
|
||||
foreach (AudioMonitor *m, instances_) {
|
||||
m->PushSampleBuffer(d);
|
||||
}
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetParams(const AudioParams& params);
|
||||
void SetParams(const AudioParams ¶ms);
|
||||
|
||||
void Stop();
|
||||
void Stop();
|
||||
|
||||
void PushSampleBuffer(const SampleBuffer &samples);
|
||||
void PushSampleBuffer(const SampleBuffer &samples);
|
||||
|
||||
void StartWaveform(const AudioWaveformCache *waveform, const rational& start, int playback_speed);
|
||||
void StartWaveform(const AudioWaveformCache *waveform,
|
||||
const rational &start, int playback_speed);
|
||||
|
||||
protected:
|
||||
virtual void paintGL() override;
|
||||
virtual void paintGL() override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent* event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
void SetUpdateLoop(bool e);
|
||||
void SetUpdateLoop(bool e);
|
||||
|
||||
void UpdateValuesFromWaveform(QVector<double> &v, qint64 delta_time);
|
||||
void UpdateValuesFromWaveform(QVector<double> &v, qint64 delta_time);
|
||||
|
||||
void AudioVisualWaveformSampleToInternalValues(const AudioVisualWaveform::Sample &in, QVector<double> &out);
|
||||
void AudioVisualWaveformSampleToInternalValues(
|
||||
const AudioVisualWaveform::Sample &in, QVector<double> &out);
|
||||
|
||||
void PushValue(const QVector<double>& v);
|
||||
void PushValue(const QVector<double> &v);
|
||||
|
||||
void BytesToSampleSummary(const QByteArray& bytes, QVector<double>& v);
|
||||
void BytesToSampleSummary(const QByteArray &bytes, QVector<double> &v);
|
||||
|
||||
QVector<double> GetAverages() const;
|
||||
QVector<double> GetAverages() const;
|
||||
|
||||
AudioParams params_;
|
||||
AudioParams params_;
|
||||
|
||||
qint64 last_time_;
|
||||
qint64 last_time_;
|
||||
|
||||
const AudioWaveformCache* waveform_;
|
||||
rational waveform_time_;
|
||||
rational waveform_length_;
|
||||
const AudioWaveformCache *waveform_;
|
||||
rational waveform_time_;
|
||||
rational waveform_length_;
|
||||
|
||||
int playback_speed_;
|
||||
int playback_speed_;
|
||||
|
||||
QVector< QVector<double> > values_;
|
||||
QVector<bool> peaked_;
|
||||
QVector<QVector<double>> values_;
|
||||
QVector<bool> peaked_;
|
||||
|
||||
QPixmap cached_background_;
|
||||
int cached_channels_;
|
||||
|
||||
static QVector<AudioMonitor*> instances_;
|
||||
QPixmap cached_background_;
|
||||
int cached_channels_;
|
||||
|
||||
static QVector<AudioMonitor *> instances_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,79 +23,86 @@
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
|
||||
namespace olive {
|
||||
|
||||
BezierWidget::BezierWidget(QWidget *parent) :
|
||||
QWidget{parent}
|
||||
namespace olive
|
||||
{
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
|
||||
int row = 0;
|
||||
BezierWidget::BezierWidget(QWidget *parent)
|
||||
: QWidget{ parent }
|
||||
{
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
|
||||
layout->addWidget(new QLabel(tr("Center:")), row, 0);
|
||||
int row = 0;
|
||||
|
||||
x_slider_ = new FloatSlider();
|
||||
connect(x_slider_, &FloatSlider::ValueChanged, this, &BezierWidget::ValueChanged);
|
||||
layout->addWidget(x_slider_, row, 1);
|
||||
layout->addWidget(new QLabel(tr("Center:")), row, 0);
|
||||
|
||||
y_slider_ = new FloatSlider();
|
||||
connect(y_slider_, &FloatSlider::ValueChanged, this, &BezierWidget::ValueChanged);
|
||||
layout->addWidget(y_slider_, row, 2);
|
||||
x_slider_ = new FloatSlider();
|
||||
connect(x_slider_, &FloatSlider::ValueChanged, this,
|
||||
&BezierWidget::ValueChanged);
|
||||
layout->addWidget(x_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
y_slider_ = new FloatSlider();
|
||||
connect(y_slider_, &FloatSlider::ValueChanged, this,
|
||||
&BezierWidget::ValueChanged);
|
||||
layout->addWidget(y_slider_, row, 2);
|
||||
|
||||
QGroupBox *bezier_group = new QGroupBox(tr("Bezier"));
|
||||
layout->addWidget(bezier_group, row, 0, 1, 3);
|
||||
row++;
|
||||
|
||||
QGridLayout *bezier_layout = new QGridLayout(bezier_group);
|
||||
QGroupBox *bezier_group = new QGroupBox(tr("Bezier"));
|
||||
layout->addWidget(bezier_group, row, 0, 1, 3);
|
||||
|
||||
row = 0;
|
||||
QGridLayout *bezier_layout = new QGridLayout(bezier_group);
|
||||
|
||||
bezier_layout->addWidget(new QLabel(tr("In:")), row, 0);
|
||||
row = 0;
|
||||
|
||||
cp1_x_slider_ = new FloatSlider();
|
||||
connect(cp1_x_slider_, &FloatSlider::ValueChanged, this, &BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp1_x_slider_, row, 1);
|
||||
bezier_layout->addWidget(new QLabel(tr("In:")), row, 0);
|
||||
|
||||
cp1_y_slider_ = new FloatSlider();
|
||||
connect(cp1_y_slider_, &FloatSlider::ValueChanged, this, &BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp1_y_slider_, row, 2);
|
||||
cp1_x_slider_ = new FloatSlider();
|
||||
connect(cp1_x_slider_, &FloatSlider::ValueChanged, this,
|
||||
&BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp1_x_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
cp1_y_slider_ = new FloatSlider();
|
||||
connect(cp1_y_slider_, &FloatSlider::ValueChanged, this,
|
||||
&BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp1_y_slider_, row, 2);
|
||||
|
||||
bezier_layout->addWidget(new QLabel(tr("Out:")), row, 0);
|
||||
row++;
|
||||
|
||||
cp2_x_slider_ = new FloatSlider();
|
||||
connect(cp2_x_slider_, &FloatSlider::ValueChanged, this, &BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp2_x_slider_, row, 1);
|
||||
bezier_layout->addWidget(new QLabel(tr("Out:")), row, 0);
|
||||
|
||||
cp2_y_slider_ = new FloatSlider();
|
||||
connect(cp2_y_slider_, &FloatSlider::ValueChanged, this, &BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp2_y_slider_, row, 2);
|
||||
cp2_x_slider_ = new FloatSlider();
|
||||
connect(cp2_x_slider_, &FloatSlider::ValueChanged, this,
|
||||
&BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp2_x_slider_, row, 1);
|
||||
|
||||
cp2_y_slider_ = new FloatSlider();
|
||||
connect(cp2_y_slider_, &FloatSlider::ValueChanged, this,
|
||||
&BezierWidget::ValueChanged);
|
||||
bezier_layout->addWidget(cp2_y_slider_, row, 2);
|
||||
}
|
||||
|
||||
Bezier BezierWidget::GetValue() const
|
||||
{
|
||||
Bezier b;
|
||||
Bezier b;
|
||||
|
||||
b.set_x(x_slider_->GetValue());
|
||||
b.set_y(y_slider_->GetValue());
|
||||
b.set_cp1_x(cp1_x_slider_->GetValue());
|
||||
b.set_cp1_y(cp1_y_slider_->GetValue());
|
||||
b.set_cp2_x(cp2_x_slider_->GetValue());
|
||||
b.set_cp2_y(cp2_y_slider_->GetValue());
|
||||
b.set_x(x_slider_->GetValue());
|
||||
b.set_y(y_slider_->GetValue());
|
||||
b.set_cp1_x(cp1_x_slider_->GetValue());
|
||||
b.set_cp1_y(cp1_y_slider_->GetValue());
|
||||
b.set_cp2_x(cp2_x_slider_->GetValue());
|
||||
b.set_cp2_y(cp2_y_slider_->GetValue());
|
||||
|
||||
return b;
|
||||
return b;
|
||||
}
|
||||
|
||||
void BezierWidget::SetValue(const Bezier &b)
|
||||
{
|
||||
x_slider_->SetValue(b.x());
|
||||
y_slider_->SetValue(b.y());
|
||||
cp1_x_slider_->SetValue(b.cp1_x());
|
||||
cp1_y_slider_->SetValue(b.cp1_y());
|
||||
cp2_x_slider_->SetValue(b.cp2_x());
|
||||
cp2_y_slider_->SetValue(b.cp2_y());
|
||||
x_slider_->SetValue(b.x());
|
||||
y_slider_->SetValue(b.y());
|
||||
cp1_x_slider_->SetValue(b.cp1_x());
|
||||
cp1_y_slider_->SetValue(b.cp1_y());
|
||||
cp2_x_slider_->SetValue(b.cp2_x());
|
||||
cp2_y_slider_->SetValue(b.cp2_y());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,48 +27,65 @@
|
||||
|
||||
#include "widget/slider/floatslider.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
using namespace core;
|
||||
|
||||
class BezierWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class BezierWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BezierWidget(QWidget *parent = nullptr);
|
||||
explicit BezierWidget(QWidget *parent = nullptr);
|
||||
|
||||
Bezier GetValue() const;
|
||||
Bezier GetValue() const;
|
||||
|
||||
void SetValue(const Bezier &b);
|
||||
void SetValue(const Bezier &b);
|
||||
|
||||
FloatSlider *x_slider() const { return x_slider_; }
|
||||
FloatSlider *x_slider() const
|
||||
{
|
||||
return x_slider_;
|
||||
}
|
||||
|
||||
FloatSlider *y_slider() const { return y_slider_; }
|
||||
FloatSlider *y_slider() const
|
||||
{
|
||||
return y_slider_;
|
||||
}
|
||||
|
||||
FloatSlider *cp1_x_slider() const { return cp1_x_slider_; }
|
||||
FloatSlider *cp1_x_slider() const
|
||||
{
|
||||
return cp1_x_slider_;
|
||||
}
|
||||
|
||||
FloatSlider *cp1_y_slider() const { return cp1_y_slider_; }
|
||||
FloatSlider *cp1_y_slider() const
|
||||
{
|
||||
return cp1_y_slider_;
|
||||
}
|
||||
|
||||
FloatSlider *cp2_x_slider() const { return cp2_x_slider_; }
|
||||
FloatSlider *cp2_x_slider() const
|
||||
{
|
||||
return cp2_x_slider_;
|
||||
}
|
||||
|
||||
FloatSlider *cp2_y_slider() const { return cp2_y_slider_; }
|
||||
FloatSlider *cp2_y_slider() const
|
||||
{
|
||||
return cp2_y_slider_;
|
||||
}
|
||||
|
||||
signals:
|
||||
void ValueChanged();
|
||||
void ValueChanged();
|
||||
|
||||
private:
|
||||
FloatSlider *x_slider_;
|
||||
FloatSlider *x_slider_;
|
||||
|
||||
FloatSlider *y_slider_;
|
||||
FloatSlider *y_slider_;
|
||||
|
||||
FloatSlider *cp1_x_slider_;
|
||||
FloatSlider *cp1_x_slider_;
|
||||
|
||||
FloatSlider *cp1_y_slider_;
|
||||
FloatSlider *cp1_y_slider_;
|
||||
|
||||
FloatSlider *cp2_x_slider_;
|
||||
|
||||
FloatSlider *cp2_y_slider_;
|
||||
FloatSlider *cp2_x_slider_;
|
||||
|
||||
FloatSlider *cp2_y_slider_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,30 +22,31 @@
|
||||
|
||||
#include <QMouseEvent>
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
ClickableLabel::ClickableLabel(const QString &text, QWidget *parent) :
|
||||
QLabel(text, parent)
|
||||
ClickableLabel::ClickableLabel(const QString &text, QWidget *parent)
|
||||
: QLabel(text, parent)
|
||||
{
|
||||
}
|
||||
|
||||
ClickableLabel::ClickableLabel(QWidget *parent) :
|
||||
QLabel(parent)
|
||||
ClickableLabel::ClickableLabel(QWidget *parent)
|
||||
: QLabel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ClickableLabel::mouseReleaseEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton && underMouse()) {
|
||||
emit MouseClicked();
|
||||
}
|
||||
if (event->button() == Qt::LeftButton && underMouse()) {
|
||||
emit MouseClicked();
|
||||
}
|
||||
}
|
||||
|
||||
void ClickableLabel::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
emit MouseDoubleClicked();
|
||||
}
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
emit MouseDoubleClicked();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,23 +25,22 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ClickableLabel : public QLabel
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ClickableLabel : public QLabel {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ClickableLabel(const QString& text, QWidget* parent = nullptr);
|
||||
ClickableLabel(QWidget* parent = nullptr);
|
||||
ClickableLabel(const QString &text, QWidget *parent = nullptr);
|
||||
ClickableLabel(QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
signals:
|
||||
void MouseClicked();
|
||||
void MouseDoubleClicked();
|
||||
|
||||
void MouseClicked();
|
||||
void MouseDoubleClicked();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,29 +22,30 @@
|
||||
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
CollapseButton::CollapseButton(QWidget *parent) :
|
||||
QPushButton(parent)
|
||||
namespace olive
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
setStyleSheet("border: none; background: none;");
|
||||
setCheckable(true);
|
||||
setChecked(true);
|
||||
setIconSize(QSize(fontMetrics().height()/2, fontMetrics().height()/2));
|
||||
|
||||
connect(this, &CollapseButton::toggled, this, &CollapseButton::UpdateIcon);
|
||||
CollapseButton::CollapseButton(QWidget *parent)
|
||||
: QPushButton(parent)
|
||||
{
|
||||
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
setStyleSheet("border: none; background: none;");
|
||||
setCheckable(true);
|
||||
setChecked(true);
|
||||
setIconSize(QSize(fontMetrics().height() / 2, fontMetrics().height() / 2));
|
||||
|
||||
UpdateIcon(isChecked());
|
||||
connect(this, &CollapseButton::toggled, this, &CollapseButton::UpdateIcon);
|
||||
|
||||
UpdateIcon(isChecked());
|
||||
}
|
||||
|
||||
void CollapseButton::UpdateIcon(bool e)
|
||||
{
|
||||
if (e) {
|
||||
setIcon(icon::TriDown);
|
||||
} else {
|
||||
setIcon(icon::TriRight);
|
||||
}
|
||||
if (e) {
|
||||
setIcon(icon::TriDown);
|
||||
} else {
|
||||
setIcon(icon::TriRight);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,17 +25,16 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class CollapseButton : public QPushButton
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class CollapseButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollapseButton(QWidget* parent = nullptr);
|
||||
CollapseButton(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
void UpdateIcon(bool e);
|
||||
|
||||
void UpdateIcon(bool e);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,76 +22,82 @@
|
||||
|
||||
#include "dialog/color/colordialog.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ColorButton::ColorButton(ColorManager* color_manager, bool show_dialog_on_click, QWidget *parent) :
|
||||
QPushButton(parent),
|
||||
color_manager_(color_manager),
|
||||
color_processor_(nullptr),
|
||||
dialog_open_(false)
|
||||
namespace olive
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
|
||||
if (show_dialog_on_click) {
|
||||
connect(this, &ColorButton::clicked, this, &ColorButton::ShowColorDialog);
|
||||
}
|
||||
ColorButton::ColorButton(ColorManager *color_manager, bool show_dialog_on_click,
|
||||
QWidget *parent)
|
||||
: QPushButton(parent)
|
||||
, color_manager_(color_manager)
|
||||
, color_processor_(nullptr)
|
||||
, dialog_open_(false)
|
||||
{
|
||||
setAutoFillBackground(true);
|
||||
|
||||
SetColor(Color(1.0f, 1.0f, 1.0f));
|
||||
if (show_dialog_on_click) {
|
||||
connect(this, &ColorButton::clicked, this,
|
||||
&ColorButton::ShowColorDialog);
|
||||
}
|
||||
|
||||
SetColor(Color(1.0f, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
const ManagedColor &ColorButton::GetColor() const
|
||||
{
|
||||
return color_;
|
||||
return color_;
|
||||
}
|
||||
|
||||
void ColorButton::SetColor(const ManagedColor &c)
|
||||
{
|
||||
color_ = c;
|
||||
color_ = c;
|
||||
|
||||
color_.set_color_input(color_manager_->GetCompliantColorSpace(color_.color_input()));
|
||||
color_.set_color_output(color_manager_->GetCompliantColorSpace(color_.color_output()));
|
||||
color_.set_color_input(
|
||||
color_manager_->GetCompliantColorSpace(color_.color_input()));
|
||||
color_.set_color_output(
|
||||
color_manager_->GetCompliantColorSpace(color_.color_output()));
|
||||
|
||||
UpdateColor();
|
||||
UpdateColor();
|
||||
}
|
||||
|
||||
void ColorButton::ShowColorDialog()
|
||||
{
|
||||
if (!dialog_open_) {
|
||||
dialog_open_ = true;
|
||||
ColorDialog *cd = new ColorDialog(color_manager_, color_, this);
|
||||
if (!dialog_open_) {
|
||||
dialog_open_ = true;
|
||||
ColorDialog *cd = new ColorDialog(color_manager_, color_, this);
|
||||
|
||||
connect(cd, &ColorDialog::finished, this, &ColorButton::ColorDialogFinished);
|
||||
connect(cd, &ColorDialog::finished, this,
|
||||
&ColorButton::ColorDialogFinished);
|
||||
|
||||
cd->show();
|
||||
}
|
||||
cd->show();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorButton::ColorDialogFinished(int e)
|
||||
{
|
||||
ColorDialog *cd = static_cast<ColorDialog*>(sender());
|
||||
ColorDialog *cd = static_cast<ColorDialog *>(sender());
|
||||
|
||||
if (e == QDialog::Accepted) {
|
||||
color_ = cd->GetSelectedColor();
|
||||
if (e == QDialog::Accepted) {
|
||||
color_ = cd->GetSelectedColor();
|
||||
|
||||
UpdateColor();
|
||||
UpdateColor();
|
||||
|
||||
emit ColorChanged(color_);
|
||||
}
|
||||
emit ColorChanged(color_);
|
||||
}
|
||||
|
||||
cd->deleteLater();
|
||||
cd->deleteLater();
|
||||
|
||||
dialog_open_ = false;
|
||||
dialog_open_ = false;
|
||||
}
|
||||
|
||||
void ColorButton::UpdateColor()
|
||||
{
|
||||
color_processor_ = ColorProcessor::Create(color_manager_,
|
||||
color_.color_input(),
|
||||
color_.color_output());
|
||||
color_processor_ = ColorProcessor::Create(
|
||||
color_manager_, color_.color_input(), color_.color_output());
|
||||
|
||||
QColor managed = QtUtils::toQColor(color_processor_->ConvertColor(color_));
|
||||
QColor managed = QtUtils::toQColor(color_processor_->ConvertColor(color_));
|
||||
|
||||
setStyleSheet(QStringLiteral("%1--ColorButton {background: %2;}").arg(MACRO_VAL_AS_STR(olive), managed.name()));
|
||||
setStyleSheet(QStringLiteral("%1--ColorButton {background: %2;}")
|
||||
.arg(MACRO_VAL_AS_STR(olive), managed.name()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,42 +26,42 @@
|
||||
#include "node/color/colormanager/colormanager.h"
|
||||
#include "render/managedcolor.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorButton : public QPushButton
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorButton(ColorManager* color_manager, bool show_dialog_on_click, QWidget* parent = nullptr);
|
||||
ColorButton(ColorManager* color_manager, QWidget* parent = nullptr) :
|
||||
ColorButton(color_manager, true, parent)
|
||||
{
|
||||
}
|
||||
|
||||
const ManagedColor& GetColor() const;
|
||||
class ColorButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorButton(ColorManager *color_manager, bool show_dialog_on_click,
|
||||
QWidget *parent = nullptr);
|
||||
ColorButton(ColorManager *color_manager, QWidget *parent = nullptr)
|
||||
: ColorButton(color_manager, true, parent)
|
||||
{
|
||||
}
|
||||
|
||||
const ManagedColor &GetColor() const;
|
||||
|
||||
public slots:
|
||||
void SetColor(const ManagedColor& c);
|
||||
void SetColor(const ManagedColor &c);
|
||||
|
||||
signals:
|
||||
void ColorChanged(const ManagedColor& c);
|
||||
void ColorChanged(const ManagedColor &c);
|
||||
|
||||
private slots:
|
||||
void ShowColorDialog();
|
||||
void ShowColorDialog();
|
||||
|
||||
void ColorDialogFinished(int e);
|
||||
void ColorDialogFinished(int e);
|
||||
|
||||
private:
|
||||
void UpdateColor();
|
||||
void UpdateColor();
|
||||
|
||||
ColorManager* color_manager_;
|
||||
ColorManager *color_manager_;
|
||||
|
||||
ManagedColor color_;
|
||||
ManagedColor color_;
|
||||
|
||||
ColorProcessorPtr color_processor_;
|
||||
|
||||
bool dialog_open_;
|
||||
ColorProcessorPtr color_processor_;
|
||||
|
||||
bool dialog_open_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,32 +22,33 @@
|
||||
|
||||
#include "ui/colorcoding.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ColorCodingComboBox::ColorCodingComboBox(QWidget *parent) :
|
||||
QComboBox(parent)
|
||||
namespace olive
|
||||
{
|
||||
SetColor(0);
|
||||
|
||||
ColorCodingComboBox::ColorCodingComboBox(QWidget *parent)
|
||||
: QComboBox(parent)
|
||||
{
|
||||
SetColor(0);
|
||||
}
|
||||
|
||||
void ColorCodingComboBox::showPopup()
|
||||
{
|
||||
ColorLabelMenu menu(this);
|
||||
ColorLabelMenu menu(this);
|
||||
|
||||
menu.setMinimumWidth(width());
|
||||
menu.setMinimumWidth(width());
|
||||
|
||||
QAction* a = menu.exec(parentWidget()->mapToGlobal(pos()));
|
||||
QAction *a = menu.exec(parentWidget()->mapToGlobal(pos()));
|
||||
|
||||
if (a) {
|
||||
SetColor(a->data().toInt());
|
||||
}
|
||||
if (a) {
|
||||
SetColor(a->data().toInt());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorCodingComboBox::SetColor(int index)
|
||||
{
|
||||
clear();
|
||||
addItem(ColorCoding::GetColorName(index));
|
||||
index_ = index;
|
||||
clear();
|
||||
addItem(ColorCoding::GetColorName(index));
|
||||
index_ = index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,26 +25,25 @@
|
||||
|
||||
#include "widget/colorlabelmenu/colorlabelmenu.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorCodingComboBox : public QComboBox
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ColorCodingComboBox : public QComboBox {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorCodingComboBox(QWidget* parent = nullptr);
|
||||
ColorCodingComboBox(QWidget *parent = nullptr);
|
||||
|
||||
virtual void showPopup() override;
|
||||
virtual void showPopup() override;
|
||||
|
||||
void SetColor(int index);
|
||||
void SetColor(int index);
|
||||
|
||||
int GetSelectedColor() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
int GetSelectedColor() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
private:
|
||||
int index_;
|
||||
|
||||
int index_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,54 +27,57 @@
|
||||
#include "common/qtutils.h"
|
||||
#include "ui/colorcoding.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ColorLabelMenu::ColorLabelMenu(QWidget *parent) :
|
||||
Menu(parent)
|
||||
namespace olive
|
||||
{
|
||||
// Used for size calculations
|
||||
int box_size = fontMetrics().height();
|
||||
|
||||
color_items_.resize(ColorCoding::standard_colors().size());
|
||||
for (int i=0; i<ColorCoding::standard_colors().size(); i++) {
|
||||
QPixmap p(box_size, box_size);
|
||||
ColorLabelMenu::ColorLabelMenu(QWidget *parent)
|
||||
: Menu(parent)
|
||||
{
|
||||
// Used for size calculations
|
||||
int box_size = fontMetrics().height();
|
||||
|
||||
QPainter painter(&p);
|
||||
painter.setPen(Qt::black);
|
||||
painter.setBrush(QtUtils::toQColor(ColorCoding::standard_colors().at(i)));
|
||||
painter.drawRect(p.rect().adjusted(0, 0, -1, -1));
|
||||
color_items_.resize(ColorCoding::standard_colors().size());
|
||||
for (int i = 0; i < ColorCoding::standard_colors().size(); i++) {
|
||||
QPixmap p(box_size, box_size);
|
||||
|
||||
QAction *a = AddItem(QStringLiteral("colorlabel%1").arg(i), this, &ColorLabelMenu::ActionTriggered);
|
||||
a->setIcon(p);
|
||||
a->setData(i);
|
||||
color_items_.replace(i, a);
|
||||
}
|
||||
QPainter painter(&p);
|
||||
painter.setPen(Qt::black);
|
||||
painter.setBrush(
|
||||
QtUtils::toQColor(ColorCoding::standard_colors().at(i)));
|
||||
painter.drawRect(p.rect().adjusted(0, 0, -1, -1));
|
||||
|
||||
Retranslate();
|
||||
QAction *a = AddItem(QStringLiteral("colorlabel%1").arg(i), this,
|
||||
&ColorLabelMenu::ActionTriggered);
|
||||
a->setIcon(p);
|
||||
a->setData(i);
|
||||
color_items_.replace(i, a);
|
||||
}
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void ColorLabelMenu::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
Menu::changeEvent(event);
|
||||
Menu::changeEvent(event);
|
||||
}
|
||||
|
||||
void ColorLabelMenu::Retranslate()
|
||||
{
|
||||
this->setTitle(tr("Color"));
|
||||
this->setTitle(tr("Color"));
|
||||
|
||||
for (int i=0; i<color_items_.size(); i++) {
|
||||
color_items_.at(i)->setText(ColorCoding::GetColorName(i));
|
||||
}
|
||||
for (int i = 0; i < color_items_.size(); i++) {
|
||||
color_items_.at(i)->setText(ColorCoding::GetColorName(i));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorLabelMenu::ActionTriggered()
|
||||
{
|
||||
QAction* a = static_cast<QAction*>(sender());
|
||||
emit ColorSelected(a->data().toInt());
|
||||
QAction *a = static_cast<QAction *>(sender());
|
||||
emit ColorSelected(a->data().toInt());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,27 +23,26 @@
|
||||
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorLabelMenu : public Menu
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorLabelMenu(QWidget* parent = nullptr);
|
||||
|
||||
virtual void changeEvent(QEvent* event) override;
|
||||
class ColorLabelMenu : public Menu {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorLabelMenu(QWidget *parent = nullptr);
|
||||
|
||||
virtual void changeEvent(QEvent *event) override;
|
||||
|
||||
signals:
|
||||
void ColorSelected(int i);
|
||||
void ColorSelected(int i);
|
||||
|
||||
private:
|
||||
void Retranslate();
|
||||
void Retranslate();
|
||||
|
||||
QVector<QAction*> color_items_;
|
||||
QVector<QAction *> color_items_;
|
||||
|
||||
private slots:
|
||||
void ActionTriggered();
|
||||
|
||||
void ActionTriggered();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,84 +25,91 @@
|
||||
#include "common/lerp.h"
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
ColorGradientWidget::ColorGradientWidget(Qt::Orientation orientation, QWidget *parent) :
|
||||
ColorSwatchWidget(parent),
|
||||
orientation_(orientation),
|
||||
val_(1.0)
|
||||
ColorGradientWidget::ColorGradientWidget(Qt::Orientation orientation,
|
||||
QWidget *parent)
|
||||
: ColorSwatchWidget(parent)
|
||||
, orientation_(orientation)
|
||||
, val_(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
Color ColorGradientWidget::GetColorFromScreenPos(const QPoint &p) const
|
||||
{
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
return LerpColor(start_, end_, p.x(), width());
|
||||
} else {
|
||||
return LerpColor(start_, end_, p.y(), height());
|
||||
}
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
return LerpColor(start_, end_, p.x(), width());
|
||||
} else {
|
||||
return LerpColor(start_, end_, p.y(), height());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorGradientWidget::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QWidget::paintEvent(e);
|
||||
QWidget::paintEvent(e);
|
||||
|
||||
QPainter p(this);
|
||||
QPainter p(this);
|
||||
|
||||
int min;
|
||||
int max;
|
||||
int min;
|
||||
int max;
|
||||
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
min = height();
|
||||
max = width();
|
||||
} else {
|
||||
min = width();
|
||||
max = height();
|
||||
}
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
min = height();
|
||||
max = width();
|
||||
} else {
|
||||
min = width();
|
||||
max = height();
|
||||
}
|
||||
|
||||
for (int i=0;i<max;i++) {
|
||||
p.setPen(QtUtils::toQColor(GetManagedColor(LerpColor(start_, end_, i, max))));
|
||||
for (int i = 0; i < max; i++) {
|
||||
p.setPen(QtUtils::toQColor(
|
||||
GetManagedColor(LerpColor(start_, end_, i, max))));
|
||||
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
p.drawLine(i, 0, i, height());
|
||||
} else {
|
||||
p.drawLine(0, i, width(), i);
|
||||
}
|
||||
}
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
p.drawLine(i, 0, i, height());
|
||||
} else {
|
||||
p.drawLine(0, i, width(), i);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw selector
|
||||
int selector_radius = qMax(2, min / 8);
|
||||
p.setPen(QPen(GetUISelectorColor(), qMax(1, selector_radius / 2)));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
// Draw selector
|
||||
int selector_radius = qMax(2, min / 8);
|
||||
p.setPen(QPen(GetUISelectorColor(), qMax(1, selector_radius / 2)));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
float clamped_val = std::clamp(val_, 0.0f, 1.0f);
|
||||
float clamped_val = std::clamp(val_, 0.0f, 1.0f);
|
||||
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
p.drawRect(qRound(width() * (1.0 - clamped_val)) - selector_radius, 0, selector_radius * 2, height() - 1);
|
||||
} else {
|
||||
p.drawRect(0, qRound(height() * (1.0 - clamped_val)) - selector_radius, width() - 1, selector_radius * 2);
|
||||
}
|
||||
if (orientation_ == Qt::Horizontal) {
|
||||
p.drawRect(qRound(width() * (1.0 - clamped_val)) - selector_radius, 0,
|
||||
selector_radius * 2, height() - 1);
|
||||
} else {
|
||||
p.drawRect(0, qRound(height() * (1.0 - clamped_val)) - selector_radius,
|
||||
width() - 1, selector_radius * 2);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorGradientWidget::SelectedColorChangedEvent(const Color &c, bool external)
|
||||
void ColorGradientWidget::SelectedColorChangedEvent(const Color &c,
|
||||
bool external)
|
||||
{
|
||||
float hue, sat;
|
||||
float hue, sat;
|
||||
|
||||
c.toHsv(&hue, &sat, &val_);
|
||||
c.toHsv(&hue, &sat, &val_);
|
||||
|
||||
if (external) {
|
||||
start_ = Color::fromHsv(hue, sat, 1.0);
|
||||
end_ = Color::fromHsv(hue, sat, 0.0);
|
||||
}
|
||||
if (external) {
|
||||
start_ = Color::fromHsv(hue, sat, 1.0);
|
||||
end_ = Color::fromHsv(hue, sat, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
Color ColorGradientWidget::LerpColor(const Color &a, const Color &b, int i, int max)
|
||||
Color ColorGradientWidget::LerpColor(const Color &a, const Color &b, int i,
|
||||
int max)
|
||||
{
|
||||
float t = std::clamp(static_cast<float>(i) / static_cast<float>(max), 0.0f, 1.0f);
|
||||
float t =
|
||||
std::clamp(static_cast<float>(i) / static_cast<float>(max), 0.0f, 1.0f);
|
||||
|
||||
return Color(lerp(a.red(), b.red(), t),
|
||||
lerp(a.green(), b.green(), t),
|
||||
lerp(a.blue(), b.blue(), t));
|
||||
return Color(lerp(a.red(), b.red(), t), lerp(a.green(), b.green(), t),
|
||||
lerp(a.blue(), b.blue(), t));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,34 +23,34 @@
|
||||
|
||||
#include "colorswatchwidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorGradientWidget : public ColorSwatchWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ColorGradientWidget : public ColorSwatchWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorGradientWidget(Qt::Orientation orientation, QWidget* parent = nullptr);
|
||||
ColorGradientWidget(Qt::Orientation orientation, QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual Color GetColorFromScreenPos(const QPoint& p) const override;
|
||||
virtual Color GetColorFromScreenPos(const QPoint &p) const override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
virtual void SelectedColorChangedEvent(const Color& c, bool external) override;
|
||||
virtual void SelectedColorChangedEvent(const Color &c,
|
||||
bool external) override;
|
||||
|
||||
private:
|
||||
static Color LerpColor(const Color& a, const Color& b, int i, int max);
|
||||
static Color LerpColor(const Color &a, const Color &b, int i, int max);
|
||||
|
||||
QPixmap cached_gradient_;
|
||||
QPixmap cached_gradient_;
|
||||
|
||||
Qt::Orientation orientation_;
|
||||
Qt::Orientation orientation_;
|
||||
|
||||
Color start_;
|
||||
Color start_;
|
||||
|
||||
Color end_;
|
||||
|
||||
float val_;
|
||||
Color end_;
|
||||
|
||||
float val_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,57 +24,60 @@
|
||||
|
||||
#include "common/qtutils.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
ColorPreviewBox::ColorPreviewBox(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
to_ref_processor_(nullptr),
|
||||
to_display_processor_(nullptr)
|
||||
ColorPreviewBox::ColorPreviewBox(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, to_ref_processor_(nullptr)
|
||||
, to_display_processor_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorPreviewBox::SetColorProcessor(ColorProcessorPtr to_ref, ColorProcessorPtr to_display)
|
||||
void ColorPreviewBox::SetColorProcessor(ColorProcessorPtr to_ref,
|
||||
ColorProcessorPtr to_display)
|
||||
{
|
||||
to_ref_processor_ = to_ref;
|
||||
to_display_processor_ = to_display;
|
||||
to_ref_processor_ = to_ref;
|
||||
to_display_processor_ = to_display;
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorPreviewBox::SetColor(const Color &c)
|
||||
{
|
||||
color_ = c;
|
||||
update();
|
||||
color_ = c;
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorPreviewBox::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
QWidget::paintEvent(e);
|
||||
QWidget::paintEvent(e);
|
||||
|
||||
QColor c;
|
||||
QColor c;
|
||||
|
||||
// Color management
|
||||
if (to_ref_processor_ && to_display_processor_) {
|
||||
c = QtUtils::toQColor(to_display_processor_->ConvertColor(to_ref_processor_->ConvertColor(color_)));
|
||||
} else {
|
||||
c = QtUtils::toQColor(color_);
|
||||
}
|
||||
// Color management
|
||||
if (to_ref_processor_ && to_display_processor_) {
|
||||
c = QtUtils::toQColor(to_display_processor_->ConvertColor(
|
||||
to_ref_processor_->ConvertColor(color_)));
|
||||
} else {
|
||||
c = QtUtils::toQColor(color_);
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
QPainter p(this);
|
||||
|
||||
QRect draw_rect = rect().adjusted(0, 0, -1, -1);
|
||||
QRect draw_rect = rect().adjusted(0, 0, -1, -1);
|
||||
|
||||
p.setPen(Qt::black);
|
||||
p.setPen(Qt::black);
|
||||
|
||||
if (color_.alpha() < 1.0) {
|
||||
// Draw black background so the background isn't the window color
|
||||
p.setBrush(Qt::black);
|
||||
p.drawRect(draw_rect);
|
||||
}
|
||||
if (color_.alpha() < 1.0) {
|
||||
// Draw black background so the background isn't the window color
|
||||
p.setBrush(Qt::black);
|
||||
p.drawRect(draw_rect);
|
||||
}
|
||||
|
||||
// Draw with color over the top
|
||||
p.setBrush(c);
|
||||
p.drawRect(draw_rect);
|
||||
// Draw with color over the top
|
||||
p.setBrush(c);
|
||||
p.drawRect(draw_rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,29 +25,29 @@
|
||||
|
||||
#include "render/colorprocessor.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorPreviewBox : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorPreviewBox(QWidget* parent = nullptr);
|
||||
|
||||
void SetColorProcessor(ColorProcessorPtr to_ref, ColorProcessorPtr to_display);
|
||||
class ColorPreviewBox : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorPreviewBox(QWidget *parent = nullptr);
|
||||
|
||||
void SetColorProcessor(ColorProcessorPtr to_ref,
|
||||
ColorProcessorPtr to_display);
|
||||
|
||||
public slots:
|
||||
void SetColor(const Color& c);
|
||||
void SetColor(const Color &c);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
private:
|
||||
Color color_;
|
||||
Color color_;
|
||||
|
||||
ColorProcessorPtr to_ref_processor_;
|
||||
|
||||
ColorProcessorPtr to_display_processor_;
|
||||
ColorProcessorPtr to_ref_processor_;
|
||||
|
||||
ColorProcessorPtr to_display_processor_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,181 +23,192 @@
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
|
||||
namespace olive {
|
||||
|
||||
ColorSpaceChooser::ColorSpaceChooser(ColorManager* color_manager, bool enable_input_field, bool enable_display_fields, QWidget *parent):
|
||||
QGroupBox(parent),
|
||||
color_manager_(color_manager)
|
||||
namespace olive
|
||||
{
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
|
||||
setTitle(tr("Color Management"));
|
||||
ColorSpaceChooser::ColorSpaceChooser(ColorManager *color_manager,
|
||||
bool enable_input_field,
|
||||
bool enable_display_fields,
|
||||
QWidget *parent)
|
||||
: QGroupBox(parent)
|
||||
, color_manager_(color_manager)
|
||||
{
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
|
||||
int row = 0;
|
||||
setTitle(tr("Color Management"));
|
||||
|
||||
if (enable_input_field) {
|
||||
int row = 0;
|
||||
|
||||
QString field_text;
|
||||
if (enable_input_field) {
|
||||
QString field_text;
|
||||
|
||||
if (enable_display_fields) {
|
||||
// If the display fields are visible, identify this as the input
|
||||
field_text = tr("Input:");
|
||||
} else {
|
||||
// Otherwise, this widget will essentially just serve as a list of standard color spaces
|
||||
field_text = tr("Color Space:");
|
||||
}
|
||||
if (enable_display_fields) {
|
||||
// If the display fields are visible, identify this as the input
|
||||
field_text = tr("Input:");
|
||||
} else {
|
||||
// Otherwise, this widget will essentially just serve as a list of standard color spaces
|
||||
field_text = tr("Color Space:");
|
||||
}
|
||||
|
||||
layout->addWidget(new QLabel(field_text), row, 0);
|
||||
layout->addWidget(new QLabel(field_text), row, 0);
|
||||
|
||||
input_combobox_ = new QComboBox();
|
||||
layout->addWidget(input_combobox_, row, 1);
|
||||
input_combobox_ = new QComboBox();
|
||||
layout->addWidget(input_combobox_, row, 1);
|
||||
|
||||
QStringList input_spaces = color_manager->ListAvailableColorspaces();
|
||||
QStringList input_spaces = color_manager->ListAvailableColorspaces();
|
||||
|
||||
foreach (const QString& s, input_spaces) {
|
||||
input_combobox_->addItem(s);
|
||||
}
|
||||
foreach (const QString &s, input_spaces) {
|
||||
input_combobox_->addItem(s);
|
||||
}
|
||||
|
||||
if (!color_manager_->GetDefaultInputColorSpace().isEmpty()) {
|
||||
input_combobox_->setCurrentText(color_manager_->GetDefaultInputColorSpace());
|
||||
}
|
||||
if (!color_manager_->GetDefaultInputColorSpace().isEmpty()) {
|
||||
input_combobox_->setCurrentText(
|
||||
color_manager_->GetDefaultInputColorSpace());
|
||||
}
|
||||
|
||||
connect(input_combobox_, &QComboBox::currentTextChanged, this, &ColorSpaceChooser::ComboBoxChanged);
|
||||
connect(input_combobox_, &QComboBox::currentTextChanged, this,
|
||||
&ColorSpaceChooser::ComboBoxChanged);
|
||||
|
||||
row++;
|
||||
} else {
|
||||
input_combobox_ = nullptr;
|
||||
}
|
||||
row++;
|
||||
} else {
|
||||
input_combobox_ = nullptr;
|
||||
}
|
||||
|
||||
if (enable_display_fields) {
|
||||
{
|
||||
layout->addWidget(new QLabel(tr("Display:")), row, 0);
|
||||
if (enable_display_fields) {
|
||||
{
|
||||
layout->addWidget(new QLabel(tr("Display:")), row, 0);
|
||||
|
||||
display_combobox_ = new QComboBox();
|
||||
layout->addWidget(display_combobox_, row, 1);
|
||||
display_combobox_ = new QComboBox();
|
||||
layout->addWidget(display_combobox_, row, 1);
|
||||
|
||||
QStringList display_spaces = color_manager->ListAvailableDisplays();
|
||||
QStringList display_spaces = color_manager->ListAvailableDisplays();
|
||||
|
||||
foreach (const QString& s, display_spaces) {
|
||||
display_combobox_->addItem(s);
|
||||
}
|
||||
foreach (const QString &s, display_spaces) {
|
||||
display_combobox_->addItem(s);
|
||||
}
|
||||
|
||||
display_combobox_->setCurrentText(color_manager_->GetDefaultDisplay());
|
||||
display_combobox_->setCurrentText(
|
||||
color_manager_->GetDefaultDisplay());
|
||||
|
||||
connect(display_combobox_, &QComboBox::currentTextChanged, this, &ColorSpaceChooser::ComboBoxChanged);
|
||||
}
|
||||
connect(display_combobox_, &QComboBox::currentTextChanged, this,
|
||||
&ColorSpaceChooser::ComboBoxChanged);
|
||||
}
|
||||
|
||||
row++;
|
||||
row++;
|
||||
|
||||
{
|
||||
layout->addWidget(new QLabel(tr("View:")), row, 0);
|
||||
{
|
||||
layout->addWidget(new QLabel(tr("View:")), row, 0);
|
||||
|
||||
view_combobox_ = new QComboBox();
|
||||
layout->addWidget(view_combobox_, row, 1);
|
||||
view_combobox_ = new QComboBox();
|
||||
layout->addWidget(view_combobox_, row, 1);
|
||||
|
||||
UpdateViews(display_combobox_->currentText());
|
||||
UpdateViews(display_combobox_->currentText());
|
||||
|
||||
connect(view_combobox_, &QComboBox::currentTextChanged, this, &ColorSpaceChooser::ComboBoxChanged);
|
||||
}
|
||||
connect(view_combobox_, &QComboBox::currentTextChanged, this,
|
||||
&ColorSpaceChooser::ComboBoxChanged);
|
||||
}
|
||||
|
||||
row++;
|
||||
row++;
|
||||
|
||||
{
|
||||
layout->addWidget(new QLabel(tr("Look:")), row, 0);
|
||||
{
|
||||
layout->addWidget(new QLabel(tr("Look:")), row, 0);
|
||||
|
||||
look_combobox_ = new QComboBox();
|
||||
layout->addWidget(look_combobox_, row, 1);
|
||||
look_combobox_ = new QComboBox();
|
||||
layout->addWidget(look_combobox_, row, 1);
|
||||
|
||||
QStringList looks = color_manager->ListAvailableLooks();
|
||||
QStringList looks = color_manager->ListAvailableLooks();
|
||||
|
||||
look_combobox_->addItem(tr("(None)"), QString());
|
||||
look_combobox_->addItem(tr("(None)"), QString());
|
||||
|
||||
foreach (const QString& s, looks) {
|
||||
look_combobox_->addItem(s, s);
|
||||
}
|
||||
foreach (const QString &s, looks) {
|
||||
look_combobox_->addItem(s, s);
|
||||
}
|
||||
|
||||
connect(look_combobox_, &QComboBox::currentTextChanged, this, &ColorSpaceChooser::ComboBoxChanged);
|
||||
}
|
||||
} else {
|
||||
display_combobox_ = nullptr;
|
||||
view_combobox_ = nullptr;
|
||||
look_combobox_ = nullptr;
|
||||
}
|
||||
connect(look_combobox_, &QComboBox::currentTextChanged, this,
|
||||
&ColorSpaceChooser::ComboBoxChanged);
|
||||
}
|
||||
} else {
|
||||
display_combobox_ = nullptr;
|
||||
view_combobox_ = nullptr;
|
||||
look_combobox_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QString ColorSpaceChooser::input() const
|
||||
{
|
||||
if (input_combobox_) {
|
||||
return input_combobox_->currentText();
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
if (input_combobox_) {
|
||||
return input_combobox_->currentText();
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
||||
ColorTransform ColorSpaceChooser::output() const
|
||||
{
|
||||
return ColorTransform(display_combobox_->currentText(),
|
||||
view_combobox_->currentText(),
|
||||
look_combobox_->currentIndex() == 0 ? QString() : look_combobox_->currentText());
|
||||
return ColorTransform(display_combobox_->currentText(),
|
||||
view_combobox_->currentText(),
|
||||
look_combobox_->currentIndex() == 0 ?
|
||||
QString() :
|
||||
look_combobox_->currentText());
|
||||
}
|
||||
|
||||
void ColorSpaceChooser::set_input(const QString &s)
|
||||
{
|
||||
input_combobox_->setCurrentText(color_manager_->GetCompliantColorSpace(s));
|
||||
input_combobox_->setCurrentText(color_manager_->GetCompliantColorSpace(s));
|
||||
}
|
||||
|
||||
void ColorSpaceChooser::set_output(const ColorTransform &out)
|
||||
{
|
||||
ColorTransform compliant = color_manager_->GetCompliantColorSpace(out);
|
||||
ColorTransform compliant = color_manager_->GetCompliantColorSpace(out);
|
||||
|
||||
display_combobox_->setCurrentText(compliant.display());
|
||||
view_combobox_->setCurrentText(compliant.view());
|
||||
display_combobox_->setCurrentText(compliant.display());
|
||||
view_combobox_->setCurrentText(compliant.view());
|
||||
|
||||
if (compliant.look().isEmpty()) {
|
||||
look_combobox_->setCurrentIndex(0);
|
||||
} else {
|
||||
look_combobox_->setCurrentText(compliant.look());
|
||||
}
|
||||
if (compliant.look().isEmpty()) {
|
||||
look_combobox_->setCurrentIndex(0);
|
||||
} else {
|
||||
look_combobox_->setCurrentText(compliant.look());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSpaceChooser::UpdateViews(const QString& display)
|
||||
void ColorSpaceChooser::UpdateViews(const QString &display)
|
||||
{
|
||||
QString v = view_combobox_->currentText();
|
||||
QString v = view_combobox_->currentText();
|
||||
|
||||
view_combobox_->clear();
|
||||
view_combobox_->clear();
|
||||
|
||||
QStringList views = color_manager_->ListAvailableViews(display);
|
||||
QStringList views = color_manager_->ListAvailableViews(display);
|
||||
|
||||
foreach (const QString& s, views) {
|
||||
view_combobox_->addItem(s);
|
||||
}
|
||||
foreach (const QString &s, views) {
|
||||
view_combobox_->addItem(s);
|
||||
}
|
||||
|
||||
if (views.contains(v)) {
|
||||
// If we have the view we had before, set it again
|
||||
view_combobox_->setCurrentText(v);
|
||||
} else {
|
||||
// Otherwise reset to default view for this display
|
||||
view_combobox_->setCurrentText(color_manager_->GetDefaultView(display));
|
||||
}
|
||||
if (views.contains(v)) {
|
||||
// If we have the view we had before, set it again
|
||||
view_combobox_->setCurrentText(v);
|
||||
} else {
|
||||
// Otherwise reset to default view for this display
|
||||
view_combobox_->setCurrentText(color_manager_->GetDefaultView(display));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSpaceChooser::ComboBoxChanged()
|
||||
{
|
||||
if (sender() == display_combobox_) {
|
||||
UpdateViews(display_combobox_->currentText());
|
||||
}
|
||||
if (sender() == display_combobox_) {
|
||||
UpdateViews(display_combobox_->currentText());
|
||||
}
|
||||
|
||||
if (input_combobox_) {
|
||||
emit InputColorSpaceChanged(input());
|
||||
}
|
||||
if (input_combobox_) {
|
||||
emit InputColorSpaceChanged(input());
|
||||
}
|
||||
|
||||
if (display_combobox_) {
|
||||
emit OutputColorSpaceChanged(output());
|
||||
}
|
||||
if (display_combobox_) {
|
||||
emit OutputColorSpaceChanged(output());
|
||||
}
|
||||
|
||||
if (input_combobox_ && display_combobox_) {
|
||||
emit ColorSpaceChanged(input(), output());
|
||||
}
|
||||
if (input_combobox_ && display_combobox_) {
|
||||
emit ColorSpaceChanged(input(), output());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,44 +26,46 @@
|
||||
|
||||
#include "node/color/colormanager/colormanager.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorSpaceChooser : public QGroupBox
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ColorSpaceChooser : public QGroupBox {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorSpaceChooser(ColorManager* color_manager, bool enable_input_field = true, bool enable_display_fields = true, QWidget* parent = nullptr);
|
||||
ColorSpaceChooser(ColorManager *color_manager,
|
||||
bool enable_input_field = true,
|
||||
bool enable_display_fields = true,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
QString input() const;
|
||||
ColorTransform output() const;
|
||||
QString input() const;
|
||||
ColorTransform output() const;
|
||||
|
||||
void set_input(const QString& s);
|
||||
void set_output(const ColorTransform& out);
|
||||
void set_input(const QString &s);
|
||||
void set_output(const ColorTransform &out);
|
||||
|
||||
signals:
|
||||
void InputColorSpaceChanged(const QString& input);
|
||||
void InputColorSpaceChanged(const QString &input);
|
||||
|
||||
void OutputColorSpaceChanged(const ColorTransform& out);
|
||||
void OutputColorSpaceChanged(const ColorTransform &out);
|
||||
|
||||
void ColorSpaceChanged(const QString& input, const ColorTransform& out);
|
||||
void ColorSpaceChanged(const QString &input, const ColorTransform &out);
|
||||
|
||||
private slots:
|
||||
void UpdateViews(const QString &display);
|
||||
void UpdateViews(const QString &display);
|
||||
|
||||
private:
|
||||
ColorManager* color_manager_;
|
||||
ColorManager *color_manager_;
|
||||
|
||||
QComboBox* input_combobox_;
|
||||
QComboBox *input_combobox_;
|
||||
|
||||
QComboBox* display_combobox_;
|
||||
QComboBox *display_combobox_;
|
||||
|
||||
QComboBox* view_combobox_;
|
||||
QComboBox *view_combobox_;
|
||||
|
||||
QComboBox* look_combobox_;
|
||||
QComboBox *look_combobox_;
|
||||
|
||||
private slots:
|
||||
void ComboBoxChanged();
|
||||
|
||||
void ComboBoxChanged();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,199 +25,195 @@
|
||||
#include "common/filefunctions.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const int kDefaultColorCount = 16;
|
||||
const Color kDefaultColors[kDefaultColorCount] = {
|
||||
Color(1.0, 1.0, 1.0),
|
||||
Color(1.0, 1.0, 0.0),
|
||||
Color(1.0, 0.5, 0.0),
|
||||
Color(1.0, 0.0, 0.0),
|
||||
Color(1.0, 0.0, 1.0),
|
||||
Color(0.5, 0.0, 1.0),
|
||||
Color(0.0, 0.0, 1.0),
|
||||
Color(0.0, 0.5, 1.0),
|
||||
Color(0.0, 1.0, 0.0),
|
||||
Color(0.0, 0.5, 0.0),
|
||||
Color(0.5, 0.25, 0.0),
|
||||
Color(0.75, 0.5, 0.25),
|
||||
Color(0.75, 0.75, 0.75),
|
||||
Color(0.5, 0.5, 0.5),
|
||||
Color(0.25, 0.25, 0.25),
|
||||
Color(0.0, 0.0, 0.0)
|
||||
Color(1.0, 1.0, 1.0), Color(1.0, 1.0, 0.0), Color(1.0, 0.5, 0.0),
|
||||
Color(1.0, 0.0, 0.0), Color(1.0, 0.0, 1.0), Color(0.5, 0.0, 1.0),
|
||||
Color(0.0, 0.0, 1.0), Color(0.0, 0.5, 1.0), Color(0.0, 1.0, 0.0),
|
||||
Color(0.0, 0.5, 0.0), Color(0.5, 0.25, 0.0), Color(0.75, 0.5, 0.25),
|
||||
Color(0.75, 0.75, 0.75), Color(0.5, 0.5, 0.5), Color(0.25, 0.25, 0.25),
|
||||
Color(0.0, 0.0, 0.0)
|
||||
};
|
||||
|
||||
ColorSwatchChooser::ColorSwatchChooser(ColorManager *manager, QWidget *parent) :
|
||||
QWidget(parent)
|
||||
ColorSwatchChooser::ColorSwatchChooser(ColorManager *manager, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
auto layout = new QGridLayout(this);
|
||||
auto layout = new QGridLayout(this);
|
||||
|
||||
for (int x=0; x<kColCount; x++) {
|
||||
for (int y=0; y<kRowCount; y++) {
|
||||
// Create button
|
||||
auto b = new ColorButton(manager, false);
|
||||
b->setFixedWidth(b->sizeHint().height()/2*3);
|
||||
b->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
layout->addWidget(b, y, x);
|
||||
for (int x = 0; x < kColCount; x++) {
|
||||
for (int y = 0; y < kRowCount; y++) {
|
||||
// Create button
|
||||
auto b = new ColorButton(manager, false);
|
||||
b->setFixedWidth(b->sizeHint().height() / 2 * 3);
|
||||
b->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
layout->addWidget(b, y, x);
|
||||
|
||||
// Save button in buttons array
|
||||
int btn_index = x + kColCount*y;
|
||||
buttons_[btn_index] = b;
|
||||
// Save button in buttons array
|
||||
int btn_index = x + kColCount * y;
|
||||
buttons_[btn_index] = b;
|
||||
|
||||
// Set default color
|
||||
SetDefaultColor(btn_index);
|
||||
// Set default color
|
||||
SetDefaultColor(btn_index);
|
||||
|
||||
// Connect clicks
|
||||
connect(b, &ColorButton::clicked, this, &ColorSwatchChooser::HandleButtonClick);
|
||||
connect(b, &ColorButton::customContextMenuRequested, this, &ColorSwatchChooser::HandleContextMenu);
|
||||
}
|
||||
}
|
||||
// Connect clicks
|
||||
connect(b, &ColorButton::clicked, this,
|
||||
&ColorSwatchChooser::HandleButtonClick);
|
||||
connect(b, &ColorButton::customContextMenuRequested, this,
|
||||
&ColorSwatchChooser::HandleContextMenu);
|
||||
}
|
||||
}
|
||||
|
||||
LoadSwatches();
|
||||
LoadSwatches();
|
||||
}
|
||||
|
||||
void ColorSwatchChooser::SetDefaultColor(int index)
|
||||
{
|
||||
if (index < kDefaultColorCount) {
|
||||
buttons_[index]->SetColor(kDefaultColors[index]);
|
||||
} else {
|
||||
buttons_[index]->SetColor(Color(1.0, 1.0, 1.0));
|
||||
}
|
||||
if (index < kDefaultColorCount) {
|
||||
buttons_[index]->SetColor(kDefaultColors[index]);
|
||||
} else {
|
||||
buttons_[index]->SetColor(Color(1.0, 1.0, 1.0));
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSwatchChooser::HandleButtonClick()
|
||||
{
|
||||
auto b = static_cast<ColorButton*>(sender());
|
||||
auto b = static_cast<ColorButton *>(sender());
|
||||
|
||||
emit ColorClicked(b->GetColor());
|
||||
SetCurrentColor(b->GetColor());
|
||||
emit ColorClicked(b->GetColor());
|
||||
SetCurrentColor(b->GetColor());
|
||||
}
|
||||
|
||||
void ColorSwatchChooser::HandleContextMenu()
|
||||
{
|
||||
Menu m(this);
|
||||
Menu m(this);
|
||||
|
||||
auto save_action = m.addAction(tr("Save Color Here"));
|
||||
connect(save_action, &QAction::triggered, this, &ColorSwatchChooser::SaveCurrentColor);
|
||||
auto save_action = m.addAction(tr("Save Color Here"));
|
||||
connect(save_action, &QAction::triggered, this,
|
||||
&ColorSwatchChooser::SaveCurrentColor);
|
||||
|
||||
m.addSeparator();
|
||||
m.addSeparator();
|
||||
|
||||
auto reset_action = m.addAction(tr("Reset To Default"));
|
||||
connect(reset_action, &QAction::triggered, this, &ColorSwatchChooser::ResetMenuButton);
|
||||
auto reset_action = m.addAction(tr("Reset To Default"));
|
||||
connect(reset_action, &QAction::triggered, this,
|
||||
&ColorSwatchChooser::ResetMenuButton);
|
||||
|
||||
menu_btn_ = static_cast<ColorButton*>(sender());
|
||||
menu_btn_ = static_cast<ColorButton *>(sender());
|
||||
|
||||
m.exec(QCursor::pos());
|
||||
m.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void ColorSwatchChooser::SaveCurrentColor()
|
||||
{
|
||||
menu_btn_->SetColor(current_);
|
||||
menu_btn_->SetColor(current_);
|
||||
|
||||
SaveSwatches();
|
||||
SaveSwatches();
|
||||
}
|
||||
|
||||
void ColorSwatchChooser::ResetMenuButton()
|
||||
{
|
||||
for (int i=0; i<kBtnCount; i++) {
|
||||
if (buttons_[i] == menu_btn_) {
|
||||
SetDefaultColor(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < kBtnCount; i++) {
|
||||
if (buttons_[i] == menu_btn_) {
|
||||
SetDefaultColor(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString ColorSwatchChooser::GetSwatchFilename()
|
||||
{
|
||||
return QDir(FileFunctions::GetConfigurationLocation()).filePath(QStringLiteral("swatch"));
|
||||
return QDir(FileFunctions::GetConfigurationLocation())
|
||||
.filePath(QStringLiteral("swatch"));
|
||||
}
|
||||
|
||||
void ColorSwatchChooser::LoadSwatches()
|
||||
{
|
||||
QFile f(GetSwatchFilename());
|
||||
if (f.open(QFile::ReadOnly)) {
|
||||
QDataStream d(&f);
|
||||
QFile f(GetSwatchFilename());
|
||||
if (f.open(QFile::ReadOnly)) {
|
||||
QDataStream d(&f);
|
||||
|
||||
uint version;
|
||||
d >> version;
|
||||
uint version;
|
||||
d >> version;
|
||||
|
||||
if (version == 1) {
|
||||
int index = 0;
|
||||
while (index < kBtnCount && !d.atEnd()) {
|
||||
Color::DataType r;
|
||||
QString s;
|
||||
ManagedColor c;
|
||||
ColorTransform t;
|
||||
bool is_display;
|
||||
if (version == 1) {
|
||||
int index = 0;
|
||||
while (index < kBtnCount && !d.atEnd()) {
|
||||
Color::DataType r;
|
||||
QString s;
|
||||
ManagedColor c;
|
||||
ColorTransform t;
|
||||
bool is_display;
|
||||
|
||||
c.set_alpha(1.0);
|
||||
c.set_alpha(1.0);
|
||||
|
||||
d >> r;
|
||||
c.set_red(r);
|
||||
d >> r;
|
||||
c.set_red(r);
|
||||
|
||||
d >> r;
|
||||
c.set_green(r);
|
||||
d >> r;
|
||||
c.set_green(r);
|
||||
|
||||
d >> r;
|
||||
c.set_blue(r);
|
||||
d >> r;
|
||||
c.set_blue(r);
|
||||
|
||||
d >> s;
|
||||
c.set_color_input(s);
|
||||
d >> s;
|
||||
c.set_color_input(s);
|
||||
|
||||
d >> is_display;
|
||||
if (is_display) {
|
||||
QString display, view, look;
|
||||
d >> display;
|
||||
d >> view;
|
||||
d >> look;
|
||||
c.set_color_output(ColorTransform(display, view, look));
|
||||
} else {
|
||||
d >> s;
|
||||
c.set_color_output(ColorTransform(s));
|
||||
}
|
||||
d >> is_display;
|
||||
if (is_display) {
|
||||
QString display, view, look;
|
||||
d >> display;
|
||||
d >> view;
|
||||
d >> look;
|
||||
c.set_color_output(ColorTransform(display, view, look));
|
||||
} else {
|
||||
d >> s;
|
||||
c.set_color_output(ColorTransform(s));
|
||||
}
|
||||
|
||||
buttons_[index]->SetColor(c);
|
||||
buttons_[index]->SetColor(c);
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
f.close();
|
||||
}
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSwatchChooser::SaveSwatches()
|
||||
{
|
||||
QString fn = GetSwatchFilename();
|
||||
QFile f(fn);
|
||||
QString fn = GetSwatchFilename();
|
||||
QFile f(fn);
|
||||
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
QDataStream d(&f);
|
||||
if (f.open(QFile::WriteOnly)) {
|
||||
QDataStream d(&f);
|
||||
|
||||
const uint version = 1;
|
||||
d << version;
|
||||
const uint version = 1;
|
||||
d << version;
|
||||
|
||||
for (int i=0; i<kBtnCount; i++) {
|
||||
const ManagedColor &c = buttons_[i]->GetColor();
|
||||
d << c.red();
|
||||
d << c.green();
|
||||
d << c.blue();
|
||||
d << c.color_input();
|
||||
d << c.color_output().is_display();
|
||||
for (int i = 0; i < kBtnCount; i++) {
|
||||
const ManagedColor &c = buttons_[i]->GetColor();
|
||||
d << c.red();
|
||||
d << c.green();
|
||||
d << c.blue();
|
||||
d << c.color_input();
|
||||
d << c.color_output().is_display();
|
||||
|
||||
if (c.color_output().is_display()) {
|
||||
d << c.color_output().display();
|
||||
d << c.color_output().view();
|
||||
d << c.color_output().look();
|
||||
} else {
|
||||
d << c.color_output().output();
|
||||
}
|
||||
}
|
||||
if (c.color_output().is_display()) {
|
||||
d << c.color_output().display();
|
||||
d << c.color_output().view();
|
||||
d << c.color_output().look();
|
||||
} else {
|
||||
d << c.color_output().output();
|
||||
}
|
||||
}
|
||||
|
||||
f.close();
|
||||
} else {
|
||||
qCritical() << "Failed to open swatch file" << fn << "for writing";
|
||||
}
|
||||
f.close();
|
||||
} else {
|
||||
qCritical() << "Failed to open swatch file" << fn << "for writing";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,48 +24,47 @@
|
||||
#include "node/color/colormanager/colormanager.h"
|
||||
#include "widget/colorbutton/colorbutton.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorSwatchChooser : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ColorSwatchChooser : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorSwatchChooser(ColorManager *manager, QWidget *parent = nullptr);
|
||||
ColorSwatchChooser(ColorManager *manager, QWidget *parent = nullptr);
|
||||
|
||||
public slots:
|
||||
void SetCurrentColor(const ManagedColor &c)
|
||||
{
|
||||
current_ = c;
|
||||
}
|
||||
void SetCurrentColor(const ManagedColor &c)
|
||||
{
|
||||
current_ = c;
|
||||
}
|
||||
|
||||
signals:
|
||||
void ColorClicked(const ManagedColor &c);
|
||||
void ColorClicked(const ManagedColor &c);
|
||||
|
||||
private:
|
||||
void SetDefaultColor(int index);
|
||||
void SetDefaultColor(int index);
|
||||
|
||||
static QString GetSwatchFilename();
|
||||
static QString GetSwatchFilename();
|
||||
|
||||
void LoadSwatches();
|
||||
void SaveSwatches();
|
||||
void LoadSwatches();
|
||||
void SaveSwatches();
|
||||
|
||||
static const int kRowCount = 4;
|
||||
static const int kColCount = 8;
|
||||
static const int kBtnCount = kRowCount*kColCount;
|
||||
ColorButton *buttons_[kBtnCount];
|
||||
static const int kRowCount = 4;
|
||||
static const int kColCount = 8;
|
||||
static const int kBtnCount = kRowCount * kColCount;
|
||||
ColorButton *buttons_[kBtnCount];
|
||||
|
||||
ManagedColor current_;
|
||||
ColorButton *menu_btn_;
|
||||
ManagedColor current_;
|
||||
ColorButton *menu_btn_;
|
||||
|
||||
private slots:
|
||||
void HandleButtonClick();
|
||||
void HandleButtonClick();
|
||||
|
||||
void HandleContextMenu();
|
||||
void HandleContextMenu();
|
||||
|
||||
void SaveCurrentColor();
|
||||
|
||||
void ResetMenuButton();
|
||||
void SaveCurrentColor();
|
||||
|
||||
void ResetMenuButton();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -24,51 +24,53 @@
|
||||
|
||||
#include "ui/colorcoding.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
ColorSwatchWidget::ColorSwatchWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
to_linear_processor_(nullptr),
|
||||
to_display_processor_(nullptr)
|
||||
ColorSwatchWidget::ColorSwatchWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, to_linear_processor_(nullptr)
|
||||
, to_display_processor_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
const Color &ColorSwatchWidget::GetSelectedColor() const
|
||||
{
|
||||
return selected_color_;
|
||||
return selected_color_;
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::SetColorProcessor(ColorProcessorPtr to_linear, ColorProcessorPtr to_display)
|
||||
void ColorSwatchWidget::SetColorProcessor(ColorProcessorPtr to_linear,
|
||||
ColorProcessorPtr to_display)
|
||||
{
|
||||
to_linear_processor_ = to_linear;
|
||||
to_display_processor_ = to_display;
|
||||
to_linear_processor_ = to_linear;
|
||||
to_display_processor_ = to_display;
|
||||
|
||||
// Force full update
|
||||
SelectedColorChangedEvent(GetSelectedColor(), true);
|
||||
update();
|
||||
// Force full update
|
||||
SelectedColorChangedEvent(GetSelectedColor(), true);
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::SetSelectedColor(const Color &c)
|
||||
{
|
||||
SetSelectedColorInternal(c, true);
|
||||
SetSelectedColorInternal(c, true);
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
QWidget::mousePressEvent(e);
|
||||
QWidget::mousePressEvent(e);
|
||||
|
||||
SetSelectedColorInternal(GetColorFromScreenPos(e->pos()), false);
|
||||
emit SelectedColorChanged(GetSelectedColor());
|
||||
SetSelectedColorInternal(GetColorFromScreenPos(e->pos()), false);
|
||||
emit SelectedColorChanged(GetSelectedColor());
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::mouseMoveEvent(QMouseEvent *e)
|
||||
{
|
||||
QWidget::mouseMoveEvent(e);
|
||||
QWidget::mouseMoveEvent(e);
|
||||
|
||||
if (e->buttons() & Qt::LeftButton) {
|
||||
SetSelectedColorInternal(GetColorFromScreenPos(e->pos()), false);
|
||||
emit SelectedColorChanged(GetSelectedColor());
|
||||
}
|
||||
if (e->buttons() & Qt::LeftButton) {
|
||||
SetSelectedColorInternal(GetColorFromScreenPos(e->pos()), false);
|
||||
emit SelectedColorChanged(GetSelectedColor());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::SelectedColorChangedEvent(const Color &, bool)
|
||||
@@ -77,23 +79,24 @@ void ColorSwatchWidget::SelectedColorChangedEvent(const Color &, bool)
|
||||
|
||||
Qt::GlobalColor ColorSwatchWidget::GetUISelectorColor() const
|
||||
{
|
||||
return ColorCoding::GetUISelectorColor(GetSelectedColor());
|
||||
return ColorCoding::GetUISelectorColor(GetSelectedColor());
|
||||
}
|
||||
|
||||
Color ColorSwatchWidget::GetManagedColor(const Color &input) const
|
||||
{
|
||||
if (to_linear_processor_ && to_display_processor_) {
|
||||
return to_display_processor_->ConvertColor(to_linear_processor_->ConvertColor(input));
|
||||
}
|
||||
if (to_linear_processor_ && to_display_processor_) {
|
||||
return to_display_processor_->ConvertColor(
|
||||
to_linear_processor_->ConvertColor(input));
|
||||
}
|
||||
|
||||
return input;
|
||||
return input;
|
||||
}
|
||||
|
||||
void ColorSwatchWidget::SetSelectedColorInternal(const Color &c, bool external)
|
||||
{
|
||||
selected_color_ = c;
|
||||
SelectedColorChangedEvent(c, external);
|
||||
update();
|
||||
selected_color_ = c;
|
||||
SelectedColorChangedEvent(c, external);
|
||||
update();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,46 +25,46 @@
|
||||
|
||||
#include "render/colorprocessor.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorSwatchWidget : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ColorSwatchWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorSwatchWidget(QWidget* parent = nullptr);
|
||||
ColorSwatchWidget(QWidget *parent = nullptr);
|
||||
|
||||
const Color& GetSelectedColor() const;
|
||||
const Color &GetSelectedColor() const;
|
||||
|
||||
void SetColorProcessor(ColorProcessorPtr to_linear, ColorProcessorPtr to_display);
|
||||
void SetColorProcessor(ColorProcessorPtr to_linear,
|
||||
ColorProcessorPtr to_display);
|
||||
|
||||
public slots:
|
||||
void SetSelectedColor(const Color& c);
|
||||
void SetSelectedColor(const Color &c);
|
||||
|
||||
signals:
|
||||
void SelectedColorChanged(const Color& c);
|
||||
void SelectedColorChanged(const Color &c);
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent* e) override;
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
|
||||
virtual void mouseMoveEvent(QMouseEvent* e) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *e) override;
|
||||
|
||||
virtual Color GetColorFromScreenPos(const QPoint& p) const = 0;
|
||||
virtual Color GetColorFromScreenPos(const QPoint &p) const = 0;
|
||||
|
||||
virtual void SelectedColorChangedEvent(const Color& c, bool external);
|
||||
virtual void SelectedColorChangedEvent(const Color &c, bool external);
|
||||
|
||||
Qt::GlobalColor GetUISelectorColor() const;
|
||||
Qt::GlobalColor GetUISelectorColor() const;
|
||||
|
||||
Color GetManagedColor(const Color& input) const;
|
||||
Color GetManagedColor(const Color &input) const;
|
||||
|
||||
private:
|
||||
void SetSelectedColorInternal(const Color& c, bool external);
|
||||
void SetSelectedColorInternal(const Color &c, bool external);
|
||||
|
||||
Color selected_color_;
|
||||
Color selected_color_;
|
||||
|
||||
ColorProcessorPtr to_linear_processor_;
|
||||
|
||||
ColorProcessorPtr to_display_processor_;
|
||||
ColorProcessorPtr to_linear_processor_;
|
||||
|
||||
ColorProcessorPtr to_display_processor_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,462 +28,493 @@
|
||||
#include "core.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
ColorValuesWidget::ColorValuesWidget(ColorManager *manager, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
manager_(manager),
|
||||
input_to_ref_(nullptr),
|
||||
ref_to_display_(nullptr),
|
||||
display_to_ref_(nullptr),
|
||||
ref_to_input_(nullptr)
|
||||
namespace olive
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
// Create preview box
|
||||
{
|
||||
QHBoxLayout* preview_layout = new QHBoxLayout();
|
||||
ColorValuesWidget::ColorValuesWidget(ColorManager *manager, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, manager_(manager)
|
||||
, input_to_ref_(nullptr)
|
||||
, ref_to_display_(nullptr)
|
||||
, display_to_ref_(nullptr)
|
||||
, ref_to_input_(nullptr)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
|
||||
preview_layout->setContentsMargins(0, 0, 0, 0);
|
||||
// Create preview box
|
||||
{
|
||||
QHBoxLayout *preview_layout = new QHBoxLayout();
|
||||
|
||||
preview_layout->addWidget(new QLabel(tr("Preview")));
|
||||
preview_layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
preview_ = new ColorPreviewBox();
|
||||
preview_->setFixedHeight(fontMetrics().height() * 3 / 2);
|
||||
preview_layout->addWidget(preview_);
|
||||
preview_layout->addWidget(new QLabel(tr("Preview")));
|
||||
|
||||
color_picker_btn_ = new QPushButton();
|
||||
color_picker_btn_->setIcon(icon::ColorPicker);
|
||||
color_picker_btn_->setFixedWidth(color_picker_btn_->sizeHint().height());
|
||||
color_picker_btn_->setCheckable(true);
|
||||
connect(color_picker_btn_, &QPushButton::toggled, this, &ColorValuesWidget::ColorPickedBtnToggled);
|
||||
connect(Core::instance(), &Core::ColorPickerColorEmitted, this, &ColorValuesWidget::SetReferenceColor);
|
||||
preview_layout->addWidget(color_picker_btn_);
|
||||
preview_ = new ColorPreviewBox();
|
||||
preview_->setFixedHeight(fontMetrics().height() * 3 / 2);
|
||||
preview_layout->addWidget(preview_);
|
||||
|
||||
layout->addLayout(preview_layout);
|
||||
}
|
||||
color_picker_btn_ = new QPushButton();
|
||||
color_picker_btn_->setIcon(icon::ColorPicker);
|
||||
color_picker_btn_->setFixedWidth(
|
||||
color_picker_btn_->sizeHint().height());
|
||||
color_picker_btn_->setCheckable(true);
|
||||
connect(color_picker_btn_, &QPushButton::toggled, this,
|
||||
&ColorValuesWidget::ColorPickedBtnToggled);
|
||||
connect(Core::instance(), &Core::ColorPickerColorEmitted, this,
|
||||
&ColorValuesWidget::SetReferenceColor);
|
||||
preview_layout->addWidget(color_picker_btn_);
|
||||
|
||||
// Create value tabs
|
||||
{
|
||||
QTabWidget* tabs = new QTabWidget();
|
||||
layout->addLayout(preview_layout);
|
||||
}
|
||||
|
||||
input_tab_ = new ColorValuesTab(true);
|
||||
tabs->addTab(input_tab_, tr("Input"));
|
||||
connect(input_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::UpdateValuesFromInput);
|
||||
connect(input_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::ColorChanged);
|
||||
connect(input_tab_, &ColorValuesTab::ColorChanged, preview_, &ColorPreviewBox::SetColor);
|
||||
// Create value tabs
|
||||
{
|
||||
QTabWidget *tabs = new QTabWidget();
|
||||
|
||||
reference_tab_ = new ColorValuesTab();
|
||||
tabs->addTab(reference_tab_, tr("Reference"));
|
||||
connect(reference_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::UpdateValuesFromRef);
|
||||
input_tab_ = new ColorValuesTab(true);
|
||||
tabs->addTab(input_tab_, tr("Input"));
|
||||
connect(input_tab_, &ColorValuesTab::ColorChanged, this,
|
||||
&ColorValuesWidget::UpdateValuesFromInput);
|
||||
connect(input_tab_, &ColorValuesTab::ColorChanged, this,
|
||||
&ColorValuesWidget::ColorChanged);
|
||||
connect(input_tab_, &ColorValuesTab::ColorChanged, preview_,
|
||||
&ColorPreviewBox::SetColor);
|
||||
|
||||
display_tab_ = new ColorValuesTab();
|
||||
tabs->addTab(display_tab_, tr("Display"));
|
||||
connect(display_tab_, &ColorValuesTab::ColorChanged, this, &ColorValuesWidget::UpdateValuesFromDisplay);
|
||||
reference_tab_ = new ColorValuesTab();
|
||||
tabs->addTab(reference_tab_, tr("Reference"));
|
||||
connect(reference_tab_, &ColorValuesTab::ColorChanged, this,
|
||||
&ColorValuesWidget::UpdateValuesFromRef);
|
||||
|
||||
// FIXME: Display -> Ref temporarily disabled due to OCIO crash (see ColorDialog::ColorSpaceChanged for more info)
|
||||
display_tab_->setEnabled(false);
|
||||
display_tab_ = new ColorValuesTab();
|
||||
tabs->addTab(display_tab_, tr("Display"));
|
||||
connect(display_tab_, &ColorValuesTab::ColorChanged, this,
|
||||
&ColorValuesWidget::UpdateValuesFromDisplay);
|
||||
|
||||
layout->addWidget(tabs);
|
||||
}
|
||||
// FIXME: Display -> Ref temporarily disabled due to OCIO crash (see ColorDialog::ColorSpaceChanged for more info)
|
||||
display_tab_->setEnabled(false);
|
||||
|
||||
layout->addWidget(tabs);
|
||||
}
|
||||
}
|
||||
|
||||
Color ColorValuesWidget::GetColor() const
|
||||
{
|
||||
return reference_tab_->GetColor();
|
||||
return reference_tab_->GetColor();
|
||||
}
|
||||
|
||||
void ColorValuesWidget::SetColorProcessor(ColorProcessorPtr input_to_ref, ColorProcessorPtr ref_to_display, ColorProcessorPtr display_to_ref, ColorProcessorPtr ref_to_input)
|
||||
void ColorValuesWidget::SetColorProcessor(ColorProcessorPtr input_to_ref,
|
||||
ColorProcessorPtr ref_to_display,
|
||||
ColorProcessorPtr display_to_ref,
|
||||
ColorProcessorPtr ref_to_input)
|
||||
{
|
||||
input_to_ref_ = input_to_ref;
|
||||
ref_to_display_ = ref_to_display;
|
||||
display_to_ref_ = display_to_ref;
|
||||
ref_to_input_ = ref_to_input;
|
||||
input_to_ref_ = input_to_ref;
|
||||
ref_to_display_ = ref_to_display;
|
||||
display_to_ref_ = display_to_ref;
|
||||
ref_to_input_ = ref_to_input;
|
||||
|
||||
UpdateValuesFromInput();
|
||||
UpdateValuesFromInput();
|
||||
|
||||
preview_->SetColorProcessor(input_to_ref_, ref_to_display_);
|
||||
preview_->SetColorProcessor(input_to_ref_, ref_to_display_);
|
||||
}
|
||||
|
||||
bool ColorValuesWidget::eventFilter(QObject *watcher, QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
// Should signal to Core to stop pixel sampling and to us to remove our event filter
|
||||
bool use_this_color = true;
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
// Should signal to Core to stop pixel sampling and to us to remove our event filter
|
||||
bool use_this_color = true;
|
||||
|
||||
foreach (QWidget *w, ignore_pick_from_) {
|
||||
if (w->underMouse()) {
|
||||
use_this_color = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (QWidget *w, ignore_pick_from_) {
|
||||
if (w->underMouse()) {
|
||||
use_this_color = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_this_color) {
|
||||
picker_end_color_ = GetColor();
|
||||
}
|
||||
color_picker_btn_->setChecked(false);
|
||||
return true;
|
||||
} else if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *key_ev = static_cast<QKeyEvent*>(event);
|
||||
if (use_this_color) {
|
||||
picker_end_color_ = GetColor();
|
||||
}
|
||||
color_picker_btn_->setChecked(false);
|
||||
return true;
|
||||
} else if (event->type() == QEvent::KeyPress) {
|
||||
QKeyEvent *key_ev = static_cast<QKeyEvent *>(event);
|
||||
|
||||
if (key_ev->key() == Qt::Key_Escape) {
|
||||
color_picker_btn_->setChecked(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (key_ev->key() == Qt::Key_Escape) {
|
||||
color_picker_btn_->setChecked(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return QWidget::eventFilter(watcher, event);
|
||||
return QWidget::eventFilter(watcher, event);
|
||||
}
|
||||
|
||||
void ColorValuesWidget::SetColor(const Color &c)
|
||||
{
|
||||
input_tab_->SetColor(c);
|
||||
preview_->SetColor(c);
|
||||
input_tab_->SetColor(c);
|
||||
preview_->SetColor(c);
|
||||
|
||||
UpdateValuesFromInput();
|
||||
UpdateValuesFromInput();
|
||||
}
|
||||
|
||||
void ColorValuesWidget::SetReferenceColor(const Color &c)
|
||||
{
|
||||
reference_tab_->SetColor(c);
|
||||
reference_tab_->SetColor(c);
|
||||
|
||||
UpdateValuesFromRef();
|
||||
UpdateValuesFromRef();
|
||||
}
|
||||
|
||||
void ColorValuesWidget::UpdateValuesFromInput()
|
||||
{
|
||||
UpdateRefFromInput();
|
||||
UpdateDisplayFromRef();
|
||||
UpdateRefFromInput();
|
||||
UpdateDisplayFromRef();
|
||||
}
|
||||
|
||||
void ColorValuesWidget::UpdateValuesFromRef()
|
||||
{
|
||||
UpdateInputFromRef();
|
||||
UpdateDisplayFromRef();
|
||||
UpdateInputFromRef();
|
||||
UpdateDisplayFromRef();
|
||||
}
|
||||
|
||||
void ColorValuesWidget::UpdateValuesFromDisplay()
|
||||
{
|
||||
UpdateRefFromDisplay();
|
||||
UpdateInputFromRef();
|
||||
UpdateRefFromDisplay();
|
||||
UpdateInputFromRef();
|
||||
}
|
||||
|
||||
void ColorValuesWidget::ColorPickedBtnToggled(bool e)
|
||||
{
|
||||
Core::instance()->RequestPixelSamplingInViewers(e);
|
||||
Core::instance()->RequestPixelSamplingInViewers(e);
|
||||
|
||||
if (e) {
|
||||
qApp->installEventFilter(this);
|
||||
if (e) {
|
||||
qApp->installEventFilter(this);
|
||||
|
||||
// Store current color in case it needs to be restored
|
||||
picker_end_color_ = GetColor();
|
||||
} else {
|
||||
qApp->removeEventFilter(this);
|
||||
// Store current color in case it needs to be restored
|
||||
picker_end_color_ = GetColor();
|
||||
} else {
|
||||
qApp->removeEventFilter(this);
|
||||
|
||||
// Restore original color (or use overridden color from eventFilter)
|
||||
SetReferenceColor(picker_end_color_);
|
||||
emit ColorChanged(input_tab_->GetColor());
|
||||
}
|
||||
// Restore original color (or use overridden color from eventFilter)
|
||||
SetReferenceColor(picker_end_color_);
|
||||
emit ColorChanged(input_tab_->GetColor());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorValuesWidget::UpdateInputFromRef()
|
||||
{
|
||||
if (ref_to_input_) {
|
||||
input_tab_->SetColor(ref_to_input_->ConvertColor(reference_tab_->GetColor()));
|
||||
} else {
|
||||
input_tab_->SetColor(reference_tab_->GetColor());
|
||||
}
|
||||
if (ref_to_input_) {
|
||||
input_tab_->SetColor(
|
||||
ref_to_input_->ConvertColor(reference_tab_->GetColor()));
|
||||
} else {
|
||||
input_tab_->SetColor(reference_tab_->GetColor());
|
||||
}
|
||||
|
||||
preview_->SetColor(input_tab_->GetColor());
|
||||
emit ColorChanged(input_tab_->GetColor());
|
||||
preview_->SetColor(input_tab_->GetColor());
|
||||
emit ColorChanged(input_tab_->GetColor());
|
||||
}
|
||||
|
||||
void ColorValuesWidget::UpdateDisplayFromRef()
|
||||
{
|
||||
if (ref_to_display_) {
|
||||
display_tab_->SetColor(ref_to_display_->ConvertColor(reference_tab_->GetColor()));
|
||||
} else {
|
||||
display_tab_->SetColor(reference_tab_->GetColor());
|
||||
}
|
||||
if (ref_to_display_) {
|
||||
display_tab_->SetColor(
|
||||
ref_to_display_->ConvertColor(reference_tab_->GetColor()));
|
||||
} else {
|
||||
display_tab_->SetColor(reference_tab_->GetColor());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorValuesWidget::UpdateRefFromInput()
|
||||
{
|
||||
if (input_to_ref_) {
|
||||
reference_tab_->SetColor(input_to_ref_->ConvertColor(input_tab_->GetColor()));
|
||||
} else {
|
||||
reference_tab_->SetColor(input_tab_->GetColor());
|
||||
}
|
||||
if (input_to_ref_) {
|
||||
reference_tab_->SetColor(
|
||||
input_to_ref_->ConvertColor(input_tab_->GetColor()));
|
||||
} else {
|
||||
reference_tab_->SetColor(input_tab_->GetColor());
|
||||
}
|
||||
}
|
||||
|
||||
void ColorValuesWidget::UpdateRefFromDisplay()
|
||||
{
|
||||
if (display_to_ref_) {
|
||||
reference_tab_->SetColor(display_to_ref_->ConvertColor(display_tab_->GetColor()));
|
||||
} else {
|
||||
reference_tab_->SetColor(display_tab_->GetColor());
|
||||
}
|
||||
if (display_to_ref_) {
|
||||
reference_tab_->SetColor(
|
||||
display_to_ref_->ConvertColor(display_tab_->GetColor()));
|
||||
} else {
|
||||
reference_tab_->SetColor(display_tab_->GetColor());
|
||||
}
|
||||
}
|
||||
|
||||
const double ColorValuesTab::kLegacyMultiplier = 255.0;
|
||||
|
||||
ColorValuesTab::ColorValuesTab(bool with_legacy_option, QWidget *parent) :
|
||||
QWidget(parent)
|
||||
ColorValuesTab::ColorValuesTab(bool with_legacy_option, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QGridLayout* layout = new QGridLayout(this);
|
||||
QGridLayout *layout = new QGridLayout(this);
|
||||
|
||||
int row = 0;
|
||||
int row = 0;
|
||||
|
||||
if (with_legacy_option) {
|
||||
legacy_box_ = new QCheckBox(tr("Use legacy (8-bit) values"));
|
||||
legacy_box_->setChecked(OLIVE_CONFIG("UseLegacyColorInInputTab").toBool());
|
||||
connect(legacy_box_, &QCheckBox::clicked, this, &ColorValuesTab::LegacyChanged);
|
||||
layout->addWidget(legacy_box_, row, 0, 1, 2);
|
||||
row++;
|
||||
} else {
|
||||
legacy_box_ = nullptr;
|
||||
}
|
||||
if (with_legacy_option) {
|
||||
legacy_box_ = new QCheckBox(tr("Use legacy (8-bit) values"));
|
||||
legacy_box_->setChecked(
|
||||
OLIVE_CONFIG("UseLegacyColorInInputTab").toBool());
|
||||
connect(legacy_box_, &QCheckBox::clicked, this,
|
||||
&ColorValuesTab::LegacyChanged);
|
||||
layout->addWidget(legacy_box_, row, 0, 1, 2);
|
||||
row++;
|
||||
} else {
|
||||
legacy_box_ = nullptr;
|
||||
}
|
||||
|
||||
sliders_.resize(3);
|
||||
sliders_.resize(3);
|
||||
|
||||
layout->addWidget(new QLabel(tr("Red")), row, 0);
|
||||
layout->addWidget(new QLabel(tr("Red")), row, 0);
|
||||
|
||||
red_slider_ = CreateColorSlider();
|
||||
sliders_[0] = red_slider_;
|
||||
layout->addWidget(red_slider_, row, 1);
|
||||
red_slider_ = CreateColorSlider();
|
||||
sliders_[0] = red_slider_;
|
||||
layout->addWidget(red_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
row++;
|
||||
|
||||
layout->addWidget(new QLabel(tr("Green")), row, 0);
|
||||
layout->addWidget(new QLabel(tr("Green")), row, 0);
|
||||
|
||||
green_slider_ = CreateColorSlider();
|
||||
sliders_[1] = green_slider_;
|
||||
layout->addWidget(green_slider_, row, 1);
|
||||
green_slider_ = CreateColorSlider();
|
||||
sliders_[1] = green_slider_;
|
||||
layout->addWidget(green_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
row++;
|
||||
|
||||
layout->addWidget(new QLabel(tr("Blue")), row, 0);
|
||||
layout->addWidget(new QLabel(tr("Blue")), row, 0);
|
||||
|
||||
blue_slider_ = CreateColorSlider();
|
||||
sliders_[2] = blue_slider_;
|
||||
layout->addWidget(blue_slider_, row, 1);
|
||||
blue_slider_ = CreateColorSlider();
|
||||
sliders_[2] = blue_slider_;
|
||||
layout->addWidget(blue_slider_, row, 1);
|
||||
|
||||
row++;
|
||||
row++;
|
||||
|
||||
hex_lbl_ = new QLabel(tr("Web"));
|
||||
layout->addWidget(hex_lbl_, row, 0);
|
||||
hex_lbl_ = new QLabel(tr("Web"));
|
||||
layout->addWidget(hex_lbl_, row, 0);
|
||||
|
||||
hex_slider_ = new StringSlider();
|
||||
connect(hex_slider_, &StringSlider::ValueChanged, this, &ColorValuesTab::HexChanged);
|
||||
layout->addWidget(hex_slider_, row, 1);
|
||||
hex_slider_ = new StringSlider();
|
||||
connect(hex_slider_, &StringSlider::ValueChanged, this,
|
||||
&ColorValuesTab::HexChanged);
|
||||
layout->addWidget(hex_slider_, row, 1);
|
||||
|
||||
if (legacy_box_) {
|
||||
LegacyChanged(AreSlidersLegacyValues());
|
||||
}
|
||||
if (legacy_box_) {
|
||||
LegacyChanged(AreSlidersLegacyValues());
|
||||
}
|
||||
}
|
||||
|
||||
Color ColorValuesTab::GetColor() const
|
||||
{
|
||||
return Color(GetRed(), GetGreen(), GetBlue());
|
||||
return Color(GetRed(), GetGreen(), GetBlue());
|
||||
}
|
||||
|
||||
void ColorValuesTab::SetColor(const Color &c)
|
||||
{
|
||||
SetRed(c.red());
|
||||
SetGreen(c.green());
|
||||
SetBlue(c.blue());
|
||||
SetRed(c.red());
|
||||
SetGreen(c.green());
|
||||
SetBlue(c.blue());
|
||||
}
|
||||
|
||||
double ColorValuesTab::GetRed() const
|
||||
{
|
||||
return GetValueInternal(red_slider_);
|
||||
return GetValueInternal(red_slider_);
|
||||
}
|
||||
|
||||
double ColorValuesTab::GetGreen() const
|
||||
{
|
||||
return GetValueInternal(green_slider_);
|
||||
return GetValueInternal(green_slider_);
|
||||
}
|
||||
|
||||
double ColorValuesTab::GetBlue() const
|
||||
{
|
||||
return GetValueInternal(blue_slider_);
|
||||
return GetValueInternal(blue_slider_);
|
||||
}
|
||||
|
||||
void ColorValuesTab::SetRed(double r)
|
||||
{
|
||||
SetValueInternal(red_slider_, r);
|
||||
SetValueInternal(red_slider_, r);
|
||||
}
|
||||
|
||||
void ColorValuesTab::SetGreen(double g)
|
||||
{
|
||||
SetValueInternal(green_slider_, g);
|
||||
SetValueInternal(green_slider_, g);
|
||||
}
|
||||
|
||||
void ColorValuesTab::SetBlue(double b)
|
||||
{
|
||||
SetValueInternal(blue_slider_, b);
|
||||
SetValueInternal(blue_slider_, b);
|
||||
}
|
||||
|
||||
double ColorValuesTab::GetValueInternal(FloatSlider *slider) const
|
||||
{
|
||||
double d = slider->GetValue();
|
||||
double d = slider->GetValue();
|
||||
|
||||
if (AreSlidersLegacyValues()) {
|
||||
d /= kLegacyMultiplier;
|
||||
}
|
||||
if (AreSlidersLegacyValues()) {
|
||||
d /= kLegacyMultiplier;
|
||||
}
|
||||
|
||||
return d;
|
||||
return d;
|
||||
}
|
||||
|
||||
void ColorValuesTab::SetValueInternal(FloatSlider *slider, double v)
|
||||
{
|
||||
if (AreSlidersLegacyValues()) {
|
||||
v *= kLegacyMultiplier;
|
||||
}
|
||||
if (AreSlidersLegacyValues()) {
|
||||
v *= kLegacyMultiplier;
|
||||
}
|
||||
|
||||
slider->SetValue(v);
|
||||
UpdateHex();
|
||||
slider->SetValue(v);
|
||||
UpdateHex();
|
||||
}
|
||||
|
||||
FloatSlider *ColorValuesTab::CreateColorSlider()
|
||||
{
|
||||
FloatSlider* fs = new FloatSlider();
|
||||
fs->SetLadderElementCount(1);
|
||||
connect(fs, &FloatSlider::ValueChanged, this, &ColorValuesTab::SliderChanged);
|
||||
return fs;
|
||||
FloatSlider *fs = new FloatSlider();
|
||||
fs->SetLadderElementCount(1);
|
||||
connect(fs, &FloatSlider::ValueChanged, this,
|
||||
&ColorValuesTab::SliderChanged);
|
||||
return fs;
|
||||
}
|
||||
|
||||
void ColorValuesTab::SliderChanged()
|
||||
{
|
||||
emit ColorChanged(GetColor());
|
||||
UpdateHex();
|
||||
emit ColorChanged(GetColor());
|
||||
UpdateHex();
|
||||
}
|
||||
|
||||
void ColorValuesTab::LegacyChanged(bool legacy)
|
||||
{
|
||||
OLIVE_CONFIG("UseLegacyColorInInputTab") = legacy;
|
||||
OLIVE_CONFIG("UseLegacyColorInInputTab") = legacy;
|
||||
|
||||
double legacy_multiplier = legacy ? kLegacyMultiplier : 1.0/kLegacyMultiplier;
|
||||
int decimal_places = legacy ? 0 : 5;
|
||||
double drag_multiplier = legacy ? 1.0 : 0.01;
|
||||
double legacy_multiplier = legacy ? kLegacyMultiplier :
|
||||
1.0 / kLegacyMultiplier;
|
||||
int decimal_places = legacy ? 0 : 5;
|
||||
double drag_multiplier = legacy ? 1.0 : 0.01;
|
||||
|
||||
foreach (FloatSlider *s, sliders_) {
|
||||
s->SetValue(s->GetValue() * legacy_multiplier);
|
||||
s->SetDecimalPlaces(decimal_places);
|
||||
s->SetDragMultiplier(drag_multiplier);
|
||||
}
|
||||
foreach (FloatSlider *s, sliders_) {
|
||||
s->SetValue(s->GetValue() * legacy_multiplier);
|
||||
s->SetDecimalPlaces(decimal_places);
|
||||
s->SetDragMultiplier(drag_multiplier);
|
||||
}
|
||||
|
||||
UpdateHex();
|
||||
UpdateHex();
|
||||
}
|
||||
|
||||
QString RGBValToString(double d)
|
||||
{
|
||||
QString s = QString::number(d);
|
||||
QString s = QString::number(d);
|
||||
|
||||
if (!s.contains('.')) {
|
||||
s.append(QStringLiteral(".0"));
|
||||
}
|
||||
if (!s.contains('.')) {
|
||||
s.append(QStringLiteral(".0"));
|
||||
}
|
||||
|
||||
return s;
|
||||
return s;
|
||||
}
|
||||
|
||||
void ColorValuesTab::UpdateHex()
|
||||
{
|
||||
if (AreSlidersLegacyValues()) {
|
||||
double r = red_slider_->GetValue();
|
||||
double g = green_slider_->GetValue();
|
||||
double b = blue_slider_->GetValue();
|
||||
if (AreSlidersLegacyValues()) {
|
||||
double r = red_slider_->GetValue();
|
||||
double g = green_slider_->GetValue();
|
||||
double b = blue_slider_->GetValue();
|
||||
|
||||
if (r > kLegacyMultiplier || g > kLegacyMultiplier || b > kLegacyMultiplier) {
|
||||
hex_slider_->SetValue(tr("(Invalid)"));
|
||||
} else {
|
||||
uint32_t rgb = (uint8_t(r) << 16) | (uint8_t(g) << 8) | uint8_t(b);
|
||||
if (r > kLegacyMultiplier || g > kLegacyMultiplier ||
|
||||
b > kLegacyMultiplier) {
|
||||
hex_slider_->SetValue(tr("(Invalid)"));
|
||||
} else {
|
||||
uint32_t rgb = (uint8_t(r) << 16) | (uint8_t(g) << 8) | uint8_t(b);
|
||||
|
||||
hex_slider_->SetValue(QStringLiteral("%1").arg(rgb, 6, 16, QLatin1Char('0')).toUpper());
|
||||
}
|
||||
} else {
|
||||
hex_slider_->SetValue(QStringLiteral("rgb(%1, %2, %3)").arg(RGBValToString(red_slider_->GetValue()), RGBValToString(green_slider_->GetValue()), RGBValToString(blue_slider_->GetValue())));
|
||||
}
|
||||
hex_slider_->SetValue(QStringLiteral("%1")
|
||||
.arg(rgb, 6, 16, QLatin1Char('0'))
|
||||
.toUpper());
|
||||
}
|
||||
} else {
|
||||
hex_slider_->SetValue(
|
||||
QStringLiteral("rgb(%1, %2, %3)")
|
||||
.arg(RGBValToString(red_slider_->GetValue()),
|
||||
RGBValToString(green_slider_->GetValue()),
|
||||
RGBValToString(blue_slider_->GetValue())));
|
||||
}
|
||||
}
|
||||
|
||||
bool ParseRGBString(QString s, double *r, double *g, double *b)
|
||||
{
|
||||
// Trim whitespace
|
||||
s = s.trimmed();
|
||||
// Trim whitespace
|
||||
s = s.trimmed();
|
||||
|
||||
s.remove(QStringLiteral("rgba"), Qt::CaseInsensitive);
|
||||
s.remove(QStringLiteral("rgb"), Qt::CaseInsensitive);
|
||||
s.remove('(');
|
||||
s.remove(')');
|
||||
s.remove(QStringLiteral("rgba"), Qt::CaseInsensitive);
|
||||
s.remove(QStringLiteral("rgb"), Qt::CaseInsensitive);
|
||||
s.remove('(');
|
||||
s.remove(')');
|
||||
|
||||
QStringList vals = s.split(',');
|
||||
if (vals.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
QStringList vals = s.split(',');
|
||||
if (vals.size() < 3) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
*r = vals.at(0).toDouble(&ok);
|
||||
if (!ok) return false;
|
||||
bool ok;
|
||||
*r = vals.at(0).toDouble(&ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
*g = vals.at(1).toDouble(&ok);
|
||||
if (!ok) return false;
|
||||
*g = vals.at(1).toDouble(&ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
*b = vals.at(2).toDouble(&ok);
|
||||
if (!ok) return false;
|
||||
*b = vals.at(2).toDouble(&ok);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ColorValuesTab::HexChanged(const QString &s)
|
||||
{
|
||||
bool ok;
|
||||
uint32_t hex = s.toULong(&ok, 16);
|
||||
bool ok;
|
||||
uint32_t hex = s.toULong(&ok, 16);
|
||||
|
||||
if (ok) {
|
||||
if (hex >= 0x1000000) {
|
||||
hex >>= 8;
|
||||
}
|
||||
if (ok) {
|
||||
if (hex >= 0x1000000) {
|
||||
hex >>= 8;
|
||||
}
|
||||
|
||||
uint32_t r = (hex & 0xFF0000) >> 16;
|
||||
uint32_t g = (hex & 0x00FF00) >> 8;
|
||||
uint32_t b = (hex & 0x0000FF);
|
||||
uint32_t r = (hex & 0xFF0000) >> 16;
|
||||
uint32_t g = (hex & 0x00FF00) >> 8;
|
||||
uint32_t b = (hex & 0x0000FF);
|
||||
|
||||
if (AreSlidersLegacyValues()) {
|
||||
red_slider_->SetValue(r);
|
||||
green_slider_->SetValue(g);
|
||||
blue_slider_->SetValue(b);
|
||||
} else {
|
||||
red_slider_->SetValue(double(r)/kLegacyMultiplier);
|
||||
green_slider_->SetValue(double(g)/kLegacyMultiplier);
|
||||
blue_slider_->SetValue(double(b)/kLegacyMultiplier);
|
||||
}
|
||||
if (AreSlidersLegacyValues()) {
|
||||
red_slider_->SetValue(r);
|
||||
green_slider_->SetValue(g);
|
||||
blue_slider_->SetValue(b);
|
||||
} else {
|
||||
red_slider_->SetValue(double(r) / kLegacyMultiplier);
|
||||
green_slider_->SetValue(double(g) / kLegacyMultiplier);
|
||||
blue_slider_->SetValue(double(b) / kLegacyMultiplier);
|
||||
}
|
||||
|
||||
emit ColorChanged(GetColor());
|
||||
} else {
|
||||
// Attempt to parse rgb/rgba
|
||||
double r, g, b;
|
||||
if (ParseRGBString(s, &r, &g, &b)) {
|
||||
if (AreSlidersLegacyValues()) {
|
||||
red_slider_->SetValue(r*kLegacyMultiplier);
|
||||
green_slider_->SetValue(g*kLegacyMultiplier);
|
||||
blue_slider_->SetValue(b*kLegacyMultiplier);
|
||||
} else {
|
||||
red_slider_->SetValue(r);
|
||||
green_slider_->SetValue(g);
|
||||
blue_slider_->SetValue(b);
|
||||
}
|
||||
emit ColorChanged(GetColor());
|
||||
} else {
|
||||
// Attempt to parse rgb/rgba
|
||||
double r, g, b;
|
||||
if (ParseRGBString(s, &r, &g, &b)) {
|
||||
if (AreSlidersLegacyValues()) {
|
||||
red_slider_->SetValue(r * kLegacyMultiplier);
|
||||
green_slider_->SetValue(g * kLegacyMultiplier);
|
||||
blue_slider_->SetValue(b * kLegacyMultiplier);
|
||||
} else {
|
||||
red_slider_->SetValue(r);
|
||||
green_slider_->SetValue(g);
|
||||
blue_slider_->SetValue(b);
|
||||
}
|
||||
|
||||
emit ColorChanged(GetColor());
|
||||
}
|
||||
}
|
||||
emit ColorChanged(GetColor());
|
||||
}
|
||||
}
|
||||
|
||||
// Conform string to our formatting
|
||||
UpdateHex();
|
||||
// Conform string to our formatting
|
||||
UpdateHex();
|
||||
}
|
||||
|
||||
bool ColorValuesTab::AreSlidersLegacyValues() const
|
||||
{
|
||||
return legacy_box_ && legacy_box_->isChecked();
|
||||
return legacy_box_ && legacy_box_->isChecked();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,130 +30,127 @@
|
||||
#include "widget/slider/floatslider.h"
|
||||
#include "widget/slider/stringslider.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorValuesTab : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ColorValuesTab : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorValuesTab(bool with_legacy_option = false, QWidget* parent = nullptr);
|
||||
ColorValuesTab(bool with_legacy_option = false, QWidget *parent = nullptr);
|
||||
|
||||
Color GetColor() const;
|
||||
Color GetColor() const;
|
||||
|
||||
void SetColor(const Color& c);
|
||||
void SetColor(const Color &c);
|
||||
|
||||
double GetRed() const;
|
||||
double GetGreen() const;
|
||||
double GetBlue() const;
|
||||
void SetRed(double r);
|
||||
void SetGreen(double g);
|
||||
void SetBlue(double b);
|
||||
double GetRed() const;
|
||||
double GetGreen() const;
|
||||
double GetBlue() const;
|
||||
void SetRed(double r);
|
||||
void SetGreen(double g);
|
||||
void SetBlue(double b);
|
||||
|
||||
signals:
|
||||
void ColorChanged(const Color& c);
|
||||
void ColorChanged(const Color &c);
|
||||
|
||||
private:
|
||||
static const double kLegacyMultiplier;
|
||||
static const double kLegacyMultiplier;
|
||||
|
||||
double GetValueInternal(FloatSlider *slider) const;
|
||||
void SetValueInternal(FloatSlider *slider, double v);
|
||||
double GetValueInternal(FloatSlider *slider) const;
|
||||
void SetValueInternal(FloatSlider *slider, double v);
|
||||
|
||||
bool AreSlidersLegacyValues() const;
|
||||
bool AreSlidersLegacyValues() const;
|
||||
|
||||
FloatSlider* CreateColorSlider();
|
||||
FloatSlider *CreateColorSlider();
|
||||
|
||||
FloatSlider* red_slider_;
|
||||
FloatSlider* green_slider_;
|
||||
FloatSlider* blue_slider_;
|
||||
FloatSlider *red_slider_;
|
||||
FloatSlider *green_slider_;
|
||||
FloatSlider *blue_slider_;
|
||||
|
||||
QLabel *hex_lbl_;
|
||||
StringSlider *hex_slider_;
|
||||
QLabel *hex_lbl_;
|
||||
StringSlider *hex_slider_;
|
||||
|
||||
QVector<FloatSlider*> sliders_;
|
||||
QVector<FloatSlider *> sliders_;
|
||||
|
||||
QCheckBox *legacy_box_;
|
||||
QCheckBox *legacy_box_;
|
||||
|
||||
private slots:
|
||||
void SliderChanged();
|
||||
void SliderChanged();
|
||||
|
||||
void LegacyChanged(bool e);
|
||||
void LegacyChanged(bool e);
|
||||
|
||||
void UpdateHex();
|
||||
|
||||
void HexChanged(const QString &s);
|
||||
void UpdateHex();
|
||||
|
||||
void HexChanged(const QString &s);
|
||||
};
|
||||
|
||||
class ColorValuesWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class ColorValuesWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorValuesWidget(ColorManager* manager, QWidget* parent = nullptr);
|
||||
ColorValuesWidget(ColorManager *manager, QWidget *parent = nullptr);
|
||||
|
||||
Color GetColor() const;
|
||||
Color GetColor() const;
|
||||
|
||||
void SetColorProcessor(ColorProcessorPtr input_to_ref,
|
||||
ColorProcessorPtr ref_to_display,
|
||||
ColorProcessorPtr display_to_ref,
|
||||
ColorProcessorPtr ref_to_input);
|
||||
void SetColorProcessor(ColorProcessorPtr input_to_ref,
|
||||
ColorProcessorPtr ref_to_display,
|
||||
ColorProcessorPtr display_to_ref,
|
||||
ColorProcessorPtr ref_to_input);
|
||||
|
||||
virtual bool eventFilter(QObject *watcher, QEvent *event) override;
|
||||
virtual bool eventFilter(QObject *watcher, QEvent *event) override;
|
||||
|
||||
void IgnorePickFrom(QWidget *w)
|
||||
{
|
||||
ignore_pick_from_.append(w);
|
||||
}
|
||||
void IgnorePickFrom(QWidget *w)
|
||||
{
|
||||
ignore_pick_from_.append(w);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetColor(const Color& c);
|
||||
void SetColor(const Color &c);
|
||||
|
||||
void SetReferenceColor(const Color& c);
|
||||
void SetReferenceColor(const Color &c);
|
||||
|
||||
signals:
|
||||
void ColorChanged(const Color& c);
|
||||
void ColorChanged(const Color &c);
|
||||
|
||||
private:
|
||||
void UpdateInputFromRef();
|
||||
void UpdateInputFromRef();
|
||||
|
||||
void UpdateDisplayFromRef();
|
||||
void UpdateDisplayFromRef();
|
||||
|
||||
void UpdateRefFromInput();
|
||||
void UpdateRefFromInput();
|
||||
|
||||
void UpdateRefFromDisplay();
|
||||
void UpdateRefFromDisplay();
|
||||
|
||||
ColorManager* manager_;
|
||||
ColorManager *manager_;
|
||||
|
||||
ColorPreviewBox* preview_;
|
||||
ColorPreviewBox *preview_;
|
||||
|
||||
ColorValuesTab* input_tab_;
|
||||
ColorValuesTab *input_tab_;
|
||||
|
||||
ColorValuesTab* reference_tab_;
|
||||
ColorValuesTab *reference_tab_;
|
||||
|
||||
ColorValuesTab* display_tab_;
|
||||
ColorValuesTab *display_tab_;
|
||||
|
||||
ColorProcessorPtr input_to_ref_;
|
||||
ColorProcessorPtr input_to_ref_;
|
||||
|
||||
ColorProcessorPtr ref_to_display_;
|
||||
ColorProcessorPtr ref_to_display_;
|
||||
|
||||
ColorProcessorPtr display_to_ref_;
|
||||
ColorProcessorPtr display_to_ref_;
|
||||
|
||||
ColorProcessorPtr ref_to_input_;
|
||||
ColorProcessorPtr ref_to_input_;
|
||||
|
||||
QPushButton *color_picker_btn_;
|
||||
QPushButton *color_picker_btn_;
|
||||
|
||||
Color picker_end_color_;
|
||||
Color picker_end_color_;
|
||||
|
||||
QVector<QWidget *> ignore_pick_from_;
|
||||
QVector<QWidget *> ignore_pick_from_;
|
||||
|
||||
private slots:
|
||||
void UpdateValuesFromInput();
|
||||
void UpdateValuesFromInput();
|
||||
|
||||
void UpdateValuesFromRef();
|
||||
void UpdateValuesFromRef();
|
||||
|
||||
void UpdateValuesFromDisplay();
|
||||
|
||||
void ColorPickedBtnToggled(bool e);
|
||||
void UpdateValuesFromDisplay();
|
||||
|
||||
void ColorPickedBtnToggled(bool e);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,155 +25,160 @@
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define M_180_OVER_PI 57.295791433133264917914229473464
|
||||
#define M_RADIAN_TO_0_1 0.15915497620314795810531730409296
|
||||
|
||||
ColorWheelWidget::ColorWheelWidget(QWidget *parent) :
|
||||
ColorSwatchWidget(parent),
|
||||
val_(1.0f),
|
||||
force_redraw_(false)
|
||||
ColorWheelWidget::ColorWheelWidget(QWidget *parent)
|
||||
: ColorSwatchWidget(parent)
|
||||
, val_(1.0f)
|
||||
, force_redraw_(false)
|
||||
{
|
||||
}
|
||||
|
||||
Color ColorWheelWidget::GetColorFromScreenPos(const QPoint &p) const
|
||||
{
|
||||
return GetColorFromTriangle(GetTriangleFromCoords(rect().center(), p));
|
||||
return GetColorFromTriangle(GetTriangleFromCoords(rect().center(), p));
|
||||
}
|
||||
|
||||
void ColorWheelWidget::resizeEvent(QResizeEvent *e)
|
||||
{
|
||||
ColorSwatchWidget::resizeEvent(e);
|
||||
ColorSwatchWidget::resizeEvent(e);
|
||||
|
||||
emit DiameterChanged(GetDiameter());
|
||||
emit DiameterChanged(GetDiameter());
|
||||
}
|
||||
|
||||
void ColorWheelWidget::paintEvent(QPaintEvent *e)
|
||||
{
|
||||
ColorSwatchWidget::paintEvent(e);
|
||||
ColorSwatchWidget::paintEvent(e);
|
||||
|
||||
int diameter = GetDiameter();
|
||||
int diameter = GetDiameter();
|
||||
|
||||
// Half diameter
|
||||
int radius = diameter / 2;
|
||||
// Half diameter
|
||||
int radius = diameter / 2;
|
||||
|
||||
if (cached_wheel_.width() != diameter || force_redraw_) {
|
||||
cached_wheel_ = QPixmap(QSize(diameter, diameter));
|
||||
cached_wheel_.fill(Qt::transparent);
|
||||
force_redraw_ = false;
|
||||
if (cached_wheel_.width() != diameter || force_redraw_) {
|
||||
cached_wheel_ = QPixmap(QSize(diameter, diameter));
|
||||
cached_wheel_.fill(Qt::transparent);
|
||||
force_redraw_ = false;
|
||||
|
||||
QPainter p(&cached_wheel_);
|
||||
QPoint center(radius, radius);
|
||||
QPainter p(&cached_wheel_);
|
||||
QPoint center(radius, radius);
|
||||
|
||||
for (int i=0;i<diameter;i++) {
|
||||
for (int j=0;j<diameter;j++) {
|
||||
Triangle tri = GetTriangleFromCoords(center, j, i);
|
||||
for (int i = 0; i < diameter; i++) {
|
||||
for (int j = 0; j < diameter; j++) {
|
||||
Triangle tri = GetTriangleFromCoords(center, j, i);
|
||||
|
||||
if (tri.hypotenuse <= radius) {
|
||||
Color managed = GetManagedColor(GetColorFromTriangle(tri));
|
||||
QColor c = QtUtils::toQColor(managed);
|
||||
if (tri.hypotenuse <= radius) {
|
||||
Color managed = GetManagedColor(GetColorFromTriangle(tri));
|
||||
QColor c = QtUtils::toQColor(managed);
|
||||
|
||||
// Very basic antialiasing around the edges of the wheel
|
||||
qreal alpha = qMin(1.0, radius - tri.hypotenuse);
|
||||
c.setAlphaF(alpha);
|
||||
// Very basic antialiasing around the edges of the wheel
|
||||
qreal alpha = qMin(1.0, radius - tri.hypotenuse);
|
||||
c.setAlphaF(alpha);
|
||||
|
||||
p.setPen(c);
|
||||
p.setPen(c);
|
||||
|
||||
p.drawPoint(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
p.drawPoint(i, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QPainter p(this);
|
||||
QPainter p(this);
|
||||
|
||||
// Draw wheel pixmap
|
||||
int x, y;
|
||||
// Draw wheel pixmap
|
||||
int x, y;
|
||||
|
||||
if (width() == height()) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else if (width() > height()) {
|
||||
x = (width() - height()) / 2;
|
||||
y = 0;
|
||||
} else {
|
||||
x = 0;
|
||||
y = (height() - width()) / 2;
|
||||
}
|
||||
if (width() == height()) {
|
||||
x = 0;
|
||||
y = 0;
|
||||
} else if (width() > height()) {
|
||||
x = (width() - height()) / 2;
|
||||
y = 0;
|
||||
} else {
|
||||
x = 0;
|
||||
y = (height() - width()) / 2;
|
||||
}
|
||||
|
||||
p.drawPixmap(x, y, cached_wheel_);
|
||||
p.drawPixmap(x, y, cached_wheel_);
|
||||
|
||||
// Draw selection
|
||||
// Really rough algorithm for determining whether the selector UI should be white or black
|
||||
|
||||
// Draw selection
|
||||
// Really rough algorithm for determining whether the selector UI should be white or black
|
||||
int selector_radius = qMax(1, radius / 32);
|
||||
p.setPen(QPen(GetUISelectorColor(), qMax(1, selector_radius / 4)));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
|
||||
int selector_radius = qMax(1, radius / 32);
|
||||
p.setPen(QPen(GetUISelectorColor(), qMax(1, selector_radius / 4)));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
p.drawEllipse(GetCoordsFromColor(GetSelectedColor()), selector_radius, selector_radius);
|
||||
p.drawEllipse(GetCoordsFromColor(GetSelectedColor()), selector_radius,
|
||||
selector_radius);
|
||||
}
|
||||
|
||||
void ColorWheelWidget::SelectedColorChangedEvent(const Color &c, bool external)
|
||||
{
|
||||
if (external) {
|
||||
force_redraw_ = true;
|
||||
val_ = std::clamp(c.value(), 0.0f, 1.0f);
|
||||
}
|
||||
if (external) {
|
||||
force_redraw_ = true;
|
||||
val_ = std::clamp(c.value(), 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int ColorWheelWidget::GetDiameter() const
|
||||
{
|
||||
return qMin(width(), height());
|
||||
return qMin(width(), height());
|
||||
}
|
||||
|
||||
qreal ColorWheelWidget::GetRadius() const
|
||||
{
|
||||
return GetDiameter() * 0.5;
|
||||
return GetDiameter() * 0.5;
|
||||
}
|
||||
|
||||
ColorWheelWidget::Triangle ColorWheelWidget::GetTriangleFromCoords(const QPoint ¢er, const QPoint &p) const
|
||||
ColorWheelWidget::Triangle
|
||||
ColorWheelWidget::GetTriangleFromCoords(const QPoint ¢er,
|
||||
const QPoint &p) const
|
||||
{
|
||||
return GetTriangleFromCoords(center, p.y(), p.x());
|
||||
return GetTriangleFromCoords(center, p.y(), p.x());
|
||||
}
|
||||
|
||||
ColorWheelWidget::Triangle ColorWheelWidget::GetTriangleFromCoords(const QPoint ¢er, qreal y, qreal x) const
|
||||
ColorWheelWidget::Triangle
|
||||
ColorWheelWidget::GetTriangleFromCoords(const QPoint ¢er, qreal y,
|
||||
qreal x) const
|
||||
{
|
||||
qreal opposite = y - center.y();
|
||||
qreal adjacent = x - center.x();
|
||||
qreal hypotenuse = qSqrt(qPow(adjacent, 2) + qPow(opposite, 2));
|
||||
qreal opposite = y - center.y();
|
||||
qreal adjacent = x - center.x();
|
||||
qreal hypotenuse = qSqrt(qPow(adjacent, 2) + qPow(opposite, 2));
|
||||
|
||||
return {opposite, adjacent, hypotenuse};
|
||||
return { opposite, adjacent, hypotenuse };
|
||||
}
|
||||
|
||||
Color ColorWheelWidget::GetColorFromTriangle(const ColorWheelWidget::Triangle &tri) const
|
||||
Color ColorWheelWidget::GetColorFromTriangle(
|
||||
const ColorWheelWidget::Triangle &tri) const
|
||||
{
|
||||
qreal hue = qAtan2(tri.opposite, tri.adjacent) * M_180_OVER_PI + 180.0;
|
||||
qreal sat = qMin(1.0, (tri.hypotenuse / GetRadius()));
|
||||
qreal hue = qAtan2(tri.opposite, tri.adjacent) * M_180_OVER_PI + 180.0;
|
||||
qreal sat = qMin(1.0, (tri.hypotenuse / GetRadius()));
|
||||
|
||||
return Color::fromHsv(hue, sat, val_);
|
||||
return Color::fromHsv(hue, sat, val_);
|
||||
}
|
||||
|
||||
QPoint ColorWheelWidget::GetCoordsFromColor(const Color &c) const
|
||||
{
|
||||
float hue, sat, val;
|
||||
c.toHsv(&hue, &sat, &val);
|
||||
float hue, sat, val;
|
||||
c.toHsv(&hue, &sat, &val);
|
||||
|
||||
qreal hypotenuse = sat * GetRadius();
|
||||
qreal hypotenuse = sat * GetRadius();
|
||||
|
||||
qreal radian_angle = (hue - 180.0) / M_180_OVER_PI;
|
||||
qreal radian_angle = (hue - 180.0) / M_180_OVER_PI;
|
||||
|
||||
qreal opposite = qSin(radian_angle) * hypotenuse;
|
||||
qreal opposite = qSin(radian_angle) * hypotenuse;
|
||||
|
||||
qreal adjacent = qCos(radian_angle) * hypotenuse;
|
||||
qreal adjacent = qCos(radian_angle) * hypotenuse;
|
||||
|
||||
QPoint pos(qRound(adjacent), qRound(opposite));
|
||||
QPoint pos(qRound(adjacent), qRound(opposite));
|
||||
|
||||
pos += rect().center();
|
||||
pos += rect().center();
|
||||
|
||||
return pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,49 +25,50 @@
|
||||
|
||||
#include "colorswatchwidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class ColorWheelWidget : public ColorSwatchWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class ColorWheelWidget : public ColorSwatchWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorWheelWidget(QWidget* parent = nullptr);
|
||||
ColorWheelWidget(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void DiameterChanged(int radius);
|
||||
void DiameterChanged(int radius);
|
||||
|
||||
protected:
|
||||
virtual Color GetColorFromScreenPos(const QPoint& p) const override;
|
||||
virtual Color GetColorFromScreenPos(const QPoint &p) const override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent* e) override;
|
||||
virtual void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
virtual void paintEvent(QPaintEvent* e) override;
|
||||
virtual void paintEvent(QPaintEvent *e) override;
|
||||
|
||||
virtual void SelectedColorChangedEvent(const Color& c, bool external) override;
|
||||
virtual void SelectedColorChangedEvent(const Color &c,
|
||||
bool external) override;
|
||||
|
||||
private:
|
||||
int GetDiameter() const;
|
||||
int GetDiameter() const;
|
||||
|
||||
qreal GetRadius() const;
|
||||
qreal GetRadius() const;
|
||||
|
||||
struct Triangle {
|
||||
qreal opposite;
|
||||
qreal adjacent;
|
||||
qreal hypotenuse;
|
||||
};
|
||||
struct Triangle {
|
||||
qreal opposite;
|
||||
qreal adjacent;
|
||||
qreal hypotenuse;
|
||||
};
|
||||
|
||||
Triangle GetTriangleFromCoords(const QPoint ¢er, const QPoint& p) const;
|
||||
Triangle GetTriangleFromCoords(const QPoint ¢er, qreal y, qreal x) const;
|
||||
Triangle GetTriangleFromCoords(const QPoint ¢er, const QPoint &p) const;
|
||||
Triangle GetTriangleFromCoords(const QPoint ¢er, qreal y,
|
||||
qreal x) const;
|
||||
|
||||
Color GetColorFromTriangle(const Triangle& tri) const;
|
||||
QPoint GetCoordsFromColor(const Color& c) const;
|
||||
Color GetColorFromTriangle(const Triangle &tri) const;
|
||||
QPoint GetCoordsFromColor(const Color &c) const;
|
||||
|
||||
QPixmap cached_wheel_;
|
||||
QPixmap cached_wheel_;
|
||||
|
||||
float val_;
|
||||
|
||||
bool force_redraw_;
|
||||
float val_;
|
||||
|
||||
bool force_redraw_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,39 +20,36 @@
|
||||
|
||||
#include "columnedgridlayout.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
ColumnedGridLayout::ColumnedGridLayout(QWidget* parent,
|
||||
int maximum_columns) :
|
||||
QGridLayout (parent),
|
||||
maximum_columns_(maximum_columns)
|
||||
ColumnedGridLayout::ColumnedGridLayout(QWidget *parent, int maximum_columns)
|
||||
: QGridLayout(parent)
|
||||
, maximum_columns_(maximum_columns)
|
||||
{
|
||||
}
|
||||
|
||||
void ColumnedGridLayout::Add(QWidget *widget)
|
||||
{
|
||||
if (maximum_columns_ > 0) {
|
||||
if (maximum_columns_ > 0) {
|
||||
int row = count() / maximum_columns_;
|
||||
int column = count() % maximum_columns_;
|
||||
|
||||
int row = count() / maximum_columns_;
|
||||
int column = count() % maximum_columns_;
|
||||
addWidget(widget, row, column);
|
||||
|
||||
addWidget(widget, row, column);
|
||||
|
||||
} else {
|
||||
|
||||
addWidget(widget);
|
||||
|
||||
}
|
||||
} else {
|
||||
addWidget(widget);
|
||||
}
|
||||
}
|
||||
|
||||
int ColumnedGridLayout::MaximumColumns() const
|
||||
{
|
||||
return maximum_columns_;
|
||||
return maximum_columns_;
|
||||
}
|
||||
|
||||
void ColumnedGridLayout::SetMaximumColumns(int maximum_columns)
|
||||
{
|
||||
maximum_columns_ = maximum_columns;
|
||||
maximum_columns_ = maximum_columns;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The ColumnedGridLayout class
|
||||
@@ -33,19 +34,17 @@ namespace olive {
|
||||
* A simple derivative of QGridLayout that provides a automatic row/column layout based on a specified maximum
|
||||
* column count.
|
||||
*/
|
||||
class ColumnedGridLayout : public QGridLayout
|
||||
{
|
||||
Q_OBJECT
|
||||
class ColumnedGridLayout : public QGridLayout {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColumnedGridLayout(QWidget* parent = nullptr,
|
||||
int maximum_columns = 0);
|
||||
ColumnedGridLayout(QWidget *parent = nullptr, int maximum_columns = 0);
|
||||
|
||||
void Add(QWidget* widget);
|
||||
int MaximumColumns() const;
|
||||
void SetMaximumColumns(int maximum_columns);
|
||||
void Add(QWidget *widget);
|
||||
int MaximumColumns() const;
|
||||
void SetMaximumColumns(int maximum_columns);
|
||||
|
||||
private:
|
||||
int maximum_columns_;
|
||||
int maximum_columns_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,101 +25,108 @@
|
||||
#include "widget/keyframeview/keyframeview.h"
|
||||
#include "widget/slider/floatslider.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class CurveView : public KeyframeView
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class CurveView : public KeyframeView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CurveView(QWidget* parent = nullptr);
|
||||
CurveView(QWidget *parent = nullptr);
|
||||
|
||||
void ConnectInput(const NodeKeyframeTrackReference &ref);
|
||||
void ConnectInput(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void DisconnectInput(const NodeKeyframeTrackReference &ref);
|
||||
void DisconnectInput(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void SelectKeyframesOfInput(const NodeKeyframeTrackReference &ref);
|
||||
void SelectKeyframesOfInput(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void SetKeyframeTrackColor(const NodeKeyframeTrackReference& ref, const QColor& color);
|
||||
void SetKeyframeTrackColor(const NodeKeyframeTrackReference &ref,
|
||||
const QColor &color);
|
||||
|
||||
const QHash<NodeKeyframeTrackReference, KeyframeViewInputConnection*> &GetConnections() const
|
||||
{
|
||||
return track_connections_;
|
||||
}
|
||||
const QHash<NodeKeyframeTrackReference, KeyframeViewInputConnection *> &
|
||||
GetConnections() const
|
||||
{
|
||||
return track_connections_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void ZoomToFit();
|
||||
void ZoomToFit();
|
||||
|
||||
void ZoomToFitSelected();
|
||||
void ZoomToFitSelected();
|
||||
|
||||
void ResetZoom();
|
||||
void ResetZoom();
|
||||
|
||||
protected:
|
||||
virtual void drawBackground(QPainter* painter, const QRectF& rect) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawBackground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
virtual void ContextMenuEvent(Menu &m) override;
|
||||
virtual void ContextMenuEvent(Menu &m) override;
|
||||
|
||||
virtual void SceneRectUpdateEvent(QRectF &r) override;
|
||||
virtual void SceneRectUpdateEvent(QRectF &r) override;
|
||||
|
||||
virtual qreal GetKeyframeSceneY(KeyframeViewInputConnection *track, NodeKeyframe *key) override;
|
||||
virtual qreal GetKeyframeSceneY(KeyframeViewInputConnection *track,
|
||||
NodeKeyframe *key) override;
|
||||
|
||||
virtual void DrawKeyframe(QPainter *painter, NodeKeyframe *key, KeyframeViewInputConnection *track, const QRectF &key_rect) override;
|
||||
virtual void DrawKeyframe(QPainter *painter, NodeKeyframe *key,
|
||||
KeyframeViewInputConnection *track,
|
||||
const QRectF &key_rect) override;
|
||||
|
||||
virtual bool FirstChanceMousePress(QMouseEvent *event) override;
|
||||
virtual void FirstChanceMouseMove(QMouseEvent *event) override;
|
||||
virtual void FirstChanceMouseRelease(QMouseEvent *event) override;
|
||||
virtual bool FirstChanceMousePress(QMouseEvent *event) override;
|
||||
virtual void FirstChanceMouseMove(QMouseEvent *event) override;
|
||||
virtual void FirstChanceMouseRelease(QMouseEvent *event) override;
|
||||
|
||||
virtual void KeyframeDragStart(QMouseEvent *event) override;
|
||||
virtual void KeyframeDragMove(QMouseEvent *event, QString &tip) override;
|
||||
virtual void KeyframeDragRelease(QMouseEvent *event, MultiUndoCommand *command) override;
|
||||
virtual void KeyframeDragStart(QMouseEvent *event) override;
|
||||
virtual void KeyframeDragMove(QMouseEvent *event, QString &tip) override;
|
||||
virtual void KeyframeDragRelease(QMouseEvent *event,
|
||||
MultiUndoCommand *command) override;
|
||||
|
||||
private:
|
||||
void ZoomToFitInternal(bool selected_only);
|
||||
void ZoomToFitInternal(bool selected_only);
|
||||
|
||||
qreal GetItemYFromKeyframeValue(NodeKeyframe* key);
|
||||
qreal GetUnscaledItemYFromKeyframeValue(NodeKeyframe* key);
|
||||
qreal GetItemYFromKeyframeValue(NodeKeyframe *key);
|
||||
qreal GetUnscaledItemYFromKeyframeValue(NodeKeyframe *key);
|
||||
|
||||
QPointF ScalePoint(const QPointF& point);
|
||||
QPointF ScalePoint(const QPointF &point);
|
||||
|
||||
static FloatSlider::DisplayType GetFloatDisplayTypeFromKeyframe(NodeKeyframe *key);
|
||||
static FloatSlider::DisplayType
|
||||
GetFloatDisplayTypeFromKeyframe(NodeKeyframe *key);
|
||||
|
||||
static double GetOffsetFromKeyframe(NodeKeyframe *key);
|
||||
static double GetOffsetFromKeyframe(NodeKeyframe *key);
|
||||
|
||||
void AdjustLines();
|
||||
void AdjustLines();
|
||||
|
||||
QPointF GetKeyframePosition(NodeKeyframe *key);
|
||||
QPointF GetKeyframePosition(NodeKeyframe *key);
|
||||
|
||||
static QPointF GenerateBezierControlPosition(const NodeKeyframe::BezierType mode,
|
||||
const QPointF& start_point,
|
||||
const QPointF& scaled_cursor_diff);
|
||||
static QPointF
|
||||
GenerateBezierControlPosition(const NodeKeyframe::BezierType mode,
|
||||
const QPointF &start_point,
|
||||
const QPointF &scaled_cursor_diff);
|
||||
|
||||
QPointF GetScaledCursorPos(const QPointF &cursor_pos);
|
||||
QPointF GetScaledCursorPos(const QPointF &cursor_pos);
|
||||
|
||||
QHash<NodeKeyframeTrackReference, QColor> keyframe_colors_;
|
||||
QHash<NodeKeyframeTrackReference, KeyframeViewInputConnection*> track_connections_;
|
||||
QHash<NodeKeyframeTrackReference, QColor> keyframe_colors_;
|
||||
QHash<NodeKeyframeTrackReference, KeyframeViewInputConnection *>
|
||||
track_connections_;
|
||||
|
||||
int text_padding_;
|
||||
int text_padding_;
|
||||
|
||||
int minimum_grid_space_;
|
||||
int minimum_grid_space_;
|
||||
|
||||
QVector<NodeKeyframeTrackReference> connected_inputs_;
|
||||
QVector<NodeKeyframeTrackReference> connected_inputs_;
|
||||
|
||||
struct BezierPoint
|
||||
{
|
||||
QRectF rect;
|
||||
NodeKeyframe *keyframe;
|
||||
NodeKeyframe::BezierType type;
|
||||
};
|
||||
struct BezierPoint {
|
||||
QRectF rect;
|
||||
NodeKeyframe *keyframe;
|
||||
NodeKeyframe::BezierType type;
|
||||
};
|
||||
|
||||
QVector<BezierPoint> bezier_pts_;
|
||||
const BezierPoint *dragging_bezier_pt_;
|
||||
QVector<BezierPoint> bezier_pts_;
|
||||
const BezierPoint *dragging_bezier_pt_;
|
||||
|
||||
QPointF dragging_bezier_point_start_;
|
||||
QPointF dragging_bezier_point_opposing_start_;
|
||||
QPointF drag_start_;
|
||||
|
||||
QVector<QVariant> drag_keyframe_values_;
|
||||
QPointF dragging_bezier_point_start_;
|
||||
QPointF dragging_bezier_point_opposing_start_;
|
||||
QPointF drag_start_;
|
||||
|
||||
QVector<QVariant> drag_keyframe_values_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -32,346 +32,365 @@
|
||||
#include "widget/keyframeview/keyframeviewundo.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super TimeBasedWidget
|
||||
|
||||
CurveWidget::CurveWidget(QWidget *parent) :
|
||||
super(parent)
|
||||
CurveWidget::CurveWidget(QWidget *parent)
|
||||
: super(parent)
|
||||
{
|
||||
QHBoxLayout* outer_layout = new QHBoxLayout(this);
|
||||
QHBoxLayout *outer_layout = new QHBoxLayout(this);
|
||||
|
||||
QSplitter* splitter = new QSplitter();
|
||||
outer_layout->addWidget(splitter);
|
||||
QSplitter *splitter = new QSplitter();
|
||||
outer_layout->addWidget(splitter);
|
||||
|
||||
tree_view_ = new NodeTreeView();
|
||||
tree_view_->SetOnlyShowKeyframable(true);
|
||||
tree_view_->SetShowKeyframeTracksAsRows(true);
|
||||
connect(tree_view_, &NodeTreeView::InputSelectionChanged, this, &CurveWidget::InputSelectionChanged);
|
||||
splitter->addWidget(tree_view_);
|
||||
tree_view_ = new NodeTreeView();
|
||||
tree_view_->SetOnlyShowKeyframable(true);
|
||||
tree_view_->SetShowKeyframeTracksAsRows(true);
|
||||
connect(tree_view_, &NodeTreeView::InputSelectionChanged, this,
|
||||
&CurveWidget::InputSelectionChanged);
|
||||
splitter->addWidget(tree_view_);
|
||||
|
||||
QWidget* workarea = new QWidget();
|
||||
QVBoxLayout* layout = new QVBoxLayout(workarea);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
splitter->addWidget(workarea);
|
||||
QWidget *workarea = new QWidget();
|
||||
QVBoxLayout *layout = new QVBoxLayout(workarea);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
splitter->addWidget(workarea);
|
||||
|
||||
QHBoxLayout* top_controls = new QHBoxLayout();
|
||||
QHBoxLayout *top_controls = new QHBoxLayout();
|
||||
|
||||
key_control_ = new NodeParamViewKeyframeControl(false);
|
||||
top_controls->addWidget(key_control_);
|
||||
key_control_ = new NodeParamViewKeyframeControl(false);
|
||||
top_controls->addWidget(key_control_);
|
||||
|
||||
top_controls->addStretch();
|
||||
top_controls->addStretch();
|
||||
|
||||
linear_button_ = new QPushButton(tr("Linear"));
|
||||
linear_button_->setCheckable(true);
|
||||
linear_button_->setEnabled(false);
|
||||
top_controls->addWidget(linear_button_);
|
||||
connect(linear_button_, &QPushButton::clicked, this, &CurveWidget::KeyframeTypeButtonTriggered);
|
||||
linear_button_ = new QPushButton(tr("Linear"));
|
||||
linear_button_->setCheckable(true);
|
||||
linear_button_->setEnabled(false);
|
||||
top_controls->addWidget(linear_button_);
|
||||
connect(linear_button_, &QPushButton::clicked, this,
|
||||
&CurveWidget::KeyframeTypeButtonTriggered);
|
||||
|
||||
bezier_button_ = new QPushButton(tr("Bezier"));
|
||||
bezier_button_->setCheckable(true);
|
||||
bezier_button_->setEnabled(false);
|
||||
top_controls->addWidget(bezier_button_);
|
||||
connect(bezier_button_, &QPushButton::clicked, this, &CurveWidget::KeyframeTypeButtonTriggered);
|
||||
bezier_button_ = new QPushButton(tr("Bezier"));
|
||||
bezier_button_->setCheckable(true);
|
||||
bezier_button_->setEnabled(false);
|
||||
top_controls->addWidget(bezier_button_);
|
||||
connect(bezier_button_, &QPushButton::clicked, this,
|
||||
&CurveWidget::KeyframeTypeButtonTriggered);
|
||||
|
||||
hold_button_ = new QPushButton(tr("Hold"));
|
||||
hold_button_->setCheckable(true);
|
||||
hold_button_->setEnabled(false);
|
||||
top_controls->addWidget(hold_button_);
|
||||
connect(hold_button_, &QPushButton::clicked, this, &CurveWidget::KeyframeTypeButtonTriggered);
|
||||
hold_button_ = new QPushButton(tr("Hold"));
|
||||
hold_button_->setCheckable(true);
|
||||
hold_button_->setEnabled(false);
|
||||
top_controls->addWidget(hold_button_);
|
||||
connect(hold_button_, &QPushButton::clicked, this,
|
||||
&CurveWidget::KeyframeTypeButtonTriggered);
|
||||
|
||||
layout->addLayout(top_controls);
|
||||
layout->addLayout(top_controls);
|
||||
|
||||
// We use a separate layout for the ruler+view combination so that there's no spacing between them
|
||||
QVBoxLayout* ruler_view_layout = new QVBoxLayout();
|
||||
ruler_view_layout->setContentsMargins(0, 0, 0, 0);
|
||||
ruler_view_layout->setSpacing(0);
|
||||
// We use a separate layout for the ruler+view combination so that there's no spacing between them
|
||||
QVBoxLayout *ruler_view_layout = new QVBoxLayout();
|
||||
ruler_view_layout->setContentsMargins(0, 0, 0, 0);
|
||||
ruler_view_layout->setSpacing(0);
|
||||
|
||||
ruler_view_layout->addWidget(ruler());
|
||||
ruler_view_layout->addWidget(ruler());
|
||||
|
||||
view_ = new CurveView();
|
||||
ConnectTimelineView(view_);
|
||||
view_->SetSnapService(this);
|
||||
ruler_view_layout->addWidget(view_);
|
||||
view_ = new CurveView();
|
||||
ConnectTimelineView(view_);
|
||||
view_->SetSnapService(this);
|
||||
ruler_view_layout->addWidget(view_);
|
||||
|
||||
layout->addLayout(ruler_view_layout);
|
||||
layout->addLayout(ruler_view_layout);
|
||||
|
||||
// Connect ruler and view together
|
||||
connect(view_, &CurveView::SelectionChanged, this, &CurveWidget::SelectionChanged);
|
||||
connect(view_, &CurveView::Dragged, this, &CurveWidget::KeyframeViewDragged);
|
||||
connect(view_, &CurveView::Released, this, &CurveWidget::KeyframeViewReleased);
|
||||
// Connect ruler and view together
|
||||
connect(view_, &CurveView::SelectionChanged, this,
|
||||
&CurveWidget::SelectionChanged);
|
||||
connect(view_, &CurveView::Dragged, this,
|
||||
&CurveWidget::KeyframeViewDragged);
|
||||
connect(view_, &CurveView::Released, this,
|
||||
&CurveWidget::KeyframeViewReleased);
|
||||
|
||||
// TimeBasedWidget's scrollbar has extra functionality that we can take advantage of
|
||||
view_->setHorizontalScrollBar(scrollbar());
|
||||
// TimeBasedWidget's scrollbar has extra functionality that we can take advantage of
|
||||
view_->setHorizontalScrollBar(scrollbar());
|
||||
|
||||
// Disable collapsing the main curve view (but allow collapsing the tree)
|
||||
splitter->setCollapsible(1, false);
|
||||
// Disable collapsing the main curve view (but allow collapsing the tree)
|
||||
splitter->setCollapsible(1, false);
|
||||
|
||||
SetScale(120.0);
|
||||
SetScale(120.0);
|
||||
}
|
||||
|
||||
const double &CurveWidget::GetVerticalScale()
|
||||
{
|
||||
return view_->GetYScale();
|
||||
return view_->GetYScale();
|
||||
}
|
||||
|
||||
void CurveWidget::SetVerticalScale(const double &vscale)
|
||||
{
|
||||
view_->SetYScale(vscale);
|
||||
view_->SetYScale(vscale);
|
||||
}
|
||||
|
||||
void CurveWidget::DeleteSelected()
|
||||
{
|
||||
view_->DeleteSelected();
|
||||
view_->DeleteSelected();
|
||||
}
|
||||
|
||||
Node *CurveWidget::GetSelectedNodeWithID(const QString &id)
|
||||
{
|
||||
for (auto it=view_->GetConnections().cbegin(); it!=view_->GetConnections().cend(); it++) {
|
||||
Node *n = it.key().input().node();
|
||||
if (n->id() == id) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
for (auto it = view_->GetConnections().cbegin();
|
||||
it != view_->GetConnections().cend(); it++) {
|
||||
Node *n = it.key().input().node();
|
||||
if (n->id() == id) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CurveWidget::CopySelected(bool cut)
|
||||
{
|
||||
if (super::CopySelected(cut)) {
|
||||
return true;
|
||||
}
|
||||
if (super::CopySelected(cut)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return view_->CopySelected(cut);
|
||||
return view_->CopySelected(cut);
|
||||
}
|
||||
|
||||
bool CurveWidget::Paste()
|
||||
{
|
||||
if (super::Paste()) {
|
||||
return true;
|
||||
}
|
||||
if (super::Paste()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return view_->Paste(std::bind(&CurveWidget::GetSelectedNodeWithID, this, std::placeholders::_1));
|
||||
return view_->Paste(std::bind(&CurveWidget::GetSelectedNodeWithID, this,
|
||||
std::placeholders::_1));
|
||||
}
|
||||
|
||||
void CurveWidget::SetNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
tree_view_->SetNodes(nodes);
|
||||
tree_view_->SetNodes(nodes);
|
||||
|
||||
// Save new node list
|
||||
nodes_ = nodes;
|
||||
// Save new node list
|
||||
nodes_ = nodes;
|
||||
|
||||
// Generate colors
|
||||
foreach (Node *node, nodes_) {
|
||||
foreach (const QString& input, node->inputs()) {
|
||||
if (node->IsInputKeyframable(input) && !node->IsInputHidden(input)) {
|
||||
int arr_sz = node->InputArraySize(input);
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
// Generate a random color for this input
|
||||
const QVector<NodeKeyframeTrack>& tracks = node->GetKeyframeTracks(input, i);
|
||||
// Generate colors
|
||||
foreach (Node *node, nodes_) {
|
||||
foreach (const QString &input, node->inputs()) {
|
||||
if (node->IsInputKeyframable(input) &&
|
||||
!node->IsInputHidden(input)) {
|
||||
int arr_sz = node->InputArraySize(input);
|
||||
for (int i = -1; i < arr_sz; i++) {
|
||||
// Generate a random color for this input
|
||||
const QVector<NodeKeyframeTrack> &tracks =
|
||||
node->GetKeyframeTracks(input, i);
|
||||
|
||||
for (int j=0; j<tracks.size(); j++) {
|
||||
NodeKeyframeTrackReference ref(NodeInput(node, input, i), j);
|
||||
for (int j = 0; j < tracks.size(); j++) {
|
||||
NodeKeyframeTrackReference ref(
|
||||
NodeInput(node, input, i), j);
|
||||
|
||||
if (!keyframe_colors_.contains(ref)) {
|
||||
QColor c = QColor::fromHsl(std::rand()%360, 255, 160);
|
||||
if (!keyframe_colors_.contains(ref)) {
|
||||
QColor c =
|
||||
QColor::fromHsl(std::rand() % 360, 255, 160);
|
||||
|
||||
keyframe_colors_.insert(ref, c);
|
||||
tree_view_->SetKeyframeTrackColor(ref, c);
|
||||
view_->SetKeyframeTrackColor(ref, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
keyframe_colors_.insert(ref, c);
|
||||
tree_view_->SetKeyframeTrackColor(ref, c);
|
||||
view_->SetKeyframeTrackColor(ref, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurveWidget::TimebaseChangedEvent(const rational &timebase)
|
||||
{
|
||||
super::TimebaseChangedEvent(timebase);
|
||||
super::TimebaseChangedEvent(timebase);
|
||||
|
||||
view_->SetTimebase(timebase);
|
||||
view_->SetTimebase(timebase);
|
||||
}
|
||||
|
||||
void CurveWidget::ScaleChangedEvent(const double &scale)
|
||||
{
|
||||
super::ScaleChangedEvent(scale);
|
||||
super::ScaleChangedEvent(scale);
|
||||
|
||||
view_->SetScale(scale);
|
||||
view_->SetScale(scale);
|
||||
}
|
||||
|
||||
void CurveWidget::TimeTargetChangedEvent(ViewerOutput *target)
|
||||
{
|
||||
TimeTargetObject::TimeTargetChangedEvent(target);
|
||||
TimeTargetObject::TimeTargetChangedEvent(target);
|
||||
|
||||
key_control_->SetTimeTarget(target);
|
||||
key_control_->SetTimeTarget(target);
|
||||
|
||||
view_->SetTimeTarget(target);
|
||||
view_->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
void CurveWidget::ConnectedNodeChangeEvent(ViewerOutput *n)
|
||||
{
|
||||
super::ConnectedNodeChangeEvent(n);
|
||||
super::ConnectedNodeChangeEvent(n);
|
||||
|
||||
key_control_->SetTimeTarget(n);
|
||||
key_control_->SetTimeTarget(n);
|
||||
|
||||
SetTimeTarget(n);
|
||||
SetTimeTarget(n);
|
||||
}
|
||||
|
||||
void CurveWidget::SetKeyframeButtonEnabled(bool enable)
|
||||
{
|
||||
linear_button_->setEnabled(enable);
|
||||
bezier_button_->setEnabled(enable);
|
||||
hold_button_->setEnabled(enable);
|
||||
linear_button_->setEnabled(enable);
|
||||
bezier_button_->setEnabled(enable);
|
||||
hold_button_->setEnabled(enable);
|
||||
}
|
||||
|
||||
void CurveWidget::SetKeyframeButtonChecked(bool checked)
|
||||
{
|
||||
linear_button_->setChecked(checked);
|
||||
bezier_button_->setChecked(checked);
|
||||
hold_button_->setChecked(checked);
|
||||
linear_button_->setChecked(checked);
|
||||
bezier_button_->setChecked(checked);
|
||||
hold_button_->setChecked(checked);
|
||||
}
|
||||
|
||||
void CurveWidget::SetKeyframeButtonCheckedFromType(NodeKeyframe::Type type)
|
||||
{
|
||||
linear_button_->setChecked(type == NodeKeyframe::kLinear);
|
||||
bezier_button_->setChecked(type == NodeKeyframe::kBezier);
|
||||
hold_button_->setChecked(type == NodeKeyframe::kHold);
|
||||
linear_button_->setChecked(type == NodeKeyframe::kLinear);
|
||||
bezier_button_->setChecked(type == NodeKeyframe::kBezier);
|
||||
hold_button_->setChecked(type == NodeKeyframe::kHold);
|
||||
}
|
||||
|
||||
void CurveWidget::ConnectInput(Node *node, const QString &input, int element)
|
||||
{
|
||||
if (element == -1 && node->InputIsArray(input)) {
|
||||
// This is the root element, connect all elements (if applicable)
|
||||
int arr_sz = node->InputArraySize(input);
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
ConnectInputInternal(node, input, i);
|
||||
}
|
||||
} else {
|
||||
// This is a single element, just connect it as-is
|
||||
ConnectInputInternal(node, input, element);
|
||||
}
|
||||
if (element == -1 && node->InputIsArray(input)) {
|
||||
// This is the root element, connect all elements (if applicable)
|
||||
int arr_sz = node->InputArraySize(input);
|
||||
for (int i = -1; i < arr_sz; i++) {
|
||||
ConnectInputInternal(node, input, i);
|
||||
}
|
||||
} else {
|
||||
// This is a single element, just connect it as-is
|
||||
ConnectInputInternal(node, input, element);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveWidget::ConnectInputInternal(Node *node, const QString &input, int element)
|
||||
void CurveWidget::ConnectInputInternal(Node *node, const QString &input,
|
||||
int element)
|
||||
{
|
||||
NodeInput input_ref(node, input, element);
|
||||
int track_count = NodeValue::get_number_of_keyframe_tracks(input_ref.GetDataType());
|
||||
for (int i=0; i<track_count; i++) {
|
||||
NodeKeyframeTrackReference track_ref(input_ref, i);
|
||||
view_->ConnectInput(track_ref);
|
||||
selected_tracks_.append(track_ref);
|
||||
}
|
||||
NodeInput input_ref(node, input, element);
|
||||
int track_count =
|
||||
NodeValue::get_number_of_keyframe_tracks(input_ref.GetDataType());
|
||||
for (int i = 0; i < track_count; i++) {
|
||||
NodeKeyframeTrackReference track_ref(input_ref, i);
|
||||
view_->ConnectInput(track_ref);
|
||||
selected_tracks_.append(track_ref);
|
||||
}
|
||||
}
|
||||
|
||||
void CurveWidget::SelectionChanged()
|
||||
{
|
||||
const std::vector<NodeKeyframe*> &selected = view_->GetSelectedKeyframes();
|
||||
const std::vector<NodeKeyframe *> &selected = view_->GetSelectedKeyframes();
|
||||
|
||||
SetKeyframeButtonChecked(false);
|
||||
SetKeyframeButtonEnabled(!selected.empty());
|
||||
SetKeyframeButtonChecked(false);
|
||||
SetKeyframeButtonEnabled(!selected.empty());
|
||||
|
||||
if (!selected.empty()) {
|
||||
bool all_same_type = true;
|
||||
NodeKeyframe::Type type = selected.front()->type();
|
||||
if (!selected.empty()) {
|
||||
bool all_same_type = true;
|
||||
NodeKeyframe::Type type = selected.front()->type();
|
||||
|
||||
for (size_t i=1;i<selected.size();i++) {
|
||||
NodeKeyframe* prev_item = selected.at(i-1);
|
||||
NodeKeyframe* this_item = selected.at(i);
|
||||
for (size_t i = 1; i < selected.size(); i++) {
|
||||
NodeKeyframe *prev_item = selected.at(i - 1);
|
||||
NodeKeyframe *this_item = selected.at(i);
|
||||
|
||||
if (prev_item->type() != this_item->type()) {
|
||||
all_same_type = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prev_item->type() != this_item->type()) {
|
||||
all_same_type = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (all_same_type) {
|
||||
SetKeyframeButtonCheckedFromType(type);
|
||||
}
|
||||
}
|
||||
if (all_same_type) {
|
||||
SetKeyframeButtonCheckedFromType(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CurveWidget::KeyframeTypeButtonTriggered(bool checked)
|
||||
{
|
||||
QPushButton* key_btn = static_cast<QPushButton*>(sender());
|
||||
QPushButton *key_btn = static_cast<QPushButton *>(sender());
|
||||
|
||||
if (!checked) {
|
||||
// Keyframe buttons cannot be checked off, we undo this action here
|
||||
key_btn->setChecked(true);
|
||||
return;
|
||||
}
|
||||
if (!checked) {
|
||||
// Keyframe buttons cannot be checked off, we undo this action here
|
||||
key_btn->setChecked(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get selected items and do nothing if there are none
|
||||
const std::vector<NodeKeyframe*> &selected = view_->GetSelectedKeyframes();
|
||||
if (selected.empty()) {
|
||||
return;
|
||||
}
|
||||
// Get selected items and do nothing if there are none
|
||||
const std::vector<NodeKeyframe *> &selected = view_->GetSelectedKeyframes();
|
||||
if (selected.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set all selected keyframes to this type
|
||||
NodeKeyframe::Type new_type;
|
||||
// Set all selected keyframes to this type
|
||||
NodeKeyframe::Type new_type;
|
||||
|
||||
// Determine which type to set
|
||||
if (key_btn == bezier_button_) {
|
||||
new_type = NodeKeyframe::kBezier;
|
||||
} else if (key_btn == hold_button_) {
|
||||
new_type = NodeKeyframe::kHold;
|
||||
} else {
|
||||
new_type = NodeKeyframe::kLinear;
|
||||
}
|
||||
// Determine which type to set
|
||||
if (key_btn == bezier_button_) {
|
||||
new_type = NodeKeyframe::kBezier;
|
||||
} else if (key_btn == hold_button_) {
|
||||
new_type = NodeKeyframe::kHold;
|
||||
} else {
|
||||
new_type = NodeKeyframe::kLinear;
|
||||
}
|
||||
|
||||
// Ensure only the appropriate button is checked
|
||||
SetKeyframeButtonCheckedFromType(new_type);
|
||||
// Ensure only the appropriate button is checked
|
||||
SetKeyframeButtonCheckedFromType(new_type);
|
||||
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
foreach (NodeKeyframe* item, selected) {
|
||||
command->add_child(new KeyframeSetTypeCommand(item, new_type));
|
||||
}
|
||||
foreach (NodeKeyframe *item, selected) {
|
||||
command->add_child(new KeyframeSetTypeCommand(item, new_type));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, tr("Changed Type of %1 Keyframe(s) to %2"));
|
||||
Core::instance()->undo_stack()->push(
|
||||
command, tr("Changed Type of %1 Keyframe(s) to %2"));
|
||||
}
|
||||
|
||||
void CurveWidget::InputSelectionChanged(const NodeKeyframeTrackReference& ref)
|
||||
void CurveWidget::InputSelectionChanged(const NodeKeyframeTrackReference &ref)
|
||||
{
|
||||
key_control_->SetInput(ref.input());
|
||||
key_control_->SetInput(ref.input());
|
||||
|
||||
foreach (const NodeKeyframeTrackReference &c, selected_tracks_) {
|
||||
view_->DisconnectInput(c);
|
||||
}
|
||||
foreach (const NodeKeyframeTrackReference &c, selected_tracks_) {
|
||||
view_->DisconnectInput(c);
|
||||
}
|
||||
|
||||
selected_tracks_.clear();
|
||||
selected_tracks_.clear();
|
||||
|
||||
if (ref.IsValid() && !ref.input().IsArray()) {
|
||||
// This reference is a track, connect it only
|
||||
view_->ConnectInput(ref);
|
||||
selected_tracks_.append(ref);
|
||||
} else if (ref.input().IsValid()) {
|
||||
// This reference is a input, connect all tracks
|
||||
ConnectInput(ref.input().node(), ref.input().input(), ref.input().element());
|
||||
} else if (Node *node = ref.input().node()) {
|
||||
// This is a node, add all inputs
|
||||
foreach (const QString &input, node->inputs()) {
|
||||
if (node->IsInputKeyframable(input) && !node->IsInputHidden(input)) {
|
||||
ConnectInput(node, input, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ref.IsValid() && !ref.input().IsArray()) {
|
||||
// This reference is a track, connect it only
|
||||
view_->ConnectInput(ref);
|
||||
selected_tracks_.append(ref);
|
||||
} else if (ref.input().IsValid()) {
|
||||
// This reference is a input, connect all tracks
|
||||
ConnectInput(ref.input().node(), ref.input().input(),
|
||||
ref.input().element());
|
||||
} else if (Node *node = ref.input().node()) {
|
||||
// This is a node, add all inputs
|
||||
foreach (const QString &input, node->inputs()) {
|
||||
if (node->IsInputKeyframable(input) &&
|
||||
!node->IsInputHidden(input)) {
|
||||
ConnectInput(node, input, -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view_->ZoomToFit();
|
||||
view_->ZoomToFit();
|
||||
}
|
||||
|
||||
void CurveWidget::KeyframeViewDragged(int x, int y)
|
||||
{
|
||||
SetCatchUpScrollValue(x);
|
||||
SetCatchUpScrollValue(view_->verticalScrollBar(), y, view_->height());
|
||||
SetCatchUpScrollValue(x);
|
||||
SetCatchUpScrollValue(view_->verticalScrollBar(), y, view_->height());
|
||||
}
|
||||
|
||||
void CurveWidget::KeyframeViewReleased()
|
||||
{
|
||||
StopCatchUpScrollTimer();
|
||||
StopCatchUpScrollTimer(view_->verticalScrollBar());
|
||||
StopCatchUpScrollTimer();
|
||||
StopCatchUpScrollTimer(view_->verticalScrollBar());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,100 +32,101 @@
|
||||
#include "widget/nodetreeview/nodetreeview.h"
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class CurveWidget : public TimeBasedWidget, public TimeTargetObject
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class CurveWidget : public TimeBasedWidget, public TimeTargetObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CurveWidget(QWidget* parent = nullptr);
|
||||
CurveWidget(QWidget *parent = nullptr);
|
||||
|
||||
const double& GetVerticalScale();
|
||||
void SetVerticalScale(const double& vscale);
|
||||
const double &GetVerticalScale();
|
||||
void SetVerticalScale(const double &vscale);
|
||||
|
||||
void DeleteSelected();
|
||||
void DeleteSelected();
|
||||
|
||||
void SelectAll()
|
||||
{
|
||||
view_->SelectAll();
|
||||
}
|
||||
void SelectAll()
|
||||
{
|
||||
view_->SelectAll();
|
||||
}
|
||||
|
||||
void DeselectAll()
|
||||
{
|
||||
view_->DeselectAll();
|
||||
}
|
||||
void DeselectAll()
|
||||
{
|
||||
view_->DeselectAll();
|
||||
}
|
||||
|
||||
Node *GetSelectedNodeWithID(const QString &id);
|
||||
Node *GetSelectedNodeWithID(const QString &id);
|
||||
|
||||
virtual bool CopySelected(bool cut) override;
|
||||
virtual bool CopySelected(bool cut) override;
|
||||
|
||||
virtual bool Paste() override;
|
||||
virtual bool Paste() override;
|
||||
|
||||
public slots:
|
||||
void SetNodes(const QVector<Node *> &nodes);
|
||||
void SetNodes(const QVector<Node *> &nodes);
|
||||
|
||||
protected:
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
|
||||
virtual void TimeTargetChangedEvent(ViewerOutput *target) override;
|
||||
virtual void TimeTargetChangedEvent(ViewerOutput *target) override;
|
||||
|
||||
virtual void ConnectedNodeChangeEvent(ViewerOutput* n) override;
|
||||
virtual void ConnectedNodeChangeEvent(ViewerOutput *n) override;
|
||||
|
||||
virtual const QVector<KeyframeViewInputConnection*> *GetSnapKeyframes() const override
|
||||
{
|
||||
return &view_->GetKeyframeTracks();
|
||||
}
|
||||
virtual const QVector<KeyframeViewInputConnection *> *
|
||||
GetSnapKeyframes() const override
|
||||
{
|
||||
return &view_->GetKeyframeTracks();
|
||||
}
|
||||
|
||||
virtual const TimeTargetObject *GetKeyframeTimeTarget() const override
|
||||
{
|
||||
return view_;
|
||||
}
|
||||
virtual const TimeTargetObject *GetKeyframeTimeTarget() const override
|
||||
{
|
||||
return view_;
|
||||
}
|
||||
|
||||
virtual const std::vector<NodeKeyframe*> *GetSnapIgnoreKeyframes() const override
|
||||
{
|
||||
return &view_->GetSelectedKeyframes();
|
||||
}
|
||||
virtual const std::vector<NodeKeyframe *> *
|
||||
GetSnapIgnoreKeyframes() const override
|
||||
{
|
||||
return &view_->GetSelectedKeyframes();
|
||||
}
|
||||
|
||||
private:
|
||||
void SetKeyframeButtonEnabled(bool enable);
|
||||
void SetKeyframeButtonEnabled(bool enable);
|
||||
|
||||
void SetKeyframeButtonChecked(bool checked);
|
||||
void SetKeyframeButtonChecked(bool checked);
|
||||
|
||||
void SetKeyframeButtonCheckedFromType(NodeKeyframe::Type type);
|
||||
void SetKeyframeButtonCheckedFromType(NodeKeyframe::Type type);
|
||||
|
||||
void ConnectInput(Node *node, const QString &input, int element);
|
||||
void ConnectInput(Node *node, const QString &input, int element);
|
||||
|
||||
void ConnectInputInternal(Node *node, const QString &input, int element);
|
||||
void ConnectInputInternal(Node *node, const QString &input, int element);
|
||||
|
||||
QHash<NodeKeyframeTrackReference, QColor> keyframe_colors_;
|
||||
QHash<NodeKeyframeTrackReference, QColor> keyframe_colors_;
|
||||
|
||||
NodeTreeView* tree_view_;
|
||||
NodeTreeView *tree_view_;
|
||||
|
||||
QPushButton* linear_button_;
|
||||
QPushButton *linear_button_;
|
||||
|
||||
QPushButton* bezier_button_;
|
||||
QPushButton *bezier_button_;
|
||||
|
||||
QPushButton* hold_button_;
|
||||
QPushButton *hold_button_;
|
||||
|
||||
CurveView* view_;
|
||||
CurveView *view_;
|
||||
|
||||
NodeParamViewKeyframeControl* key_control_;
|
||||
NodeParamViewKeyframeControl *key_control_;
|
||||
|
||||
QVector<Node*> nodes_;
|
||||
QVector<Node *> nodes_;
|
||||
|
||||
QVector<NodeKeyframeTrackReference> selected_tracks_;
|
||||
QVector<NodeKeyframeTrackReference> selected_tracks_;
|
||||
|
||||
private slots:
|
||||
void SelectionChanged();
|
||||
void SelectionChanged();
|
||||
|
||||
void KeyframeTypeButtonTriggered(bool checked);
|
||||
void KeyframeTypeButtonTriggered(bool checked);
|
||||
|
||||
void InputSelectionChanged(const NodeKeyframeTrackReference& ref);
|
||||
|
||||
void KeyframeViewDragged(int x, int y);
|
||||
void KeyframeViewReleased();
|
||||
void InputSelectionChanged(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void KeyframeViewDragged(int x, int y);
|
||||
void KeyframeViewReleased();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,50 +26,54 @@
|
||||
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
FileField::FileField(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
directory_mode_(false)
|
||||
namespace olive
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
FileField::FileField(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, directory_mode_(false)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
|
||||
line_edit_ = new QLineEdit();
|
||||
connect(line_edit_, &QLineEdit::textChanged, this, &FileField::LineEditChanged);
|
||||
connect(line_edit_, &QLineEdit::textEdited, this, &FileField::FilenameChanged);
|
||||
layout->addWidget(line_edit_);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
browse_btn_ = new QPushButton();
|
||||
browse_btn_->setIcon(icon::Open);
|
||||
connect(browse_btn_, &QPushButton::clicked, this, &FileField::BrowseBtnClicked);
|
||||
layout->addWidget(browse_btn_);
|
||||
line_edit_ = new QLineEdit();
|
||||
connect(line_edit_, &QLineEdit::textChanged, this,
|
||||
&FileField::LineEditChanged);
|
||||
connect(line_edit_, &QLineEdit::textEdited, this,
|
||||
&FileField::FilenameChanged);
|
||||
layout->addWidget(line_edit_);
|
||||
|
||||
browse_btn_ = new QPushButton();
|
||||
browse_btn_->setIcon(icon::Open);
|
||||
connect(browse_btn_, &QPushButton::clicked, this,
|
||||
&FileField::BrowseBtnClicked);
|
||||
layout->addWidget(browse_btn_);
|
||||
}
|
||||
|
||||
void FileField::BrowseBtnClicked()
|
||||
{
|
||||
QString s;
|
||||
QString s;
|
||||
|
||||
if (directory_mode_) {
|
||||
s = QFileDialog::getExistingDirectory(this, tr("Open Directory"));
|
||||
} else {
|
||||
s = QFileDialog::getOpenFileName(this, tr("Open File"));
|
||||
}
|
||||
if (directory_mode_) {
|
||||
s = QFileDialog::getExistingDirectory(this, tr("Open Directory"));
|
||||
} else {
|
||||
s = QFileDialog::getOpenFileName(this, tr("Open File"));
|
||||
}
|
||||
|
||||
if (!s.isEmpty()) {
|
||||
line_edit_->setText(s);
|
||||
emit FilenameChanged(s);
|
||||
}
|
||||
if (!s.isEmpty()) {
|
||||
line_edit_->setText(s);
|
||||
emit FilenameChanged(s);
|
||||
}
|
||||
}
|
||||
|
||||
void FileField::LineEditChanged(const QString& text)
|
||||
void FileField::LineEditChanged(const QString &text)
|
||||
{
|
||||
if (QFileInfo::exists(text) || text.isEmpty()) {
|
||||
line_edit_->setStyleSheet(QString());
|
||||
} else {
|
||||
line_edit_->setStyleSheet(QStringLiteral("QLineEdit {color: red;}"));
|
||||
}
|
||||
if (QFileInfo::exists(text) || text.isEmpty()) {
|
||||
line_edit_->setStyleSheet(QString());
|
||||
} else {
|
||||
line_edit_->setStyleSheet(QStringLiteral("QLineEdit {color: red;}"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,49 +24,48 @@
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
|
||||
namespace olive {
|
||||
|
||||
class FileField : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class FileField : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileField(QWidget* parent = nullptr);
|
||||
FileField(QWidget *parent = nullptr);
|
||||
|
||||
QString GetFilename() const
|
||||
{
|
||||
return line_edit_->text();
|
||||
}
|
||||
QString GetFilename() const
|
||||
{
|
||||
return line_edit_->text();
|
||||
}
|
||||
|
||||
void SetFilename(const QString& s)
|
||||
{
|
||||
line_edit_->setText(s);
|
||||
}
|
||||
void SetFilename(const QString &s)
|
||||
{
|
||||
line_edit_->setText(s);
|
||||
}
|
||||
|
||||
void SetPlaceholder(const QString& s)
|
||||
{
|
||||
line_edit_->setPlaceholderText(s);
|
||||
}
|
||||
void SetPlaceholder(const QString &s)
|
||||
{
|
||||
line_edit_->setPlaceholderText(s);
|
||||
}
|
||||
|
||||
void SetDirectoryMode(bool e)
|
||||
{
|
||||
directory_mode_ = e;
|
||||
}
|
||||
void SetDirectoryMode(bool e)
|
||||
{
|
||||
directory_mode_ = e;
|
||||
}
|
||||
|
||||
signals:
|
||||
void FilenameChanged(const QString& filename);
|
||||
void FilenameChanged(const QString &filename);
|
||||
|
||||
private:
|
||||
QLineEdit* line_edit_;
|
||||
QLineEdit *line_edit_;
|
||||
|
||||
QPushButton* browse_btn_;
|
||||
QPushButton *browse_btn_;
|
||||
|
||||
bool directory_mode_;
|
||||
bool directory_mode_;
|
||||
|
||||
private slots:
|
||||
void BrowseBtnClicked();
|
||||
|
||||
void LineEditChanged(const QString &text);
|
||||
void BrowseBtnClicked();
|
||||
|
||||
void LineEditChanged(const QString &text);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -48,153 +48,156 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include <QtWidgets>
|
||||
|
||||
#include "flowlayout.h"
|
||||
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
|
||||
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
|
||||
: QLayout(parent)
|
||||
, m_hSpace(hSpacing)
|
||||
, m_vSpace(vSpacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
|
||||
: m_hSpace(hSpacing), m_vSpace(vSpacing)
|
||||
: m_hSpace(hSpacing)
|
||||
, m_vSpace(vSpacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
FlowLayout::~FlowLayout()
|
||||
{
|
||||
QLayoutItem *item;
|
||||
while ((item = takeAt(0)))
|
||||
delete item;
|
||||
QLayoutItem *item;
|
||||
while ((item = takeAt(0)))
|
||||
delete item;
|
||||
}
|
||||
|
||||
void FlowLayout::addItem(QLayoutItem *item)
|
||||
{
|
||||
itemList.append(item);
|
||||
itemList.append(item);
|
||||
}
|
||||
|
||||
int FlowLayout::horizontalSpacing() const
|
||||
{
|
||||
if (m_hSpace >= 0) {
|
||||
return m_hSpace;
|
||||
} else {
|
||||
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
||||
}
|
||||
if (m_hSpace >= 0) {
|
||||
return m_hSpace;
|
||||
} else {
|
||||
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
||||
}
|
||||
}
|
||||
|
||||
int FlowLayout::verticalSpacing() const
|
||||
{
|
||||
if (m_vSpace >= 0) {
|
||||
return m_vSpace;
|
||||
} else {
|
||||
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
|
||||
}
|
||||
if (m_vSpace >= 0) {
|
||||
return m_vSpace;
|
||||
} else {
|
||||
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
|
||||
}
|
||||
}
|
||||
|
||||
int FlowLayout::count() const
|
||||
{
|
||||
return itemList.size();
|
||||
return itemList.size();
|
||||
}
|
||||
|
||||
QLayoutItem *FlowLayout::itemAt(int index) const
|
||||
{
|
||||
return itemList.value(index);
|
||||
return itemList.value(index);
|
||||
}
|
||||
|
||||
QLayoutItem *FlowLayout::takeAt(int index)
|
||||
{
|
||||
if (index >= 0 && index < itemList.size())
|
||||
return itemList.takeAt(index);
|
||||
else
|
||||
return 0;
|
||||
if (index >= 0 && index < itemList.size())
|
||||
return itemList.takeAt(index);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
Qt::Orientations FlowLayout::expandingDirections() const
|
||||
{
|
||||
return Qt::Horizontal | Qt::Vertical;
|
||||
return Qt::Horizontal | Qt::Vertical;
|
||||
}
|
||||
|
||||
bool FlowLayout::hasHeightForWidth() const
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
int FlowLayout::heightForWidth(int width) const
|
||||
{
|
||||
int height = doLayout(QRect(0, 0, width, 0), true);
|
||||
return height;
|
||||
int height = doLayout(QRect(0, 0, width, 0), true);
|
||||
return height;
|
||||
}
|
||||
|
||||
void FlowLayout::setGeometry(const QRect &rect)
|
||||
{
|
||||
QLayout::setGeometry(rect);
|
||||
doLayout(rect, false);
|
||||
QLayout::setGeometry(rect);
|
||||
doLayout(rect, false);
|
||||
}
|
||||
|
||||
QSize FlowLayout::sizeHint() const
|
||||
{
|
||||
return minimumSize();
|
||||
return minimumSize();
|
||||
}
|
||||
|
||||
QSize FlowLayout::minimumSize() const
|
||||
{
|
||||
QSize size;
|
||||
QLayoutItem *item;
|
||||
foreach (item, itemList)
|
||||
size = size.expandedTo(item->minimumSize());
|
||||
QSize size;
|
||||
QLayoutItem *item;
|
||||
foreach (item, itemList)
|
||||
size = size.expandedTo(item->minimumSize());
|
||||
|
||||
size += QSize(2*contentsMargins().left(), 2*contentsMargins().top());
|
||||
return size;
|
||||
size += QSize(2 * contentsMargins().left(), 2 * contentsMargins().top());
|
||||
return size;
|
||||
}
|
||||
|
||||
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
|
||||
{
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
||||
int x = effectiveRect.x();
|
||||
int y = effectiveRect.y();
|
||||
int lineHeight = 0;
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
||||
int x = effectiveRect.x();
|
||||
int y = effectiveRect.y();
|
||||
int lineHeight = 0;
|
||||
|
||||
QLayoutItem *item;
|
||||
foreach (item, itemList) {
|
||||
QWidget *wid = item->widget();
|
||||
int spaceX = horizontalSpacing();
|
||||
if (spaceX == -1)
|
||||
spaceX = wid->style()->layoutSpacing(
|
||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
|
||||
int spaceY = verticalSpacing();
|
||||
if (spaceY == -1)
|
||||
spaceY = wid->style()->layoutSpacing(
|
||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
|
||||
int nextX = x + item->sizeHint().width() + spaceX;
|
||||
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
|
||||
x = effectiveRect.x();
|
||||
y = y + lineHeight + spaceY;
|
||||
nextX = x + item->sizeHint().width() + spaceX;
|
||||
lineHeight = 0;
|
||||
}
|
||||
QLayoutItem *item;
|
||||
foreach (item, itemList) {
|
||||
QWidget *wid = item->widget();
|
||||
int spaceX = horizontalSpacing();
|
||||
if (spaceX == -1)
|
||||
spaceX = wid->style()->layoutSpacing(QSizePolicy::PushButton,
|
||||
QSizePolicy::PushButton,
|
||||
Qt::Horizontal);
|
||||
int spaceY = verticalSpacing();
|
||||
if (spaceY == -1)
|
||||
spaceY = wid->style()->layoutSpacing(
|
||||
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);
|
||||
int nextX = x + item->sizeHint().width() + spaceX;
|
||||
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
|
||||
x = effectiveRect.x();
|
||||
y = y + lineHeight + spaceY;
|
||||
nextX = x + item->sizeHint().width() + spaceX;
|
||||
lineHeight = 0;
|
||||
}
|
||||
|
||||
if (!testOnly)
|
||||
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
|
||||
if (!testOnly)
|
||||
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
|
||||
|
||||
x = nextX;
|
||||
lineHeight = qMax(lineHeight, item->sizeHint().height());
|
||||
}
|
||||
return y + lineHeight - rect.y() + bottom;
|
||||
x = nextX;
|
||||
lineHeight = qMax(lineHeight, item->sizeHint().height());
|
||||
}
|
||||
return y + lineHeight - rect.y() + bottom;
|
||||
}
|
||||
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
|
||||
{
|
||||
QObject *parent = this->parent();
|
||||
if (!parent) {
|
||||
return -1;
|
||||
} else if (parent->isWidgetType()) {
|
||||
QWidget *pw = static_cast<QWidget *>(parent);
|
||||
return pw->style()->pixelMetric(pm, 0, pw);
|
||||
} else {
|
||||
return static_cast<QLayout *>(parent)->spacing();
|
||||
}
|
||||
QObject *parent = this->parent();
|
||||
if (!parent) {
|
||||
return -1;
|
||||
} else if (parent->isWidgetType()) {
|
||||
QWidget *pw = static_cast<QWidget *>(parent);
|
||||
return pw->style()->pixelMetric(pm, 0, pw);
|
||||
} else {
|
||||
return static_cast<QLayout *>(parent)->spacing();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,40 +48,39 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef FLOWLAYOUT_H
|
||||
#define FLOWLAYOUT_H
|
||||
|
||||
#include <QLayout>
|
||||
#include <QRect>
|
||||
#include <QStyle>
|
||||
class FlowLayout : public QLayout
|
||||
{
|
||||
class FlowLayout : public QLayout {
|
||||
public:
|
||||
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||
~FlowLayout();
|
||||
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1,
|
||||
int vSpacing = -1);
|
||||
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||
~FlowLayout();
|
||||
|
||||
void addItem(QLayoutItem *item) override;
|
||||
int horizontalSpacing() const;
|
||||
int verticalSpacing() const;
|
||||
Qt::Orientations expandingDirections() const override;
|
||||
bool hasHeightForWidth() const override;
|
||||
int heightForWidth(int) const override;
|
||||
int count() const override;
|
||||
QLayoutItem *itemAt(int index) const override;
|
||||
QSize minimumSize() const override;
|
||||
void setGeometry(const QRect &rect) override;
|
||||
QSize sizeHint() const override;
|
||||
QLayoutItem *takeAt(int index) override;
|
||||
void addItem(QLayoutItem *item) override;
|
||||
int horizontalSpacing() const;
|
||||
int verticalSpacing() const;
|
||||
Qt::Orientations expandingDirections() const override;
|
||||
bool hasHeightForWidth() const override;
|
||||
int heightForWidth(int) const override;
|
||||
int count() const override;
|
||||
QLayoutItem *itemAt(int index) const override;
|
||||
QSize minimumSize() const override;
|
||||
void setGeometry(const QRect &rect) override;
|
||||
QSize sizeHint() const override;
|
||||
QLayoutItem *takeAt(int index) override;
|
||||
|
||||
private:
|
||||
int doLayout(const QRect &rect, bool testOnly) const;
|
||||
int smartSpacing(QStyle::PixelMetric pm) const;
|
||||
int doLayout(const QRect &rect, bool testOnly) const;
|
||||
int smartSpacing(QStyle::PixelMetric pm) const;
|
||||
|
||||
QList<QLayoutItem *> itemList;
|
||||
int m_hSpace;
|
||||
int m_vSpace;
|
||||
QList<QLayoutItem *> itemList;
|
||||
int m_hSpace;
|
||||
int m_vSpace;
|
||||
};
|
||||
|
||||
#endif // FLOWLAYOUT_H
|
||||
|
||||
@@ -22,34 +22,34 @@
|
||||
|
||||
#include <QKeyEvent>
|
||||
|
||||
namespace olive {
|
||||
|
||||
FocusableLineEdit::FocusableLineEdit(QWidget *parent) :
|
||||
QLineEdit(parent)
|
||||
namespace olive
|
||||
{
|
||||
|
||||
FocusableLineEdit::FocusableLineEdit(QWidget *parent)
|
||||
: QLineEdit(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void FocusableLineEdit::keyPressEvent(QKeyEvent *e)
|
||||
{
|
||||
switch (e->key()) {
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
emit Confirmed();
|
||||
break;
|
||||
case Qt::Key_Escape:
|
||||
emit Cancelled();
|
||||
break;
|
||||
default:
|
||||
QLineEdit::keyPressEvent(e);
|
||||
}
|
||||
switch (e->key()) {
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
emit Confirmed();
|
||||
break;
|
||||
case Qt::Key_Escape:
|
||||
emit Cancelled();
|
||||
break;
|
||||
default:
|
||||
QLineEdit::keyPressEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
void FocusableLineEdit::focusOutEvent(QFocusEvent *e)
|
||||
{
|
||||
QLineEdit::focusOutEvent(e);
|
||||
QLineEdit::focusOutEvent(e);
|
||||
|
||||
emit Confirmed();
|
||||
emit Confirmed();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,25 +25,23 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class FocusableLineEdit : public QLineEdit
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class FocusableLineEdit : public QLineEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FocusableLineEdit(QWidget* parent = nullptr);
|
||||
FocusableLineEdit(QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void Confirmed();
|
||||
void Confirmed();
|
||||
|
||||
void Cancelled();
|
||||
void Cancelled();
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent *) override;
|
||||
|
||||
void focusOutEvent(QFocusEvent *) override;
|
||||
|
||||
void keyPressEvent(QKeyEvent *) override;
|
||||
|
||||
void focusOutEvent(QFocusEvent *) override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,218 +25,206 @@
|
||||
#include "config/config.h"
|
||||
#include "core.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QGraphicsView
|
||||
|
||||
HandMovableView::HandMovableView(QWidget* parent) :
|
||||
super(parent),
|
||||
dragging_hand_(false),
|
||||
is_timeline_axes_(false)
|
||||
HandMovableView::HandMovableView(QWidget *parent)
|
||||
: super(parent)
|
||||
, dragging_hand_(false)
|
||||
, is_timeline_axes_(false)
|
||||
{
|
||||
connect(Core::instance(), &Core::ToolChanged, this, &HandMovableView::ApplicationToolChanged);
|
||||
connect(Core::instance(), &Core::ToolChanged, this,
|
||||
&HandMovableView::ApplicationToolChanged);
|
||||
}
|
||||
|
||||
void HandMovableView::ApplicationToolChanged(Tool::Item tool)
|
||||
{
|
||||
if (tool == Tool::kHand) {
|
||||
setDragMode(ScrollHandDrag);
|
||||
setInteractive(false);
|
||||
} else {
|
||||
setDragMode(default_drag_mode_);
|
||||
setInteractive(true);
|
||||
}
|
||||
if (tool == Tool::kHand) {
|
||||
setDragMode(ScrollHandDrag);
|
||||
setInteractive(false);
|
||||
} else {
|
||||
setDragMode(default_drag_mode_);
|
||||
setInteractive(true);
|
||||
}
|
||||
|
||||
ToolChangedEvent(tool);
|
||||
ToolChangedEvent(tool);
|
||||
}
|
||||
|
||||
bool HandMovableView::HandPress(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::MiddleButton) {
|
||||
pre_hand_drag_mode_ = dragMode();
|
||||
dragging_hand_ = true;
|
||||
if (event->button() == Qt::MiddleButton) {
|
||||
pre_hand_drag_mode_ = dragMode();
|
||||
dragging_hand_ = true;
|
||||
|
||||
setDragMode(ScrollHandDrag);
|
||||
setInteractive(false);
|
||||
setDragMode(ScrollHandDrag);
|
||||
setInteractive(false);
|
||||
|
||||
// Transform mouse event to act like the left button is pressed
|
||||
QMouseEvent transformed(event->type(),
|
||||
event->pos(),
|
||||
Qt::LeftButton,
|
||||
Qt::LeftButton,
|
||||
event->modifiers());
|
||||
// Transform mouse event to act like the left button is pressed
|
||||
QMouseEvent transformed(event->type(), event->pos(), Qt::LeftButton,
|
||||
Qt::LeftButton, event->modifiers());
|
||||
|
||||
transformed_pos_ = QPoint(0, 0);
|
||||
transformed_pos_ = QPoint(0, 0);
|
||||
|
||||
super::mousePressEvent(&transformed);
|
||||
super::mousePressEvent(&transformed);
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandMovableView::HandMove(QMouseEvent *event)
|
||||
{
|
||||
if (dragging_hand_) {
|
||||
// Transform mouse event to act like the left button is pressed
|
||||
QPoint adjustment(0, 0);
|
||||
if (dragging_hand_) {
|
||||
// Transform mouse event to act like the left button is pressed
|
||||
QPoint adjustment(0, 0);
|
||||
|
||||
QMouseEvent transformed(event->type(),
|
||||
event->pos() - transformed_pos_,
|
||||
Qt::LeftButton,
|
||||
Qt::LeftButton,
|
||||
event->modifiers());
|
||||
QMouseEvent transformed(event->type(), event->pos() - transformed_pos_,
|
||||
Qt::LeftButton, Qt::LeftButton,
|
||||
event->modifiers());
|
||||
|
||||
if (event->pos().x() < 0) {
|
||||
transformed_pos_.setX(transformed_pos_.x() + width());
|
||||
adjustment.setX(width());
|
||||
} else if (event->pos().x() >= width()) {
|
||||
transformed_pos_.setX(transformed_pos_.x() - width());
|
||||
adjustment.setX(-width());
|
||||
}
|
||||
if (event->pos().x() < 0) {
|
||||
transformed_pos_.setX(transformed_pos_.x() + width());
|
||||
adjustment.setX(width());
|
||||
} else if (event->pos().x() >= width()) {
|
||||
transformed_pos_.setX(transformed_pos_.x() - width());
|
||||
adjustment.setX(-width());
|
||||
}
|
||||
|
||||
if (event->pos().y() < 0) {
|
||||
transformed_pos_.setY(transformed_pos_.y() + height());
|
||||
adjustment.setY(height());
|
||||
} else if (event->pos().y() >= height()) {
|
||||
transformed_pos_.setY(transformed_pos_.y() - height());
|
||||
adjustment.setY(-height());
|
||||
}
|
||||
if (event->pos().y() < 0) {
|
||||
transformed_pos_.setY(transformed_pos_.y() + height());
|
||||
adjustment.setY(height());
|
||||
} else if (event->pos().y() >= height()) {
|
||||
transformed_pos_.setY(transformed_pos_.y() - height());
|
||||
adjustment.setY(-height());
|
||||
}
|
||||
|
||||
if (!adjustment.isNull()) {
|
||||
QCursor::setPos(QCursor::pos() + adjustment);
|
||||
}
|
||||
if (!adjustment.isNull()) {
|
||||
QCursor::setPos(QCursor::pos() + adjustment);
|
||||
}
|
||||
|
||||
super::mouseMoveEvent(&transformed);
|
||||
}
|
||||
return dragging_hand_;
|
||||
super::mouseMoveEvent(&transformed);
|
||||
}
|
||||
return dragging_hand_;
|
||||
}
|
||||
|
||||
bool HandMovableView::HandRelease(QMouseEvent *event)
|
||||
{
|
||||
if (dragging_hand_) {
|
||||
// Transform mouse event to act like the left button is pressed
|
||||
QMouseEvent transformed(event->type(),
|
||||
event->localPos(),
|
||||
event->windowPos(),
|
||||
event->screenPos(),
|
||||
Qt::LeftButton,
|
||||
Qt::LeftButton,
|
||||
event->modifiers(),
|
||||
event->source());
|
||||
if (dragging_hand_) {
|
||||
// Transform mouse event to act like the left button is pressed
|
||||
QMouseEvent transformed(event->type(), event->localPos(),
|
||||
event->windowPos(), event->screenPos(),
|
||||
Qt::LeftButton, Qt::LeftButton,
|
||||
event->modifiers(), event->source());
|
||||
|
||||
super::mouseReleaseEvent(&transformed);
|
||||
super::mouseReleaseEvent(&transformed);
|
||||
|
||||
setInteractive(true);
|
||||
setDragMode(pre_hand_drag_mode_);
|
||||
setInteractive(true);
|
||||
setDragMode(pre_hand_drag_mode_);
|
||||
|
||||
dragging_hand_ = false;
|
||||
dragging_hand_ = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandMovableView::SetDefaultDragMode(HandMovableView::DragMode mode)
|
||||
{
|
||||
default_drag_mode_ = mode;
|
||||
setDragMode(default_drag_mode_);
|
||||
default_drag_mode_ = mode;
|
||||
setDragMode(default_drag_mode_);
|
||||
}
|
||||
|
||||
const HandMovableView::DragMode &HandMovableView::GetDefaultDragMode() const
|
||||
{
|
||||
return default_drag_mode_;
|
||||
return default_drag_mode_;
|
||||
}
|
||||
|
||||
bool HandMovableView::WheelEventIsAZoomEvent(QWheelEvent *event)
|
||||
{
|
||||
return (static_cast<bool>(event->modifiers() & Qt::ControlModifier) == !OLIVE_CONFIG("ScrollZooms").toBool());
|
||||
return (static_cast<bool>(event->modifiers() & Qt::ControlModifier) ==
|
||||
!OLIVE_CONFIG("ScrollZooms").toBool());
|
||||
}
|
||||
|
||||
qreal HandMovableView::GetScrollZoomMultiplier(QWheelEvent *event)
|
||||
{
|
||||
qreal v = (static_cast<qreal>(event->angleDelta().x() + event->angleDelta().y()) * 0.001);
|
||||
if (event->inverted()) {
|
||||
v = -v;
|
||||
}
|
||||
return 1.0 + v;
|
||||
qreal v =
|
||||
(static_cast<qreal>(event->angleDelta().x() + event->angleDelta().y()) *
|
||||
0.001);
|
||||
if (event->inverted()) {
|
||||
v = -v;
|
||||
}
|
||||
return 1.0 + v;
|
||||
}
|
||||
|
||||
void HandMovableView::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
if (WheelEventIsAZoomEvent(event)) {
|
||||
if (!event->angleDelta().isNull()) {
|
||||
qreal multiplier = GetScrollZoomMultiplier(event);
|
||||
if (WheelEventIsAZoomEvent(event)) {
|
||||
if (!event->angleDelta().isNull()) {
|
||||
qreal multiplier = GetScrollZoomMultiplier(event);
|
||||
|
||||
QPointF cursor_pos;
|
||||
QPointF cursor_pos;
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||
cursor_pos = event->position();
|
||||
cursor_pos = event->position();
|
||||
#else
|
||||
cursor_pos = event->posF();
|
||||
cursor_pos = event->posF();
|
||||
#endif
|
||||
|
||||
ZoomIntoCursorPosition(event, multiplier, cursor_pos);
|
||||
}
|
||||
} else if (is_timeline_axes_) {
|
||||
ZoomIntoCursorPosition(event, multiplier, cursor_pos);
|
||||
}
|
||||
} else if (is_timeline_axes_) {
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
|
||||
|
||||
QPoint angle_delta = event->angleDelta();
|
||||
QPoint angle_delta = event->angleDelta();
|
||||
|
||||
if (OLIVE_CONFIG("InvertTimelineScrollAxes").toBool() // Check if config is set to invert timeline axes
|
||||
&& event->source() != Qt::MouseEventSynthesizedBySystem) { // Never flip axes on Apple trackpads though
|
||||
angle_delta = QPoint(angle_delta.y(), angle_delta.x());
|
||||
}
|
||||
if (OLIVE_CONFIG("InvertTimelineScrollAxes")
|
||||
.toBool() // Check if config is set to invert timeline axes
|
||||
&&
|
||||
event->source() !=
|
||||
Qt::MouseEventSynthesizedBySystem) { // Never flip axes on Apple trackpads though
|
||||
angle_delta = QPoint(angle_delta.y(), angle_delta.x());
|
||||
}
|
||||
|
||||
QWheelEvent e(
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
event->position(),
|
||||
event->globalPosition(),
|
||||
#else
|
||||
event->pos(),
|
||||
event->globalPos(),
|
||||
#endif
|
||||
event->pixelDelta(),
|
||||
angle_delta,
|
||||
event->buttons(),
|
||||
event->modifiers(),
|
||||
event->phase(),
|
||||
event->inverted(),
|
||||
event->source()
|
||||
);
|
||||
QWheelEvent e(
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
event->position(), event->globalPosition(),
|
||||
#else
|
||||
event->pos(), event->globalPos(),
|
||||
#endif
|
||||
event->pixelDelta(), angle_delta, event->buttons(),
|
||||
event->modifiers(), event->phase(), event->inverted(),
|
||||
event->source());
|
||||
|
||||
#else
|
||||
|
||||
Qt::Orientation orientation = event->orientation();
|
||||
Qt::Orientation orientation = event->orientation();
|
||||
|
||||
if (OLIVE_CONFIG("InvertTimelineScrollAxes").toBool()) {
|
||||
orientation = (orientation == Qt::Horizontal) ? Qt::Vertical : Qt::Horizontal;
|
||||
}
|
||||
if (OLIVE_CONFIG("InvertTimelineScrollAxes").toBool()) {
|
||||
orientation = (orientation == Qt::Horizontal) ? Qt::Vertical :
|
||||
Qt::Horizontal;
|
||||
}
|
||||
|
||||
QWheelEvent e(
|
||||
event->pos(),
|
||||
event->globalPos(),
|
||||
event->pixelDelta(),
|
||||
event->angleDelta(),
|
||||
event->delta(),
|
||||
orientation,
|
||||
event->buttons(),
|
||||
event->modifiers()
|
||||
);
|
||||
QWheelEvent e(event->pos(), event->globalPos(), event->pixelDelta(),
|
||||
event->angleDelta(), event->delta(), orientation,
|
||||
event->buttons(), event->modifiers());
|
||||
#endif
|
||||
|
||||
super::wheelEvent(&e);
|
||||
} else {
|
||||
super::wheelEvent(event);
|
||||
}
|
||||
super::wheelEvent(&e);
|
||||
} else {
|
||||
super::wheelEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void HandMovableView::ZoomIntoCursorPosition(QWheelEvent *event, double multiplier, const QPointF &cursor_pos)
|
||||
void HandMovableView::ZoomIntoCursorPosition(QWheelEvent *event,
|
||||
double multiplier,
|
||||
const QPointF &cursor_pos)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(multiplier)
|
||||
Q_UNUSED(cursor_pos)
|
||||
Q_UNUSED(event)
|
||||
Q_UNUSED(multiplier)
|
||||
Q_UNUSED(cursor_pos)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,49 +26,57 @@
|
||||
|
||||
#include "tool/tool.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class HandMovableView : public QGraphicsView
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class HandMovableView : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
HandMovableView(QWidget* parent = nullptr);
|
||||
HandMovableView(QWidget *parent = nullptr);
|
||||
|
||||
static bool WheelEventIsAZoomEvent(QWheelEvent* event);
|
||||
static bool WheelEventIsAZoomEvent(QWheelEvent *event);
|
||||
|
||||
static qreal GetScrollZoomMultiplier(QWheelEvent* event);
|
||||
static qreal GetScrollZoomMultiplier(QWheelEvent *event);
|
||||
|
||||
virtual void CatchUpScrollEvent(){}
|
||||
virtual void CatchUpScrollEvent()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void ToolChangedEvent(Tool::Item tool){Q_UNUSED(tool)}
|
||||
virtual void ToolChangedEvent(Tool::Item tool)
|
||||
{
|
||||
Q_UNUSED(tool)
|
||||
}
|
||||
|
||||
bool HandPress(QMouseEvent* event);
|
||||
bool HandMove(QMouseEvent* event);
|
||||
bool HandRelease(QMouseEvent* event);
|
||||
bool HandPress(QMouseEvent *event);
|
||||
bool HandMove(QMouseEvent *event);
|
||||
bool HandRelease(QMouseEvent *event);
|
||||
|
||||
void SetDefaultDragMode(DragMode mode);
|
||||
const DragMode& GetDefaultDragMode() const;
|
||||
void SetDefaultDragMode(DragMode mode);
|
||||
const DragMode &GetDefaultDragMode() const;
|
||||
|
||||
virtual void wheelEvent(QWheelEvent* event) override;
|
||||
virtual void wheelEvent(QWheelEvent *event) override;
|
||||
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent* event, double multiplier, const QPointF &cursor_pos);
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier,
|
||||
const QPointF &cursor_pos);
|
||||
|
||||
void SetIsTimelineAxes(bool e) { is_timeline_axes_ = e; }
|
||||
void SetIsTimelineAxes(bool e)
|
||||
{
|
||||
is_timeline_axes_ = e;
|
||||
}
|
||||
|
||||
private:
|
||||
bool dragging_hand_;
|
||||
DragMode pre_hand_drag_mode_;
|
||||
bool dragging_hand_;
|
||||
DragMode pre_hand_drag_mode_;
|
||||
|
||||
DragMode default_drag_mode_;
|
||||
DragMode default_drag_mode_;
|
||||
|
||||
QPointF transformed_pos_;
|
||||
QPointF transformed_pos_;
|
||||
|
||||
bool is_timeline_axes_;
|
||||
bool is_timeline_axes_;
|
||||
|
||||
private slots:
|
||||
void ApplicationToolChanged(Tool::Item tool);
|
||||
|
||||
void ApplicationToolChanged(Tool::Item tool);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,28 +22,34 @@
|
||||
|
||||
#include "core.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
HistoryWidget::HistoryWidget(QWidget *parent) :
|
||||
QTreeView(parent)
|
||||
namespace olive
|
||||
{
|
||||
stack_ = Core::instance()->undo_stack();
|
||||
|
||||
this->setModel(stack_);
|
||||
this->setRootIsDecorated(false);
|
||||
connect(stack_, &UndoStack::indexChanged, this, &HistoryWidget::indexChanged);
|
||||
connect(this->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &HistoryWidget::currentRowChanged);
|
||||
HistoryWidget::HistoryWidget(QWidget *parent)
|
||||
: QTreeView(parent)
|
||||
{
|
||||
stack_ = Core::instance()->undo_stack();
|
||||
|
||||
this->setModel(stack_);
|
||||
this->setRootIsDecorated(false);
|
||||
connect(stack_, &UndoStack::indexChanged, this,
|
||||
&HistoryWidget::indexChanged);
|
||||
connect(this->selectionModel(), &QItemSelectionModel::currentRowChanged,
|
||||
this, &HistoryWidget::currentRowChanged);
|
||||
}
|
||||
|
||||
void HistoryWidget::indexChanged(int i)
|
||||
{
|
||||
this->selectionModel()->select(this->model()->index(i-1, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows);
|
||||
this->selectionModel()->select(this->model()->index(i - 1, 0),
|
||||
QItemSelectionModel::ClearAndSelect |
|
||||
QItemSelectionModel::Rows);
|
||||
}
|
||||
|
||||
void HistoryWidget::currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous)
|
||||
void HistoryWidget::currentRowChanged(const QModelIndex ¤t,
|
||||
const QModelIndex &previous)
|
||||
{
|
||||
size_t jump_to = (current.row() + 1);
|
||||
stack_->jump(jump_to);
|
||||
size_t jump_to = (current.row() + 1);
|
||||
stack_->jump(jump_to);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,24 +25,24 @@
|
||||
|
||||
#include "undo/undostack.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class HistoryWidget : public QTreeView
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class HistoryWidget : public QTreeView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
HistoryWidget(QWidget *parent = nullptr);
|
||||
HistoryWidget(QWidget *parent = nullptr);
|
||||
|
||||
private:
|
||||
UndoStack *stack_;
|
||||
UndoStack *stack_;
|
||||
|
||||
size_t current_row_;
|
||||
size_t current_row_;
|
||||
|
||||
private slots:
|
||||
void indexChanged(int i);
|
||||
|
||||
void currentRowChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void indexChanged(int i);
|
||||
|
||||
void currentRowChanged(const QModelIndex ¤t,
|
||||
const QModelIndex &previous);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -30,144 +30,162 @@
|
||||
#include "widget/timebased/timebasedviewselectionmanager.h"
|
||||
#include "widget/timetarget/timetarget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class KeyframeView : public TimeBasedView, public TimeTargetObject
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class KeyframeView : public TimeBasedView, public TimeTargetObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyframeView(QWidget* parent = nullptr);
|
||||
KeyframeView(QWidget *parent = nullptr);
|
||||
|
||||
void DeleteSelected();
|
||||
void DeleteSelected();
|
||||
|
||||
using ElementConnections = QVector<KeyframeViewInputConnection *>;
|
||||
using InputConnections = QVector<ElementConnections>;
|
||||
using NodeConnections = QMap<QString, InputConnections>;
|
||||
using ElementConnections = QVector<KeyframeViewInputConnection *>;
|
||||
using InputConnections = QVector<ElementConnections>;
|
||||
using NodeConnections = QMap<QString, InputConnections>;
|
||||
|
||||
NodeConnections AddKeyframesOfNode(Node* n);
|
||||
NodeConnections AddKeyframesOfNode(Node *n);
|
||||
|
||||
InputConnections AddKeyframesOfInput(Node *n, const QString &input);
|
||||
InputConnections AddKeyframesOfInput(Node *n, const QString &input);
|
||||
|
||||
ElementConnections AddKeyframesOfElement(const NodeInput &input);
|
||||
ElementConnections AddKeyframesOfElement(const NodeInput &input);
|
||||
|
||||
KeyframeViewInputConnection *AddKeyframesOfTrack(const NodeKeyframeTrackReference &ref);
|
||||
KeyframeViewInputConnection *
|
||||
AddKeyframesOfTrack(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void RemoveKeyframesOfTrack(KeyframeViewInputConnection *connection);
|
||||
void RemoveKeyframesOfTrack(KeyframeViewInputConnection *connection);
|
||||
|
||||
void SelectAll();
|
||||
void SelectAll();
|
||||
|
||||
void DeselectAll();
|
||||
void DeselectAll();
|
||||
|
||||
void Clear();
|
||||
void Clear();
|
||||
|
||||
const std::vector<NodeKeyframe*> &GetSelectedKeyframes() const
|
||||
{
|
||||
return selection_manager_.GetSelectedObjects();
|
||||
}
|
||||
const std::vector<NodeKeyframe *> &GetSelectedKeyframes() const
|
||||
{
|
||||
return selection_manager_.GetSelectedObjects();
|
||||
}
|
||||
|
||||
const QVector<KeyframeViewInputConnection*> &GetKeyframeTracks() const
|
||||
{
|
||||
return tracks_;
|
||||
}
|
||||
const QVector<KeyframeViewInputConnection *> &GetKeyframeTracks() const
|
||||
{
|
||||
return tracks_;
|
||||
}
|
||||
|
||||
virtual void SelectionManagerSelectEvent(void *obj) override;
|
||||
virtual void SelectionManagerDeselectEvent(void *obj) override;
|
||||
virtual void SelectionManagerSelectEvent(void *obj) override;
|
||||
virtual void SelectionManagerDeselectEvent(void *obj) override;
|
||||
|
||||
void SetMaxScroll(int i)
|
||||
{
|
||||
max_scroll_ = i;
|
||||
UpdateSceneRect();
|
||||
}
|
||||
void SetMaxScroll(int i)
|
||||
{
|
||||
max_scroll_ = i;
|
||||
UpdateSceneRect();
|
||||
}
|
||||
|
||||
bool CopySelected(bool cut);
|
||||
bool CopySelected(bool cut);
|
||||
|
||||
bool Paste(std::function<Node *(const QString &)> find_node_function);
|
||||
bool Paste(std::function<Node *(const QString &)> find_node_function);
|
||||
|
||||
virtual void CatchUpScrollEvent() override;
|
||||
virtual void CatchUpScrollEvent() override;
|
||||
|
||||
signals:
|
||||
void Dragged(int current_x, int current_y);
|
||||
void Dragged(int current_x, int current_y);
|
||||
|
||||
void SelectionChanged();
|
||||
void SelectionChanged();
|
||||
|
||||
void Released();
|
||||
void Released();
|
||||
|
||||
protected:
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
virtual void drawForeground(QPainter *painter, const QRectF &rect) override;
|
||||
|
||||
virtual void DrawKeyframe(QPainter *painter, NodeKeyframe *key, KeyframeViewInputConnection *track, const QRectF &key_rect);
|
||||
virtual void DrawKeyframe(QPainter *painter, NodeKeyframe *key,
|
||||
KeyframeViewInputConnection *track,
|
||||
const QRectF &key_rect);
|
||||
|
||||
virtual void ScaleChangedEvent(const double& scale) override;
|
||||
virtual void ScaleChangedEvent(const double &scale) override;
|
||||
|
||||
virtual void TimeTargetChangedEvent(ViewerOutput *v) override;
|
||||
virtual void TimeTargetChangedEvent(ViewerOutput *v) override;
|
||||
|
||||
virtual void TimebaseChangedEvent(const rational &timebase) override;
|
||||
virtual void TimebaseChangedEvent(const rational &timebase) override;
|
||||
|
||||
virtual void ContextMenuEvent(Menu &m);
|
||||
virtual void ContextMenuEvent(Menu &m);
|
||||
|
||||
virtual bool FirstChanceMousePress(QMouseEvent *event){return false;}
|
||||
virtual void FirstChanceMouseMove(QMouseEvent *event){}
|
||||
virtual void FirstChanceMouseRelease(QMouseEvent *event){}
|
||||
virtual bool FirstChanceMousePress(QMouseEvent *event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
virtual void FirstChanceMouseMove(QMouseEvent *event)
|
||||
{
|
||||
}
|
||||
virtual void FirstChanceMouseRelease(QMouseEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void KeyframeDragStart(QMouseEvent *event){}
|
||||
virtual void KeyframeDragMove(QMouseEvent *event, QString &tip){}
|
||||
virtual void KeyframeDragRelease(QMouseEvent *event, MultiUndoCommand *command){}
|
||||
virtual void KeyframeDragStart(QMouseEvent *event)
|
||||
{
|
||||
}
|
||||
virtual void KeyframeDragMove(QMouseEvent *event, QString &tip)
|
||||
{
|
||||
}
|
||||
virtual void KeyframeDragRelease(QMouseEvent *event,
|
||||
MultiUndoCommand *command)
|
||||
{
|
||||
}
|
||||
|
||||
void SelectKeyframe(NodeKeyframe *key);
|
||||
void SelectKeyframe(NodeKeyframe *key);
|
||||
|
||||
void DeselectKeyframe(NodeKeyframe *key);
|
||||
void DeselectKeyframe(NodeKeyframe *key);
|
||||
|
||||
bool IsKeyframeSelected(NodeKeyframe *key) const
|
||||
{
|
||||
return selection_manager_.IsSelected(key);
|
||||
}
|
||||
bool IsKeyframeSelected(NodeKeyframe *key) const
|
||||
{
|
||||
return selection_manager_.IsSelected(key);
|
||||
}
|
||||
|
||||
rational GetUnadjustedKeyframeTime(NodeKeyframe *key, const rational &time);
|
||||
rational GetUnadjustedKeyframeTime(NodeKeyframe *key)
|
||||
{
|
||||
return GetUnadjustedKeyframeTime(key, key->time());
|
||||
}
|
||||
rational GetUnadjustedKeyframeTime(NodeKeyframe *key, const rational &time);
|
||||
rational GetUnadjustedKeyframeTime(NodeKeyframe *key)
|
||||
{
|
||||
return GetUnadjustedKeyframeTime(key, key->time());
|
||||
}
|
||||
|
||||
rational GetAdjustedKeyframeTime(NodeKeyframe *key);
|
||||
rational GetAdjustedKeyframeTime(NodeKeyframe *key);
|
||||
|
||||
double GetKeyframeSceneX(NodeKeyframe *key);
|
||||
double GetKeyframeSceneX(NodeKeyframe *key);
|
||||
|
||||
virtual qreal GetKeyframeSceneY(KeyframeViewInputConnection *track, NodeKeyframe *key);
|
||||
virtual qreal GetKeyframeSceneY(KeyframeViewInputConnection *track,
|
||||
NodeKeyframe *key);
|
||||
|
||||
void SetAutoSelectSiblings(bool e)
|
||||
{
|
||||
autoselect_siblings_ = e;
|
||||
}
|
||||
void SetAutoSelectSiblings(bool e)
|
||||
{
|
||||
autoselect_siblings_ = e;
|
||||
}
|
||||
|
||||
virtual void SceneRectUpdateEvent(QRectF& rect) override;
|
||||
virtual void SceneRectUpdateEvent(QRectF &rect) override;
|
||||
|
||||
protected slots:
|
||||
void Redraw();
|
||||
void Redraw();
|
||||
|
||||
private:
|
||||
rational CalculateNewTimeFromScreen(const rational& old_time, double cursor_diff);
|
||||
rational CalculateNewTimeFromScreen(const rational &old_time,
|
||||
double cursor_diff);
|
||||
|
||||
QVector<KeyframeViewInputConnection*> tracks_;
|
||||
QVector<KeyframeViewInputConnection *> tracks_;
|
||||
|
||||
TimeBasedViewSelectionManager<NodeKeyframe> selection_manager_;
|
||||
TimeBasedViewSelectionManager<NodeKeyframe> selection_manager_;
|
||||
|
||||
bool autoselect_siblings_;
|
||||
bool autoselect_siblings_;
|
||||
|
||||
int max_scroll_;
|
||||
int max_scroll_;
|
||||
|
||||
bool first_chance_mouse_event_;
|
||||
bool first_chance_mouse_event_;
|
||||
|
||||
private slots:
|
||||
void ShowContextMenu();
|
||||
void ShowContextMenu();
|
||||
|
||||
void ShowKeyframePropertiesDialog();
|
||||
|
||||
void UpdateRubberBandForScroll();
|
||||
void ShowKeyframePropertiesDialog();
|
||||
|
||||
void UpdateRubberBandForScroll();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,79 +22,87 @@
|
||||
|
||||
#include "keyframeview.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
KeyframeViewInputConnection::KeyframeViewInputConnection(const NodeKeyframeTrackReference &input, KeyframeView *parent) :
|
||||
QObject(parent),
|
||||
keyframe_view_(parent),
|
||||
input_(input),
|
||||
y_(0),
|
||||
y_behavior_(kSingleRow),
|
||||
brush_(Qt::white)
|
||||
namespace olive
|
||||
{
|
||||
Node *n = input.input().node();
|
||||
|
||||
connect(n, &Node::KeyframeAdded, this, &KeyframeViewInputConnection::AddKeyframe);
|
||||
connect(n, &Node::KeyframeRemoved, this, &KeyframeViewInputConnection::RemoveKeyframe);
|
||||
connect(n, &Node::KeyframeTimeChanged, this, &KeyframeViewInputConnection::KeyframeChanged);
|
||||
connect(n, &Node::KeyframeTypeChanged, this, &KeyframeViewInputConnection::KeyframeChanged);
|
||||
connect(n, &Node::KeyframeTypeChanged, this, &KeyframeViewInputConnection::KeyframeTypeChanged);
|
||||
connect(n, &Node::KeyframeValueChanged, this, &KeyframeViewInputConnection::KeyframeChanged);
|
||||
KeyframeViewInputConnection::KeyframeViewInputConnection(
|
||||
const NodeKeyframeTrackReference &input, KeyframeView *parent)
|
||||
: QObject(parent)
|
||||
, keyframe_view_(parent)
|
||||
, input_(input)
|
||||
, y_(0)
|
||||
, y_behavior_(kSingleRow)
|
||||
, brush_(Qt::white)
|
||||
{
|
||||
Node *n = input.input().node();
|
||||
|
||||
connect(n, &Node::KeyframeAdded, this,
|
||||
&KeyframeViewInputConnection::AddKeyframe);
|
||||
connect(n, &Node::KeyframeRemoved, this,
|
||||
&KeyframeViewInputConnection::RemoveKeyframe);
|
||||
connect(n, &Node::KeyframeTimeChanged, this,
|
||||
&KeyframeViewInputConnection::KeyframeChanged);
|
||||
connect(n, &Node::KeyframeTypeChanged, this,
|
||||
&KeyframeViewInputConnection::KeyframeChanged);
|
||||
connect(n, &Node::KeyframeTypeChanged, this,
|
||||
&KeyframeViewInputConnection::KeyframeTypeChanged);
|
||||
connect(n, &Node::KeyframeValueChanged, this,
|
||||
&KeyframeViewInputConnection::KeyframeChanged);
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::SetKeyframeY(int y)
|
||||
{
|
||||
if (y_ != y) {
|
||||
y_ = y;
|
||||
if (y_ != y) {
|
||||
y_ = y;
|
||||
|
||||
emit RequireUpdate();
|
||||
}
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::SetYBehavior(YBehavior e)
|
||||
{
|
||||
if (y_behavior_ != e) {
|
||||
y_behavior_ = e;
|
||||
if (y_behavior_ != e) {
|
||||
y_behavior_ = e;
|
||||
|
||||
emit RequireUpdate();
|
||||
}
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::SetBrush(const QBrush &brush)
|
||||
{
|
||||
if (brush_ != brush) {
|
||||
brush_ = brush;
|
||||
if (brush_ != brush) {
|
||||
brush_ = brush;
|
||||
|
||||
emit RequireUpdate();
|
||||
}
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::AddKeyframe(NodeKeyframe *key)
|
||||
{
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::RemoveKeyframe(NodeKeyframe *key)
|
||||
{
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::KeyframeChanged(NodeKeyframe *key)
|
||||
{
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit RequireUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
void KeyframeViewInputConnection::KeyframeTypeChanged(NodeKeyframe *key)
|
||||
{
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit TypeChanged();
|
||||
}
|
||||
if (key->key_track_ref() == input_) {
|
||||
emit TypeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,72 +26,72 @@
|
||||
#include "node/node.h"
|
||||
#include "node/param.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class KeyframeView;
|
||||
|
||||
class KeyframeViewInputConnection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class KeyframeViewInputConnection : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyframeViewInputConnection(const NodeKeyframeTrackReference &input, KeyframeView *parent);
|
||||
KeyframeViewInputConnection(const NodeKeyframeTrackReference &input,
|
||||
KeyframeView *parent);
|
||||
|
||||
const int &GetKeyframeY() const
|
||||
{
|
||||
return y_;
|
||||
}
|
||||
const int &GetKeyframeY() const
|
||||
{
|
||||
return y_;
|
||||
}
|
||||
|
||||
void SetKeyframeY(int y);
|
||||
void SetKeyframeY(int y);
|
||||
|
||||
enum YBehavior {
|
||||
kSingleRow,
|
||||
kValueIsHeight
|
||||
};
|
||||
enum YBehavior { kSingleRow, kValueIsHeight };
|
||||
|
||||
void SetYBehavior(YBehavior e);
|
||||
void SetYBehavior(YBehavior e);
|
||||
|
||||
const QVector<NodeKeyframe*> &GetKeyframes() const
|
||||
{
|
||||
return input_.input().node()->GetKeyframeTracks(input_.input()).at(input_.track());
|
||||
}
|
||||
const QVector<NodeKeyframe *> &GetKeyframes() const
|
||||
{
|
||||
return input_.input()
|
||||
.node()
|
||||
->GetKeyframeTracks(input_.input())
|
||||
.at(input_.track());
|
||||
}
|
||||
|
||||
const QBrush &GetBrush() const
|
||||
{
|
||||
return brush_;
|
||||
}
|
||||
const QBrush &GetBrush() const
|
||||
{
|
||||
return brush_;
|
||||
}
|
||||
|
||||
const NodeKeyframeTrackReference &GetReference() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
const NodeKeyframeTrackReference &GetReference() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
|
||||
void SetBrush(const QBrush &brush);
|
||||
void SetBrush(const QBrush &brush);
|
||||
|
||||
signals:
|
||||
void RequireUpdate();
|
||||
void RequireUpdate();
|
||||
|
||||
void TypeChanged();
|
||||
void TypeChanged();
|
||||
|
||||
private:
|
||||
KeyframeView *keyframe_view_;
|
||||
KeyframeView *keyframe_view_;
|
||||
|
||||
NodeKeyframeTrackReference input_;
|
||||
NodeKeyframeTrackReference input_;
|
||||
|
||||
int y_;
|
||||
int y_;
|
||||
|
||||
YBehavior y_behavior_;
|
||||
YBehavior y_behavior_;
|
||||
|
||||
QBrush brush_;
|
||||
QBrush brush_;
|
||||
|
||||
private slots:
|
||||
void AddKeyframe(NodeKeyframe *key);
|
||||
void AddKeyframe(NodeKeyframe *key);
|
||||
|
||||
void RemoveKeyframe(NodeKeyframe *key);
|
||||
void RemoveKeyframe(NodeKeyframe *key);
|
||||
|
||||
void KeyframeChanged(NodeKeyframe *key);
|
||||
|
||||
void KeyframeTypeChanged(NodeKeyframe *key);
|
||||
void KeyframeChanged(NodeKeyframe *key);
|
||||
|
||||
void KeyframeTypeChanged(NodeKeyframe *key);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,59 +23,64 @@
|
||||
#include "node/node.h"
|
||||
#include "node/project/sequence/sequence.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type) :
|
||||
key_(key),
|
||||
old_type_(key->type()),
|
||||
new_type_(type)
|
||||
KeyframeSetTypeCommand::KeyframeSetTypeCommand(NodeKeyframe *key,
|
||||
NodeKeyframe::Type type)
|
||||
: key_(key)
|
||||
, old_type_(key->type())
|
||||
, new_type_(type)
|
||||
{
|
||||
}
|
||||
|
||||
Project *KeyframeSetTypeCommand::GetRelevantProject() const
|
||||
{
|
||||
return key_->parent()->project();
|
||||
return key_->parent()->project();
|
||||
}
|
||||
|
||||
void KeyframeSetTypeCommand::redo()
|
||||
{
|
||||
key_->set_type(new_type_);
|
||||
key_->set_type(new_type_);
|
||||
}
|
||||
|
||||
void KeyframeSetTypeCommand::undo()
|
||||
{
|
||||
key_->set_type(old_type_);
|
||||
key_->set_type(old_type_);
|
||||
}
|
||||
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point) :
|
||||
key_(key),
|
||||
mode_(mode),
|
||||
old_point_(key->bezier_control(mode_)),
|
||||
new_point_(point)
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(
|
||||
NodeKeyframe *key, NodeKeyframe::BezierType mode, const QPointF &point)
|
||||
: key_(key)
|
||||
, mode_(mode)
|
||||
, old_point_(key->bezier_control(mode_))
|
||||
, new_point_(point)
|
||||
{
|
||||
}
|
||||
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF &new_point, const QPointF &old_point) :
|
||||
key_(key),
|
||||
mode_(mode),
|
||||
old_point_(old_point),
|
||||
new_point_(new_point)
|
||||
KeyframeSetBezierControlPoint::KeyframeSetBezierControlPoint(
|
||||
NodeKeyframe *key, NodeKeyframe::BezierType mode, const QPointF &new_point,
|
||||
const QPointF &old_point)
|
||||
: key_(key)
|
||||
, mode_(mode)
|
||||
, old_point_(old_point)
|
||||
, new_point_(new_point)
|
||||
{
|
||||
}
|
||||
|
||||
Project *KeyframeSetBezierControlPoint::GetRelevantProject() const
|
||||
{
|
||||
return key_->parent()->project();
|
||||
return key_->parent()->project();
|
||||
}
|
||||
|
||||
void KeyframeSetBezierControlPoint::redo()
|
||||
{
|
||||
key_->set_bezier_control(mode_, new_point_);
|
||||
key_->set_bezier_control(mode_, new_point_);
|
||||
}
|
||||
|
||||
void KeyframeSetBezierControlPoint::undo()
|
||||
{
|
||||
key_->set_bezier_control(mode_, old_point_);
|
||||
key_->set_bezier_control(mode_, old_point_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,47 +24,51 @@
|
||||
#include "node/keyframe.h"
|
||||
#include "undo/undocommand.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class KeyframeSetTypeCommand : public UndoCommand {
|
||||
public:
|
||||
KeyframeSetTypeCommand(NodeKeyframe* key, NodeKeyframe::Type type);
|
||||
KeyframeSetTypeCommand(NodeKeyframe *key, NodeKeyframe::Type type);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
virtual Project *GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeKeyframe* key_;
|
||||
NodeKeyframe *key_;
|
||||
|
||||
NodeKeyframe::Type old_type_;
|
||||
|
||||
NodeKeyframe::Type new_type_;
|
||||
NodeKeyframe::Type old_type_;
|
||||
|
||||
NodeKeyframe::Type new_type_;
|
||||
};
|
||||
|
||||
class KeyframeSetBezierControlPoint : public UndoCommand {
|
||||
public:
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& point);
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe* key, NodeKeyframe::BezierType mode, const QPointF& new_point, const QPointF& old_point);
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe *key,
|
||||
NodeKeyframe::BezierType mode,
|
||||
const QPointF &point);
|
||||
KeyframeSetBezierControlPoint(NodeKeyframe *key,
|
||||
NodeKeyframe::BezierType mode,
|
||||
const QPointF &new_point,
|
||||
const QPointF &old_point);
|
||||
|
||||
virtual Project* GetRelevantProject() const override;
|
||||
virtual Project *GetRelevantProject() const override;
|
||||
|
||||
protected:
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
virtual void redo() override;
|
||||
virtual void undo() override;
|
||||
|
||||
private:
|
||||
NodeKeyframe* key_;
|
||||
NodeKeyframe *key_;
|
||||
|
||||
NodeKeyframe::BezierType mode_;
|
||||
NodeKeyframe::BezierType mode_;
|
||||
|
||||
QPointF old_point_;
|
||||
|
||||
QPointF new_point_;
|
||||
QPointF old_point_;
|
||||
|
||||
QPointF new_point_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,396 +27,411 @@
|
||||
#include "render/opengl/openglrenderer.h"
|
||||
#include "render/rendermanager.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QWidget
|
||||
|
||||
ManagedDisplayWidget::ManagedDisplayWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
color_manager_(nullptr),
|
||||
color_service_(nullptr)
|
||||
ManagedDisplayWidget::ManagedDisplayWidget(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, color_manager_(nullptr)
|
||||
, color_service_(nullptr)
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
// Create OpenGL widget
|
||||
inner_widget_ = new ManagedDisplayWidgetOpenGL();
|
||||
inner_widget_->setAttribute(Qt::WA_TranslucentBackground, false);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnInit,
|
||||
this, &ManagedDisplayWidget::OnInit, Qt::DirectConnection);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnDestroy,
|
||||
this, &ManagedDisplayWidget::OnDestroy, Qt::DirectConnection);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnPaint,
|
||||
this, &ManagedDisplayWidget::OnPaint, Qt::DirectConnection);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::frameSwapped,
|
||||
this, &ManagedDisplayWidget::frameSwapped, Qt::DirectConnection);
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
// Create OpenGL widget
|
||||
inner_widget_ = new ManagedDisplayWidgetOpenGL();
|
||||
inner_widget_->setAttribute(Qt::WA_TranslucentBackground, false);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnInit, this,
|
||||
&ManagedDisplayWidget::OnInit, Qt::DirectConnection);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnDestroy, this,
|
||||
&ManagedDisplayWidget::OnDestroy, Qt::DirectConnection);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnPaint, this,
|
||||
&ManagedDisplayWidget::OnPaint, Qt::DirectConnection);
|
||||
connect(static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::frameSwapped, this,
|
||||
&ManagedDisplayWidget::frameSwapped, Qt::DirectConnection);
|
||||
|
||||
inner_widget_->installEventFilter(this);
|
||||
inner_widget_->installEventFilter(this);
|
||||
|
||||
// Create OpenGL renderer
|
||||
attached_renderer_ = new OpenGLRenderer(this);
|
||||
// Create OpenGL renderer
|
||||
attached_renderer_ = new OpenGLRenderer(this);
|
||||
|
||||
// Create widget wrapper for OpenGL window
|
||||
// Create widget wrapper for OpenGL window
|
||||
#ifdef USE_QOPENGLWINDOW
|
||||
wrapper_ = QWidget::createWindowContainer(static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_));
|
||||
wrapper_ = QWidget::createWindowContainer(
|
||||
static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_));
|
||||
#else
|
||||
wrapper_ = inner_widget_;
|
||||
wrapper_ = inner_widget_;
|
||||
#endif
|
||||
layout->addWidget(wrapper_);
|
||||
} else {
|
||||
inner_widget_ = nullptr;
|
||||
wrapper_ = nullptr;
|
||||
}
|
||||
layout->addWidget(wrapper_);
|
||||
} else {
|
||||
inner_widget_ = nullptr;
|
||||
wrapper_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ManagedDisplayWidget::~ManagedDisplayWidget()
|
||||
{
|
||||
MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR_INNER;
|
||||
MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR_INNER;
|
||||
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
disconnect(static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnDestroy,
|
||||
this, &ManagedDisplayWidget::OnDestroy);
|
||||
}
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
disconnect(static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_),
|
||||
&ManagedDisplayWidgetOpenGL::OnDestroy, this,
|
||||
&ManagedDisplayWidget::OnDestroy);
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::ConnectColorManager(ColorManager *color_manager)
|
||||
{
|
||||
if (color_manager_ == color_manager) {
|
||||
return;
|
||||
}
|
||||
if (color_manager_ == color_manager) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (color_manager_ != nullptr) {
|
||||
disconnect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayWidget::ColorConfigChanged);
|
||||
disconnect(color_manager_, &ColorManager::ReferenceSpaceChanged, this, &ManagedDisplayWidget::ColorConfigChanged);
|
||||
}
|
||||
if (color_manager_ != nullptr) {
|
||||
disconnect(color_manager_, &ColorManager::ConfigChanged, this,
|
||||
&ManagedDisplayWidget::ColorConfigChanged);
|
||||
disconnect(color_manager_, &ColorManager::ReferenceSpaceChanged, this,
|
||||
&ManagedDisplayWidget::ColorConfigChanged);
|
||||
}
|
||||
|
||||
color_manager_ = color_manager;
|
||||
color_manager_ = color_manager;
|
||||
|
||||
if (color_manager_ != nullptr) {
|
||||
connect(color_manager_, &ColorManager::ConfigChanged, this, &ManagedDisplayWidget::ColorConfigChanged);
|
||||
connect(color_manager_, &ColorManager::ReferenceSpaceChanged, this, &ManagedDisplayWidget::ColorConfigChanged);
|
||||
}
|
||||
if (color_manager_ != nullptr) {
|
||||
connect(color_manager_, &ColorManager::ConfigChanged, this,
|
||||
&ManagedDisplayWidget::ColorConfigChanged);
|
||||
connect(color_manager_, &ColorManager::ReferenceSpaceChanged, this,
|
||||
&ManagedDisplayWidget::ColorConfigChanged);
|
||||
}
|
||||
|
||||
ColorConfigChanged();
|
||||
emit ColorManagerChanged(color_manager_);
|
||||
ColorConfigChanged();
|
||||
emit ColorManagerChanged(color_manager_);
|
||||
}
|
||||
|
||||
ColorManager *ManagedDisplayWidget::color_manager() const
|
||||
{
|
||||
return color_manager_;
|
||||
return color_manager_;
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::DisconnectColorManager()
|
||||
{
|
||||
ConnectColorManager(nullptr);
|
||||
ConnectColorManager(nullptr);
|
||||
}
|
||||
|
||||
const ColorTransform &ManagedDisplayWidget::GetColorTransform() const
|
||||
{
|
||||
return color_transform_;
|
||||
return color_transform_;
|
||||
}
|
||||
|
||||
Menu *ManagedDisplayWidget::GetColorSpaceMenu(QMenu *parent, bool auto_connect)
|
||||
{
|
||||
QStringList colorspaces = color_manager()->ListAvailableColorspaces();
|
||||
QStringList colorspaces = color_manager()->ListAvailableColorspaces();
|
||||
|
||||
Menu* ocio_colorspace_menu = new Menu(tr("Color Space"), parent);
|
||||
Menu *ocio_colorspace_menu = new Menu(tr("Color Space"), parent);
|
||||
|
||||
if (auto_connect) {
|
||||
connect(ocio_colorspace_menu, &Menu::triggered, this, &ManagedDisplayWidget::MenuColorspaceSelect);
|
||||
}
|
||||
if (auto_connect) {
|
||||
connect(ocio_colorspace_menu, &Menu::triggered, this,
|
||||
&ManagedDisplayWidget::MenuColorspaceSelect);
|
||||
}
|
||||
|
||||
foreach (const QString& c, colorspaces) {
|
||||
QAction* action = ocio_colorspace_menu->addAction(c);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.output() == c);
|
||||
action->setData(c);
|
||||
}
|
||||
foreach (const QString &c, colorspaces) {
|
||||
QAction *action = ocio_colorspace_menu->addAction(c);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.output() == c);
|
||||
action->setData(c);
|
||||
}
|
||||
|
||||
return ocio_colorspace_menu;
|
||||
return ocio_colorspace_menu;
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::ColorConfigChanged()
|
||||
{
|
||||
if (!color_manager_) {
|
||||
color_service_ = nullptr;
|
||||
return;
|
||||
}
|
||||
if (!color_manager_) {
|
||||
color_service_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
SetColorTransform(color_manager_->GetCompliantColorSpace(color_transform_, false));
|
||||
SetColorTransform(
|
||||
color_manager_->GetCompliantColorSpace(color_transform_, false));
|
||||
}
|
||||
|
||||
ColorProcessorPtr ManagedDisplayWidget::color_service()
|
||||
{
|
||||
return color_service_;
|
||||
return color_service_;
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::ShowDefaultContextMenu()
|
||||
{
|
||||
Menu m(this);
|
||||
Menu m(this);
|
||||
|
||||
if (color_manager_) {
|
||||
m.addMenu(GetColorSpaceMenu(&m));
|
||||
m.addSeparator();
|
||||
m.addMenu(GetDisplayMenu(&m));
|
||||
m.addMenu(GetViewMenu(&m));
|
||||
m.addMenu(GetLookMenu(&m));
|
||||
} else {
|
||||
QAction* a = m.addAction(tr("No color manager connected"));
|
||||
a->setEnabled(false);
|
||||
}
|
||||
if (color_manager_) {
|
||||
m.addMenu(GetColorSpaceMenu(&m));
|
||||
m.addSeparator();
|
||||
m.addMenu(GetDisplayMenu(&m));
|
||||
m.addMenu(GetViewMenu(&m));
|
||||
m.addMenu(GetLookMenu(&m));
|
||||
} else {
|
||||
QAction *a = m.addAction(tr("No color manager connected"));
|
||||
a->setEnabled(false);
|
||||
}
|
||||
|
||||
m.exec(QCursor::pos());
|
||||
m.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::MenuDisplaySelect(QAction *action)
|
||||
{
|
||||
const ColorTransform& old_transform = GetColorTransform();
|
||||
const ColorTransform &old_transform = GetColorTransform();
|
||||
|
||||
ColorTransform new_transform = color_manager()->GetCompliantColorSpace(ColorTransform(action->data().toString(),
|
||||
old_transform.view(),
|
||||
old_transform.look()));
|
||||
ColorTransform new_transform = color_manager()->GetCompliantColorSpace(
|
||||
ColorTransform(action->data().toString(), old_transform.view(),
|
||||
old_transform.look()));
|
||||
|
||||
SetColorTransform(new_transform);
|
||||
SetColorTransform(new_transform);
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::MenuViewSelect(QAction *action)
|
||||
{
|
||||
const ColorTransform& old_transform = GetColorTransform();
|
||||
const ColorTransform &old_transform = GetColorTransform();
|
||||
|
||||
ColorTransform new_transform = color_manager()->GetCompliantColorSpace(ColorTransform(old_transform.display(),
|
||||
action->data().toString(),
|
||||
old_transform.look()));
|
||||
ColorTransform new_transform = color_manager()->GetCompliantColorSpace(
|
||||
ColorTransform(old_transform.display(), action->data().toString(),
|
||||
old_transform.look()));
|
||||
|
||||
SetColorTransform(new_transform);
|
||||
SetColorTransform(new_transform);
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::MenuLookSelect(QAction *action)
|
||||
{
|
||||
const ColorTransform& old_transform = GetColorTransform();
|
||||
const ColorTransform &old_transform = GetColorTransform();
|
||||
|
||||
ColorTransform new_transform = color_manager()->GetCompliantColorSpace(ColorTransform(old_transform.display(),
|
||||
old_transform.view(),
|
||||
action->data().toString()));
|
||||
ColorTransform new_transform = color_manager()->GetCompliantColorSpace(
|
||||
ColorTransform(old_transform.display(), old_transform.view(),
|
||||
action->data().toString()));
|
||||
|
||||
SetColorTransform(new_transform);
|
||||
SetColorTransform(new_transform);
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::MenuColorspaceSelect(QAction *action)
|
||||
{
|
||||
SetColorTransform(color_manager()->GetCompliantColorSpace(ColorTransform(action->data().toString())));
|
||||
SetColorTransform(color_manager()->GetCompliantColorSpace(
|
||||
ColorTransform(action->data().toString())));
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::OnDestroy()
|
||||
{
|
||||
attached_renderer_->Destroy();
|
||||
attached_renderer_->PostDestroy();
|
||||
attached_renderer_->Destroy();
|
||||
attached_renderer_->PostDestroy();
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::SetColorTransform(const ColorTransform &transform)
|
||||
{
|
||||
color_transform_ = transform;
|
||||
color_transform_ = transform;
|
||||
|
||||
SetupColorProcessor();
|
||||
SetupColorProcessor();
|
||||
|
||||
ColorProcessorChangedEvent();
|
||||
ColorProcessorChangedEvent();
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::OnInit()
|
||||
{
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
QOpenGLContext* context = static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_)->context();
|
||||
static_cast<OpenGLRenderer*>(attached_renderer_)->Init(context);
|
||||
static_cast<OpenGLRenderer*>(attached_renderer_)->PostInit();
|
||||
}
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
QOpenGLContext *context =
|
||||
static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_)->context();
|
||||
static_cast<OpenGLRenderer *>(attached_renderer_)->Init(context);
|
||||
static_cast<OpenGLRenderer *>(attached_renderer_)->PostInit();
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::EnableDefaultContextMenu()
|
||||
{
|
||||
connect(this, &ManagedDisplayWidget::customContextMenuRequested, this, &ManagedDisplayWidget::ShowDefaultContextMenu);
|
||||
connect(this, &ManagedDisplayWidget::customContextMenuRequested, this,
|
||||
&ManagedDisplayWidget::ShowDefaultContextMenu);
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::ColorProcessorChangedEvent()
|
||||
{
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::makeCurrent()
|
||||
{
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_)->makeCurrent();
|
||||
}
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_)->makeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::doneCurrent()
|
||||
{
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_)->doneCurrent();
|
||||
}
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_)->doneCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
QPaintDevice *ManagedDisplayWidget::paint_device() const
|
||||
{
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
return static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
return static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_);
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::SetInnerMouseTracking(bool e)
|
||||
{
|
||||
if (wrapper_) {
|
||||
wrapper_->setMouseTracking(e);
|
||||
}
|
||||
if (wrapper_) {
|
||||
wrapper_->setMouseTracking(e);
|
||||
}
|
||||
}
|
||||
|
||||
VideoParams ManagedDisplayWidget::GetViewportParams() const
|
||||
{
|
||||
int device_width = width() * devicePixelRatioF();
|
||||
int device_height = height() * devicePixelRatioF();
|
||||
PixelFormat device_format = static_cast<PixelFormat::Format>(OLIVE_CONFIG("OfflinePixelFormat").toInt());
|
||||
return VideoParams(device_width, device_height, device_format, VideoParams::kInternalChannelCount);
|
||||
int device_width = width() * devicePixelRatioF();
|
||||
int device_height = height() * devicePixelRatioF();
|
||||
PixelFormat device_format = static_cast<PixelFormat::Format>(
|
||||
OLIVE_CONFIG("OfflinePixelFormat").toInt());
|
||||
return VideoParams(device_width, device_height, device_format,
|
||||
VideoParams::kInternalChannelCount);
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::update()
|
||||
{
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
static_cast<ManagedDisplayWidgetOpenGL*>(inner_widget_)->update();
|
||||
}
|
||||
if (RenderManager::instance()->backend() == RenderManager::kOpenGL) {
|
||||
static_cast<ManagedDisplayWidgetOpenGL *>(inner_widget_)->update();
|
||||
}
|
||||
}
|
||||
|
||||
bool ManagedDisplayWidget::eventFilter(QObject *o, QEvent *e)
|
||||
{
|
||||
if (o != inner_widget_) {
|
||||
return super::eventFilter(o, e);
|
||||
}
|
||||
if (o != inner_widget_) {
|
||||
return super::eventFilter(o, e);
|
||||
}
|
||||
|
||||
switch (e->type()) {
|
||||
case QEvent::FocusIn:
|
||||
// HACK: QWindow focus isn't accounted for in QApplication::focusChanged, so we handle it
|
||||
// manually here.
|
||||
PanelManager::instance()->FocusChanged(nullptr, this);
|
||||
break;
|
||||
case QEvent::ContextMenu:
|
||||
{
|
||||
QContextMenuEvent *ctx = static_cast<QContextMenuEvent*>(e);
|
||||
emit customContextMenuRequested(ctx->pos());
|
||||
return true;
|
||||
}
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
// HACK: QWindows don't seem to receive ContextMenu events on right click (only when pressing
|
||||
// the menu button on the keyboard) so we handle it manually here
|
||||
/*QMouseEvent *ev = static_cast<QMouseEvent*>(e);
|
||||
switch (e->type()) {
|
||||
case QEvent::FocusIn:
|
||||
// HACK: QWindow focus isn't accounted for in QApplication::focusChanged, so we handle it
|
||||
// manually here.
|
||||
PanelManager::instance()->FocusChanged(nullptr, this);
|
||||
break;
|
||||
case QEvent::ContextMenu: {
|
||||
QContextMenuEvent *ctx = static_cast<QContextMenuEvent *>(e);
|
||||
emit customContextMenuRequested(ctx->pos());
|
||||
return true;
|
||||
}
|
||||
case QEvent::MouseButtonPress: {
|
||||
// HACK: QWindows don't seem to receive ContextMenu events on right click (only when pressing
|
||||
// the menu button on the keyboard) so we handle it manually here
|
||||
/*QMouseEvent *ev = static_cast<QMouseEvent*>(e);
|
||||
if (ev->button() == Qt::RightButton) {
|
||||
emit customContextMenuRequested(ev->pos());
|
||||
return true;
|
||||
}*/
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return super::eventFilter(o, e);
|
||||
return super::eventFilter(o, e);
|
||||
}
|
||||
|
||||
Menu* ManagedDisplayWidget::GetDisplayMenu(QMenu* parent, bool auto_connect)
|
||||
Menu *ManagedDisplayWidget::GetDisplayMenu(QMenu *parent, bool auto_connect)
|
||||
{
|
||||
QStringList displays = color_manager()->ListAvailableDisplays();
|
||||
QStringList displays = color_manager()->ListAvailableDisplays();
|
||||
|
||||
Menu* ocio_display_menu = new Menu(tr("Display"), parent);
|
||||
Menu *ocio_display_menu = new Menu(tr("Display"), parent);
|
||||
|
||||
if (auto_connect) {
|
||||
connect(ocio_display_menu, &Menu::triggered, this, &ManagedDisplayWidget::MenuDisplaySelect);
|
||||
}
|
||||
if (auto_connect) {
|
||||
connect(ocio_display_menu, &Menu::triggered, this,
|
||||
&ManagedDisplayWidget::MenuDisplaySelect);
|
||||
}
|
||||
|
||||
foreach (const QString& d, displays) {
|
||||
QAction* action = ocio_display_menu->addAction(d);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.display() == d);
|
||||
action->setData(d);
|
||||
}
|
||||
foreach (const QString &d, displays) {
|
||||
QAction *action = ocio_display_menu->addAction(d);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.display() == d);
|
||||
action->setData(d);
|
||||
}
|
||||
|
||||
return ocio_display_menu;
|
||||
return ocio_display_menu;
|
||||
}
|
||||
|
||||
Menu* ManagedDisplayWidget::GetViewMenu(QMenu* parent, bool auto_connect)
|
||||
Menu *ManagedDisplayWidget::GetViewMenu(QMenu *parent, bool auto_connect)
|
||||
{
|
||||
QStringList views = color_manager()->ListAvailableViews(color_transform_.display());
|
||||
QStringList views =
|
||||
color_manager()->ListAvailableViews(color_transform_.display());
|
||||
|
||||
Menu* ocio_view_menu = new Menu(tr("View"), parent);
|
||||
Menu *ocio_view_menu = new Menu(tr("View"), parent);
|
||||
|
||||
if (auto_connect) {
|
||||
connect(ocio_view_menu, &Menu::triggered, this, &ManagedDisplayWidget::MenuViewSelect);
|
||||
}
|
||||
if (auto_connect) {
|
||||
connect(ocio_view_menu, &Menu::triggered, this,
|
||||
&ManagedDisplayWidget::MenuViewSelect);
|
||||
}
|
||||
|
||||
foreach (const QString& v, views) {
|
||||
QAction* action = ocio_view_menu->addAction(v);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.view() == v);
|
||||
action->setData(v);
|
||||
}
|
||||
foreach (const QString &v, views) {
|
||||
QAction *action = ocio_view_menu->addAction(v);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.view() == v);
|
||||
action->setData(v);
|
||||
}
|
||||
|
||||
return ocio_view_menu;
|
||||
return ocio_view_menu;
|
||||
}
|
||||
|
||||
Menu* ManagedDisplayWidget::GetLookMenu(QMenu* parent, bool auto_connect)
|
||||
Menu *ManagedDisplayWidget::GetLookMenu(QMenu *parent, bool auto_connect)
|
||||
{
|
||||
QStringList looks = color_manager()->ListAvailableLooks();
|
||||
QStringList looks = color_manager()->ListAvailableLooks();
|
||||
|
||||
Menu* ocio_look_menu = new Menu(tr("Look"), parent);
|
||||
Menu *ocio_look_menu = new Menu(tr("Look"), parent);
|
||||
|
||||
if (auto_connect) {
|
||||
connect(ocio_look_menu, &Menu::triggered, this, &ManagedDisplayWidget::MenuLookSelect);
|
||||
}
|
||||
if (auto_connect) {
|
||||
connect(ocio_look_menu, &Menu::triggered, this,
|
||||
&ManagedDisplayWidget::MenuLookSelect);
|
||||
}
|
||||
|
||||
// Setup "no look" action
|
||||
QAction* no_look_action = ocio_look_menu->addAction(tr("(None)"));
|
||||
no_look_action->setCheckable(true);
|
||||
no_look_action->setChecked(color_transform_.look().isEmpty());
|
||||
no_look_action->setData(QString());
|
||||
// Setup "no look" action
|
||||
QAction *no_look_action = ocio_look_menu->addAction(tr("(None)"));
|
||||
no_look_action->setCheckable(true);
|
||||
no_look_action->setChecked(color_transform_.look().isEmpty());
|
||||
no_look_action->setData(QString());
|
||||
|
||||
// Set up the rest of the looks
|
||||
foreach (const QString& l, looks) {
|
||||
QAction* action = ocio_look_menu->addAction(l);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.look() == l);
|
||||
action->setData(l);
|
||||
}
|
||||
// Set up the rest of the looks
|
||||
foreach (const QString &l, looks) {
|
||||
QAction *action = ocio_look_menu->addAction(l);
|
||||
action->setCheckable(true);
|
||||
action->setChecked(color_transform_.look() == l);
|
||||
action->setData(l);
|
||||
}
|
||||
|
||||
return ocio_look_menu;
|
||||
return ocio_look_menu;
|
||||
}
|
||||
|
||||
void ManagedDisplayWidget::SetupColorProcessor()
|
||||
{
|
||||
color_service_ = nullptr;
|
||||
color_service_ = nullptr;
|
||||
|
||||
if (color_manager_) {
|
||||
// (Re)create color processor
|
||||
try {
|
||||
color_service_ = ColorProcessor::Create(color_manager_,
|
||||
color_manager_->GetReferenceColorSpace(),
|
||||
color_transform_);
|
||||
} catch (OCIO::Exception& e) {
|
||||
QMessageBox::critical(this,
|
||||
tr("OpenColorIO Error"),
|
||||
tr("Failed to set color configuration: %1").arg(e.what()),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
} else {
|
||||
color_service_ = nullptr;
|
||||
}
|
||||
if (color_manager_) {
|
||||
// (Re)create color processor
|
||||
try {
|
||||
color_service_ = ColorProcessor::Create(
|
||||
color_manager_, color_manager_->GetReferenceColorSpace(),
|
||||
color_transform_);
|
||||
} catch (OCIO::Exception &e) {
|
||||
QMessageBox::critical(
|
||||
this, tr("OpenColorIO Error"),
|
||||
tr("Failed to set color configuration: %1").arg(e.what()),
|
||||
QMessageBox::Ok);
|
||||
}
|
||||
} else {
|
||||
color_service_ = nullptr;
|
||||
}
|
||||
|
||||
emit ColorProcessorChanged(color_service_);
|
||||
emit ColorProcessorChanged(color_service_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -35,282 +35,285 @@
|
||||
#include "render/renderer.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class ManagedDisplayWidgetOpenGL
|
||||
#ifdef USE_QOPENGLWINDOW
|
||||
: public QOpenGLWindow
|
||||
: public QOpenGLWindow
|
||||
#else
|
||||
: public QOpenGLWidget
|
||||
: public QOpenGLWidget
|
||||
#endif
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
ManagedDisplayWidgetOpenGL() = default;
|
||||
ManagedDisplayWidgetOpenGL() = default;
|
||||
|
||||
virtual ~ManagedDisplayWidgetOpenGL() override
|
||||
{
|
||||
if (context()) {
|
||||
DestroyListener();
|
||||
disconnect(context(), &QOpenGLContext::aboutToBeDestroyed,
|
||||
this, &ManagedDisplayWidgetOpenGL::DestroyListener);
|
||||
}
|
||||
}
|
||||
virtual ~ManagedDisplayWidgetOpenGL() override
|
||||
{
|
||||
if (context()) {
|
||||
DestroyListener();
|
||||
disconnect(context(), &QOpenGLContext::aboutToBeDestroyed, this,
|
||||
&ManagedDisplayWidgetOpenGL::DestroyListener);
|
||||
}
|
||||
}
|
||||
|
||||
signals:
|
||||
// Render signals
|
||||
void OnInit();
|
||||
void OnPaint();
|
||||
void OnDestroy();
|
||||
// Render signals
|
||||
void OnInit();
|
||||
void OnPaint();
|
||||
void OnDestroy();
|
||||
|
||||
protected:
|
||||
virtual void initializeGL() override
|
||||
{
|
||||
connect(context(), &QOpenGLContext::aboutToBeDestroyed,
|
||||
this, &ManagedDisplayWidgetOpenGL::DestroyListener,
|
||||
Qt::DirectConnection);
|
||||
virtual void initializeGL() override
|
||||
{
|
||||
connect(context(), &QOpenGLContext::aboutToBeDestroyed, this,
|
||||
&ManagedDisplayWidgetOpenGL::DestroyListener,
|
||||
Qt::DirectConnection);
|
||||
|
||||
emit OnInit();
|
||||
}
|
||||
emit OnInit();
|
||||
}
|
||||
|
||||
virtual void paintGL() override
|
||||
{
|
||||
emit OnPaint();
|
||||
}
|
||||
virtual void paintGL() override
|
||||
{
|
||||
emit OnPaint();
|
||||
}
|
||||
|
||||
private slots:
|
||||
void DestroyListener()
|
||||
{
|
||||
makeCurrent();
|
||||
void DestroyListener()
|
||||
{
|
||||
makeCurrent();
|
||||
|
||||
emit OnDestroy();
|
||||
|
||||
doneCurrent();
|
||||
}
|
||||
emit OnDestroy();
|
||||
|
||||
doneCurrent();
|
||||
}
|
||||
};
|
||||
|
||||
#define MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR_INNER \
|
||||
makeCurrent();OnDestroy();doneCurrent()
|
||||
#define MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR(x) \
|
||||
virtual ~x() override{MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR_INNER;}
|
||||
makeCurrent(); \
|
||||
OnDestroy(); \
|
||||
doneCurrent()
|
||||
#define MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR(x) \
|
||||
virtual ~x() override \
|
||||
{ \
|
||||
MANAGEDDISPLAYWIDGET_DEFAULT_DESTRUCTOR_INNER; \
|
||||
}
|
||||
|
||||
class ManagedDisplayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class ManagedDisplayWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
ManagedDisplayWidget(QWidget* parent = nullptr);
|
||||
ManagedDisplayWidget(QWidget *parent = nullptr);
|
||||
|
||||
virtual ~ManagedDisplayWidget() override;
|
||||
virtual ~ManagedDisplayWidget() override;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Disconnect a ColorManager (equivalent to ConnectColorManager(nullptr))
|
||||
*/
|
||||
void DisconnectColorManager();
|
||||
void DisconnectColorManager();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Access currently connected ColorManager (nullptr if none)
|
||||
*/
|
||||
ColorManager* color_manager() const;
|
||||
ColorManager *color_manager() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get current color transform
|
||||
*/
|
||||
const ColorTransform& GetColorTransform() const;
|
||||
const ColorTransform &GetColorTransform() const;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get menu that can be used to select the colorspace
|
||||
*/
|
||||
Menu* GetColorSpaceMenu(QMenu* parent, bool auto_connect = true);
|
||||
Menu *GetColorSpaceMenu(QMenu *parent, bool auto_connect = true);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get menu that can be used to select the display transform
|
||||
*/
|
||||
Menu* GetDisplayMenu(QMenu* parent, bool auto_connect = true);
|
||||
Menu *GetDisplayMenu(QMenu *parent, bool auto_connect = true);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get menu that can be used to select the view transform
|
||||
*/
|
||||
Menu* GetViewMenu(QMenu* parent, bool auto_connect = true);
|
||||
Menu *GetViewMenu(QMenu *parent, bool auto_connect = true);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get menu that can be used to select the look transform
|
||||
*/
|
||||
Menu* GetLookMenu(QMenu* parent, bool auto_connect = true);
|
||||
Menu *GetLookMenu(QMenu *parent, bool auto_connect = true);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Passes update signal through to inner widget
|
||||
*/
|
||||
void update();
|
||||
void update();
|
||||
|
||||
virtual bool eventFilter(QObject *o, QEvent *e) override;
|
||||
virtual bool eventFilter(QObject *o, QEvent *e) override;
|
||||
|
||||
public slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Replaces the color transform with a new one
|
||||
*/
|
||||
void SetColorTransform(const ColorTransform& transform);
|
||||
void SetColorTransform(const ColorTransform &transform);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Connect a ColorManager (ColorManagers usually belong to the Project)
|
||||
*/
|
||||
void ConnectColorManager(ColorManager* color_manager);
|
||||
void ConnectColorManager(ColorManager *color_manager);
|
||||
|
||||
signals:
|
||||
/**
|
||||
/**
|
||||
* @brief Emitted when the color processor changes
|
||||
*/
|
||||
void ColorProcessorChanged(ColorProcessorPtr processor);
|
||||
void ColorProcessorChanged(ColorProcessorPtr processor);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Emitted when a new color manager is connected
|
||||
*/
|
||||
void ColorManagerChanged(ColorManager* color_manager);
|
||||
void ColorManagerChanged(ColorManager *color_manager);
|
||||
|
||||
void frameSwapped();
|
||||
void frameSwapped();
|
||||
|
||||
protected:
|
||||
/**
|
||||
/**
|
||||
* @brief Provides access to the color processor (nullptr if none is set)
|
||||
*/
|
||||
ColorProcessorPtr color_service();
|
||||
ColorProcessorPtr color_service();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Enables a context menu that allows simple access to the DVL pipeline
|
||||
*/
|
||||
void EnableDefaultContextMenu();
|
||||
void EnableDefaultContextMenu();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Function called whenever the processor changes
|
||||
*
|
||||
* Default functionality is just to call update()
|
||||
*/
|
||||
virtual void ColorProcessorChangedEvent();
|
||||
virtual void ColorProcessorChangedEvent();
|
||||
|
||||
Renderer* renderer() const
|
||||
{
|
||||
return attached_renderer_;
|
||||
}
|
||||
Renderer *renderer() const
|
||||
{
|
||||
return attached_renderer_;
|
||||
}
|
||||
|
||||
void makeCurrent();
|
||||
void makeCurrent();
|
||||
|
||||
void doneCurrent();
|
||||
void doneCurrent();
|
||||
|
||||
#ifdef USE_QOPENGLWINDOW
|
||||
QWindow*
|
||||
QWindow *
|
||||
#else
|
||||
QWidget*
|
||||
QWidget *
|
||||
#endif
|
||||
inner_widget() const
|
||||
{
|
||||
return inner_widget_;
|
||||
}
|
||||
inner_widget() const
|
||||
{
|
||||
return inner_widget_;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Get inner widget as paint device for QPainter
|
||||
*
|
||||
* NOTE: This will be incompatible with QVulkanWindow so functions using it
|
||||
* will need to be replaced soon.
|
||||
*/
|
||||
QPaintDevice *paint_device() const;
|
||||
QPaintDevice *paint_device() const;
|
||||
|
||||
void SetInnerMouseTracking(bool e);
|
||||
void SetInnerMouseTracking(bool e);
|
||||
|
||||
QRect GetInnerRect() const
|
||||
{
|
||||
return wrapper_ ? wrapper_->rect() : QRect();
|
||||
}
|
||||
QRect GetInnerRect() const
|
||||
{
|
||||
return wrapper_ ? wrapper_->rect() : QRect();
|
||||
}
|
||||
|
||||
VideoParams GetViewportParams() const;
|
||||
VideoParams GetViewportParams() const;
|
||||
|
||||
protected slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Called whenever the internal rendering context has been created
|
||||
*/
|
||||
virtual void OnInit();
|
||||
virtual void OnInit();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Called while the internal rendering context is being rendered
|
||||
*/
|
||||
virtual void OnPaint() = 0;
|
||||
virtual void OnPaint() = 0;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Called just before the internal rendering context is destroyed
|
||||
*/
|
||||
virtual void OnDestroy();
|
||||
virtual void OnDestroy();
|
||||
|
||||
private:
|
||||
/**
|
||||
/**
|
||||
* @brief Call this if this user has selected a different display/view/look to recreate the processor
|
||||
*/
|
||||
void SetupColorProcessor();
|
||||
void SetupColorProcessor();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Cleanup function
|
||||
*/
|
||||
void ClearOCIOLutTexture();
|
||||
void ClearOCIOLutTexture();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Main drawing surface abstraction
|
||||
*/
|
||||
#ifdef USE_QOPENGLWINDOW
|
||||
QWindow* inner_widget_;
|
||||
QWindow *inner_widget_;
|
||||
#else
|
||||
QWidget* inner_widget_;
|
||||
QWidget *inner_widget_;
|
||||
#endif
|
||||
QWidget *wrapper_;
|
||||
QWidget *wrapper_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Renderer abstraction
|
||||
*/
|
||||
Renderer* attached_renderer_;
|
||||
Renderer *attached_renderer_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Connected color manager
|
||||
*/
|
||||
ColorManager* color_manager_;
|
||||
ColorManager *color_manager_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Color management service
|
||||
*/
|
||||
ColorProcessorPtr color_service_;
|
||||
ColorProcessorPtr color_service_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Internal color transform storage
|
||||
*/
|
||||
ColorTransform color_transform_;
|
||||
ColorTransform color_transform_;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Sets all color settings to the defaults pertaining to this configuration
|
||||
*/
|
||||
void ColorConfigChanged();
|
||||
void ColorConfigChanged();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief The default context menu shown
|
||||
*/
|
||||
void ShowDefaultContextMenu();
|
||||
void ShowDefaultContextMenu();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief If GetDisplayMenu() is called with `auto_connect` set to true, it will be connected to this
|
||||
*/
|
||||
void MenuDisplaySelect(QAction* action);
|
||||
void MenuDisplaySelect(QAction *action);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief If GetViewMenu() is called with `auto_connect` set to true, it will be connected to this
|
||||
*/
|
||||
void MenuViewSelect(QAction* action);
|
||||
void MenuViewSelect(QAction *action);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief If GetLookMenu() is called with `auto_connect` set to true, it will be connected to this
|
||||
*/
|
||||
void MenuLookSelect(QAction* action);
|
||||
void MenuLookSelect(QAction *action);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief If GetColorSpaceMenu() is called with `auto_connect` set to true, it will be connected to this
|
||||
*/
|
||||
void MenuColorspaceSelect(QAction* action);
|
||||
|
||||
void MenuColorspaceSelect(QAction *action);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+43
-41
@@ -22,90 +22,92 @@
|
||||
|
||||
#include "ui/style/style.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
Menu::Menu(QMenuBar *bar)
|
||||
{
|
||||
bar->addMenu(this);
|
||||
bar->addMenu(this);
|
||||
|
||||
Init();
|
||||
Init();
|
||||
}
|
||||
|
||||
Menu::Menu(Menu *menu)
|
||||
{
|
||||
menu->addMenu(this);
|
||||
menu->addMenu(this);
|
||||
|
||||
Init();
|
||||
Init();
|
||||
}
|
||||
|
||||
Menu::Menu(QWidget *parent) :
|
||||
QMenu(parent)
|
||||
Menu::Menu(QWidget *parent)
|
||||
: QMenu(parent)
|
||||
{
|
||||
Init();
|
||||
Init();
|
||||
}
|
||||
|
||||
Menu::Menu(const QString &s, QWidget *parent) :
|
||||
QMenu(s, parent)
|
||||
Menu::Menu(const QString &s, QWidget *parent)
|
||||
: QMenu(s, parent)
|
||||
{
|
||||
Init();
|
||||
Init();
|
||||
}
|
||||
|
||||
QAction *Menu::AddActionWithData(const QString &text, const QVariant &d, const QVariant &compare)
|
||||
QAction *Menu::AddActionWithData(const QString &text, const QVariant &d,
|
||||
const QVariant &compare)
|
||||
{
|
||||
QAction* a = addAction(text);
|
||||
QAction *a = addAction(text);
|
||||
|
||||
a->setData(d);
|
||||
a->setCheckable(true);
|
||||
a->setChecked(d == compare);
|
||||
a->setData(d);
|
||||
a->setCheckable(true);
|
||||
a->setChecked(d == compare);
|
||||
|
||||
return a;
|
||||
return a;
|
||||
}
|
||||
|
||||
QAction* Menu::InsertAlphabetically(const QString &s)
|
||||
QAction *Menu::InsertAlphabetically(const QString &s)
|
||||
{
|
||||
QAction* action = new QAction(s, this);
|
||||
InsertAlphabetically(action);
|
||||
return action;
|
||||
QAction *action = new QAction(s, this);
|
||||
InsertAlphabetically(action);
|
||||
return action;
|
||||
}
|
||||
|
||||
void Menu::InsertAlphabetically(QAction *entry)
|
||||
{
|
||||
QList<QAction*> actions = this->actions();
|
||||
QList<QAction *> actions = this->actions();
|
||||
|
||||
foreach (QAction* action, actions) {
|
||||
if (action->text() > entry->text()) {
|
||||
insertAction(action, entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
foreach (QAction *action, actions) {
|
||||
if (action->text() > entry->text()) {
|
||||
insertAction(action, entry);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
addAction(entry);
|
||||
addAction(entry);
|
||||
}
|
||||
|
||||
void Menu::InsertAlphabetically(Menu *menu)
|
||||
{
|
||||
InsertAlphabetically(menu->menuAction());
|
||||
InsertAlphabetically(menu->menuAction());
|
||||
}
|
||||
|
||||
void Menu::ConformItem(QAction *a, const QString &id, const QKeySequence &key)
|
||||
{
|
||||
a->setProperty("id", id);
|
||||
a->setProperty("id", id);
|
||||
|
||||
if (!key.isEmpty()) {
|
||||
a->setShortcut(key);
|
||||
a->setProperty("keydefault", key);
|
||||
if (!key.isEmpty()) {
|
||||
a->setShortcut(key);
|
||||
a->setProperty("keydefault", key);
|
||||
|
||||
// Set to application context so that ViewerWindows still trigger shortcuts
|
||||
a->setShortcutContext(Qt::ApplicationShortcut);
|
||||
}
|
||||
// Set to application context so that ViewerWindows still trigger shortcuts
|
||||
a->setShortcutContext(Qt::ApplicationShortcut);
|
||||
}
|
||||
}
|
||||
|
||||
void Menu::Init()
|
||||
{
|
||||
// HACK: Disables embossing on disabled text for a slightly nicer UI
|
||||
QPalette p = palette();
|
||||
p.setColor(QPalette::Disabled, QPalette::Light, QColor(0, 0, 0, 0));
|
||||
setPalette(p);
|
||||
// HACK: Disables embossing on disabled text for a slightly nicer UI
|
||||
QPalette p = palette();
|
||||
p.setColor(QPalette::Disabled, QPalette::Light, QColor(0, 0, 0, 0));
|
||||
setPalette(p);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+76
-83
@@ -27,7 +27,8 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A menu widget for context menus and menu bars
|
||||
@@ -44,59 +45,58 @@ namespace olive {
|
||||
*
|
||||
* It is always recommended to use this over QMenu in any situation.
|
||||
*/
|
||||
class Menu : public QMenu
|
||||
{
|
||||
class Menu : public QMenu {
|
||||
public:
|
||||
Menu(QMenuBar* bar);
|
||||
Menu(QMenuBar *bar);
|
||||
|
||||
template <typename Func>
|
||||
/**
|
||||
template <typename Func>
|
||||
/**
|
||||
* @brief Construct a Menu and add it to a QMenuBar
|
||||
*
|
||||
* This Menu can be connected to a slot that's triggered when the Menu is "about to show". Use `receiver` and
|
||||
* `member` to connect this (same syntax as QObject::connect) or leave as nullptr to not.
|
||||
*/
|
||||
Menu(QMenuBar* bar,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member)
|
||||
{
|
||||
bar->addMenu(this);
|
||||
Menu(QMenuBar *bar,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member)
|
||||
{
|
||||
bar->addMenu(this);
|
||||
|
||||
Init();
|
||||
ConnectAboutToShow(receiver, member);
|
||||
}
|
||||
Init();
|
||||
ConnectAboutToShow(receiver, member);
|
||||
}
|
||||
|
||||
Menu(Menu* menu);
|
||||
Menu(Menu *menu);
|
||||
|
||||
template <typename Func>
|
||||
/**
|
||||
template <typename Func>
|
||||
/**
|
||||
* @brief Construct a Menu and add it as a submenu to another Menu
|
||||
*
|
||||
* This Menu can be connected to a slot that's triggered when the Menu is "about to show". Use `receiver` and
|
||||
* `member` to connect this (same syntax as QObject::connect) or leave as nullptr to not.
|
||||
*/
|
||||
Menu(Menu* menu,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member)
|
||||
{
|
||||
menu->addMenu(this);
|
||||
Menu(Menu *menu,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member)
|
||||
{
|
||||
menu->addMenu(this);
|
||||
|
||||
Init();
|
||||
ConnectAboutToShow(receiver, member);
|
||||
}
|
||||
Init();
|
||||
ConnectAboutToShow(receiver, member);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Construct a popup menu
|
||||
*/
|
||||
Menu(QWidget* parent = nullptr);
|
||||
Menu(QWidget *parent = nullptr);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Construct a popup menu
|
||||
*/
|
||||
Menu(const QString& s, QWidget* parent = nullptr);
|
||||
Menu(const QString &s, QWidget *parent = nullptr);
|
||||
|
||||
template <typename Func>
|
||||
/**
|
||||
template <typename Func>
|
||||
/**
|
||||
* @brief Create a menu item and add it to this menu
|
||||
*
|
||||
* @param id
|
||||
@@ -119,28 +119,27 @@ public:
|
||||
*
|
||||
* The QAction that was created and added to this Menu
|
||||
*/
|
||||
QAction* AddItem(const QString& id,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member,
|
||||
const QKeySequence &key = QKeySequence())
|
||||
{
|
||||
QAction* a = CreateItem(this, id, receiver, member, key);
|
||||
QAction *
|
||||
AddItem(const QString &id,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member, const QKeySequence &key = QKeySequence())
|
||||
{
|
||||
QAction *a = CreateItem(this, id, receiver, member, key);
|
||||
|
||||
addAction(a);
|
||||
addAction(a);
|
||||
|
||||
return a;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
QAction* AddActionWithData(const QString& text,
|
||||
const QVariant& d,
|
||||
const QVariant& compare);
|
||||
QAction *AddActionWithData(const QString &text, const QVariant &d,
|
||||
const QVariant &compare);
|
||||
|
||||
QAction *InsertAlphabetically(const QString& s);
|
||||
void InsertAlphabetically(QAction* entry);
|
||||
void InsertAlphabetically(Menu* menu);
|
||||
QAction *InsertAlphabetically(const QString &s);
|
||||
void InsertAlphabetically(QAction *entry);
|
||||
void InsertAlphabetically(Menu *menu);
|
||||
|
||||
template <typename Func>
|
||||
/**
|
||||
template <typename Func>
|
||||
/**
|
||||
* @brief Create a menu item
|
||||
*
|
||||
* @param parent
|
||||
@@ -167,25 +166,20 @@ public:
|
||||
*
|
||||
* The QAction that was created and added to this Menu
|
||||
*/
|
||||
static QAction* CreateItem(QObject* parent,
|
||||
const QString& id,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member,
|
||||
const QKeySequence &key = QKeySequence())
|
||||
{
|
||||
QAction* a = new QAction(parent);
|
||||
static QAction *CreateItem(
|
||||
QObject *parent, const QString &id,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member, const QKeySequence &key = QKeySequence())
|
||||
{
|
||||
QAction *a = new QAction(parent);
|
||||
|
||||
ConformItem(a,
|
||||
id,
|
||||
receiver,
|
||||
member,
|
||||
key);
|
||||
ConformItem(a, id, receiver, member, key);
|
||||
|
||||
return a;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename Func>
|
||||
/**
|
||||
template <typename Func>
|
||||
/**
|
||||
* @brief Conform a QAction to Olive's ID/keydefault system
|
||||
*
|
||||
* If a QAction was created elsewhere (e.g. through QUndoStack::createUndoAction()), this function will give it
|
||||
@@ -211,30 +205,29 @@ public:
|
||||
*
|
||||
* Default keyboard sequence
|
||||
*/
|
||||
static void ConformItem(QAction *a,
|
||||
const QString& id,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member,
|
||||
const QKeySequence &key = QKeySequence())
|
||||
{
|
||||
ConformItem(a, id, key);
|
||||
static void ConformItem(
|
||||
QAction *a, const QString &id,
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member, const QKeySequence &key = QKeySequence())
|
||||
{
|
||||
ConformItem(a, id, key);
|
||||
|
||||
connect(a, &QAction::triggered, receiver, member);
|
||||
}
|
||||
connect(a, &QAction::triggered, receiver, member);
|
||||
}
|
||||
|
||||
static void ConformItem(QAction *a,
|
||||
const QString& id,
|
||||
const QKeySequence &key = QKeySequence());
|
||||
static void ConformItem(QAction *a, const QString &id,
|
||||
const QKeySequence &key = QKeySequence());
|
||||
|
||||
private:
|
||||
void Init();
|
||||
|
||||
template <typename Func>
|
||||
void ConnectAboutToShow(const typename QtPrivate::FunctionPointer<Func>::Object *receiver, Func member)
|
||||
{
|
||||
connect(this, &Menu::aboutToShow, receiver, member);
|
||||
}
|
||||
void Init();
|
||||
|
||||
template <typename Func>
|
||||
void ConnectAboutToShow(
|
||||
const typename QtPrivate::FunctionPointer<Func>::Object *receiver,
|
||||
Func member)
|
||||
{
|
||||
connect(this, &Menu::aboutToShow, receiver, member);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+248
-195
@@ -27,373 +27,426 @@
|
||||
#include "panel/timeline/timeline.h"
|
||||
#include "window/mainwindow/mainwindow.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
MenuShared* MenuShared::instance_ = nullptr;
|
||||
MenuShared *MenuShared::instance_ = nullptr;
|
||||
|
||||
MenuShared::MenuShared()
|
||||
{
|
||||
// "New" menu shared items
|
||||
new_project_item_ = Menu::CreateItem(this, "newproj", Core::instance(), &Core::CreateNewProject, tr("Ctrl+N"));
|
||||
new_sequence_item_ = Menu::CreateItem(this, "newseq", Core::instance(), &Core::CreateNewSequence, tr("Ctrl+Shift+N"));
|
||||
new_folder_item_ = Menu::CreateItem(this, "newfolder", Core::instance(), &Core::CreateNewFolder);
|
||||
// "New" menu shared items
|
||||
new_project_item_ = Menu::CreateItem(this, "newproj", Core::instance(),
|
||||
&Core::CreateNewProject, tr("Ctrl+N"));
|
||||
new_sequence_item_ = Menu::CreateItem(this, "newseq", Core::instance(),
|
||||
&Core::CreateNewSequence,
|
||||
tr("Ctrl+Shift+N"));
|
||||
new_folder_item_ = Menu::CreateItem(this, "newfolder", Core::instance(),
|
||||
&Core::CreateNewFolder);
|
||||
|
||||
// "Edit" menu shared items
|
||||
edit_cut_item_ = Menu::CreateItem(this, "cut", this, &MenuShared::CutTriggered, tr("Ctrl+X"));
|
||||
edit_copy_item_ = Menu::CreateItem(this, "copy", this, &MenuShared::CopyTriggered, tr("Ctrl+C"));
|
||||
edit_paste_item_ = Menu::CreateItem(this, "paste", this, &MenuShared::PasteTriggered, tr("Ctrl+V"));
|
||||
edit_paste_insert_item_ = Menu::CreateItem(this, "pasteinsert", this, &MenuShared::PasteInsertTriggered, tr("Ctrl+Shift+V"));
|
||||
edit_duplicate_item_ = Menu::CreateItem(this, "duplicate", this, &MenuShared::DuplicateTriggered, tr("Ctrl+D"));
|
||||
edit_rename_item_ = Menu::CreateItem(this, "rename", this, &MenuShared::RenameSelectedTriggered, tr("F2"));
|
||||
edit_delete_item_ = Menu::CreateItem(this, "delete", this, &MenuShared::DeleteSelectedTriggered, tr("Del"));
|
||||
edit_ripple_delete_item_ = Menu::CreateItem(this, "rippledelete", this, &MenuShared::RippleDeleteTriggered, tr("Shift+Del"));
|
||||
edit_split_item_ = Menu::CreateItem(this, "split", this, &MenuShared::SplitAtPlayheadTriggered, tr("Ctrl+K"));
|
||||
edit_speedduration_item_ = Menu::CreateItem(this, "speeddur", this, &MenuShared::SpeedDurationTriggered, tr("Ctrl+R"));
|
||||
// "Edit" menu shared items
|
||||
edit_cut_item_ = Menu::CreateItem(this, "cut", this,
|
||||
&MenuShared::CutTriggered, tr("Ctrl+X"));
|
||||
edit_copy_item_ = Menu::CreateItem(
|
||||
this, "copy", this, &MenuShared::CopyTriggered, tr("Ctrl+C"));
|
||||
edit_paste_item_ = Menu::CreateItem(
|
||||
this, "paste", this, &MenuShared::PasteTriggered, tr("Ctrl+V"));
|
||||
edit_paste_insert_item_ =
|
||||
Menu::CreateItem(this, "pasteinsert", this,
|
||||
&MenuShared::PasteInsertTriggered, tr("Ctrl+Shift+V"));
|
||||
edit_duplicate_item_ = Menu::CreateItem(
|
||||
this, "duplicate", this, &MenuShared::DuplicateTriggered, tr("Ctrl+D"));
|
||||
edit_rename_item_ = Menu::CreateItem(
|
||||
this, "rename", this, &MenuShared::RenameSelectedTriggered, tr("F2"));
|
||||
edit_delete_item_ = Menu::CreateItem(
|
||||
this, "delete", this, &MenuShared::DeleteSelectedTriggered, tr("Del"));
|
||||
edit_ripple_delete_item_ =
|
||||
Menu::CreateItem(this, "rippledelete", this,
|
||||
&MenuShared::RippleDeleteTriggered, tr("Shift+Del"));
|
||||
edit_split_item_ = Menu::CreateItem(this, "split", this,
|
||||
&MenuShared::SplitAtPlayheadTriggered,
|
||||
tr("Ctrl+K"));
|
||||
edit_speedduration_item_ =
|
||||
Menu::CreateItem(this, "speeddur", this,
|
||||
&MenuShared::SpeedDurationTriggered, tr("Ctrl+R"));
|
||||
|
||||
// List of addable items
|
||||
for (int i=0;i<Tool::kAddableCount;i++) {
|
||||
Tool::AddableObject t = static_cast<Tool::AddableObject>(i);
|
||||
QAction *a = Menu::CreateItem(this, QStringLiteral("add:%1").arg(Tool::GetAddableObjectID(t)), this, &MenuShared::AddableItemTriggered);
|
||||
a->setData(t);
|
||||
addable_items_.append(a);
|
||||
}
|
||||
// List of addable items
|
||||
for (int i = 0; i < Tool::kAddableCount; i++) {
|
||||
Tool::AddableObject t = static_cast<Tool::AddableObject>(i);
|
||||
QAction *a = Menu::CreateItem(
|
||||
this, QStringLiteral("add:%1").arg(Tool::GetAddableObjectID(t)),
|
||||
this, &MenuShared::AddableItemTriggered);
|
||||
a->setData(t);
|
||||
addable_items_.append(a);
|
||||
}
|
||||
|
||||
// "In/Out" menu shared items
|
||||
inout_set_in_item_ = Menu::CreateItem(this, "setinpoint", this, &MenuShared::SetInTriggered, tr("I"));
|
||||
inout_set_out_item_ = Menu::CreateItem(this, "setoutpoint", this, &MenuShared::SetOutTriggered, tr("O"));
|
||||
inout_reset_in_item_ = Menu::CreateItem(this, "resetin", this, &MenuShared::ResetInTriggered);
|
||||
inout_reset_out_item_ = Menu::CreateItem(this, "resetout", this, &MenuShared::ResetOutTriggered);
|
||||
inout_clear_inout_item_ = Menu::CreateItem(this, "clearinout", this, &MenuShared::ClearInOutTriggered, tr("G"));
|
||||
// "In/Out" menu shared items
|
||||
inout_set_in_item_ = Menu::CreateItem(this, "setinpoint", this,
|
||||
&MenuShared::SetInTriggered, tr("I"));
|
||||
inout_set_out_item_ = Menu::CreateItem(
|
||||
this, "setoutpoint", this, &MenuShared::SetOutTriggered, tr("O"));
|
||||
inout_reset_in_item_ =
|
||||
Menu::CreateItem(this, "resetin", this, &MenuShared::ResetInTriggered);
|
||||
inout_reset_out_item_ = Menu::CreateItem(this, "resetout", this,
|
||||
&MenuShared::ResetOutTriggered);
|
||||
inout_clear_inout_item_ = Menu::CreateItem(
|
||||
this, "clearinout", this, &MenuShared::ClearInOutTriggered, tr("G"));
|
||||
|
||||
// "Clip Edit" menu shared items
|
||||
clip_add_default_transition_item_ = Menu::CreateItem(this, "deftransition", this, &MenuShared::DefaultTransitionTriggered, tr("Ctrl+Shift+D"));
|
||||
clip_link_unlink_item_ = Menu::CreateItem(this, "linkunlink", this, &MenuShared::ToggleLinksTriggered, tr("Ctrl+L"));
|
||||
clip_enable_disable_item_ = Menu::CreateItem(this, "enabledisable", this, &MenuShared::EnableDisableTriggered, tr("Shift+E"));
|
||||
clip_nest_item_ = Menu::CreateItem(this, "nest", this, &MenuShared::NestTriggered);
|
||||
// "Clip Edit" menu shared items
|
||||
clip_add_default_transition_item_ = Menu::CreateItem(
|
||||
this, "deftransition", this, &MenuShared::DefaultTransitionTriggered,
|
||||
tr("Ctrl+Shift+D"));
|
||||
clip_link_unlink_item_ = Menu::CreateItem(this, "linkunlink", this,
|
||||
&MenuShared::ToggleLinksTriggered,
|
||||
tr("Ctrl+L"));
|
||||
clip_enable_disable_item_ =
|
||||
Menu::CreateItem(this, "enabledisable", this,
|
||||
&MenuShared::EnableDisableTriggered, tr("Shift+E"));
|
||||
clip_nest_item_ =
|
||||
Menu::CreateItem(this, "nest", this, &MenuShared::NestTriggered);
|
||||
|
||||
// TimeRuler menu shared items
|
||||
frame_view_mode_group_ = new QActionGroup(this);
|
||||
// TimeRuler menu shared items
|
||||
frame_view_mode_group_ = new QActionGroup(this);
|
||||
|
||||
view_timecode_view_dropframe_item_ = Menu::CreateItem(this, "modedropframe", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_dropframe_item_->setData(Timecode::kTimecodeDropFrame);
|
||||
view_timecode_view_dropframe_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_dropframe_item_);
|
||||
view_timecode_view_dropframe_item_ = Menu::CreateItem(
|
||||
this, "modedropframe", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_dropframe_item_->setData(Timecode::kTimecodeDropFrame);
|
||||
view_timecode_view_dropframe_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_dropframe_item_);
|
||||
|
||||
view_timecode_view_nondropframe_item_ = Menu::CreateItem(this, "modenondropframe", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_nondropframe_item_->setData(Timecode::kTimecodeNonDropFrame);
|
||||
view_timecode_view_nondropframe_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_nondropframe_item_);
|
||||
view_timecode_view_nondropframe_item_ = Menu::CreateItem(
|
||||
this, "modenondropframe", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_nondropframe_item_->setData(
|
||||
Timecode::kTimecodeNonDropFrame);
|
||||
view_timecode_view_nondropframe_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_nondropframe_item_);
|
||||
|
||||
view_timecode_view_seconds_item_ = Menu::CreateItem(this, "modeseconds", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_seconds_item_->setData(Timecode::kTimecodeSeconds);
|
||||
view_timecode_view_seconds_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_seconds_item_);
|
||||
view_timecode_view_seconds_item_ = Menu::CreateItem(
|
||||
this, "modeseconds", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_seconds_item_->setData(Timecode::kTimecodeSeconds);
|
||||
view_timecode_view_seconds_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_seconds_item_);
|
||||
|
||||
view_timecode_view_frames_item_ = Menu::CreateItem(this, "modeframes", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_frames_item_->setData(Timecode::kFrames);
|
||||
view_timecode_view_frames_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_frames_item_);
|
||||
view_timecode_view_frames_item_ = Menu::CreateItem(
|
||||
this, "modeframes", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_frames_item_->setData(Timecode::kFrames);
|
||||
view_timecode_view_frames_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_frames_item_);
|
||||
|
||||
view_timecode_view_milliseconds_item_ = Menu::CreateItem(this, "milliseconds", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_milliseconds_item_->setData(Timecode::kMilliseconds);
|
||||
view_timecode_view_milliseconds_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_milliseconds_item_);
|
||||
view_timecode_view_milliseconds_item_ = Menu::CreateItem(
|
||||
this, "milliseconds", this, &MenuShared::TimecodeDisplayTriggered);
|
||||
view_timecode_view_milliseconds_item_->setData(Timecode::kMilliseconds);
|
||||
view_timecode_view_milliseconds_item_->setCheckable(true);
|
||||
frame_view_mode_group_->addAction(view_timecode_view_milliseconds_item_);
|
||||
|
||||
// Color coding menu items
|
||||
color_coding_menu_ = new ColorLabelMenu();
|
||||
connect(color_coding_menu_, &ColorLabelMenu::ColorSelected, this, &MenuShared::ColorLabelTriggered);
|
||||
// Color coding menu items
|
||||
color_coding_menu_ = new ColorLabelMenu();
|
||||
connect(color_coding_menu_, &ColorLabelMenu::ColorSelected, this,
|
||||
&MenuShared::ColorLabelTriggered);
|
||||
|
||||
Retranslate();
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
MenuShared::~MenuShared()
|
||||
{
|
||||
delete color_coding_menu_;
|
||||
delete color_coding_menu_;
|
||||
}
|
||||
|
||||
void MenuShared::CreateInstance()
|
||||
{
|
||||
instance_ = new MenuShared();
|
||||
instance_ = new MenuShared();
|
||||
}
|
||||
|
||||
void MenuShared::DestroyInstance()
|
||||
{
|
||||
delete instance_;
|
||||
delete instance_;
|
||||
}
|
||||
|
||||
void MenuShared::AddItemsForNewMenu(Menu *m)
|
||||
{
|
||||
m->addAction(new_project_item_);
|
||||
m->addSeparator();
|
||||
m->addAction(new_sequence_item_);
|
||||
m->addAction(new_folder_item_);
|
||||
m->addAction(new_project_item_);
|
||||
m->addSeparator();
|
||||
m->addAction(new_sequence_item_);
|
||||
m->addAction(new_folder_item_);
|
||||
}
|
||||
|
||||
void MenuShared::AddItemsForEditMenu(Menu *m, bool for_clips)
|
||||
{
|
||||
m->addAction(Core::instance()->undo_stack()->GetUndoAction());
|
||||
m->addAction(Core::instance()->undo_stack()->GetRedoAction());
|
||||
m->addAction(Core::instance()->undo_stack()->GetUndoAction());
|
||||
m->addAction(Core::instance()->undo_stack()->GetRedoAction());
|
||||
|
||||
m->addSeparator();
|
||||
m->addSeparator();
|
||||
|
||||
m->addAction(edit_cut_item_);
|
||||
m->addAction(edit_copy_item_);
|
||||
m->addAction(edit_paste_item_);
|
||||
m->addAction(edit_paste_insert_item_);
|
||||
m->addAction(edit_duplicate_item_);
|
||||
m->addAction(edit_rename_item_);
|
||||
m->addAction(edit_delete_item_);
|
||||
m->addAction(edit_cut_item_);
|
||||
m->addAction(edit_copy_item_);
|
||||
m->addAction(edit_paste_item_);
|
||||
m->addAction(edit_paste_insert_item_);
|
||||
m->addAction(edit_duplicate_item_);
|
||||
m->addAction(edit_rename_item_);
|
||||
m->addAction(edit_delete_item_);
|
||||
|
||||
if (for_clips) {
|
||||
m->addAction(edit_ripple_delete_item_);
|
||||
m->addAction(edit_split_item_);
|
||||
m->addAction(edit_speedduration_item_);
|
||||
if (for_clips) {
|
||||
m->addAction(edit_ripple_delete_item_);
|
||||
m->addAction(edit_split_item_);
|
||||
m->addAction(edit_speedduration_item_);
|
||||
|
||||
m->addSeparator();
|
||||
m->addSeparator();
|
||||
|
||||
m->addAction(clip_add_default_transition_item_);
|
||||
m->addAction(clip_link_unlink_item_);
|
||||
m->addAction(clip_enable_disable_item_);
|
||||
m->addAction(clip_nest_item_);
|
||||
}
|
||||
m->addAction(clip_add_default_transition_item_);
|
||||
m->addAction(clip_link_unlink_item_);
|
||||
m->addAction(clip_enable_disable_item_);
|
||||
m->addAction(clip_nest_item_);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuShared::AddItemsForAddableObjectsMenu(Menu *m)
|
||||
{
|
||||
for (QAction *a : qAsConst(addable_items_)) {
|
||||
a->setChecked((a->data().toInt() == Core::instance()->GetSelectedAddableObject()));
|
||||
m->addAction(a);
|
||||
}
|
||||
for (QAction *a : qAsConst(addable_items_)) {
|
||||
a->setChecked((a->data().toInt() ==
|
||||
Core::instance()->GetSelectedAddableObject()));
|
||||
m->addAction(a);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuShared::AddItemsForInOutMenu(Menu *m)
|
||||
{
|
||||
m->addAction(inout_set_in_item_);
|
||||
m->addAction(inout_set_out_item_);
|
||||
m->addSeparator();
|
||||
m->addAction(inout_reset_in_item_);
|
||||
m->addAction(inout_reset_out_item_);
|
||||
m->addAction(inout_clear_inout_item_);
|
||||
m->addAction(inout_set_in_item_);
|
||||
m->addAction(inout_set_out_item_);
|
||||
m->addSeparator();
|
||||
m->addAction(inout_reset_in_item_);
|
||||
m->addAction(inout_reset_out_item_);
|
||||
m->addAction(inout_clear_inout_item_);
|
||||
}
|
||||
|
||||
void MenuShared::AddColorCodingMenu(Menu *m)
|
||||
{
|
||||
m->addMenu(color_coding_menu_);
|
||||
m->addMenu(color_coding_menu_);
|
||||
}
|
||||
|
||||
void MenuShared::AddItemsForClipEditMenu(Menu *m)
|
||||
{
|
||||
m->addAction(clip_add_default_transition_item_);
|
||||
m->addAction(clip_link_unlink_item_);
|
||||
m->addAction(clip_enable_disable_item_);
|
||||
m->addAction(clip_nest_item_);
|
||||
m->addAction(clip_add_default_transition_item_);
|
||||
m->addAction(clip_link_unlink_item_);
|
||||
m->addAction(clip_enable_disable_item_);
|
||||
m->addAction(clip_nest_item_);
|
||||
}
|
||||
|
||||
void MenuShared::AddItemsForTimeRulerMenu(Menu *m)
|
||||
{
|
||||
m->addAction(view_timecode_view_dropframe_item_);
|
||||
m->addAction(view_timecode_view_nondropframe_item_);
|
||||
m->addAction(view_timecode_view_seconds_item_);
|
||||
m->addAction(view_timecode_view_frames_item_);
|
||||
m->addAction(view_timecode_view_milliseconds_item_);
|
||||
m->addAction(view_timecode_view_dropframe_item_);
|
||||
m->addAction(view_timecode_view_nondropframe_item_);
|
||||
m->addAction(view_timecode_view_seconds_item_);
|
||||
m->addAction(view_timecode_view_frames_item_);
|
||||
m->addAction(view_timecode_view_milliseconds_item_);
|
||||
}
|
||||
|
||||
void MenuShared::AboutToShowTimeRulerActions(const rational& timebase)
|
||||
void MenuShared::AboutToShowTimeRulerActions(const rational &timebase)
|
||||
{
|
||||
QList<QAction*> timecode_display_actions = frame_view_mode_group_->actions();
|
||||
Timecode::Display current_timecode_display = Core::instance()->GetTimecodeDisplay();
|
||||
QList<QAction *> timecode_display_actions =
|
||||
frame_view_mode_group_->actions();
|
||||
Timecode::Display current_timecode_display =
|
||||
Core::instance()->GetTimecodeDisplay();
|
||||
|
||||
// Only show the drop-frame option if the timebase is drop-frame
|
||||
view_timecode_view_dropframe_item_->setVisible(!timebase.isNull() && Timecode::timebase_is_drop_frame(timebase));
|
||||
// Only show the drop-frame option if the timebase is drop-frame
|
||||
view_timecode_view_dropframe_item_->setVisible(
|
||||
!timebase.isNull() && Timecode::timebase_is_drop_frame(timebase));
|
||||
|
||||
if (!view_timecode_view_dropframe_item_->isVisible() && current_timecode_display == Timecode::kTimecodeDropFrame) {
|
||||
// If the current setting is drop-frame, correct to non-drop frame
|
||||
current_timecode_display = Timecode::kTimecodeNonDropFrame;
|
||||
}
|
||||
if (!view_timecode_view_dropframe_item_->isVisible() &&
|
||||
current_timecode_display == Timecode::kTimecodeDropFrame) {
|
||||
// If the current setting is drop-frame, correct to non-drop frame
|
||||
current_timecode_display = Timecode::kTimecodeNonDropFrame;
|
||||
}
|
||||
|
||||
foreach (QAction* a, timecode_display_actions) {
|
||||
if (a->data() == current_timecode_display) {
|
||||
a->setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (QAction *a, timecode_display_actions) {
|
||||
if (a->data() == current_timecode_display) {
|
||||
a->setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MenuShared *MenuShared::instance()
|
||||
{
|
||||
return instance_;
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void MenuShared::SplitAtPlayheadTriggered()
|
||||
{
|
||||
TimelinePanel* timeline = PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
TimelinePanel *timeline =
|
||||
PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
|
||||
if (timeline != nullptr) {
|
||||
timeline->SplitAtPlayhead();
|
||||
}
|
||||
if (timeline != nullptr) {
|
||||
timeline->SplitAtPlayhead();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuShared::DeleteSelectedTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->DeleteSelected();
|
||||
PanelManager::instance()->CurrentlyFocused()->DeleteSelected();
|
||||
}
|
||||
|
||||
void MenuShared::RippleDeleteTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->RippleDelete();
|
||||
PanelManager::instance()->CurrentlyFocused()->RippleDelete();
|
||||
}
|
||||
|
||||
void MenuShared::SetInTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->SetIn();
|
||||
PanelManager::instance()->CurrentlyFocused()->SetIn();
|
||||
}
|
||||
|
||||
void MenuShared::SetOutTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->SetOut();
|
||||
PanelManager::instance()->CurrentlyFocused()->SetOut();
|
||||
}
|
||||
|
||||
void MenuShared::ResetInTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->ResetIn();
|
||||
PanelManager::instance()->CurrentlyFocused()->ResetIn();
|
||||
}
|
||||
|
||||
void MenuShared::ResetOutTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->ResetOut();
|
||||
PanelManager::instance()->CurrentlyFocused()->ResetOut();
|
||||
}
|
||||
|
||||
void MenuShared::ClearInOutTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->ClearInOut();
|
||||
PanelManager::instance()->CurrentlyFocused()->ClearInOut();
|
||||
}
|
||||
|
||||
void MenuShared::ToggleLinksTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->ToggleLinks();
|
||||
PanelManager::instance()->CurrentlyFocused()->ToggleLinks();
|
||||
}
|
||||
|
||||
void MenuShared::CutTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->CutSelected();
|
||||
PanelManager::instance()->CurrentlyFocused()->CutSelected();
|
||||
}
|
||||
|
||||
void MenuShared::CopyTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->CopySelected();
|
||||
PanelManager::instance()->CurrentlyFocused()->CopySelected();
|
||||
}
|
||||
|
||||
void MenuShared::PasteTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->Paste();
|
||||
PanelManager::instance()->CurrentlyFocused()->Paste();
|
||||
}
|
||||
|
||||
void MenuShared::PasteInsertTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->PasteInsert();
|
||||
PanelManager::instance()->CurrentlyFocused()->PasteInsert();
|
||||
}
|
||||
|
||||
void MenuShared::DuplicateTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->Duplicate();
|
||||
PanelManager::instance()->CurrentlyFocused()->Duplicate();
|
||||
}
|
||||
|
||||
void MenuShared::RenameSelectedTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->RenameSelected();
|
||||
PanelManager::instance()->CurrentlyFocused()->RenameSelected();
|
||||
}
|
||||
|
||||
void MenuShared::EnableDisableTriggered()
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->ToggleSelectedEnabled();
|
||||
PanelManager::instance()->CurrentlyFocused()->ToggleSelectedEnabled();
|
||||
}
|
||||
|
||||
void MenuShared::NestTriggered()
|
||||
{
|
||||
PanelManager::instance()->MostRecentlyFocused<TimelinePanel>()->NestSelectedClips();
|
||||
PanelManager::instance()
|
||||
->MostRecentlyFocused<TimelinePanel>()
|
||||
->NestSelectedClips();
|
||||
}
|
||||
|
||||
void MenuShared::DefaultTransitionTriggered()
|
||||
{
|
||||
PanelManager::instance()->MostRecentlyFocused<TimelinePanel>()->AddDefaultTransitionsToSelected();
|
||||
PanelManager::instance()
|
||||
->MostRecentlyFocused<TimelinePanel>()
|
||||
->AddDefaultTransitionsToSelected();
|
||||
}
|
||||
|
||||
void MenuShared::TimecodeDisplayTriggered()
|
||||
{
|
||||
// Assume the sender is a QAction
|
||||
QAction* action = static_cast<QAction*>(sender());
|
||||
// Assume the sender is a QAction
|
||||
QAction *action = static_cast<QAction *>(sender());
|
||||
|
||||
// Assume its data() is a member of Timecode::Display
|
||||
Timecode::Display display = static_cast<Timecode::Display>(action->data().toInt());
|
||||
// Assume its data() is a member of Timecode::Display
|
||||
Timecode::Display display =
|
||||
static_cast<Timecode::Display>(action->data().toInt());
|
||||
|
||||
// Set the current display mode
|
||||
Core::instance()->SetTimecodeDisplay(display);
|
||||
// Set the current display mode
|
||||
Core::instance()->SetTimecodeDisplay(display);
|
||||
}
|
||||
|
||||
void MenuShared::ColorLabelTriggered(int color_index)
|
||||
{
|
||||
PanelManager::instance()->CurrentlyFocused()->SetColorLabel(color_index);
|
||||
PanelManager::instance()->CurrentlyFocused()->SetColorLabel(color_index);
|
||||
}
|
||||
|
||||
void MenuShared::SpeedDurationTriggered()
|
||||
{
|
||||
TimelinePanel* timeline = PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
TimelinePanel *timeline =
|
||||
PanelManager::instance()->MostRecentlyFocused<TimelinePanel>();
|
||||
|
||||
if (timeline) {
|
||||
timeline->ShowSpeedDurationDialogForSelectedClips();
|
||||
}
|
||||
if (timeline) {
|
||||
timeline->ShowSpeedDurationDialogForSelectedClips();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuShared::AddableItemTriggered()
|
||||
{
|
||||
QAction *a = static_cast<QAction*>(sender());
|
||||
Tool::AddableObject i = static_cast<Tool::AddableObject>(a->data().toInt());
|
||||
Core::instance()->SetTool(Tool::kAdd);
|
||||
Core::instance()->SetSelectedAddableObject(i);
|
||||
QAction *a = static_cast<QAction *>(sender());
|
||||
Tool::AddableObject i = static_cast<Tool::AddableObject>(a->data().toInt());
|
||||
Core::instance()->SetTool(Tool::kAdd);
|
||||
Core::instance()->SetSelectedAddableObject(i);
|
||||
}
|
||||
|
||||
void MenuShared::Retranslate()
|
||||
{
|
||||
// "New" menu shared items
|
||||
new_project_item_->setText(tr("&Project"));
|
||||
new_sequence_item_->setText(tr("&Sequence"));
|
||||
new_folder_item_->setText(tr("&Folder"));
|
||||
// "New" menu shared items
|
||||
new_project_item_->setText(tr("&Project"));
|
||||
new_sequence_item_->setText(tr("&Sequence"));
|
||||
new_folder_item_->setText(tr("&Folder"));
|
||||
|
||||
// "Edit" menu shared items
|
||||
edit_cut_item_->setText(tr("Cu&t"));
|
||||
edit_copy_item_->setText(tr("Cop&y"));
|
||||
edit_paste_item_->setText(tr("&Paste"));
|
||||
edit_paste_insert_item_->setText(tr("Paste Insert"));
|
||||
edit_duplicate_item_->setText(tr("Duplicate"));
|
||||
edit_rename_item_->setText(tr("Rename"));
|
||||
edit_delete_item_->setText(tr("Delete"));
|
||||
edit_ripple_delete_item_->setText(tr("Ripple Delete"));
|
||||
edit_split_item_->setText(tr("Split"));
|
||||
edit_speedduration_item_->setText(tr("Speed/Duration"));
|
||||
// "Edit" menu shared items
|
||||
edit_cut_item_->setText(tr("Cu&t"));
|
||||
edit_copy_item_->setText(tr("Cop&y"));
|
||||
edit_paste_item_->setText(tr("&Paste"));
|
||||
edit_paste_insert_item_->setText(tr("Paste Insert"));
|
||||
edit_duplicate_item_->setText(tr("Duplicate"));
|
||||
edit_rename_item_->setText(tr("Rename"));
|
||||
edit_delete_item_->setText(tr("Delete"));
|
||||
edit_ripple_delete_item_->setText(tr("Ripple Delete"));
|
||||
edit_split_item_->setText(tr("Split"));
|
||||
edit_speedduration_item_->setText(tr("Speed/Duration"));
|
||||
|
||||
for (QAction *a : qAsConst(addable_items_)) {
|
||||
a->setText(Tool::GetAddableObjectName(static_cast<Tool::AddableObject>(a->data().toInt())));
|
||||
}
|
||||
for (QAction *a : qAsConst(addable_items_)) {
|
||||
a->setText(Tool::GetAddableObjectName(
|
||||
static_cast<Tool::AddableObject>(a->data().toInt())));
|
||||
}
|
||||
|
||||
// "In/Out" menu shared items
|
||||
inout_set_in_item_->setText(tr("Set In Point"));
|
||||
inout_set_out_item_->setText(tr("Set Out Point"));
|
||||
inout_reset_in_item_->setText(tr("Reset In Point"));
|
||||
inout_reset_out_item_->setText(tr("Reset Out Point"));
|
||||
inout_clear_inout_item_->setText(tr("Clear In/Out Point"));
|
||||
// "In/Out" menu shared items
|
||||
inout_set_in_item_->setText(tr("Set In Point"));
|
||||
inout_set_out_item_->setText(tr("Set Out Point"));
|
||||
inout_reset_in_item_->setText(tr("Reset In Point"));
|
||||
inout_reset_out_item_->setText(tr("Reset Out Point"));
|
||||
inout_clear_inout_item_->setText(tr("Clear In/Out Point"));
|
||||
|
||||
// "Clip Edit" menu shared items
|
||||
clip_add_default_transition_item_->setText(tr("Add Default Transition"));
|
||||
clip_link_unlink_item_->setText(tr("Link/Unlink"));
|
||||
clip_enable_disable_item_->setText(tr("Enable/Disable"));
|
||||
clip_nest_item_->setText(tr("Nest"));
|
||||
// "Clip Edit" menu shared items
|
||||
clip_add_default_transition_item_->setText(tr("Add Default Transition"));
|
||||
clip_link_unlink_item_->setText(tr("Link/Unlink"));
|
||||
clip_enable_disable_item_->setText(tr("Enable/Disable"));
|
||||
clip_nest_item_->setText(tr("Nest"));
|
||||
|
||||
// TimeRuler menu shared items
|
||||
view_timecode_view_frames_item_->setText(tr("Frames"));
|
||||
view_timecode_view_dropframe_item_->setText(tr("Drop Frame"));
|
||||
view_timecode_view_nondropframe_item_->setText(tr("Non-Drop Frame"));
|
||||
view_timecode_view_milliseconds_item_->setText(tr("Milliseconds"));
|
||||
view_timecode_view_seconds_item_->setText(tr("Seconds"));
|
||||
// TimeRuler menu shared items
|
||||
view_timecode_view_frames_item_->setText(tr("Frames"));
|
||||
view_timecode_view_dropframe_item_->setText(tr("Drop Frame"));
|
||||
view_timecode_view_nondropframe_item_->setText(tr("Non-Drop Frame"));
|
||||
view_timecode_view_milliseconds_item_->setText(tr("Milliseconds"));
|
||||
view_timecode_view_seconds_item_->setText(tr("Seconds"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,141 +25,140 @@
|
||||
#include "widget/colorlabelmenu/colorlabelmenu.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
using namespace core;
|
||||
|
||||
/**
|
||||
* @brief A static object that provides various "stock" menus for use throughout the application
|
||||
*/
|
||||
class MenuShared : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class MenuShared : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MenuShared();
|
||||
virtual ~MenuShared() override;
|
||||
MenuShared();
|
||||
virtual ~MenuShared() override;
|
||||
|
||||
static void CreateInstance();
|
||||
static void DestroyInstance();
|
||||
static void CreateInstance();
|
||||
static void DestroyInstance();
|
||||
|
||||
void Retranslate();
|
||||
void Retranslate();
|
||||
|
||||
void AddItemsForNewMenu(Menu* m);
|
||||
void AddItemsForEditMenu(Menu* m, bool for_clips);
|
||||
void AddItemsForAddableObjectsMenu(Menu* m);
|
||||
void AddItemsForInOutMenu(Menu* m);
|
||||
void AddColorCodingMenu(Menu* m);
|
||||
void AddItemsForClipEditMenu(Menu* m);
|
||||
void AddItemsForTimeRulerMenu(Menu* m);
|
||||
void AddItemsForNewMenu(Menu *m);
|
||||
void AddItemsForEditMenu(Menu *m, bool for_clips);
|
||||
void AddItemsForAddableObjectsMenu(Menu *m);
|
||||
void AddItemsForInOutMenu(Menu *m);
|
||||
void AddColorCodingMenu(Menu *m);
|
||||
void AddItemsForClipEditMenu(Menu *m);
|
||||
void AddItemsForTimeRulerMenu(Menu *m);
|
||||
|
||||
void AboutToShowTimeRulerActions(const rational& timebase);
|
||||
void AboutToShowTimeRulerActions(const rational &timebase);
|
||||
|
||||
static MenuShared* instance();
|
||||
static MenuShared *instance();
|
||||
|
||||
QAction* edit_delete_item()
|
||||
{
|
||||
return edit_delete_item_;
|
||||
}
|
||||
QAction *edit_delete_item()
|
||||
{
|
||||
return edit_delete_item_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void DeleteSelectedTriggered();
|
||||
void DeleteSelectedTriggered();
|
||||
|
||||
private:
|
||||
// "New" menu shared items
|
||||
QAction* new_project_item_;
|
||||
QAction* new_sequence_item_;
|
||||
QAction* new_folder_item_;
|
||||
// "New" menu shared items
|
||||
QAction *new_project_item_;
|
||||
QAction *new_sequence_item_;
|
||||
QAction *new_folder_item_;
|
||||
|
||||
// "Edit" menu shared items
|
||||
QAction* edit_cut_item_;
|
||||
QAction* edit_copy_item_;
|
||||
QAction* edit_paste_item_;
|
||||
QAction* edit_paste_insert_item_;
|
||||
QAction* edit_duplicate_item_;
|
||||
QAction* edit_rename_item_;
|
||||
QAction* edit_delete_item_;
|
||||
QAction* edit_ripple_delete_item_;
|
||||
QAction* edit_split_item_;
|
||||
QAction* edit_speedduration_item_;
|
||||
// "Edit" menu shared items
|
||||
QAction *edit_cut_item_;
|
||||
QAction *edit_copy_item_;
|
||||
QAction *edit_paste_item_;
|
||||
QAction *edit_paste_insert_item_;
|
||||
QAction *edit_duplicate_item_;
|
||||
QAction *edit_rename_item_;
|
||||
QAction *edit_delete_item_;
|
||||
QAction *edit_ripple_delete_item_;
|
||||
QAction *edit_split_item_;
|
||||
QAction *edit_speedduration_item_;
|
||||
|
||||
// List of addable items
|
||||
QVector<QAction*> addable_items_;
|
||||
// List of addable items
|
||||
QVector<QAction *> addable_items_;
|
||||
|
||||
// "In/Out" menu shared items
|
||||
QAction* inout_set_in_item_;
|
||||
QAction* inout_set_out_item_;
|
||||
QAction* inout_reset_in_item_;
|
||||
QAction* inout_reset_out_item_;
|
||||
QAction* inout_clear_inout_item_;
|
||||
// "In/Out" menu shared items
|
||||
QAction *inout_set_in_item_;
|
||||
QAction *inout_set_out_item_;
|
||||
QAction *inout_reset_in_item_;
|
||||
QAction *inout_reset_out_item_;
|
||||
QAction *inout_clear_inout_item_;
|
||||
|
||||
// "Clip Edit" menu shared items
|
||||
QAction* clip_add_default_transition_item_;
|
||||
QAction* clip_link_unlink_item_;
|
||||
QAction* clip_enable_disable_item_;
|
||||
QAction* clip_nest_item_;
|
||||
// "Clip Edit" menu shared items
|
||||
QAction *clip_add_default_transition_item_;
|
||||
QAction *clip_link_unlink_item_;
|
||||
QAction *clip_enable_disable_item_;
|
||||
QAction *clip_nest_item_;
|
||||
|
||||
// TimeRuler menu shared items
|
||||
QActionGroup* frame_view_mode_group_;
|
||||
QAction* view_timecode_view_dropframe_item_;
|
||||
QAction* view_timecode_view_nondropframe_item_;
|
||||
QAction* view_timecode_view_seconds_item_;
|
||||
QAction* view_timecode_view_frames_item_;
|
||||
QAction* view_timecode_view_milliseconds_item_;
|
||||
// TimeRuler menu shared items
|
||||
QActionGroup *frame_view_mode_group_;
|
||||
QAction *view_timecode_view_dropframe_item_;
|
||||
QAction *view_timecode_view_nondropframe_item_;
|
||||
QAction *view_timecode_view_seconds_item_;
|
||||
QAction *view_timecode_view_frames_item_;
|
||||
QAction *view_timecode_view_milliseconds_item_;
|
||||
|
||||
// Color coding menu items
|
||||
ColorLabelMenu* color_coding_menu_;
|
||||
// Color coding menu items
|
||||
ColorLabelMenu *color_coding_menu_;
|
||||
|
||||
static MenuShared* instance_;
|
||||
static MenuShared *instance_;
|
||||
|
||||
private slots:
|
||||
void SplitAtPlayheadTriggered();
|
||||
void SplitAtPlayheadTriggered();
|
||||
|
||||
void RippleDeleteTriggered();
|
||||
void RippleDeleteTriggered();
|
||||
|
||||
void SetInTriggered();
|
||||
void SetInTriggered();
|
||||
|
||||
void SetOutTriggered();
|
||||
void SetOutTriggered();
|
||||
|
||||
void ResetInTriggered();
|
||||
void ResetInTriggered();
|
||||
|
||||
void ResetOutTriggered();
|
||||
void ResetOutTriggered();
|
||||
|
||||
void ClearInOutTriggered();
|
||||
void ClearInOutTriggered();
|
||||
|
||||
void ToggleLinksTriggered();
|
||||
void ToggleLinksTriggered();
|
||||
|
||||
void CutTriggered();
|
||||
void CutTriggered();
|
||||
|
||||
void CopyTriggered();
|
||||
void CopyTriggered();
|
||||
|
||||
void PasteTriggered();
|
||||
void PasteTriggered();
|
||||
|
||||
void PasteInsertTriggered();
|
||||
void PasteInsertTriggered();
|
||||
|
||||
void DuplicateTriggered();
|
||||
void DuplicateTriggered();
|
||||
|
||||
void RenameSelectedTriggered();
|
||||
void RenameSelectedTriggered();
|
||||
|
||||
void EnableDisableTriggered();
|
||||
void EnableDisableTriggered();
|
||||
|
||||
void NestTriggered();
|
||||
void NestTriggered();
|
||||
|
||||
void DefaultTransitionTriggered();
|
||||
void DefaultTransitionTriggered();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief A slot for the timecode display menu items
|
||||
*
|
||||
* Assumes a QAction* sender() and its data() is a member of enum Timecode::Display. Uses the data() to signal a
|
||||
* timecode change throughout the rest of the application.
|
||||
*/
|
||||
void TimecodeDisplayTriggered();
|
||||
void TimecodeDisplayTriggered();
|
||||
|
||||
void ColorLabelTriggered(int color_index);
|
||||
void ColorLabelTriggered(int color_index);
|
||||
|
||||
void SpeedDurationTriggered();
|
||||
|
||||
void AddableItemTriggered();
|
||||
void SpeedDurationTriggered();
|
||||
|
||||
void AddableItemTriggered();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -20,153 +20,171 @@
|
||||
|
||||
#include "multicamdisplay.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super ViewerDisplayWidget
|
||||
|
||||
MulticamDisplay::MulticamDisplay(QWidget *parent) :
|
||||
super(parent),
|
||||
node_(nullptr),
|
||||
rows_(0),
|
||||
cols_(0)
|
||||
MulticamDisplay::MulticamDisplay(QWidget *parent)
|
||||
: super(parent)
|
||||
, node_(nullptr)
|
||||
, rows_(0)
|
||||
, cols_(0)
|
||||
{
|
||||
}
|
||||
|
||||
void MulticamDisplay::OnPaint()
|
||||
{
|
||||
super::OnPaint();
|
||||
super::OnPaint();
|
||||
|
||||
if (node_) {
|
||||
QPainter p(paint_device());
|
||||
if (node_) {
|
||||
QPainter p(paint_device());
|
||||
|
||||
p.setPen(QPen(Qt::yellow, fontMetrics().height()/4));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(QPen(Qt::yellow, fontMetrics().height() / 4));
|
||||
p.setBrush(Qt::NoBrush);
|
||||
|
||||
int rows, cols;
|
||||
node_->GetRowsAndColumns(&rows, &cols);
|
||||
int rows, cols;
|
||||
node_->GetRowsAndColumns(&rows, &cols);
|
||||
|
||||
int multi = std::max(rows, cols);
|
||||
int cell_width = width() / multi;
|
||||
int cell_height = height() / multi;
|
||||
int multi = std::max(rows, cols);
|
||||
int cell_width = width() / multi;
|
||||
int cell_height = height() / multi;
|
||||
|
||||
int col, row;
|
||||
node_->IndexToRowCols(node_->GetCurrentSource(), rows, cols, &row, &col);
|
||||
int col, row;
|
||||
node_->IndexToRowCols(node_->GetCurrentSource(), rows, cols, &row,
|
||||
&col);
|
||||
|
||||
QRect r(cell_width * col, cell_height * row, cell_width, cell_height);
|
||||
p.drawRect(GenerateWorldTransform().mapRect(r));
|
||||
}
|
||||
QRect r(cell_width * col, cell_height * row, cell_width, cell_height);
|
||||
p.drawRect(GenerateWorldTransform().mapRect(r));
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamDisplay::OnDestroy()
|
||||
{
|
||||
shader_ = QVariant();
|
||||
shader_ = QVariant();
|
||||
}
|
||||
|
||||
TexturePtr MulticamDisplay::LoadCustomTextureFromFrame(const QVariant &v)
|
||||
{
|
||||
if (v.canConvert<QVector<TexturePtr> >()) {
|
||||
QVector<TexturePtr> tex = v.value<QVector<TexturePtr> >();
|
||||
if (v.canConvert<QVector<TexturePtr>>()) {
|
||||
QVector<TexturePtr> tex = v.value<QVector<TexturePtr>>();
|
||||
|
||||
TexturePtr main = renderer()->CreateTexture(this->GetViewportParams());
|
||||
TexturePtr main = renderer()->CreateTexture(this->GetViewportParams());
|
||||
|
||||
int rows, cols;
|
||||
MultiCamNode::GetRowsAndColumns(tex.size(), &rows, &cols);
|
||||
int rows, cols;
|
||||
MultiCamNode::GetRowsAndColumns(tex.size(), &rows, &cols);
|
||||
|
||||
if (shader_.isNull() || rows_ != rows || cols_ != cols) {
|
||||
if (!shader_.isNull()) {
|
||||
renderer()->DestroyNativeShader(shader_);
|
||||
}
|
||||
if (shader_.isNull() || rows_ != rows || cols_ != cols) {
|
||||
if (!shader_.isNull()) {
|
||||
renderer()->DestroyNativeShader(shader_);
|
||||
}
|
||||
|
||||
shader_ = renderer()->CreateNativeShader(ShaderCode(GenerateShaderCode(rows, cols)));
|
||||
shader_ = renderer()->CreateNativeShader(
|
||||
ShaderCode(GenerateShaderCode(rows, cols)));
|
||||
|
||||
rows_ = rows;
|
||||
cols_ = cols;
|
||||
}
|
||||
rows_ = rows;
|
||||
cols_ = cols;
|
||||
}
|
||||
|
||||
ShaderJob job;
|
||||
ShaderJob job;
|
||||
|
||||
for (int i=0; i<tex.size(); i++) {
|
||||
int c, r;
|
||||
MultiCamNode::IndexToRowCols(i, rows, cols, &r, &c);
|
||||
job.Insert(QStringLiteral("tex_%1_%2").arg(QString::number(r), QString::number(c)), NodeValue(NodeValue::kTexture, tex.at(i)));
|
||||
}
|
||||
for (int i = 0; i < tex.size(); i++) {
|
||||
int c, r;
|
||||
MultiCamNode::IndexToRowCols(i, rows, cols, &r, &c);
|
||||
job.Insert(QStringLiteral("tex_%1_%2")
|
||||
.arg(QString::number(r), QString::number(c)),
|
||||
NodeValue(NodeValue::kTexture, tex.at(i)));
|
||||
}
|
||||
|
||||
renderer()->BlitToTexture(shader_, job, main.get());
|
||||
renderer()->BlitToTexture(shader_, job, main.get());
|
||||
|
||||
return main;
|
||||
} else {
|
||||
return super::LoadCustomTextureFromFrame(v);
|
||||
}
|
||||
return main;
|
||||
} else {
|
||||
return super::LoadCustomTextureFromFrame(v);
|
||||
}
|
||||
}
|
||||
|
||||
QString dblToGlsl(double d)
|
||||
{
|
||||
return QString::number(d, 'f');
|
||||
return QString::number(d, 'f');
|
||||
}
|
||||
|
||||
QString MulticamDisplay::GenerateShaderCode(int rows, int cols)
|
||||
{
|
||||
int multiplier = std::max(cols, rows);
|
||||
int multiplier = std::max(cols, rows);
|
||||
|
||||
QStringList shader;
|
||||
QStringList shader;
|
||||
|
||||
shader.append(QStringLiteral("in vec2 ove_texcoord;"));
|
||||
shader.append(QStringLiteral("out vec4 frag_color;"));
|
||||
shader.append(QStringLiteral("in vec2 ove_texcoord;"));
|
||||
shader.append(QStringLiteral("out vec4 frag_color;"));
|
||||
|
||||
for (int x=0;x<cols;x++) {
|
||||
for (int y=0;y<rows;y++) {
|
||||
shader.append(QStringLiteral("uniform sampler2D tex_%1_%2;").arg(QString::number(y), QString::number(x)));
|
||||
shader.append(QStringLiteral("uniform bool tex_%1_%2_enabled;").arg(QString::number(y), QString::number(x)));
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < cols; x++) {
|
||||
for (int y = 0; y < rows; y++) {
|
||||
shader.append(QStringLiteral("uniform sampler2D tex_%1_%2;")
|
||||
.arg(QString::number(y), QString::number(x)));
|
||||
shader.append(QStringLiteral("uniform bool tex_%1_%2_enabled;")
|
||||
.arg(QString::number(y), QString::number(x)));
|
||||
}
|
||||
}
|
||||
|
||||
shader.append(QStringLiteral("void main() {"));
|
||||
shader.append(QStringLiteral("void main() {"));
|
||||
|
||||
for (int x=0;x<cols;x++) {
|
||||
if (x > 0) {
|
||||
shader.append(QStringLiteral(" else"));
|
||||
}
|
||||
if (x == cols-1) {
|
||||
shader.append(QStringLiteral(" {"));
|
||||
} else {
|
||||
shader.append(QStringLiteral(" if (ove_texcoord.x < %1) {").arg(dblToGlsl(double(x+1)/double(multiplier))));
|
||||
}
|
||||
for (int x = 0; x < cols; x++) {
|
||||
if (x > 0) {
|
||||
shader.append(QStringLiteral(" else"));
|
||||
}
|
||||
if (x == cols - 1) {
|
||||
shader.append(QStringLiteral(" {"));
|
||||
} else {
|
||||
shader.append(
|
||||
QStringLiteral(" if (ove_texcoord.x < %1) {")
|
||||
.arg(dblToGlsl(double(x + 1) / double(multiplier))));
|
||||
}
|
||||
|
||||
for (int y=0;y<rows;y++) {
|
||||
if (y > 0) {
|
||||
shader.append(QStringLiteral(" else"));
|
||||
}
|
||||
if (y == rows-1) {
|
||||
shader.append(QStringLiteral(" {"));
|
||||
} else {
|
||||
shader.append(QStringLiteral(" if (ove_texcoord.y < %1) {").arg(dblToGlsl(double(y+1)/double(multiplier))));
|
||||
}
|
||||
QString input = QStringLiteral("tex_%1_%2").arg(QString::number(y), QString::number(x));
|
||||
shader.append(QStringLiteral(" vec2 coord = vec2((ove_texcoord.x+%1)*%2, (ove_texcoord.y+%3)*%4);").arg(
|
||||
dblToGlsl( - double(x)/double(multiplier)),
|
||||
dblToGlsl(multiplier),
|
||||
dblToGlsl( - double(y)/double(multiplier)),
|
||||
dblToGlsl(multiplier)
|
||||
));
|
||||
shader.append(QStringLiteral(" if (%1_enabled && coord.x >= 0.0 && coord.x < 1.0 && coord.y >= 0.0 && coord.y < 1.0) {").arg(input));
|
||||
shader.append(QStringLiteral(" frag_color = texture(%1, coord);").arg(input));
|
||||
shader.append(QStringLiteral(" } else {"));
|
||||
shader.append(QStringLiteral(" discard;"));
|
||||
shader.append(QStringLiteral(" }"));
|
||||
shader.append(QStringLiteral(" }"));
|
||||
}
|
||||
for (int y = 0; y < rows; y++) {
|
||||
if (y > 0) {
|
||||
shader.append(QStringLiteral(" else"));
|
||||
}
|
||||
if (y == rows - 1) {
|
||||
shader.append(QStringLiteral(" {"));
|
||||
} else {
|
||||
shader.append(
|
||||
QStringLiteral(" if (ove_texcoord.y < %1) {")
|
||||
.arg(dblToGlsl(double(y + 1) / double(multiplier))));
|
||||
}
|
||||
QString input = QStringLiteral("tex_%1_%2")
|
||||
.arg(QString::number(y), QString::number(x));
|
||||
shader.append(
|
||||
QStringLiteral(
|
||||
" vec2 coord = vec2((ove_texcoord.x+%1)*%2, (ove_texcoord.y+%3)*%4);")
|
||||
.arg(dblToGlsl(-double(x) / double(multiplier)),
|
||||
dblToGlsl(multiplier),
|
||||
dblToGlsl(-double(y) / double(multiplier)),
|
||||
dblToGlsl(multiplier)));
|
||||
shader.append(
|
||||
QStringLiteral(
|
||||
" if (%1_enabled && coord.x >= 0.0 && coord.x < 1.0 && coord.y >= 0.0 && coord.y < 1.0) {")
|
||||
.arg(input));
|
||||
shader.append(
|
||||
QStringLiteral(" frag_color = texture(%1, coord);")
|
||||
.arg(input));
|
||||
shader.append(QStringLiteral(" } else {"));
|
||||
shader.append(QStringLiteral(" discard;"));
|
||||
shader.append(QStringLiteral(" }"));
|
||||
shader.append(QStringLiteral(" }"));
|
||||
}
|
||||
|
||||
shader.append(QStringLiteral(" }"));
|
||||
}
|
||||
shader.append(QStringLiteral(" }"));
|
||||
}
|
||||
|
||||
shader.append(QStringLiteral("}"));
|
||||
shader.append(QStringLiteral("}"));
|
||||
|
||||
return shader.join('\n');
|
||||
return shader.join('\n');
|
||||
}
|
||||
|
||||
void MulticamDisplay::SetMulticamNode(MultiCamNode *n)
|
||||
{
|
||||
node_ = n;
|
||||
node_ = n;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,32 +24,31 @@
|
||||
#include "node/input/multicam/multicamnode.h"
|
||||
#include "widget/viewer/viewerdisplay.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class MulticamDisplay : public ViewerDisplayWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MulticamDisplay(QWidget *parent = nullptr);
|
||||
|
||||
void SetMulticamNode(MultiCamNode *n);
|
||||
class MulticamDisplay : public ViewerDisplayWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MulticamDisplay(QWidget *parent = nullptr);
|
||||
|
||||
void SetMulticamNode(MultiCamNode *n);
|
||||
|
||||
protected:
|
||||
virtual void OnPaint() override;
|
||||
virtual void OnPaint() override;
|
||||
|
||||
virtual void OnDestroy() override;
|
||||
virtual void OnDestroy() override;
|
||||
|
||||
virtual TexturePtr LoadCustomTextureFromFrame(const QVariant &v) override;
|
||||
virtual TexturePtr LoadCustomTextureFromFrame(const QVariant &v) override;
|
||||
|
||||
private:
|
||||
static QString GenerateShaderCode(int rows, int cols);
|
||||
static QString GenerateShaderCode(int rows, int cols);
|
||||
|
||||
MultiCamNode *node_;
|
||||
|
||||
QVariant shader_;
|
||||
int rows_;
|
||||
int cols_;
|
||||
MultiCamNode *node_;
|
||||
|
||||
QVariant shader_;
|
||||
int rows_;
|
||||
int cols_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,164 +26,187 @@
|
||||
#include "timeline/timelineundosplit.h"
|
||||
#include "widget/timeruler/timeruler.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super TimeBasedWidget
|
||||
|
||||
MulticamWidget::MulticamWidget(QWidget *parent) :
|
||||
super{false, false, parent},
|
||||
node_(nullptr),
|
||||
clip_(nullptr)
|
||||
MulticamWidget::MulticamWidget(QWidget *parent)
|
||||
: super{ false, false, parent }
|
||||
, node_(nullptr)
|
||||
, clip_(nullptr)
|
||||
{
|
||||
auto layout = new QVBoxLayout(this);
|
||||
auto layout = new QVBoxLayout(this);
|
||||
|
||||
sizer_ = new ViewerSizer(this);
|
||||
layout->addWidget(sizer_);
|
||||
sizer_ = new ViewerSizer(this);
|
||||
layout->addWidget(sizer_);
|
||||
|
||||
display_ = new MulticamDisplay(this);
|
||||
display_->SetShowWidgetBackground(true);
|
||||
connect(display_, &ViewerDisplayWidget::DragStarted, this, &MulticamWidget::DisplayClicked);
|
||||
display_ = new MulticamDisplay(this);
|
||||
display_->SetShowWidgetBackground(true);
|
||||
connect(display_, &ViewerDisplayWidget::DragStarted, this,
|
||||
&MulticamWidget::DisplayClicked);
|
||||
|
||||
connect(sizer_, &ViewerSizer::RequestScale, display_, &ViewerDisplayWidget::SetMatrixZoom);
|
||||
connect(sizer_, &ViewerSizer::RequestTranslate, display_, &ViewerDisplayWidget::SetMatrixTranslate);
|
||||
connect(display_, &ViewerDisplayWidget::HandDragMoved, sizer_, &ViewerSizer::HandDragMove);
|
||||
sizer_->SetWidget(display_);
|
||||
connect(sizer_, &ViewerSizer::RequestScale, display_,
|
||||
&ViewerDisplayWidget::SetMatrixZoom);
|
||||
connect(sizer_, &ViewerSizer::RequestTranslate, display_,
|
||||
&ViewerDisplayWidget::SetMatrixTranslate);
|
||||
connect(display_, &ViewerDisplayWidget::HandDragMoved, sizer_,
|
||||
&ViewerSizer::HandDragMove);
|
||||
sizer_->SetWidget(display_);
|
||||
|
||||
layout->addWidget(this->ruler());
|
||||
layout->addWidget(this->scrollbar());
|
||||
layout->addWidget(this->ruler());
|
||||
layout->addWidget(this->scrollbar());
|
||||
|
||||
for (int i=0; i<9; i++) {
|
||||
new QShortcut(QStringLiteral("Ctrl+%1").arg(QString::number(i+1)), this, this, [this, i]{Switch(i, false);});
|
||||
new QShortcut(QString::number(i+1), this, this, [this, i]{Switch(i, true);});
|
||||
}
|
||||
for (int i = 0; i < 9; i++) {
|
||||
new QShortcut(QStringLiteral("Ctrl+%1").arg(QString::number(i + 1)),
|
||||
this, this, [this, i] { Switch(i, false); });
|
||||
new QShortcut(QString::number(i + 1), this, this,
|
||||
[this, i] { Switch(i, true); });
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamWidget::SetMulticamNodeInternal(ViewerOutput *viewer, MultiCamNode *n, ClipBlock *clip)
|
||||
void MulticamWidget::SetMulticamNodeInternal(ViewerOutput *viewer,
|
||||
MultiCamNode *n, ClipBlock *clip)
|
||||
{
|
||||
if (GetConnectedNode() != viewer) {
|
||||
ConnectViewerNode(viewer);
|
||||
}
|
||||
if (GetConnectedNode() != viewer) {
|
||||
ConnectViewerNode(viewer);
|
||||
}
|
||||
|
||||
if (node_ != n) {
|
||||
node_ = n;
|
||||
display_->SetMulticamNode(n);
|
||||
}
|
||||
if (node_ != n) {
|
||||
node_ = n;
|
||||
display_->SetMulticamNode(n);
|
||||
}
|
||||
|
||||
if (clip_ != clip) {
|
||||
clip_ = clip;
|
||||
}
|
||||
if (clip_ != clip) {
|
||||
clip_ = clip;
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamWidget::SetMulticamNode(ViewerOutput *viewer, MultiCamNode *n, ClipBlock *clip, const rational &time)
|
||||
void MulticamWidget::SetMulticamNode(ViewerOutput *viewer, MultiCamNode *n,
|
||||
ClipBlock *clip, const rational &time)
|
||||
{
|
||||
if (time.isNaN() || !GetConnectedNode() || time == GetConnectedNode()->GetPlayhead()) {
|
||||
SetMulticamNodeInternal(viewer, n, clip);
|
||||
play_queue_.clear();
|
||||
} else {
|
||||
MulticamNodeQueue m = {time, viewer, n, clip};
|
||||
play_queue_.push_back(m);
|
||||
}
|
||||
if (time.isNaN() || !GetConnectedNode() ||
|
||||
time == GetConnectedNode()->GetPlayhead()) {
|
||||
SetMulticamNodeInternal(viewer, n, clip);
|
||||
play_queue_.clear();
|
||||
} else {
|
||||
MulticamNodeQueue m = { time, viewer, n, clip };
|
||||
play_queue_.push_back(m);
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamWidget::ConnectNodeEvent(ViewerOutput *n)
|
||||
{
|
||||
connect(n, &ViewerOutput::SizeChanged, sizer_, &ViewerSizer::SetChildSize);
|
||||
connect(n, &ViewerOutput::PixelAspectChanged, sizer_, &ViewerSizer::SetPixelAspectRatio);
|
||||
connect(n, &ViewerOutput::SizeChanged, sizer_, &ViewerSizer::SetChildSize);
|
||||
connect(n, &ViewerOutput::PixelAspectChanged, sizer_,
|
||||
&ViewerSizer::SetPixelAspectRatio);
|
||||
|
||||
VideoParams vp = n->GetVideoParams();
|
||||
sizer_->SetChildSize(vp.width(), vp.height());
|
||||
sizer_->SetPixelAspectRatio(vp.pixel_aspect_ratio());
|
||||
VideoParams vp = n->GetVideoParams();
|
||||
sizer_->SetChildSize(vp.width(), vp.height());
|
||||
sizer_->SetPixelAspectRatio(vp.pixel_aspect_ratio());
|
||||
}
|
||||
|
||||
void MulticamWidget::DisconnectNodeEvent(ViewerOutput *n)
|
||||
{
|
||||
disconnect(n, &ViewerOutput::SizeChanged, sizer_, &ViewerSizer::SetChildSize);
|
||||
disconnect(n, &ViewerOutput::PixelAspectChanged, sizer_, &ViewerSizer::SetPixelAspectRatio);
|
||||
disconnect(n, &ViewerOutput::SizeChanged, sizer_,
|
||||
&ViewerSizer::SetChildSize);
|
||||
disconnect(n, &ViewerOutput::PixelAspectChanged, sizer_,
|
||||
&ViewerSizer::SetPixelAspectRatio);
|
||||
}
|
||||
|
||||
void MulticamWidget::TimeChangedEvent(const rational &t)
|
||||
{
|
||||
super::TimeChangedEvent(t);
|
||||
super::TimeChangedEvent(t);
|
||||
|
||||
if (!play_queue_.empty()) {
|
||||
const MulticamNodeQueue &m = play_queue_.front();
|
||||
if (m.time >= t) {
|
||||
SetMulticamNodeInternal(m.viewer, m.node, m.clip);
|
||||
play_queue_.pop_front();
|
||||
}
|
||||
}
|
||||
if (!play_queue_.empty()) {
|
||||
const MulticamNodeQueue &m = play_queue_.front();
|
||||
if (m.time >= t) {
|
||||
SetMulticamNodeInternal(m.viewer, m.node, m.clip);
|
||||
play_queue_.pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MulticamWidget::Switch(int source, bool split_clip)
|
||||
{
|
||||
if (!node_) {
|
||||
return;
|
||||
}
|
||||
if (!node_) {
|
||||
return;
|
||||
}
|
||||
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
MultiCamNode *cam = node_;
|
||||
ClipBlock *clip = clip_;
|
||||
MultiCamNode *cam = node_;
|
||||
ClipBlock *clip = clip_;
|
||||
|
||||
BlockSplitPreservingLinksCommand *split = nullptr;
|
||||
BlockSplitPreservingLinksCommand *split = nullptr;
|
||||
|
||||
if (clip_ && split_clip && clip_->in() < GetConnectedNode()->GetPlayhead() && clip_->out() > GetConnectedNode()->GetPlayhead()) {
|
||||
QVector<Block*> blocks;
|
||||
if (clip_ && split_clip &&
|
||||
clip_->in() < GetConnectedNode()->GetPlayhead() &&
|
||||
clip_->out() > GetConnectedNode()->GetPlayhead()) {
|
||||
QVector<Block *> blocks;
|
||||
|
||||
blocks.append(clip_);
|
||||
blocks.append(clip_->block_links());
|
||||
blocks.append(clip_);
|
||||
blocks.append(clip_->block_links());
|
||||
|
||||
split = new BlockSplitPreservingLinksCommand(blocks, {GetConnectedNode()->GetPlayhead()});
|
||||
split->redo_now();
|
||||
command->add_child(split);
|
||||
split = new BlockSplitPreservingLinksCommand(
|
||||
blocks, { GetConnectedNode()->GetPlayhead() });
|
||||
split->redo_now();
|
||||
command->add_child(split);
|
||||
|
||||
clip = static_cast<ClipBlock*>(split->GetSplit(clip_, 0));
|
||||
clip = static_cast<ClipBlock *>(split->GetSplit(clip_, 0));
|
||||
|
||||
cam = clip->FindMulticam();
|
||||
}
|
||||
cam = clip->FindMulticam();
|
||||
}
|
||||
|
||||
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(cam, cam->kCurrentInput)), source));
|
||||
command->add_child(new NodeParamSetStandardValueCommand(
|
||||
NodeKeyframeTrackReference(NodeInput(cam, cam->kCurrentInput)),
|
||||
source));
|
||||
|
||||
for (Block *link : clip->block_links()) {
|
||||
if (ClipBlock *clink = dynamic_cast<ClipBlock*>(link)) {
|
||||
if (MultiCamNode *mlink = clink->FindMulticam()) {
|
||||
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(NodeInput(mlink, mlink->kCurrentInput)), source));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Block *link : clip->block_links()) {
|
||||
if (ClipBlock *clink = dynamic_cast<ClipBlock *>(link)) {
|
||||
if (MultiCamNode *mlink = clink->FindMulticam()) {
|
||||
command->add_child(new NodeParamSetStandardValueCommand(
|
||||
NodeKeyframeTrackReference(
|
||||
NodeInput(mlink, mlink->kCurrentInput)),
|
||||
source));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, tr("Switched Multi-Camera Source"));
|
||||
Core::instance()->undo_stack()->push(command,
|
||||
tr("Switched Multi-Camera Source"));
|
||||
|
||||
display_->update();
|
||||
display_->update();
|
||||
|
||||
emit Switched();
|
||||
emit Switched();
|
||||
}
|
||||
|
||||
void MulticamWidget::DisplayClicked(const QPoint &p)
|
||||
{
|
||||
if (!node_) {
|
||||
return;
|
||||
}
|
||||
if (!node_) {
|
||||
return;
|
||||
}
|
||||
|
||||
QPointF click = display_->ScreenToScenePoint(p);
|
||||
int width = display_->GetVideoParams().width();
|
||||
int height = display_->GetVideoParams().height();
|
||||
QPointF click = display_->ScreenToScenePoint(p);
|
||||
int width = display_->GetVideoParams().width();
|
||||
int height = display_->GetVideoParams().height();
|
||||
|
||||
if (click.x() < 0 || click.y() < 0 || click.x() >= width || click.y() >= height) {
|
||||
return;
|
||||
}
|
||||
if (click.x() < 0 || click.y() < 0 || click.x() >= width ||
|
||||
click.y() >= height) {
|
||||
return;
|
||||
}
|
||||
|
||||
int rows, cols;
|
||||
node_->GetRowsAndColumns(&rows, &cols);
|
||||
int rows, cols;
|
||||
node_->GetRowsAndColumns(&rows, &cols);
|
||||
|
||||
int multi = std::max(cols, rows);
|
||||
int multi = std::max(cols, rows);
|
||||
|
||||
int c = click.x() / (width/multi);
|
||||
int r = click.y() / (height/multi);
|
||||
int c = click.x() / (width / multi);
|
||||
int r = click.y() / (height / multi);
|
||||
|
||||
int source = node_->RowsColsToIndex(r, c, rows, cols);
|
||||
int source = node_->RowsColsToIndex(r, c, rows, cols);
|
||||
|
||||
Switch(source, true);
|
||||
Switch(source, true);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,52 +25,55 @@
|
||||
#include "node/input/multicam/multicamnode.h"
|
||||
#include "widget/viewer/viewer.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class MulticamWidget : public TimeBasedWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class MulticamWidget : public TimeBasedWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MulticamWidget(QWidget *parent = nullptr);
|
||||
explicit MulticamWidget(QWidget *parent = nullptr);
|
||||
|
||||
MulticamDisplay *GetDisplayWidget() const { return display_; }
|
||||
MulticamDisplay *GetDisplayWidget() const
|
||||
{
|
||||
return display_;
|
||||
}
|
||||
|
||||
void SetMulticamNode(ViewerOutput *viewer, MultiCamNode *n, ClipBlock *clip, const rational &time);
|
||||
void SetMulticamNode(ViewerOutput *viewer, MultiCamNode *n, ClipBlock *clip,
|
||||
const rational &time);
|
||||
|
||||
protected:
|
||||
virtual void ConnectNodeEvent(ViewerOutput *n) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput *n) override;
|
||||
virtual void TimeChangedEvent(const rational &t) override;
|
||||
virtual void ConnectNodeEvent(ViewerOutput *n) override;
|
||||
virtual void DisconnectNodeEvent(ViewerOutput *n) override;
|
||||
virtual void TimeChangedEvent(const rational &t) override;
|
||||
|
||||
signals:
|
||||
void Switched();
|
||||
void Switched();
|
||||
|
||||
private:
|
||||
void SetMulticamNodeInternal(ViewerOutput *viewer, MultiCamNode *n, ClipBlock *clip);
|
||||
void SetMulticamNodeInternal(ViewerOutput *viewer, MultiCamNode *n,
|
||||
ClipBlock *clip);
|
||||
|
||||
void Switch(int source, bool split_clip);
|
||||
void Switch(int source, bool split_clip);
|
||||
|
||||
ViewerSizer *sizer_;
|
||||
ViewerSizer *sizer_;
|
||||
|
||||
MulticamDisplay *display_;
|
||||
MulticamDisplay *display_;
|
||||
|
||||
MultiCamNode *node_;
|
||||
MultiCamNode *node_;
|
||||
|
||||
ClipBlock *clip_;
|
||||
ClipBlock *clip_;
|
||||
|
||||
struct MulticamNodeQueue
|
||||
{
|
||||
rational time;
|
||||
ViewerOutput *viewer;
|
||||
MultiCamNode *node;
|
||||
ClipBlock *clip;
|
||||
};
|
||||
struct MulticamNodeQueue {
|
||||
rational time;
|
||||
ViewerOutput *viewer;
|
||||
MultiCamNode *node;
|
||||
ClipBlock *clip;
|
||||
};
|
||||
|
||||
std::list<MulticamNodeQueue> play_queue_;
|
||||
std::list<MulticamNodeQueue> play_queue_;
|
||||
|
||||
private slots:
|
||||
void DisplayClicked(const QPoint &p);
|
||||
|
||||
void DisplayClicked(const QPoint &p);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -28,67 +28,68 @@
|
||||
#include "ui/icons/icons.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
NodeComboBox::NodeComboBox(QWidget *parent) :
|
||||
QComboBox(parent)
|
||||
NodeComboBox::NodeComboBox(QWidget *parent)
|
||||
: QComboBox(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void NodeComboBox::showPopup()
|
||||
{
|
||||
Menu* m = NodeFactory::CreateMenu(this, true);
|
||||
Menu *m = NodeFactory::CreateMenu(this, true);
|
||||
|
||||
QAction* selected = m->exec(parentWidget()->mapToGlobal(pos()));
|
||||
QAction *selected = m->exec(parentWidget()->mapToGlobal(pos()));
|
||||
|
||||
if (selected) {
|
||||
QString new_id = NodeFactory::GetIDFromMenuAction(selected);
|
||||
if (selected) {
|
||||
QString new_id = NodeFactory::GetIDFromMenuAction(selected);
|
||||
|
||||
SetNodeInternal(new_id, true);
|
||||
}
|
||||
SetNodeInternal(new_id, true);
|
||||
}
|
||||
|
||||
delete m;
|
||||
delete m;
|
||||
}
|
||||
|
||||
const QString &NodeComboBox::GetSelectedNode() const
|
||||
{
|
||||
return selected_id_;
|
||||
return selected_id_;
|
||||
}
|
||||
|
||||
void NodeComboBox::SetNode(const QString &id)
|
||||
{
|
||||
SetNodeInternal(id, false);
|
||||
SetNodeInternal(id, false);
|
||||
}
|
||||
|
||||
void NodeComboBox::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
UpdateText();
|
||||
}
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
UpdateText();
|
||||
}
|
||||
|
||||
QComboBox::changeEvent(e);
|
||||
QComboBox::changeEvent(e);
|
||||
}
|
||||
|
||||
void NodeComboBox::UpdateText()
|
||||
{
|
||||
clear();
|
||||
clear();
|
||||
|
||||
if (!selected_id_.isEmpty()) {
|
||||
addItem(NodeFactory::GetNameFromID(selected_id_));
|
||||
}
|
||||
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;
|
||||
if (selected_id_ != id) {
|
||||
selected_id_ = id;
|
||||
|
||||
UpdateText();
|
||||
UpdateText();
|
||||
|
||||
if (emit_signal) {
|
||||
emit NodeChanged(selected_id_);
|
||||
}
|
||||
}
|
||||
if (emit_signal) {
|
||||
emit NodeChanged(selected_id_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,34 +25,33 @@
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeComboBox : public QComboBox
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeComboBox : public QComboBox {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeComboBox(QWidget* parent = nullptr);
|
||||
NodeComboBox(QWidget *parent = nullptr);
|
||||
|
||||
virtual void showPopup() override;
|
||||
virtual void showPopup() override;
|
||||
|
||||
const QString& GetSelectedNode() const;
|
||||
const QString &GetSelectedNode() const;
|
||||
|
||||
public slots:
|
||||
void SetNode(const QString& id);
|
||||
void SetNode(const QString &id);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
signals:
|
||||
void NodeChanged(const QString& id);
|
||||
void NodeChanged(const QString &id);
|
||||
|
||||
private:
|
||||
void UpdateText();
|
||||
void UpdateText();
|
||||
|
||||
void SetNodeInternal(const QString& id, bool emit_signal);
|
||||
|
||||
QString selected_id_;
|
||||
void SetNodeInternal(const QString &id, bool emit_signal);
|
||||
|
||||
QString selected_id_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -33,162 +33,176 @@
|
||||
#include "widget/keyframeview/keyframeview.h"
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamView : public TimeBasedWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeParamView : public TimeBasedWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamView(bool create_keyframe_view, QWidget* parent = nullptr);
|
||||
NodeParamView(QWidget* parent = nullptr) :
|
||||
NodeParamView(true, parent)
|
||||
{
|
||||
}
|
||||
NodeParamView(bool create_keyframe_view, QWidget *parent = nullptr);
|
||||
NodeParamView(QWidget *parent = nullptr)
|
||||
: NodeParamView(true, parent)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~NodeParamView() override;
|
||||
virtual ~NodeParamView() override;
|
||||
|
||||
void CloseContextsBelongingToProject(Project *p);
|
||||
void CloseContextsBelongingToProject(Project *p);
|
||||
|
||||
void DeleteSelected();
|
||||
void DeleteSelected();
|
||||
|
||||
void SelectAll()
|
||||
{
|
||||
keyframe_view_->SelectAll();
|
||||
}
|
||||
void SelectAll()
|
||||
{
|
||||
keyframe_view_->SelectAll();
|
||||
}
|
||||
|
||||
void DeselectAll()
|
||||
{
|
||||
keyframe_view_->DeselectAll();
|
||||
}
|
||||
void DeselectAll()
|
||||
{
|
||||
keyframe_view_->DeselectAll();
|
||||
}
|
||||
|
||||
void SetSelectedNodes(const QVector<NodeParamViewItem *> &nodes, bool handle_focused_node = true, bool emit_signal = true);
|
||||
void SetSelectedNodes(const QVector<Node::ContextPair> &nodes, bool emit_signal = true);
|
||||
void SetSelectedNodes(const QVector<NodeParamViewItem *> &nodes,
|
||||
bool handle_focused_node = true,
|
||||
bool emit_signal = true);
|
||||
void SetSelectedNodes(const QVector<Node::ContextPair> &nodes,
|
||||
bool emit_signal = true);
|
||||
|
||||
Node *GetNodeWithID(const QString &id);
|
||||
Node *GetNodeWithIDAndIgnoreList(const QString &id, const QVector<Node*> &ignore);
|
||||
Node *GetNodeWithID(const QString &id);
|
||||
Node *GetNodeWithIDAndIgnoreList(const QString &id,
|
||||
const QVector<Node *> &ignore);
|
||||
|
||||
const QVector<Node*> &GetContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
const QVector<Node *> &GetContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
|
||||
virtual bool CopySelected(bool cut) override;
|
||||
virtual bool CopySelected(bool cut) override;
|
||||
|
||||
virtual bool Paste() override;
|
||||
static bool Paste(QWidget *parent, std::function<QHash<Node *, Node*>(const ProjectSerializer::Result &)> get_existing_map_function);
|
||||
virtual bool Paste() override;
|
||||
static bool Paste(
|
||||
QWidget *parent,
|
||||
std::function<QHash<Node *, Node *>(const ProjectSerializer::Result &)>
|
||||
get_existing_map_function);
|
||||
|
||||
public slots:
|
||||
void SetContexts(const QVector<Node*> &contexts);
|
||||
void SetContexts(const QVector<Node *> &contexts);
|
||||
|
||||
void UpdateElementY();
|
||||
void UpdateElementY();
|
||||
|
||||
signals:
|
||||
void FocusedNodeChanged(Node* n);
|
||||
void FocusedNodeChanged(Node *n);
|
||||
|
||||
void SelectedNodesChanged(const QVector<Node::ContextPair> &nodes);
|
||||
void SelectedNodesChanged(const QVector<Node::ContextPair> &nodes);
|
||||
|
||||
void RequestViewerToStartEditingText();
|
||||
void RequestViewerToStartEditingText();
|
||||
|
||||
protected:
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
virtual void TimebaseChangedEvent(const rational&) override;
|
||||
virtual void ScaleChangedEvent(const double &) override;
|
||||
virtual void TimebaseChangedEvent(const rational &) override;
|
||||
|
||||
virtual void ConnectedNodeChangeEvent(ViewerOutput* n) override;
|
||||
virtual void ConnectedNodeChangeEvent(ViewerOutput *n) override;
|
||||
|
||||
virtual const QVector<KeyframeViewInputConnection*> *GetSnapKeyframes() const override
|
||||
{
|
||||
return keyframe_view_ ? &keyframe_view_->GetKeyframeTracks() : nullptr;
|
||||
}
|
||||
virtual const QVector<KeyframeViewInputConnection *> *
|
||||
GetSnapKeyframes() const override
|
||||
{
|
||||
return keyframe_view_ ? &keyframe_view_->GetKeyframeTracks() : nullptr;
|
||||
}
|
||||
|
||||
virtual const std::vector<NodeKeyframe*> *GetSnapIgnoreKeyframes() const override
|
||||
{
|
||||
return keyframe_view_ ? &keyframe_view_->GetSelectedKeyframes() : nullptr;
|
||||
}
|
||||
virtual const std::vector<NodeKeyframe *> *
|
||||
GetSnapIgnoreKeyframes() const override
|
||||
{
|
||||
return keyframe_view_ ? &keyframe_view_->GetSelectedKeyframes() :
|
||||
nullptr;
|
||||
}
|
||||
|
||||
virtual const TimeTargetObject *GetKeyframeTimeTarget() const override
|
||||
{
|
||||
return keyframe_view_;
|
||||
}
|
||||
virtual const TimeTargetObject *GetKeyframeTimeTarget() const override
|
||||
{
|
||||
return keyframe_view_;
|
||||
}
|
||||
|
||||
private:
|
||||
void QueueKeyframePositionUpdate();
|
||||
void QueueKeyframePositionUpdate();
|
||||
|
||||
void AddContext(Node *context);
|
||||
void AddContext(Node *context);
|
||||
|
||||
void RemoveContext(Node *context);
|
||||
void RemoveContext(Node *context);
|
||||
|
||||
void AddNode(Node* n, Node *ctx, NodeParamViewContext *context);
|
||||
void AddNode(Node *n, Node *ctx, NodeParamViewContext *context);
|
||||
|
||||
void SortItemsInContext(NodeParamViewContext *context);
|
||||
void SortItemsInContext(NodeParamViewContext *context);
|
||||
|
||||
NodeParamViewContext *GetContextItemFromContext(Node *context);
|
||||
NodeParamViewContext *GetContextItemFromContext(Node *context);
|
||||
|
||||
bool IsGroupMode() const
|
||||
{
|
||||
return contexts_.size() == 1 && dynamic_cast<NodeGroup*>(contexts_.first());
|
||||
}
|
||||
bool IsGroupMode() const
|
||||
{
|
||||
return contexts_.size() == 1 &&
|
||||
dynamic_cast<NodeGroup *>(contexts_.first());
|
||||
}
|
||||
|
||||
void ToggleSelect(NodeParamViewItem *item);
|
||||
void ToggleSelect(NodeParamViewItem *item);
|
||||
|
||||
QHash<Node *, Node *> GenerateExistingPasteMap(const ProjectSerializer::Result &r);
|
||||
QHash<Node *, Node *>
|
||||
GenerateExistingPasteMap(const ProjectSerializer::Result &r);
|
||||
|
||||
KeyframeView* keyframe_view_;
|
||||
KeyframeView *keyframe_view_;
|
||||
|
||||
QVector<NodeParamViewContext*> context_items_;
|
||||
QVector<NodeParamViewContext *> context_items_;
|
||||
|
||||
QScrollBar* vertical_scrollbar_;
|
||||
QScrollBar *vertical_scrollbar_;
|
||||
|
||||
int last_scroll_val_;
|
||||
int last_scroll_val_;
|
||||
|
||||
QScrollArea* param_scroll_area_;
|
||||
QScrollArea *param_scroll_area_;
|
||||
|
||||
QWidget* param_widget_container_;
|
||||
QWidget *param_widget_container_;
|
||||
|
||||
NodeParamViewDockArea* param_widget_area_;
|
||||
NodeParamViewDockArea *param_widget_area_;
|
||||
|
||||
QVector<Node*> pinned_nodes_;
|
||||
QVector<Node *> pinned_nodes_;
|
||||
|
||||
QVector<Node*> active_nodes_;
|
||||
QVector<Node *> active_nodes_;
|
||||
|
||||
NodeParamViewItem* focused_node_;
|
||||
QVector<NodeParamViewItem*> selected_nodes_;
|
||||
NodeParamViewItem *focused_node_;
|
||||
QVector<NodeParamViewItem *> selected_nodes_;
|
||||
|
||||
QVector<Node*> contexts_;
|
||||
QVector<Node*> current_contexts_;
|
||||
QVector<Node *> contexts_;
|
||||
QVector<Node *> current_contexts_;
|
||||
|
||||
bool show_all_nodes_;
|
||||
bool show_all_nodes_;
|
||||
|
||||
private slots:
|
||||
void UpdateGlobalScrollBar();
|
||||
void UpdateGlobalScrollBar();
|
||||
|
||||
void PinNode(bool pin);
|
||||
void PinNode(bool pin);
|
||||
|
||||
//void FocusChanged(QWidget *old, QWidget *now);
|
||||
//void FocusChanged(QWidget *old, QWidget *now);
|
||||
|
||||
void NodeAddedToContext(Node *n);
|
||||
void NodeAddedToContext(Node *n);
|
||||
|
||||
void NodeRemovedFromContext(Node *n);
|
||||
void NodeRemovedFromContext(Node *n);
|
||||
|
||||
void InputCheckBoxChanged(const NodeInput &input, bool e);
|
||||
void InputCheckBoxChanged(const NodeInput &input, bool e);
|
||||
|
||||
void GroupInputPassthroughAdded(olive::NodeGroup *group, const olive::NodeInput &input);
|
||||
void GroupInputPassthroughAdded(olive::NodeGroup *group,
|
||||
const olive::NodeInput &input);
|
||||
|
||||
void GroupInputPassthroughRemoved(olive::NodeGroup *group, const olive::NodeInput &input);
|
||||
void GroupInputPassthroughRemoved(olive::NodeGroup *group,
|
||||
const olive::NodeInput &input);
|
||||
|
||||
void UpdateContexts();
|
||||
void UpdateContexts();
|
||||
|
||||
void ItemAboutToBeRemoved(NodeParamViewItem *item);
|
||||
void ItemAboutToBeRemoved(NodeParamViewItem *item);
|
||||
|
||||
void ItemClicked();
|
||||
void ItemClicked();
|
||||
|
||||
void SelectNodeFromConnectedLink(Node *node);
|
||||
void SelectNodeFromConnectedLink(Node *node);
|
||||
|
||||
void RequestEditTextInViewer();
|
||||
|
||||
void InputArraySizeChanged(const QString &input, int old_size, int new_size);
|
||||
void RequestEditTextInViewer();
|
||||
|
||||
void InputArraySizeChanged(const QString &input, int old_size,
|
||||
int new_size);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,64 +25,70 @@
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamViewArrayWidget::NodeParamViewArrayWidget(Node *node, const QString &input, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
node_(node),
|
||||
input_(input)
|
||||
namespace olive
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
|
||||
count_lbl_ = new QLabel();
|
||||
layout->addWidget(count_lbl_);
|
||||
NodeParamViewArrayWidget::NodeParamViewArrayWidget(Node *node,
|
||||
const QString &input,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, node_(node)
|
||||
, input_(input)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
|
||||
connect(node_, &Node::InputArraySizeChanged, this, &NodeParamViewArrayWidget::UpdateCounter);
|
||||
count_lbl_ = new QLabel();
|
||||
layout->addWidget(count_lbl_);
|
||||
|
||||
UpdateCounter(input_, 0, node_->InputArraySize(input_));
|
||||
connect(node_, &Node::InputArraySizeChanged, this,
|
||||
&NodeParamViewArrayWidget::UpdateCounter);
|
||||
|
||||
UpdateCounter(input_, 0, node_->InputArraySize(input_));
|
||||
}
|
||||
|
||||
void NodeParamViewArrayWidget::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
|
||||
emit DoubleClicked();
|
||||
emit DoubleClicked();
|
||||
}
|
||||
|
||||
void NodeParamViewArrayWidget::UpdateCounter(const QString& input, int old_size, int new_size)
|
||||
void NodeParamViewArrayWidget::UpdateCounter(const QString &input, int old_size,
|
||||
int new_size)
|
||||
{
|
||||
Q_UNUSED(old_size)
|
||||
if (input == input_) {
|
||||
count_lbl_->setText(tr("%n element(s)", nullptr, new_size));
|
||||
}
|
||||
Q_UNUSED(old_size)
|
||||
if (input == input_) {
|
||||
count_lbl_->setText(tr("%n element(s)", nullptr, new_size));
|
||||
}
|
||||
}
|
||||
|
||||
NodeParamViewArrayButton::NodeParamViewArrayButton(NodeParamViewArrayButton::Type type, QWidget *parent) :
|
||||
QPushButton(parent),
|
||||
type_(type)
|
||||
NodeParamViewArrayButton::NodeParamViewArrayButton(
|
||||
NodeParamViewArrayButton::Type type, QWidget *parent)
|
||||
: QPushButton(parent)
|
||||
, type_(type)
|
||||
{
|
||||
Retranslate();
|
||||
Retranslate();
|
||||
|
||||
int sz = sizeHint().height() / 3 * 2;
|
||||
setFixedSize(sz, sz);
|
||||
int sz = sizeHint().height() / 3 * 2;
|
||||
setFixedSize(sz, sz);
|
||||
}
|
||||
|
||||
void NodeParamViewArrayButton::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
QPushButton::changeEvent(event);
|
||||
QPushButton::changeEvent(event);
|
||||
}
|
||||
|
||||
void NodeParamViewArrayButton::Retranslate()
|
||||
{
|
||||
if (type_ == kAdd) {
|
||||
setText(tr("+"));
|
||||
} else {
|
||||
setText(tr("-"));
|
||||
}
|
||||
if (type_ == kAdd) {
|
||||
setText(tr("+"));
|
||||
} else {
|
||||
setText(tr("-"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,51 +27,46 @@
|
||||
|
||||
#include "node/param.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewArrayButton : public QPushButton
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Type {
|
||||
kAdd,
|
||||
kRemove
|
||||
};
|
||||
|
||||
NodeParamViewArrayButton(Type type, QWidget* parent = nullptr);
|
||||
class NodeParamViewArrayButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum Type { kAdd, kRemove };
|
||||
|
||||
NodeParamViewArrayButton(Type type, QWidget *parent = nullptr);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent* event) override;
|
||||
virtual void changeEvent(QEvent *event) override;
|
||||
|
||||
private:
|
||||
void Retranslate();
|
||||
|
||||
Type type_;
|
||||
void Retranslate();
|
||||
|
||||
Type type_;
|
||||
};
|
||||
|
||||
class NodeParamViewArrayWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
class NodeParamViewArrayWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewArrayWidget(Node* node, const QString& input, QWidget* parent = nullptr);
|
||||
NodeParamViewArrayWidget(Node *node, const QString &input,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
signals:
|
||||
void DoubleClicked();
|
||||
void DoubleClicked();
|
||||
|
||||
protected:
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
Node* node_;
|
||||
Node *node_;
|
||||
|
||||
QString input_;
|
||||
QString input_;
|
||||
|
||||
QLabel* count_lbl_;
|
||||
QLabel *count_lbl_;
|
||||
|
||||
private slots:
|
||||
void UpdateCounter(const QString &input, int old_size, int new_size);
|
||||
|
||||
void UpdateCounter(const QString &input, int old_size, int new_size);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -29,161 +29,175 @@
|
||||
#include "widget/collapsebutton/collapsebutton.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamViewConnectedLabel::NodeParamViewConnectedLabel(const NodeInput &input, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
input_(input),
|
||||
connected_node_(nullptr),
|
||||
viewer_(nullptr)
|
||||
namespace olive
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QSizePolicy p = sizePolicy();
|
||||
p.setHorizontalStretch(1);
|
||||
p.setHorizontalPolicy(QSizePolicy::Expanding);
|
||||
setSizePolicy(p);
|
||||
NodeParamViewConnectedLabel::NodeParamViewConnectedLabel(const NodeInput &input,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, input_(input)
|
||||
, connected_node_(nullptr)
|
||||
, viewer_(nullptr)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// Set up label area
|
||||
QHBoxLayout *label_layout = new QHBoxLayout();
|
||||
label_layout->setSpacing(QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral(" ")));
|
||||
label_layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addLayout(label_layout);
|
||||
QSizePolicy p = sizePolicy();
|
||||
p.setHorizontalStretch(1);
|
||||
p.setHorizontalPolicy(QSizePolicy::Expanding);
|
||||
setSizePolicy(p);
|
||||
|
||||
CollapseButton *collapse_btn = new CollapseButton(this);
|
||||
collapse_btn->setChecked(false);
|
||||
label_layout->addWidget(collapse_btn);
|
||||
// Set up label area
|
||||
QHBoxLayout *label_layout = new QHBoxLayout();
|
||||
label_layout->setSpacing(
|
||||
QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral(" ")));
|
||||
label_layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addLayout(label_layout);
|
||||
|
||||
label_layout->addWidget(new QLabel(tr("Connected to"), this));
|
||||
CollapseButton *collapse_btn = new CollapseButton(this);
|
||||
collapse_btn->setChecked(false);
|
||||
label_layout->addWidget(collapse_btn);
|
||||
|
||||
connected_to_lbl_ = new ClickableLabel(this);
|
||||
connected_to_lbl_->setCursor(Qt::PointingHandCursor);
|
||||
connected_to_lbl_->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(connected_to_lbl_, &ClickableLabel::MouseClicked, this, &NodeParamViewConnectedLabel::ConnectionClicked);
|
||||
connect(connected_to_lbl_, &ClickableLabel::customContextMenuRequested, this, &NodeParamViewConnectedLabel::ShowLabelContextMenu);
|
||||
label_layout->addWidget(connected_to_lbl_);
|
||||
label_layout->addWidget(new QLabel(tr("Connected to"), this));
|
||||
|
||||
label_layout->addStretch();
|
||||
connected_to_lbl_ = new ClickableLabel(this);
|
||||
connected_to_lbl_->setCursor(Qt::PointingHandCursor);
|
||||
connected_to_lbl_->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(connected_to_lbl_, &ClickableLabel::MouseClicked, this,
|
||||
&NodeParamViewConnectedLabel::ConnectionClicked);
|
||||
connect(connected_to_lbl_, &ClickableLabel::customContextMenuRequested,
|
||||
this, &NodeParamViewConnectedLabel::ShowLabelContextMenu);
|
||||
label_layout->addWidget(connected_to_lbl_);
|
||||
|
||||
// Set up "link" font
|
||||
QFont link_font = connected_to_lbl_->font();
|
||||
link_font.setUnderline(true);
|
||||
connected_to_lbl_->setForegroundRole(QPalette::Link);
|
||||
connected_to_lbl_->setFont(link_font);
|
||||
label_layout->addStretch();
|
||||
|
||||
if (input_.IsConnected()) {
|
||||
InputConnected(input_.GetConnectedOutput(), input_);
|
||||
} else {
|
||||
InputDisconnected(nullptr, input_);
|
||||
}
|
||||
// Set up "link" font
|
||||
QFont link_font = connected_to_lbl_->font();
|
||||
link_font.setUnderline(true);
|
||||
connected_to_lbl_->setForegroundRole(QPalette::Link);
|
||||
connected_to_lbl_->setFont(link_font);
|
||||
|
||||
connect(input_.node(), &Node::InputConnected, this, &NodeParamViewConnectedLabel::InputConnected);
|
||||
connect(input_.node(), &Node::InputDisconnected, this, &NodeParamViewConnectedLabel::InputDisconnected);
|
||||
if (input_.IsConnected()) {
|
||||
InputConnected(input_.GetConnectedOutput(), input_);
|
||||
} else {
|
||||
InputDisconnected(nullptr, input_);
|
||||
}
|
||||
|
||||
// Creating the tree is expensive, hold off until the user specifically requests it
|
||||
value_tree_ = nullptr;
|
||||
connect(collapse_btn, &CollapseButton::toggled, this, &NodeParamViewConnectedLabel::SetValueTreeVisible);
|
||||
connect(input_.node(), &Node::InputConnected, this,
|
||||
&NodeParamViewConnectedLabel::InputConnected);
|
||||
connect(input_.node(), &Node::InputDisconnected, this,
|
||||
&NodeParamViewConnectedLabel::InputDisconnected);
|
||||
|
||||
// Creating the tree is expensive, hold off until the user specifically requests it
|
||||
value_tree_ = nullptr;
|
||||
connect(collapse_btn, &CollapseButton::toggled, this,
|
||||
&NodeParamViewConnectedLabel::SetValueTreeVisible);
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::SetViewerNode(ViewerOutput *viewer)
|
||||
{
|
||||
if (viewer_) {
|
||||
disconnect(viewer_, &ViewerOutput::PlayheadChanged, this, &NodeParamViewConnectedLabel::UpdateValueTree);
|
||||
}
|
||||
if (viewer_) {
|
||||
disconnect(viewer_, &ViewerOutput::PlayheadChanged, this,
|
||||
&NodeParamViewConnectedLabel::UpdateValueTree);
|
||||
}
|
||||
|
||||
viewer_ = viewer;
|
||||
viewer_ = viewer;
|
||||
|
||||
if (viewer_) {
|
||||
connect(viewer_, &ViewerOutput::PlayheadChanged, this, &NodeParamViewConnectedLabel::UpdateValueTree);
|
||||
UpdateValueTree();
|
||||
}
|
||||
if (viewer_) {
|
||||
connect(viewer_, &ViewerOutput::PlayheadChanged, this,
|
||||
&NodeParamViewConnectedLabel::UpdateValueTree);
|
||||
UpdateValueTree();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::CreateTree()
|
||||
{
|
||||
// Set up table area
|
||||
value_tree_ = new NodeValueTree(this);
|
||||
layout()->addWidget(value_tree_);
|
||||
// Set up table area
|
||||
value_tree_ = new NodeValueTree(this);
|
||||
layout()->addWidget(value_tree_);
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::InputConnected(Node *output, const NodeInput& input)
|
||||
void NodeParamViewConnectedLabel::InputConnected(Node *output,
|
||||
const NodeInput &input)
|
||||
{
|
||||
if (input_ != input) {
|
||||
return;
|
||||
}
|
||||
if (input_ != input) {
|
||||
return;
|
||||
}
|
||||
|
||||
connected_node_ = output;
|
||||
connected_node_ = output;
|
||||
|
||||
UpdateLabel();
|
||||
UpdateLabel();
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::InputDisconnected(Node *output, const NodeInput &input)
|
||||
void NodeParamViewConnectedLabel::InputDisconnected(Node *output,
|
||||
const NodeInput &input)
|
||||
{
|
||||
if (input_ != input) {
|
||||
return;
|
||||
}
|
||||
if (input_ != input) {
|
||||
return;
|
||||
}
|
||||
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(output)
|
||||
|
||||
connected_node_ = nullptr;
|
||||
connected_node_ = nullptr;
|
||||
|
||||
UpdateLabel();
|
||||
UpdateLabel();
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::ShowLabelContextMenu()
|
||||
{
|
||||
Menu m(this);
|
||||
Menu m(this);
|
||||
|
||||
QAction* disconnect_action = m.addAction(tr("Disconnect"));
|
||||
connect(disconnect_action, &QAction::triggered, this, [this](){
|
||||
Core::instance()->undo_stack()->push(new NodeEdgeRemoveCommand(connected_node_, input_), Node::GetDisconnectCommandString(connected_node_, input_));
|
||||
});
|
||||
QAction *disconnect_action = m.addAction(tr("Disconnect"));
|
||||
connect(disconnect_action, &QAction::triggered, this, [this]() {
|
||||
Core::instance()->undo_stack()->push(
|
||||
new NodeEdgeRemoveCommand(connected_node_, input_),
|
||||
Node::GetDisconnectCommandString(connected_node_, input_));
|
||||
});
|
||||
|
||||
m.exec(QCursor::pos());
|
||||
m.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::ConnectionClicked()
|
||||
{
|
||||
if (connected_node_) {
|
||||
emit RequestSelectNode(connected_node_);
|
||||
}
|
||||
if (connected_node_) {
|
||||
emit RequestSelectNode(connected_node_);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::UpdateLabel()
|
||||
{
|
||||
QString s;
|
||||
QString s;
|
||||
|
||||
if (connected_node_) {
|
||||
s = connected_node_->Name();
|
||||
} else {
|
||||
s = tr("Nothing");
|
||||
}
|
||||
if (connected_node_) {
|
||||
s = connected_node_->Name();
|
||||
} else {
|
||||
s = tr("Nothing");
|
||||
}
|
||||
|
||||
connected_to_lbl_->setText(s);
|
||||
connected_to_lbl_->setText(s);
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::UpdateValueTree()
|
||||
{
|
||||
if (value_tree_ && viewer_ && value_tree_->isVisible()) {
|
||||
value_tree_->SetNode(input_, viewer_->GetPlayhead());
|
||||
}
|
||||
if (value_tree_ && viewer_ && value_tree_->isVisible()) {
|
||||
value_tree_->SetNode(input_, viewer_->GetPlayhead());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewConnectedLabel::SetValueTreeVisible(bool e)
|
||||
{
|
||||
if (value_tree_) {
|
||||
value_tree_->setVisible(e);
|
||||
}
|
||||
if (value_tree_) {
|
||||
value_tree_->setVisible(e);
|
||||
}
|
||||
|
||||
if (e) {
|
||||
if (!value_tree_) {
|
||||
CreateTree();
|
||||
value_tree_->setVisible(true);
|
||||
}
|
||||
if (e) {
|
||||
if (!value_tree_) {
|
||||
CreateTree();
|
||||
value_tree_->setVisible(true);
|
||||
}
|
||||
|
||||
UpdateValueTree();
|
||||
}
|
||||
UpdateValueTree();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,47 +25,48 @@
|
||||
#include "widget/clickablelabel/clickablelabel.h"
|
||||
#include "widget/nodevaluetree/nodevaluetree.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeParamViewConnectedLabel : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewConnectedLabel(const NodeInput& input, QWidget* parent = nullptr);
|
||||
NodeParamViewConnectedLabel(const NodeInput &input,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
void SetViewerNode(ViewerOutput *viewer);
|
||||
void SetViewerNode(ViewerOutput *viewer);
|
||||
|
||||
signals:
|
||||
void RequestSelectNode(Node *n);
|
||||
void RequestSelectNode(Node *n);
|
||||
|
||||
private slots:
|
||||
void InputConnected(Node *output, const NodeInput &input);
|
||||
void InputConnected(Node *output, const NodeInput &input);
|
||||
|
||||
void InputDisconnected(Node *output, const NodeInput &input);
|
||||
void InputDisconnected(Node *output, const NodeInput &input);
|
||||
|
||||
void ShowLabelContextMenu();
|
||||
void ShowLabelContextMenu();
|
||||
|
||||
void ConnectionClicked();
|
||||
void ConnectionClicked();
|
||||
|
||||
private:
|
||||
void UpdateLabel();
|
||||
void UpdateLabel();
|
||||
|
||||
void UpdateValueTree();
|
||||
void UpdateValueTree();
|
||||
|
||||
void CreateTree();
|
||||
void CreateTree();
|
||||
|
||||
ClickableLabel* connected_to_lbl_;
|
||||
ClickableLabel *connected_to_lbl_;
|
||||
|
||||
NodeInput input_;
|
||||
NodeInput input_;
|
||||
|
||||
Node *connected_node_;
|
||||
Node *connected_node_;
|
||||
|
||||
NodeValueTree *value_tree_;
|
||||
NodeValueTree *value_tree_;
|
||||
|
||||
ViewerOutput *viewer_;
|
||||
ViewerOutput *viewer_;
|
||||
|
||||
private slots:
|
||||
void SetValueTreeVisible(bool e);
|
||||
|
||||
void SetValueTreeVisible(bool e);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -26,103 +26,105 @@
|
||||
#include "node/factory.h"
|
||||
#include "node/nodeundo.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super NodeParamViewItemBase
|
||||
|
||||
NodeParamViewContext::NodeParamViewContext(QWidget *parent) :
|
||||
super(parent),
|
||||
type_(Track::kNone)
|
||||
NodeParamViewContext::NodeParamViewContext(QWidget *parent)
|
||||
: super(parent)
|
||||
, type_(Track::kNone)
|
||||
{
|
||||
QWidget *body = new QWidget();
|
||||
QHBoxLayout *body_layout = new QHBoxLayout(body);
|
||||
SetBody(body);
|
||||
QWidget *body = new QWidget();
|
||||
QHBoxLayout *body_layout = new QHBoxLayout(body);
|
||||
SetBody(body);
|
||||
|
||||
dock_area_ = new NodeParamViewDockArea();
|
||||
body_layout->addWidget(dock_area_);
|
||||
dock_area_ = new NodeParamViewDockArea();
|
||||
body_layout->addWidget(dock_area_);
|
||||
|
||||
setBackgroundRole(QPalette::Base);
|
||||
setBackgroundRole(QPalette::Base);
|
||||
|
||||
Retranslate();
|
||||
Retranslate();
|
||||
|
||||
connect(title_bar(), &NodeParamViewItemTitleBar::AddEffectButtonClicked, this, &NodeParamViewContext::AddEffectButtonClicked);
|
||||
connect(title_bar(), &NodeParamViewItemTitleBar::AddEffectButtonClicked,
|
||||
this, &NodeParamViewContext::AddEffectButtonClicked);
|
||||
}
|
||||
|
||||
NodeParamViewItem *NodeParamViewContext::GetItem(Node *node, Node *ctx)
|
||||
{
|
||||
for (auto it=items_.begin(); it!=items_.end(); it++) {
|
||||
NodeParamViewItem *item = *it;
|
||||
for (auto it = items_.begin(); it != items_.end(); it++) {
|
||||
NodeParamViewItem *item = *it;
|
||||
|
||||
if (item->GetNode() == node && item->GetContext() == ctx) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
if (item->GetNode() == node && item->GetContext() == ctx) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeParamViewContext::AddNode(NodeParamViewItem *item)
|
||||
{
|
||||
items_.append(item);
|
||||
dock_area_->AddItem(item);
|
||||
items_.append(item);
|
||||
dock_area_->AddItem(item);
|
||||
}
|
||||
|
||||
void NodeParamViewContext::RemoveNode(Node *node, Node *ctx)
|
||||
{
|
||||
for (auto it=items_.begin(); it!=items_.end(); ) {
|
||||
NodeParamViewItem *item = *it;
|
||||
for (auto it = items_.begin(); it != items_.end();) {
|
||||
NodeParamViewItem *item = *it;
|
||||
|
||||
if (item->GetNode() == node && item->GetContext() == ctx) {
|
||||
emit AboutToDeleteItem(item);
|
||||
delete item;
|
||||
it = items_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (item->GetNode() == node && item->GetContext() == ctx) {
|
||||
emit AboutToDeleteItem(item);
|
||||
delete item;
|
||||
it = items_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewContext::RemoveNodesWithContext(Node *ctx)
|
||||
{
|
||||
for (auto it=items_.begin(); it!=items_.end(); ) {
|
||||
NodeParamViewItem *item = *it;
|
||||
for (auto it = items_.begin(); it != items_.end();) {
|
||||
NodeParamViewItem *item = *it;
|
||||
|
||||
if (item->GetContext() == ctx) {
|
||||
emit AboutToDeleteItem(item);
|
||||
delete item;
|
||||
it = items_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
if (item->GetContext() == ctx) {
|
||||
emit AboutToDeleteItem(item);
|
||||
delete item;
|
||||
it = items_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewContext::SetInputChecked(const NodeInput &input, bool e)
|
||||
{
|
||||
foreach (NodeParamViewItem *item, items_) {
|
||||
if (item->GetNode() == input.node()) {
|
||||
item->SetInputChecked(input, e);
|
||||
}
|
||||
}
|
||||
foreach (NodeParamViewItem *item, items_) {
|
||||
if (item->GetNode() == input.node()) {
|
||||
item->SetInputChecked(input, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewContext::SetTimebase(const rational &timebase)
|
||||
{
|
||||
foreach (NodeParamViewItem* item, items_) {
|
||||
item->SetTimebase(timebase);
|
||||
}
|
||||
foreach (NodeParamViewItem *item, items_) {
|
||||
item->SetTimebase(timebase);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewContext::SetTimeTarget(ViewerOutput *n)
|
||||
{
|
||||
foreach (NodeParamViewItem* item, items_) {
|
||||
item->SetTimeTarget(n);
|
||||
}
|
||||
foreach (NodeParamViewItem *item, items_) {
|
||||
item->SetTimeTarget(n);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewContext::SetEffectType(Track::Type type)
|
||||
{
|
||||
type_ = type;
|
||||
type_ = type;
|
||||
}
|
||||
|
||||
void NodeParamViewContext::Retranslate()
|
||||
@@ -131,57 +133,64 @@ void NodeParamViewContext::Retranslate()
|
||||
|
||||
void NodeParamViewContext::AddEffectButtonClicked()
|
||||
{
|
||||
Node::Flag flag = Node::kNone;
|
||||
Node::Flag flag = Node::kNone;
|
||||
|
||||
if (type_ == Track::kVideo) {
|
||||
flag = Node::kVideoEffect;
|
||||
} else {
|
||||
flag = Node::kAudioEffect;
|
||||
}
|
||||
if (type_ == Track::kVideo) {
|
||||
flag = Node::kVideoEffect;
|
||||
} else {
|
||||
flag = Node::kAudioEffect;
|
||||
}
|
||||
|
||||
if (flag == Node::kNone) {
|
||||
return;
|
||||
}
|
||||
if (flag == Node::kNone) {
|
||||
return;
|
||||
}
|
||||
|
||||
Menu *m = NodeFactory::CreateMenu(this, false, Node::kCategoryUnknown, flag);
|
||||
connect(m, &Menu::triggered, this, &NodeParamViewContext::AddEffectMenuItemTriggered);
|
||||
m->exec(QCursor::pos());
|
||||
delete m;
|
||||
Menu *m =
|
||||
NodeFactory::CreateMenu(this, false, Node::kCategoryUnknown, flag);
|
||||
connect(m, &Menu::triggered, this,
|
||||
&NodeParamViewContext::AddEffectMenuItemTriggered);
|
||||
m->exec(QCursor::pos());
|
||||
delete m;
|
||||
}
|
||||
|
||||
void NodeParamViewContext::AddEffectMenuItemTriggered(QAction *a)
|
||||
{
|
||||
Node *n = NodeFactory::CreateFromMenuAction(a);
|
||||
Node *n = NodeFactory::CreateFromMenuAction(a);
|
||||
|
||||
if (n) {
|
||||
NodeInput new_node_input = n->GetEffectInput();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
if (n) {
|
||||
NodeInput new_node_input = n->GetEffectInput();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
QVector<Project*> graphs_added_to;
|
||||
QVector<Project *> graphs_added_to;
|
||||
|
||||
foreach (Node *ctx, contexts_) {
|
||||
NodeInput ctx_input = ctx->GetEffectInput();
|
||||
foreach (Node *ctx, contexts_) {
|
||||
NodeInput ctx_input = ctx->GetEffectInput();
|
||||
|
||||
if (!graphs_added_to.contains(ctx->parent())) {
|
||||
command->add_child(new NodeAddCommand(ctx->parent(), n));
|
||||
graphs_added_to.append(ctx->parent());
|
||||
}
|
||||
if (!graphs_added_to.contains(ctx->parent())) {
|
||||
command->add_child(new NodeAddCommand(ctx->parent(), n));
|
||||
graphs_added_to.append(ctx->parent());
|
||||
}
|
||||
|
||||
command->add_child(new NodeSetPositionCommand(n, ctx, ctx->GetNodePositionInContext(ctx)));
|
||||
command->add_child(new NodeSetPositionCommand(ctx, ctx, ctx->GetNodePositionInContext(ctx) + QPointF(1, 0)));
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
n, ctx, ctx->GetNodePositionInContext(ctx)));
|
||||
command->add_child(new NodeSetPositionCommand(
|
||||
ctx, ctx, ctx->GetNodePositionInContext(ctx) + QPointF(1, 0)));
|
||||
|
||||
if (ctx_input.IsConnected()) {
|
||||
Node *prev_output = ctx_input.GetConnectedOutput();
|
||||
if (ctx_input.IsConnected()) {
|
||||
Node *prev_output = ctx_input.GetConnectedOutput();
|
||||
|
||||
command->add_child(new NodeEdgeRemoveCommand(prev_output, ctx_input));
|
||||
command->add_child(new NodeEdgeAddCommand(prev_output, new_node_input));
|
||||
}
|
||||
command->add_child(
|
||||
new NodeEdgeRemoveCommand(prev_output, ctx_input));
|
||||
command->add_child(
|
||||
new NodeEdgeAddCommand(prev_output, new_node_input));
|
||||
}
|
||||
|
||||
command->add_child(new NodeEdgeAddCommand(n, ctx_input));
|
||||
}
|
||||
command->add_child(new NodeEdgeAddCommand(n, ctx_input));
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, tr("Added %1 to Node Chain").arg(n->Name()));
|
||||
}
|
||||
Core::instance()->undo_stack()->push(
|
||||
command, tr("Added %1 to Node Chain").arg(n->Name()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,76 +25,75 @@
|
||||
#include "nodeparamviewitembase.h"
|
||||
#include "nodeparamviewitem.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewContext : public NodeParamViewItemBase
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeParamViewContext : public NodeParamViewItemBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewContext(QWidget *parent = nullptr);
|
||||
NodeParamViewContext(QWidget *parent = nullptr);
|
||||
|
||||
NodeParamViewDockArea *GetDockArea() const
|
||||
{
|
||||
return dock_area_;
|
||||
}
|
||||
NodeParamViewDockArea *GetDockArea() const
|
||||
{
|
||||
return dock_area_;
|
||||
}
|
||||
|
||||
const QVector<Node*> &GetContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
const QVector<Node *> &GetContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
|
||||
const QVector<NodeParamViewItem*> &GetItems() const
|
||||
{
|
||||
return items_;
|
||||
}
|
||||
const QVector<NodeParamViewItem *> &GetItems() const
|
||||
{
|
||||
return items_;
|
||||
}
|
||||
|
||||
NodeParamViewItem *GetItem(Node *node, Node *ctx);
|
||||
NodeParamViewItem *GetItem(Node *node, Node *ctx);
|
||||
|
||||
void AddNode(NodeParamViewItem *item);
|
||||
void AddNode(NodeParamViewItem *item);
|
||||
|
||||
void RemoveNode(Node *node, Node *ctx);
|
||||
void RemoveNode(Node *node, Node *ctx);
|
||||
|
||||
void RemoveNodesWithContext(Node *ctx);
|
||||
void RemoveNodesWithContext(Node *ctx);
|
||||
|
||||
void SetInputChecked(const NodeInput &input, bool e);
|
||||
void SetInputChecked(const NodeInput &input, bool e);
|
||||
|
||||
void SetTimebase(const rational &timebase);
|
||||
void SetTimebase(const rational &timebase);
|
||||
|
||||
void SetTimeTarget(ViewerOutput *n);
|
||||
void SetTimeTarget(ViewerOutput *n);
|
||||
|
||||
void SetEffectType(Track::Type type);
|
||||
void SetEffectType(Track::Type type);
|
||||
|
||||
signals:
|
||||
void AboutToDeleteItem(NodeParamViewItem *item);
|
||||
void AboutToDeleteItem(NodeParamViewItem *item);
|
||||
|
||||
public slots:
|
||||
void AddContext(Node *node)
|
||||
{
|
||||
contexts_.append(node);
|
||||
}
|
||||
void AddContext(Node *node)
|
||||
{
|
||||
contexts_.append(node);
|
||||
}
|
||||
|
||||
void RemoveContext(Node *node)
|
||||
{
|
||||
contexts_.removeOne(node);
|
||||
}
|
||||
void RemoveContext(Node *node)
|
||||
{
|
||||
contexts_.removeOne(node);
|
||||
}
|
||||
|
||||
protected slots:
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
private:
|
||||
NodeParamViewDockArea *dock_area_;
|
||||
NodeParamViewDockArea *dock_area_;
|
||||
|
||||
QVector<Node*> contexts_;
|
||||
QVector<Node *> contexts_;
|
||||
|
||||
QVector<NodeParamViewItem*> items_;
|
||||
QVector<NodeParamViewItem *> items_;
|
||||
|
||||
Track::Type type_;
|
||||
Track::Type type_;
|
||||
|
||||
private slots:
|
||||
void AddEffectButtonClicked();
|
||||
|
||||
void AddEffectMenuItemTriggered(QAction *a);
|
||||
void AddEffectButtonClicked();
|
||||
|
||||
void AddEffectMenuItemTriggered(QAction *a);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,28 +22,31 @@
|
||||
|
||||
#include <QDockWidget>
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamViewDockArea::NodeParamViewDockArea(QWidget *parent) :
|
||||
QMainWindow(parent)
|
||||
namespace olive
|
||||
{
|
||||
// Disable dock widgets from tabbing and disable glitchy animations
|
||||
setDockOptions(static_cast<QMainWindow::DockOption>(0));
|
||||
|
||||
// HACK: Hide the main window separators (unfortunately the cursors still appear)
|
||||
setStyleSheet(QStringLiteral("QMainWindow::separator {background: rgba(0, 0, 0, 0)}"));
|
||||
NodeParamViewDockArea::NodeParamViewDockArea(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
// Disable dock widgets from tabbing and disable glitchy animations
|
||||
setDockOptions(static_cast<QMainWindow::DockOption>(0));
|
||||
|
||||
// HACK: Hide the main window separators (unfortunately the cursors still appear)
|
||||
setStyleSheet(QStringLiteral(
|
||||
"QMainWindow::separator {background: rgba(0, 0, 0, 0)}"));
|
||||
}
|
||||
|
||||
QMenu *NodeParamViewDockArea::createPopupMenu()
|
||||
{
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void NodeParamViewDockArea::AddItem(QDockWidget *item)
|
||||
{
|
||||
item->setAllowedAreas(Qt::LeftDockWidgetArea);
|
||||
item->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, item);
|
||||
item->setAllowedAreas(Qt::LeftDockWidgetArea);
|
||||
item->setFeatures(QDockWidget::DockWidgetClosable |
|
||||
QDockWidget::DockWidgetMovable);
|
||||
addDockWidget(Qt::LeftDockWidgetArea, item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -23,20 +23,19 @@
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
// This may look weird, but QMainWindow is just a QWidget with a fancy layout that allows
|
||||
// for docking QDockWidgets
|
||||
class NodeParamViewDockArea : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
class NodeParamViewDockArea : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit NodeParamViewDockArea(QWidget *parent = nullptr);
|
||||
explicit NodeParamViewDockArea(QWidget *parent = nullptr);
|
||||
|
||||
virtual QMenu *createPopupMenu() override;
|
||||
|
||||
void AddItem(QDockWidget *item);
|
||||
virtual QMenu *createPopupMenu() override;
|
||||
|
||||
void AddItem(QDockWidget *item);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -30,12 +30,13 @@
|
||||
#include "node/nodeundo.h"
|
||||
#include "node/project/sequence/sequence.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
const int NodeParamViewItemBody::kKeyControlColumn = 10;
|
||||
const int NodeParamViewItemBody::kArrayInsertColumn = kKeyControlColumn-1;
|
||||
const int NodeParamViewItemBody::kArrayRemoveColumn = kArrayInsertColumn-1;
|
||||
const int NodeParamViewItemBody::kExtraButtonColumn = kKeyControlColumn-1;
|
||||
const int NodeParamViewItemBody::kArrayInsertColumn = kKeyControlColumn - 1;
|
||||
const int NodeParamViewItemBody::kArrayRemoveColumn = kArrayInsertColumn - 1;
|
||||
const int NodeParamViewItemBody::kExtraButtonColumn = kKeyControlColumn - 1;
|
||||
|
||||
const int NodeParamViewItemBody::kOptionalCheckBox = 0;
|
||||
const int NodeParamViewItemBody::kArrayCollapseBtnColumn = 1;
|
||||
@@ -45,523 +46,588 @@ const int NodeParamViewItemBody::kMaxWidgetColumn = kArrayRemoveColumn;
|
||||
|
||||
#define super NodeParamViewItemBase
|
||||
|
||||
NodeParamViewItem::NodeParamViewItem(Node *node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget *parent) :
|
||||
super(parent),
|
||||
body_(nullptr),
|
||||
node_(node),
|
||||
create_checkboxes_(create_checkboxes),
|
||||
ctx_(nullptr),
|
||||
time_target_(nullptr)
|
||||
NodeParamViewItem::NodeParamViewItem(
|
||||
Node *node, NodeParamViewCheckBoxBehavior create_checkboxes,
|
||||
QWidget *parent)
|
||||
: super(parent)
|
||||
, body_(nullptr)
|
||||
, node_(node)
|
||||
, create_checkboxes_(create_checkboxes)
|
||||
, ctx_(nullptr)
|
||||
, time_target_(nullptr)
|
||||
{
|
||||
node_->Retranslate();
|
||||
node_->Retranslate();
|
||||
|
||||
// Create and add contents widget
|
||||
RecreateBody();
|
||||
// Create and add contents widget
|
||||
RecreateBody();
|
||||
|
||||
connect(node_, &Node::LabelChanged, this, &NodeParamViewItem::Retranslate);
|
||||
connect(node_, &Node::InputArraySizeChanged, this, &NodeParamViewItem::InputArraySizeChanged);
|
||||
connect(node_, &Node::LabelChanged, this, &NodeParamViewItem::Retranslate);
|
||||
connect(node_, &Node::InputArraySizeChanged, this,
|
||||
&NodeParamViewItem::InputArraySizeChanged);
|
||||
|
||||
// FIXME: Implemented to pick up when an input is set to hidden or not - DEFINITELY not a fast
|
||||
// way of doing this, but "fine" for now.
|
||||
connect(node_, &Node::InputFlagsChanged, this, &NodeParamViewItem::RecreateBody);
|
||||
// FIXME: Implemented to pick up when an input is set to hidden or not - DEFINITELY not a fast
|
||||
// way of doing this, but "fine" for now.
|
||||
connect(node_, &Node::InputFlagsChanged, this,
|
||||
&NodeParamViewItem::RecreateBody);
|
||||
|
||||
setBackgroundRole(QPalette::Window);
|
||||
setBackgroundRole(QPalette::Window);
|
||||
|
||||
// Connect title bar enabled checkbox
|
||||
//title_bar()->SetEnabledCheckBoxVisible(true);
|
||||
//title_bar()->SetEnabledCheckBoxChecked(node_->IsEnabled());
|
||||
//connect(title_bar(), &NodeParamViewItemTitleBar::EnabledCheckBoxClicked, node_, &Node::SetEnabled);
|
||||
// Connect title bar enabled checkbox
|
||||
//title_bar()->SetEnabledCheckBoxVisible(true);
|
||||
//title_bar()->SetEnabledCheckBoxChecked(node_->IsEnabled());
|
||||
//connect(title_bar(), &NodeParamViewItemTitleBar::EnabledCheckBoxClicked, node_, &Node::SetEnabled);
|
||||
|
||||
Retranslate();
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void NodeParamViewItem::Retranslate()
|
||||
{
|
||||
node_->Retranslate();
|
||||
node_->Retranslate();
|
||||
|
||||
title_bar()->SetText(GetTitleBarTextFromNode(node_));
|
||||
title_bar()->SetText(GetTitleBarTextFromNode(node_));
|
||||
|
||||
body_->Retranslate();
|
||||
body_->Retranslate();
|
||||
}
|
||||
|
||||
void NodeParamViewItem::RecreateBody()
|
||||
{
|
||||
if (body_) {
|
||||
body_->setParent(nullptr);
|
||||
body_->deleteLater();
|
||||
}
|
||||
if (body_) {
|
||||
body_->setParent(nullptr);
|
||||
body_->deleteLater();
|
||||
}
|
||||
|
||||
body_ = new NodeParamViewItemBody(node_, create_checkboxes_, this);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSelectNode, this, &NodeParamViewItem::RequestSelectNode);
|
||||
connect(body_, &NodeParamViewItemBody::ArrayExpandedChanged, this, &NodeParamViewItem::ArrayExpandedChanged);
|
||||
connect(body_, &NodeParamViewItemBody::InputCheckedChanged, this, &NodeParamViewItem::InputCheckedChanged);
|
||||
connect(body_, &NodeParamViewItemBody::RequestEditTextInViewer, this, &NodeParamViewItem::RequestEditTextInViewer);
|
||||
body_->Retranslate();
|
||||
body_->SetTimebase(timebase_);
|
||||
body_->SetTimeTarget(time_target_);
|
||||
SetBody(body_);
|
||||
body_ = new NodeParamViewItemBody(node_, create_checkboxes_, this);
|
||||
connect(body_, &NodeParamViewItemBody::RequestSelectNode, this,
|
||||
&NodeParamViewItem::RequestSelectNode);
|
||||
connect(body_, &NodeParamViewItemBody::ArrayExpandedChanged, this,
|
||||
&NodeParamViewItem::ArrayExpandedChanged);
|
||||
connect(body_, &NodeParamViewItemBody::InputCheckedChanged, this,
|
||||
&NodeParamViewItem::InputCheckedChanged);
|
||||
connect(body_, &NodeParamViewItemBody::RequestEditTextInViewer, this,
|
||||
&NodeParamViewItem::RequestEditTextInViewer);
|
||||
body_->Retranslate();
|
||||
body_->SetTimebase(timebase_);
|
||||
body_->SetTimeTarget(time_target_);
|
||||
SetBody(body_);
|
||||
}
|
||||
|
||||
int NodeParamViewItem::GetElementY(const NodeInput &c) const
|
||||
{
|
||||
if (IsExpanded()) {
|
||||
return body_->GetElementY(c);
|
||||
} else {
|
||||
// Not expanded, put keyframes at the titlebar Y
|
||||
return mapToGlobal(title_bar()->rect().center()).y();
|
||||
}
|
||||
if (IsExpanded()) {
|
||||
return body_->GetElementY(c);
|
||||
} else {
|
||||
// Not expanded, put keyframes at the titlebar Y
|
||||
return mapToGlobal(title_bar()->rect().center()).y();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItem::SetInputChecked(const NodeInput &input, bool e)
|
||||
{
|
||||
body_->SetInputChecked(input, e);
|
||||
body_->SetInputChecked(input, e);
|
||||
}
|
||||
|
||||
NodeParamViewItemBody::NodeParamViewItemBody(Node* node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget *parent) :
|
||||
QWidget(parent),
|
||||
node_(node),
|
||||
time_target_(nullptr),
|
||||
create_checkboxes_(create_checkboxes)
|
||||
NodeParamViewItemBody::NodeParamViewItemBody(
|
||||
Node *node, NodeParamViewCheckBoxBehavior create_checkboxes,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, node_(node)
|
||||
, time_target_(nullptr)
|
||||
, create_checkboxes_(create_checkboxes)
|
||||
{
|
||||
QGridLayout* root_layout = new QGridLayout(this);
|
||||
QGridLayout *root_layout = new QGridLayout(this);
|
||||
|
||||
int insert_row = 0;
|
||||
int insert_row = 0;
|
||||
|
||||
QVector<Node*> connected_signals;
|
||||
QVector<Node *> connected_signals;
|
||||
|
||||
// Create widgets all root level components
|
||||
foreach (QString input, node->inputs()) {
|
||||
Node *n = node;
|
||||
// Create widgets all root level components
|
||||
foreach (QString input, node->inputs()) {
|
||||
Node *n = node;
|
||||
|
||||
NodeInput resolved = NodeGroup::ResolveInput(NodeInput(n, input));
|
||||
if (!connected_signals.contains(resolved.node())) {
|
||||
connect(resolved.node(), &Node::InputArraySizeChanged, this, &NodeParamViewItemBody::InputArraySizeChanged);
|
||||
connect(resolved.node(), &Node::InputConnected, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
connect(resolved.node(), &Node::InputDisconnected, this, &NodeParamViewItemBody::EdgeChanged);
|
||||
NodeInput resolved = NodeGroup::ResolveInput(NodeInput(n, input));
|
||||
if (!connected_signals.contains(resolved.node())) {
|
||||
connect(resolved.node(), &Node::InputArraySizeChanged, this,
|
||||
&NodeParamViewItemBody::InputArraySizeChanged);
|
||||
connect(resolved.node(), &Node::InputConnected, this,
|
||||
&NodeParamViewItemBody::EdgeChanged);
|
||||
connect(resolved.node(), &Node::InputDisconnected, this,
|
||||
&NodeParamViewItemBody::EdgeChanged);
|
||||
|
||||
connected_signals.append(resolved.node());
|
||||
}
|
||||
connected_signals.append(resolved.node());
|
||||
}
|
||||
|
||||
input_group_lookup_.insert({resolved.node(), resolved.input()}, {n, input});
|
||||
input_group_lookup_.insert({ resolved.node(), resolved.input() },
|
||||
{ n, input });
|
||||
|
||||
if (!(n->GetInputFlags(input) & kInputFlagHidden)) {
|
||||
CreateWidgets(root_layout, n, input, -1, insert_row);
|
||||
if (!(n->GetInputFlags(input) & kInputFlagHidden)) {
|
||||
CreateWidgets(root_layout, n, input, -1, insert_row);
|
||||
|
||||
insert_row++;
|
||||
insert_row++;
|
||||
|
||||
if (n->InputIsArray(input)) {
|
||||
// Insert here
|
||||
QWidget* array_widget = new QWidget(this);
|
||||
if (n->InputIsArray(input)) {
|
||||
// Insert here
|
||||
QWidget *array_widget = new QWidget(this);
|
||||
|
||||
QGridLayout* array_layout = new QGridLayout(array_widget);
|
||||
array_layout->setContentsMargins(QtUtils::QFontMetricsWidth(fontMetrics(), QStringLiteral(" ")), 0, 0, 0);
|
||||
QGridLayout *array_layout = new QGridLayout(array_widget);
|
||||
array_layout->setContentsMargins(
|
||||
QtUtils::QFontMetricsWidth(fontMetrics(),
|
||||
QStringLiteral(" ")),
|
||||
0, 0, 0);
|
||||
|
||||
root_layout->addWidget(array_widget, insert_row, 1, 1, 10);
|
||||
root_layout->addWidget(array_widget, insert_row, 1, 1, 10);
|
||||
|
||||
// Start with zero elements for efficiency. We will make the widgets for them if the user
|
||||
// requests the array UI to be expanded
|
||||
int arr_sz = 0;
|
||||
// Start with zero elements for efficiency. We will make the widgets for them if the user
|
||||
// requests the array UI to be expanded
|
||||
int arr_sz = 0;
|
||||
|
||||
// Add one last add button for appending to the array
|
||||
NodeParamViewArrayButton* append_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd, this);
|
||||
connect(append_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayAppendClicked);
|
||||
array_layout->addWidget(append_btn, arr_sz, kArrayInsertColumn);
|
||||
// Add one last add button for appending to the array
|
||||
NodeParamViewArrayButton *append_btn =
|
||||
new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd,
|
||||
this);
|
||||
connect(append_btn, &NodeParamViewArrayButton::clicked, this,
|
||||
&NodeParamViewItemBody::ArrayAppendClicked);
|
||||
array_layout->addWidget(append_btn, arr_sz, kArrayInsertColumn);
|
||||
|
||||
array_widget->setVisible(false);
|
||||
array_widget->setVisible(false);
|
||||
|
||||
array_ui_.insert({n, input}, {array_widget, arr_sz, append_btn});
|
||||
array_ui_.insert({ n, input },
|
||||
{ array_widget, arr_sz, append_btn });
|
||||
|
||||
insert_row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
insert_row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::CreateWidgets(QGridLayout* layout, Node *node, const QString &input, int element, int row)
|
||||
void NodeParamViewItemBody::CreateWidgets(QGridLayout *layout, Node *node,
|
||||
const QString &input, int element,
|
||||
int row)
|
||||
{
|
||||
NodeInput input_ref(node, input, element);
|
||||
NodeInput input_ref(node, input, element);
|
||||
|
||||
InputUI ui_objects;
|
||||
InputUI ui_objects;
|
||||
|
||||
// Store layout and row
|
||||
ui_objects.layout = layout;
|
||||
ui_objects.row = row;
|
||||
// Store layout and row
|
||||
ui_objects.layout = layout;
|
||||
ui_objects.row = row;
|
||||
|
||||
// Create optional checkbox if requested
|
||||
if (create_checkboxes_) {
|
||||
ui_objects.optional_checkbox = new QCheckBox(this);
|
||||
connect(ui_objects.optional_checkbox, &QCheckBox::clicked, this, &NodeParamViewItemBody::OptionalCheckBoxClicked);
|
||||
layout->addWidget(ui_objects.optional_checkbox, row, kOptionalCheckBox);
|
||||
// Create optional checkbox if requested
|
||||
if (create_checkboxes_) {
|
||||
ui_objects.optional_checkbox = new QCheckBox(this);
|
||||
connect(ui_objects.optional_checkbox, &QCheckBox::clicked, this,
|
||||
&NodeParamViewItemBody::OptionalCheckBoxClicked);
|
||||
layout->addWidget(ui_objects.optional_checkbox, row, kOptionalCheckBox);
|
||||
|
||||
if (create_checkboxes_ == kCheckBoxesOnNonConnected && input_ref.IsConnected()) {
|
||||
ui_objects.optional_checkbox->setVisible(false);
|
||||
}
|
||||
}
|
||||
if (create_checkboxes_ == kCheckBoxesOnNonConnected &&
|
||||
input_ref.IsConnected()) {
|
||||
ui_objects.optional_checkbox->setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Add descriptor label
|
||||
ui_objects.main_label = new QLabel(this);
|
||||
// Add descriptor label
|
||||
ui_objects.main_label = new QLabel(this);
|
||||
|
||||
// Create input label
|
||||
layout->addWidget(ui_objects.main_label, row, kLabelColumn);
|
||||
// Create input label
|
||||
layout->addWidget(ui_objects.main_label, row, kLabelColumn);
|
||||
|
||||
if (node->InputIsArray(input)) {
|
||||
if (element == -1) {
|
||||
if (node->InputIsArray(input)) {
|
||||
if (element == -1) {
|
||||
// Create a collapse toggle for expanding/collapsing the array
|
||||
CollapseButton *array_collapse_btn = new CollapseButton(this);
|
||||
|
||||
// Create a collapse toggle for expanding/collapsing the array
|
||||
CollapseButton* array_collapse_btn = new CollapseButton(this);
|
||||
// Default to collapsed
|
||||
array_collapse_btn->setChecked(false);
|
||||
|
||||
// Default to collapsed
|
||||
array_collapse_btn->setChecked(false);
|
||||
// Add collapse button to layout
|
||||
layout->addWidget(array_collapse_btn, row, kArrayCollapseBtnColumn);
|
||||
|
||||
// Add collapse button to layout
|
||||
layout->addWidget(array_collapse_btn, row, kArrayCollapseBtnColumn);
|
||||
// Connect signal to show/hide array params when toggled
|
||||
connect(array_collapse_btn, &CollapseButton::toggled, this,
|
||||
&NodeParamViewItemBody::ArrayCollapseBtnPressed);
|
||||
|
||||
// Connect signal to show/hide array params when toggled
|
||||
connect(array_collapse_btn, &CollapseButton::toggled, this, &NodeParamViewItemBody::ArrayCollapseBtnPressed);
|
||||
array_collapse_buttons_.insert({ node, input }, array_collapse_btn);
|
||||
|
||||
array_collapse_buttons_.insert({node, input}, array_collapse_btn);
|
||||
} else {
|
||||
NodeParamViewArrayButton *insert_element_btn =
|
||||
new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd,
|
||||
this);
|
||||
NodeParamViewArrayButton *remove_element_btn =
|
||||
new NodeParamViewArrayButton(NodeParamViewArrayButton::kRemove,
|
||||
this);
|
||||
|
||||
} else {
|
||||
layout->addWidget(insert_element_btn, row, kArrayInsertColumn);
|
||||
layout->addWidget(remove_element_btn, row, kArrayRemoveColumn);
|
||||
|
||||
NodeParamViewArrayButton* insert_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kAdd, this);
|
||||
NodeParamViewArrayButton* remove_element_btn = new NodeParamViewArrayButton(NodeParamViewArrayButton::kRemove, this);
|
||||
ui_objects.array_insert_btn = insert_element_btn;
|
||||
ui_objects.array_remove_btn = remove_element_btn;
|
||||
|
||||
layout->addWidget(insert_element_btn, row, kArrayInsertColumn);
|
||||
layout->addWidget(remove_element_btn, row, kArrayRemoveColumn);
|
||||
connect(insert_element_btn, &NodeParamViewArrayButton::clicked,
|
||||
this, &NodeParamViewItemBody::ArrayInsertClicked);
|
||||
connect(remove_element_btn, &NodeParamViewArrayButton::clicked,
|
||||
this, &NodeParamViewItemBody::ArrayRemoveClicked);
|
||||
}
|
||||
}
|
||||
|
||||
ui_objects.array_insert_btn = insert_element_btn;
|
||||
ui_objects.array_remove_btn = remove_element_btn;
|
||||
// Create a widget/input bridge for this input
|
||||
ui_objects.widget_bridge =
|
||||
new NodeParamViewWidgetBridge(NodeInput(node, input, element), this);
|
||||
connect(ui_objects.widget_bridge,
|
||||
&NodeParamViewWidgetBridge::WidgetsRecreated, this,
|
||||
&NodeParamViewItemBody::ReplaceWidgets);
|
||||
connect(ui_objects.widget_bridge,
|
||||
&NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked, this,
|
||||
&NodeParamViewItemBody::ToggleArrayExpanded);
|
||||
connect(ui_objects.widget_bridge,
|
||||
&NodeParamViewWidgetBridge::RequestEditTextInViewer, this,
|
||||
&NodeParamViewItemBody::RequestEditTextInViewer);
|
||||
|
||||
connect(insert_element_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayInsertClicked);
|
||||
connect(remove_element_btn, &NodeParamViewArrayButton::clicked, this, &NodeParamViewItemBody::ArrayRemoveClicked);
|
||||
// Place widgets into layout
|
||||
PlaceWidgetsFromBridge(layout, ui_objects.widget_bridge, row);
|
||||
|
||||
}
|
||||
}
|
||||
// In case this input is a group, resolve that actual input to use for connected labels
|
||||
NodeInput resolved = NodeGroup::ResolveInput(input_ref);
|
||||
|
||||
// Create a widget/input bridge for this input
|
||||
ui_objects.widget_bridge = new NodeParamViewWidgetBridge(NodeInput(node, input, element), this);
|
||||
connect(ui_objects.widget_bridge, &NodeParamViewWidgetBridge::WidgetsRecreated, this, &NodeParamViewItemBody::ReplaceWidgets);
|
||||
connect(ui_objects.widget_bridge, &NodeParamViewWidgetBridge::ArrayWidgetDoubleClicked, this, &NodeParamViewItemBody::ToggleArrayExpanded);
|
||||
connect(ui_objects.widget_bridge, &NodeParamViewWidgetBridge::RequestEditTextInViewer, this, &NodeParamViewItemBody::RequestEditTextInViewer);
|
||||
if (node->IsInputConnectable(input)) {
|
||||
// Create clickable label used when an input is connected
|
||||
ui_objects.connected_label =
|
||||
new NodeParamViewConnectedLabel(resolved, this);
|
||||
connect(ui_objects.connected_label,
|
||||
&NodeParamViewConnectedLabel::RequestSelectNode, this,
|
||||
&NodeParamViewItemBody::RequestSelectNode);
|
||||
layout->addWidget(ui_objects.connected_label, row, kWidgetStartColumn,
|
||||
1, kKeyControlColumn - kWidgetStartColumn);
|
||||
}
|
||||
|
||||
// Place widgets into layout
|
||||
PlaceWidgetsFromBridge(layout, ui_objects.widget_bridge, row);
|
||||
// Add keyframe control to this layout if parameter is keyframable
|
||||
if (node->IsInputKeyframable(input)) {
|
||||
ui_objects.key_control = new NodeParamViewKeyframeControl(this);
|
||||
ui_objects.key_control->SetInput(resolved);
|
||||
layout->addWidget(ui_objects.key_control, row, kKeyControlColumn);
|
||||
}
|
||||
|
||||
// In case this input is a group, resolve that actual input to use for connected labels
|
||||
NodeInput resolved = NodeGroup::ResolveInput(input_ref);
|
||||
input_ui_map_.insert(input_ref, ui_objects);
|
||||
|
||||
if (node->IsInputConnectable(input)) {
|
||||
// Create clickable label used when an input is connected
|
||||
ui_objects.connected_label = new NodeParamViewConnectedLabel(resolved, this);
|
||||
connect(ui_objects.connected_label, &NodeParamViewConnectedLabel::RequestSelectNode, this, &NodeParamViewItemBody::RequestSelectNode);
|
||||
layout->addWidget(ui_objects.connected_label, row, kWidgetStartColumn, 1, kKeyControlColumn - kWidgetStartColumn);
|
||||
}
|
||||
if (node->IsInputConnectable(input)) {
|
||||
UpdateUIForEdgeConnection(input_ref);
|
||||
}
|
||||
|
||||
// Add keyframe control to this layout if parameter is keyframable
|
||||
if (node->IsInputKeyframable(input)) {
|
||||
ui_objects.key_control = new NodeParamViewKeyframeControl(this);
|
||||
ui_objects.key_control->SetInput(resolved);
|
||||
layout->addWidget(ui_objects.key_control, row, kKeyControlColumn);
|
||||
}
|
||||
|
||||
input_ui_map_.insert(input_ref, ui_objects);
|
||||
|
||||
if (node->IsInputConnectable(input)) {
|
||||
UpdateUIForEdgeConnection(input_ref);
|
||||
}
|
||||
|
||||
SetTimeTargetOnInputUI(ui_objects);
|
||||
SetTimebaseOnInputUI(ui_objects);
|
||||
SetTimeTargetOnInputUI(ui_objects);
|
||||
SetTimebaseOnInputUI(ui_objects);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetTimeTarget(ViewerOutput *target)
|
||||
{
|
||||
time_target_ = target;
|
||||
time_target_ = target;
|
||||
|
||||
foreach (const InputUI& ui_obj, input_ui_map_) {
|
||||
SetTimeTargetOnInputUI(ui_obj);
|
||||
}
|
||||
foreach (const InputUI &ui_obj, input_ui_map_) {
|
||||
SetTimeTargetOnInputUI(ui_obj);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetTimeTargetOnInputUI(const InputUI &ui_obj)
|
||||
{
|
||||
// Only keyframable inputs have a key control widget
|
||||
if (ui_obj.key_control) {
|
||||
ui_obj.key_control->SetTimeTarget(time_target_);
|
||||
}
|
||||
if (ui_obj.connected_label) {
|
||||
ui_obj.connected_label->SetViewerNode(time_target_);
|
||||
}
|
||||
ui_obj.widget_bridge->SetTimeTarget(time_target_);
|
||||
// Only keyframable inputs have a key control widget
|
||||
if (ui_obj.key_control) {
|
||||
ui_obj.key_control->SetTimeTarget(time_target_);
|
||||
}
|
||||
if (ui_obj.connected_label) {
|
||||
ui_obj.connected_label->SetViewerNode(time_target_);
|
||||
}
|
||||
ui_obj.widget_bridge->SetTimeTarget(time_target_);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::Retranslate()
|
||||
{
|
||||
for (auto i=input_ui_map_.begin(); i!=input_ui_map_.end(); i++) {
|
||||
const NodeInput& ic = i.key();
|
||||
for (auto i = input_ui_map_.begin(); i != input_ui_map_.end(); i++) {
|
||||
const NodeInput &ic = i.key();
|
||||
|
||||
if (ic.IsArray() && ic.element() >= 0) {
|
||||
// Make the label the array index
|
||||
i.value().main_label->setText(tr("%1:").arg(ic.element() + ic.GetProperty(QStringLiteral("arraystart")).toInt()));
|
||||
} else {
|
||||
// Set to the input's name
|
||||
i.value().main_label->setText(tr("%1:").arg(ic.name()));
|
||||
}
|
||||
}
|
||||
if (ic.IsArray() && ic.element() >= 0) {
|
||||
// Make the label the array index
|
||||
i.value().main_label->setText(tr("%1:").arg(
|
||||
ic.element() +
|
||||
ic.GetProperty(QStringLiteral("arraystart")).toInt()));
|
||||
} else {
|
||||
// Set to the input's name
|
||||
i.value().main_label->setText(tr("%1:").arg(ic.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int NodeParamViewItemBody::GetElementY(NodeInput c) const
|
||||
{
|
||||
if (c.IsArray() && !array_ui_.value(c.input_pair()).widget->isVisible()) {
|
||||
// Array is collapsed, so we'll return the Y of its root
|
||||
c.set_element(-1);
|
||||
}
|
||||
if (c.IsArray() && !array_ui_.value(c.input_pair()).widget->isVisible()) {
|
||||
// Array is collapsed, so we'll return the Y of its root
|
||||
c.set_element(-1);
|
||||
}
|
||||
|
||||
//c = NodeGroup::ResolveInput(c);
|
||||
//c = NodeGroup::ResolveInput(c);
|
||||
|
||||
// Find its row in the parameters
|
||||
QLabel* lbl = input_ui_map_.value(c).main_label;
|
||||
// Find its row in the parameters
|
||||
QLabel *lbl = input_ui_map_.value(c).main_label;
|
||||
|
||||
// Find label's Y position
|
||||
QPoint lbl_center = lbl->rect().center();
|
||||
// Find label's Y position
|
||||
QPoint lbl_center = lbl->rect().center();
|
||||
|
||||
// Find global position
|
||||
lbl_center = lbl->mapToGlobal(lbl_center);
|
||||
// Find global position
|
||||
lbl_center = lbl->mapToGlobal(lbl_center);
|
||||
|
||||
// Return Y
|
||||
return lbl_center.y();
|
||||
// Return Y
|
||||
return lbl_center.y();
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::EdgeChanged(Node *output, const NodeInput& input)
|
||||
void NodeParamViewItemBody::EdgeChanged(Node *output, const NodeInput &input)
|
||||
{
|
||||
Q_UNUSED(output)
|
||||
Q_UNUSED(output)
|
||||
|
||||
const NodeInputPair &pair = input_group_lookup_.value({input.node(), input.input()});
|
||||
NodeInput resolved(pair.node, pair.input, input.element());
|
||||
const NodeInputPair &pair =
|
||||
input_group_lookup_.value({ input.node(), input.input() });
|
||||
NodeInput resolved(pair.node, pair.input, input.element());
|
||||
|
||||
UpdateUIForEdgeConnection(resolved);
|
||||
UpdateUIForEdgeConnection(resolved);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::UpdateUIForEdgeConnection(const NodeInput& input)
|
||||
void NodeParamViewItemBody::UpdateUIForEdgeConnection(const NodeInput &input)
|
||||
{
|
||||
// Show/hide bridge widgets
|
||||
if (input_ui_map_.contains(input)) {
|
||||
const InputUI& ui_objects = input_ui_map_[input];
|
||||
// Show/hide bridge widgets
|
||||
if (input_ui_map_.contains(input)) {
|
||||
const InputUI &ui_objects = input_ui_map_[input];
|
||||
|
||||
bool is_connected = NodeGroup::ResolveInput(input).IsConnected();
|
||||
bool is_connected = NodeGroup::ResolveInput(input).IsConnected();
|
||||
|
||||
foreach (QWidget* w, ui_objects.widget_bridge->widgets()) {
|
||||
w->setVisible(!is_connected);
|
||||
}
|
||||
foreach (QWidget *w, ui_objects.widget_bridge->widgets()) {
|
||||
w->setVisible(!is_connected);
|
||||
}
|
||||
|
||||
// Show/hide connection label
|
||||
ui_objects.connected_label->setVisible(is_connected);
|
||||
// Show/hide connection label
|
||||
ui_objects.connected_label->setVisible(is_connected);
|
||||
|
||||
if (ui_objects.key_control) {
|
||||
ui_objects.key_control->setVisible(!is_connected);
|
||||
}
|
||||
if (ui_objects.key_control) {
|
||||
ui_objects.key_control->setVisible(!is_connected);
|
||||
}
|
||||
|
||||
// Show/hide optional checkbox if requested
|
||||
if (create_checkboxes_ == kCheckBoxesOnNonConnected) {
|
||||
ui_objects.optional_checkbox->setVisible(!is_connected);
|
||||
}
|
||||
}
|
||||
// Show/hide optional checkbox if requested
|
||||
if (create_checkboxes_ == kCheckBoxesOnNonConnected) {
|
||||
ui_objects.optional_checkbox->setVisible(!is_connected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::PlaceWidgetsFromBridge(QGridLayout* layout, NodeParamViewWidgetBridge *bridge, int row)
|
||||
void NodeParamViewItemBody::PlaceWidgetsFromBridge(
|
||||
QGridLayout *layout, NodeParamViewWidgetBridge *bridge, int row)
|
||||
{
|
||||
// Add widgets for this parameter to the layout
|
||||
for (int i=0; i<bridge->widgets().size(); i++) {
|
||||
QWidget* w = bridge->widgets().at(i);
|
||||
// Add widgets for this parameter to the layout
|
||||
for (int i = 0; i < bridge->widgets().size(); i++) {
|
||||
QWidget *w = bridge->widgets().at(i);
|
||||
|
||||
int col = i+kWidgetStartColumn;
|
||||
int col = i + kWidgetStartColumn;
|
||||
|
||||
int colspan;
|
||||
if (i == bridge->widgets().size()-1) {
|
||||
// Span this widget among remaining columns
|
||||
colspan = kMaxWidgetColumn - col;
|
||||
} else {
|
||||
colspan = 1;
|
||||
}
|
||||
int colspan;
|
||||
if (i == bridge->widgets().size() - 1) {
|
||||
// Span this widget among remaining columns
|
||||
colspan = kMaxWidgetColumn - col;
|
||||
} else {
|
||||
colspan = 1;
|
||||
}
|
||||
|
||||
layout->addWidget(w, row, col, 1, colspan);
|
||||
}
|
||||
layout->addWidget(w, row, col, 1, colspan);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputArraySizeChangedInternal(Node *node, const QString &input, int size)
|
||||
void NodeParamViewItemBody::InputArraySizeChangedInternal(Node *node,
|
||||
const QString &input,
|
||||
int size)
|
||||
{
|
||||
NodeInputPair nip = {node, input};
|
||||
NodeInputPair nip = { node, input };
|
||||
|
||||
if (!array_ui_.contains(nip)) {
|
||||
return;
|
||||
}
|
||||
if (!array_ui_.contains(nip)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ArrayUI& array_ui = array_ui_[nip];
|
||||
ArrayUI &array_ui = array_ui_[nip];
|
||||
|
||||
if (size != array_ui.count) {
|
||||
QGridLayout* grid = static_cast<QGridLayout*>(array_ui.widget->layout());
|
||||
if (size != array_ui.count) {
|
||||
QGridLayout *grid =
|
||||
static_cast<QGridLayout *>(array_ui.widget->layout());
|
||||
|
||||
if (array_ui.count < size) {
|
||||
// Our UI count is smaller than the size, create more
|
||||
grid->addWidget(array_ui.append_btn, size, kArrayInsertColumn);
|
||||
if (array_ui.count < size) {
|
||||
// Our UI count is smaller than the size, create more
|
||||
grid->addWidget(array_ui.append_btn, size, kArrayInsertColumn);
|
||||
|
||||
for (int i=array_ui.count; i<size; i++) {
|
||||
CreateWidgets(grid, node, input, i, i);
|
||||
}
|
||||
} else {
|
||||
for (int i=array_ui.count-1; i>=size; i--) {
|
||||
// Our UI count is larger than the size, delete
|
||||
InputUI input_ui = input_ui_map_.take({node, input, i});
|
||||
delete input_ui.main_label;
|
||||
qDeleteAll(input_ui.widget_bridge->widgets());
|
||||
delete input_ui.widget_bridge;
|
||||
delete input_ui.connected_label;
|
||||
delete input_ui.key_control;
|
||||
delete input_ui.array_insert_btn;
|
||||
delete input_ui.array_remove_btn;
|
||||
}
|
||||
for (int i = array_ui.count; i < size; i++) {
|
||||
CreateWidgets(grid, node, input, i, i);
|
||||
}
|
||||
} else {
|
||||
for (int i = array_ui.count - 1; i >= size; i--) {
|
||||
// Our UI count is larger than the size, delete
|
||||
InputUI input_ui = input_ui_map_.take({ node, input, i });
|
||||
delete input_ui.main_label;
|
||||
qDeleteAll(input_ui.widget_bridge->widgets());
|
||||
delete input_ui.widget_bridge;
|
||||
delete input_ui.connected_label;
|
||||
delete input_ui.key_control;
|
||||
delete input_ui.array_insert_btn;
|
||||
delete input_ui.array_remove_btn;
|
||||
}
|
||||
|
||||
grid->addWidget(array_ui.append_btn, size, kArrayInsertColumn);
|
||||
}
|
||||
grid->addWidget(array_ui.append_btn, size, kArrayInsertColumn);
|
||||
}
|
||||
|
||||
array_ui.count = size;
|
||||
array_ui.count = size;
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
Retranslate();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayCollapseBtnPressed(bool checked)
|
||||
{
|
||||
const NodeInputPair& input = array_collapse_buttons_.key(static_cast<CollapseButton*>(sender()));
|
||||
const NodeInputPair &input =
|
||||
array_collapse_buttons_.key(static_cast<CollapseButton *>(sender()));
|
||||
|
||||
array_ui_.value(input).widget->setVisible(checked);
|
||||
if (checked) {
|
||||
// Ensure widgets are created (the signal will be ignored if they are)
|
||||
NodeInput resolved = NodeGroup::ResolveInput(NodeInput(input.node, input.input));
|
||||
InputArraySizeChangedInternal(input.node, input.input, resolved.GetArraySize());
|
||||
}
|
||||
array_ui_.value(input).widget->setVisible(checked);
|
||||
if (checked) {
|
||||
// Ensure widgets are created (the signal will be ignored if they are)
|
||||
NodeInput resolved =
|
||||
NodeGroup::ResolveInput(NodeInput(input.node, input.input));
|
||||
InputArraySizeChangedInternal(input.node, input.input,
|
||||
resolved.GetArraySize());
|
||||
}
|
||||
|
||||
emit ArrayExpandedChanged(checked);
|
||||
emit ArrayExpandedChanged(checked);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::InputArraySizeChanged(const QString& input, int old_sz, int size)
|
||||
void NodeParamViewItemBody::InputArraySizeChanged(const QString &input,
|
||||
int old_sz, int size)
|
||||
{
|
||||
Q_UNUSED(old_sz)
|
||||
Q_UNUSED(old_sz)
|
||||
|
||||
NodeInputPair nip = input_group_lookup_.value({static_cast<Node*>(sender()), input});
|
||||
NodeInputPair nip =
|
||||
input_group_lookup_.value({ static_cast<Node *>(sender()), input });
|
||||
|
||||
InputArraySizeChangedInternal(nip.node, nip.input, size);
|
||||
InputArraySizeChangedInternal(nip.node, nip.input, size);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayAppendClicked()
|
||||
{
|
||||
for (auto it=array_ui_.cbegin(); it!=array_ui_.cend(); it++) {
|
||||
if (it.value().append_btn == sender()) {
|
||||
NodeInput real_input = NodeGroup::ResolveInput(NodeInput(it.key().node, it.key().input));
|
||||
Core::instance()->undo_stack()->push(new NodeArrayInsertCommand(real_input.node(), real_input.input(), real_input.GetArraySize()),
|
||||
tr("Appended Array Element In %1 - %2").arg(real_input.node()->GetLabelAndName(), real_input.GetInputName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (auto it = array_ui_.cbegin(); it != array_ui_.cend(); it++) {
|
||||
if (it.value().append_btn == sender()) {
|
||||
NodeInput real_input = NodeGroup::ResolveInput(
|
||||
NodeInput(it.key().node, it.key().input));
|
||||
Core::instance()->undo_stack()->push(
|
||||
new NodeArrayInsertCommand(real_input.node(),
|
||||
real_input.input(),
|
||||
real_input.GetArraySize()),
|
||||
tr("Appended Array Element In %1 - %2")
|
||||
.arg(real_input.node()->GetLabelAndName(),
|
||||
real_input.GetInputName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayInsertClicked()
|
||||
{
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_insert_btn == sender()) {
|
||||
// Found our input and element
|
||||
NodeInput ic = NodeGroup::ResolveInput(it.key());
|
||||
Core::instance()->undo_stack()->push(new NodeArrayInsertCommand(ic.node(), ic.input(), ic.element()),
|
||||
tr("Inserted Array Element In %1 - %2").arg(ic.node()->GetLabelAndName(), ic.GetInputName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (auto it = input_ui_map_.cbegin(); it != input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_insert_btn == sender()) {
|
||||
// Found our input and element
|
||||
NodeInput ic = NodeGroup::ResolveInput(it.key());
|
||||
Core::instance()->undo_stack()->push(
|
||||
new NodeArrayInsertCommand(ic.node(), ic.input(), ic.element()),
|
||||
tr("Inserted Array Element In %1 - %2")
|
||||
.arg(ic.node()->GetLabelAndName(), ic.GetInputName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ArrayRemoveClicked()
|
||||
{
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_remove_btn == sender()) {
|
||||
// Found our input and element
|
||||
NodeInput ic = NodeGroup::ResolveInput(it.key());
|
||||
Core::instance()->undo_stack()->push(new NodeArrayRemoveCommand(ic.node(), ic.input(), ic.element()),
|
||||
tr("Removed Array Element In %1 - %2").arg(ic.node()->GetLabelAndName(), ic.GetInputName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (auto it = input_ui_map_.cbegin(); it != input_ui_map_.cend(); it++) {
|
||||
if (it.value().array_remove_btn == sender()) {
|
||||
// Found our input and element
|
||||
NodeInput ic = NodeGroup::ResolveInput(it.key());
|
||||
Core::instance()->undo_stack()->push(
|
||||
new NodeArrayRemoveCommand(ic.node(), ic.input(), ic.element()),
|
||||
tr("Removed Array Element In %1 - %2")
|
||||
.arg(ic.node()->GetLabelAndName(), ic.GetInputName()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ToggleArrayExpanded()
|
||||
{
|
||||
NodeParamViewWidgetBridge* bridge = static_cast<NodeParamViewWidgetBridge*>(sender());
|
||||
NodeParamViewWidgetBridge *bridge =
|
||||
static_cast<NodeParamViewWidgetBridge *>(sender());
|
||||
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().widget_bridge == bridge) {
|
||||
CollapseButton* b = array_collapse_buttons_.value(it.key().input_pair());
|
||||
b->setChecked(!b->isChecked());
|
||||
return;
|
||||
}
|
||||
}
|
||||
for (auto it = input_ui_map_.cbegin(); it != input_ui_map_.cend(); it++) {
|
||||
if (it.value().widget_bridge == bridge) {
|
||||
CollapseButton *b =
|
||||
array_collapse_buttons_.value(it.key().input_pair());
|
||||
b->setChecked(!b->isChecked());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetTimebase(const rational& timebase)
|
||||
void NodeParamViewItemBody::SetTimebase(const rational &timebase)
|
||||
{
|
||||
timebase_ = timebase;
|
||||
timebase_ = timebase;
|
||||
|
||||
foreach (const InputUI& ui_obj, input_ui_map_) {
|
||||
SetTimebaseOnInputUI(ui_obj);
|
||||
}
|
||||
foreach (const InputUI &ui_obj, input_ui_map_) {
|
||||
SetTimebaseOnInputUI(ui_obj);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetTimebaseOnInputUI(const InputUI& ui_obj)
|
||||
void NodeParamViewItemBody::SetTimebaseOnInputUI(const InputUI &ui_obj)
|
||||
{
|
||||
ui_obj.widget_bridge->SetTimebase(timebase_);
|
||||
ui_obj.widget_bridge->SetTimebase(timebase_);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::SetInputChecked(const NodeInput &input, bool e)
|
||||
{
|
||||
if (input_ui_map_.contains(input)) {
|
||||
QCheckBox *cb = input_ui_map_.value(input).optional_checkbox;
|
||||
if (cb) {
|
||||
cb->setChecked(e);
|
||||
}
|
||||
}
|
||||
if (input_ui_map_.contains(input)) {
|
||||
QCheckBox *cb = input_ui_map_.value(input).optional_checkbox;
|
||||
if (cb) {
|
||||
cb->setChecked(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ReplaceWidgets(const NodeInput &input)
|
||||
{
|
||||
InputUI ui = input_ui_map_.value(input);
|
||||
PlaceWidgetsFromBridge(ui.layout, ui.widget_bridge, ui.row);
|
||||
InputUI ui = input_ui_map_.value(input);
|
||||
PlaceWidgetsFromBridge(ui.layout, ui.widget_bridge, ui.row);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::ShowSpeedDurationDialogForNode()
|
||||
{
|
||||
// We should only get there if the node is a clip, determined by the dynamic_cast in CreateWidgets
|
||||
SpeedDurationDialog sdd({static_cast<ClipBlock*>(node_)}, timebase_, this);
|
||||
sdd.exec();
|
||||
// We should only get there if the node is a clip, determined by the dynamic_cast in CreateWidgets
|
||||
SpeedDurationDialog sdd({ static_cast<ClipBlock *>(node_) }, timebase_,
|
||||
this);
|
||||
sdd.exec();
|
||||
}
|
||||
|
||||
void NodeParamViewItemBody::OptionalCheckBoxClicked(bool e)
|
||||
{
|
||||
QCheckBox *cb = static_cast<QCheckBox*>(sender());
|
||||
QCheckBox *cb = static_cast<QCheckBox *>(sender());
|
||||
|
||||
for (auto it=input_ui_map_.cbegin(); it!=input_ui_map_.cend(); it++) {
|
||||
if (it.value().optional_checkbox == cb) {
|
||||
emit InputCheckedChanged(it.key(), e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (auto it = input_ui_map_.cbegin(); it != input_ui_map_.cend(); it++) {
|
||||
if (it.value().optional_checkbox == cb) {
|
||||
emit InputCheckedChanged(it.key(), e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NodeParamViewItemBody::InputUI::InputUI() :
|
||||
main_label(nullptr),
|
||||
widget_bridge(nullptr),
|
||||
connected_label(nullptr),
|
||||
key_control(nullptr),
|
||||
extra_btn(nullptr),
|
||||
optional_checkbox(nullptr),
|
||||
array_insert_btn(nullptr),
|
||||
array_remove_btn(nullptr)
|
||||
NodeParamViewItemBody::InputUI::InputUI()
|
||||
: main_label(nullptr)
|
||||
, widget_bridge(nullptr)
|
||||
, connected_label(nullptr)
|
||||
, key_control(nullptr)
|
||||
, extra_btn(nullptr)
|
||||
, optional_checkbox(nullptr)
|
||||
, array_insert_btn(nullptr)
|
||||
, array_remove_btn(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -38,211 +38,217 @@
|
||||
#include "widget/collapsebutton/collapsebutton.h"
|
||||
#include "widget/keyframeview/keyframeview.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
enum NodeParamViewCheckBoxBehavior {
|
||||
kNoCheckBoxes,
|
||||
kCheckBoxesOn,
|
||||
kCheckBoxesOnNonConnected
|
||||
kNoCheckBoxes,
|
||||
kCheckBoxesOn,
|
||||
kCheckBoxesOnNonConnected
|
||||
};
|
||||
|
||||
class NodeParamViewItemBody : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewItemBody(Node* node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget* parent = nullptr);
|
||||
NodeParamViewItemBody(Node *node,
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
void SetTimeTarget(ViewerOutput *target);
|
||||
void SetTimeTarget(ViewerOutput *target);
|
||||
|
||||
void Retranslate();
|
||||
void Retranslate();
|
||||
|
||||
int GetElementY(NodeInput c) const;
|
||||
int GetElementY(NodeInput c) const;
|
||||
|
||||
// Set the timebase of any timebased widgets contained here
|
||||
void SetTimebase(const rational& timebase);
|
||||
// Set the timebase of any timebased widgets contained here
|
||||
void SetTimebase(const rational &timebase);
|
||||
|
||||
void SetInputChecked(const NodeInput &input, bool e);
|
||||
void SetInputChecked(const NodeInput &input, bool e);
|
||||
|
||||
signals:
|
||||
void RequestSelectNode(Node *node);
|
||||
void RequestSelectNode(Node *node);
|
||||
|
||||
void ArrayExpandedChanged(bool e);
|
||||
void ArrayExpandedChanged(bool e);
|
||||
|
||||
void InputCheckedChanged(const NodeInput &input, bool e);
|
||||
void InputCheckedChanged(const NodeInput &input, bool e);
|
||||
|
||||
void RequestEditTextInViewer();
|
||||
void RequestEditTextInViewer();
|
||||
|
||||
private:
|
||||
void CreateWidgets(QGridLayout *layout, Node* node, const QString& input, int element, int row_index);
|
||||
void CreateWidgets(QGridLayout *layout, Node *node, const QString &input,
|
||||
int element, int row_index);
|
||||
|
||||
void UpdateUIForEdgeConnection(const NodeInput &input);
|
||||
void UpdateUIForEdgeConnection(const NodeInput &input);
|
||||
|
||||
void PlaceWidgetsFromBridge(QGridLayout *layout, NodeParamViewWidgetBridge* bridge, int row);
|
||||
void PlaceWidgetsFromBridge(QGridLayout *layout,
|
||||
NodeParamViewWidgetBridge *bridge, int row);
|
||||
|
||||
void InputArraySizeChangedInternal(Node *node, const QString &input, int size);
|
||||
void InputArraySizeChangedInternal(Node *node, const QString &input,
|
||||
int size);
|
||||
|
||||
struct InputUI {
|
||||
InputUI();
|
||||
struct InputUI {
|
||||
InputUI();
|
||||
|
||||
QLabel* main_label;
|
||||
NodeParamViewWidgetBridge* widget_bridge;
|
||||
NodeParamViewConnectedLabel* connected_label;
|
||||
NodeParamViewKeyframeControl* key_control;
|
||||
QGridLayout* layout;
|
||||
int row;
|
||||
QPushButton *extra_btn;
|
||||
QCheckBox *optional_checkbox;
|
||||
QLabel *main_label;
|
||||
NodeParamViewWidgetBridge *widget_bridge;
|
||||
NodeParamViewConnectedLabel *connected_label;
|
||||
NodeParamViewKeyframeControl *key_control;
|
||||
QGridLayout *layout;
|
||||
int row;
|
||||
QPushButton *extra_btn;
|
||||
QCheckBox *optional_checkbox;
|
||||
|
||||
NodeParamViewArrayButton* array_insert_btn;
|
||||
NodeParamViewArrayButton* array_remove_btn;
|
||||
};
|
||||
NodeParamViewArrayButton *array_insert_btn;
|
||||
NodeParamViewArrayButton *array_remove_btn;
|
||||
};
|
||||
|
||||
QHash<NodeInput, InputUI> input_ui_map_;
|
||||
QHash<NodeInput, InputUI> input_ui_map_;
|
||||
|
||||
struct ArrayUI {
|
||||
QWidget* widget;
|
||||
int count;
|
||||
NodeParamViewArrayButton* append_btn;
|
||||
};
|
||||
struct ArrayUI {
|
||||
QWidget *widget;
|
||||
int count;
|
||||
NodeParamViewArrayButton *append_btn;
|
||||
};
|
||||
|
||||
void SetTimeTargetOnInputUI(const InputUI &ui);
|
||||
void SetTimebaseOnInputUI(const InputUI &ui);
|
||||
void SetTimeTargetOnInputUI(const InputUI &ui);
|
||||
void SetTimebaseOnInputUI(const InputUI &ui);
|
||||
|
||||
Node *node_;
|
||||
Node *node_;
|
||||
|
||||
QHash<NodeInputPair, ArrayUI> array_ui_;
|
||||
QHash<NodeInputPair, ArrayUI> array_ui_;
|
||||
|
||||
QHash<NodeInputPair, CollapseButton*> array_collapse_buttons_;
|
||||
QHash<NodeInputPair, CollapseButton *> array_collapse_buttons_;
|
||||
|
||||
rational timebase_;
|
||||
rational timebase_;
|
||||
|
||||
ViewerOutput *time_target_;
|
||||
ViewerOutput *time_target_;
|
||||
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes_;
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes_;
|
||||
|
||||
QHash<NodeInputPair, NodeInputPair> input_group_lookup_;
|
||||
QHash<NodeInputPair, NodeInputPair> input_group_lookup_;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief The column to place the keyframe controls in
|
||||
*
|
||||
* Serves as an effective "maximum column" index because the keyframe button is always aligned
|
||||
* to the right edge.
|
||||
*/
|
||||
static const int kKeyControlColumn;
|
||||
static const int kKeyControlColumn;
|
||||
|
||||
static const int kArrayInsertColumn;
|
||||
static const int kArrayRemoveColumn;
|
||||
static const int kExtraButtonColumn;
|
||||
static const int kArrayInsertColumn;
|
||||
static const int kArrayRemoveColumn;
|
||||
static const int kExtraButtonColumn;
|
||||
|
||||
static const int kOptionalCheckBox;
|
||||
static const int kArrayCollapseBtnColumn;
|
||||
static const int kLabelColumn;
|
||||
static const int kWidgetStartColumn;
|
||||
static const int kMaxWidgetColumn;
|
||||
static const int kOptionalCheckBox;
|
||||
static const int kArrayCollapseBtnColumn;
|
||||
static const int kLabelColumn;
|
||||
static const int kWidgetStartColumn;
|
||||
static const int kMaxWidgetColumn;
|
||||
|
||||
private slots:
|
||||
void EdgeChanged(Node *output, const NodeInput &input);
|
||||
void EdgeChanged(Node *output, const NodeInput &input);
|
||||
|
||||
void ArrayCollapseBtnPressed(bool checked);
|
||||
void ArrayCollapseBtnPressed(bool checked);
|
||||
|
||||
void InputArraySizeChanged(const QString &input, int old_sz, int size);
|
||||
void InputArraySizeChanged(const QString &input, int old_sz, int size);
|
||||
|
||||
void ArrayAppendClicked();
|
||||
void ArrayAppendClicked();
|
||||
|
||||
void ArrayInsertClicked();
|
||||
void ArrayInsertClicked();
|
||||
|
||||
void ArrayRemoveClicked();
|
||||
void ArrayRemoveClicked();
|
||||
|
||||
void ToggleArrayExpanded();
|
||||
void ToggleArrayExpanded();
|
||||
|
||||
void ReplaceWidgets(const NodeInput& input);
|
||||
void ReplaceWidgets(const NodeInput &input);
|
||||
|
||||
void ShowSpeedDurationDialogForNode();
|
||||
|
||||
void OptionalCheckBoxClicked(bool e);
|
||||
void ShowSpeedDurationDialogForNode();
|
||||
|
||||
void OptionalCheckBoxClicked(bool e);
|
||||
};
|
||||
|
||||
class NodeParamViewItem : public NodeParamViewItemBase
|
||||
{
|
||||
Q_OBJECT
|
||||
class NodeParamViewItem : public NodeParamViewItemBase {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewItem(Node* node, NodeParamViewCheckBoxBehavior create_checkboxes, QWidget* parent = nullptr);
|
||||
NodeParamViewItem(Node *node,
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes,
|
||||
QWidget *parent = nullptr);
|
||||
|
||||
void SetTimeTarget(ViewerOutput* target)
|
||||
{
|
||||
time_target_ = target;
|
||||
void SetTimeTarget(ViewerOutput *target)
|
||||
{
|
||||
time_target_ = target;
|
||||
|
||||
body_->SetTimeTarget(target);
|
||||
}
|
||||
body_->SetTimeTarget(target);
|
||||
}
|
||||
|
||||
void SetTimebase(const rational& timebase)
|
||||
{
|
||||
timebase_ = timebase;
|
||||
void SetTimebase(const rational &timebase)
|
||||
{
|
||||
timebase_ = timebase;
|
||||
|
||||
body_->SetTimebase(timebase);
|
||||
}
|
||||
body_->SetTimebase(timebase);
|
||||
}
|
||||
|
||||
Node *GetContext() const
|
||||
{
|
||||
return ctx_;
|
||||
}
|
||||
Node *GetContext() const
|
||||
{
|
||||
return ctx_;
|
||||
}
|
||||
|
||||
void SetContext(Node *ctx)
|
||||
{
|
||||
ctx_ = ctx;
|
||||
}
|
||||
void SetContext(Node *ctx)
|
||||
{
|
||||
ctx_ = ctx;
|
||||
}
|
||||
|
||||
Node* GetNode() const
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
Node *GetNode() const
|
||||
{
|
||||
return node_;
|
||||
}
|
||||
|
||||
int GetElementY(const NodeInput& c) const;
|
||||
int GetElementY(const NodeInput &c) const;
|
||||
|
||||
void SetInputChecked(const NodeInput &input, bool e);
|
||||
void SetInputChecked(const NodeInput &input, bool e);
|
||||
|
||||
KeyframeView::NodeConnections &GetKeyframeConnections()
|
||||
{
|
||||
return keyframe_connections_;
|
||||
}
|
||||
KeyframeView::NodeConnections &GetKeyframeConnections()
|
||||
{
|
||||
return keyframe_connections_;
|
||||
}
|
||||
|
||||
void SetKeyframeConnections(const KeyframeView::NodeConnections &c)
|
||||
{
|
||||
keyframe_connections_ = c;
|
||||
}
|
||||
void SetKeyframeConnections(const KeyframeView::NodeConnections &c)
|
||||
{
|
||||
keyframe_connections_ = c;
|
||||
}
|
||||
|
||||
signals:
|
||||
void RequestSelectNode(Node *node);
|
||||
void RequestSelectNode(Node *node);
|
||||
|
||||
void ArrayExpandedChanged(bool e);
|
||||
void ArrayExpandedChanged(bool e);
|
||||
|
||||
void InputCheckedChanged(const NodeInput &input, bool e);
|
||||
void InputCheckedChanged(const NodeInput &input, bool e);
|
||||
|
||||
void RequestEditTextInViewer();
|
||||
void RequestEditTextInViewer();
|
||||
|
||||
void InputArraySizeChanged(const QString &input, int old_size, int new_size);
|
||||
void InputArraySizeChanged(const QString &input, int old_size,
|
||||
int new_size);
|
||||
|
||||
protected slots:
|
||||
virtual void Retranslate() override;
|
||||
virtual void Retranslate() override;
|
||||
|
||||
private:
|
||||
NodeParamViewItemBody* body_;
|
||||
NodeParamViewItemBody *body_;
|
||||
|
||||
Node* node_;
|
||||
Node *node_;
|
||||
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes_;
|
||||
NodeParamViewCheckBoxBehavior create_checkboxes_;
|
||||
|
||||
Node *ctx_;
|
||||
Node *ctx_;
|
||||
|
||||
ViewerOutput *time_target_;
|
||||
ViewerOutput *time_target_;
|
||||
|
||||
rational timebase_;
|
||||
rational timebase_;
|
||||
|
||||
KeyframeView::NodeConnections keyframe_connections_;
|
||||
KeyframeView::NodeConnections keyframe_connections_;
|
||||
|
||||
private slots:
|
||||
void RecreateBody();
|
||||
|
||||
void RecreateBody();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -23,104 +23,108 @@
|
||||
#include <QEvent>
|
||||
#include <QPainter>
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QDockWidget
|
||||
|
||||
NodeParamViewItemBase::NodeParamViewItemBase(QWidget *parent) :
|
||||
super(parent),
|
||||
highlighted_(false)
|
||||
NodeParamViewItemBase::NodeParamViewItemBase(QWidget *parent)
|
||||
: super(parent)
|
||||
, highlighted_(false)
|
||||
{
|
||||
// Create title bar widget
|
||||
title_bar_ = new NodeParamViewItemTitleBar(this);
|
||||
// Create title bar widget
|
||||
title_bar_ = new NodeParamViewItemTitleBar(this);
|
||||
|
||||
// Add title bar to widget
|
||||
this->setTitleBarWidget(title_bar_);
|
||||
// Add title bar to widget
|
||||
this->setTitleBarWidget(title_bar_);
|
||||
|
||||
// Connect title bar to this
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::ExpandedStateChanged, this, &NodeParamViewItemBase::SetExpanded);
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::PinToggled, this, &NodeParamViewItemBase::PinToggled);
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::Clicked, this, &NodeParamViewItemBase::Clicked);
|
||||
// Connect title bar to this
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::ExpandedStateChanged, this,
|
||||
&NodeParamViewItemBase::SetExpanded);
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::PinToggled, this,
|
||||
&NodeParamViewItemBase::PinToggled);
|
||||
connect(title_bar_, &NodeParamViewItemTitleBar::Clicked, this,
|
||||
&NodeParamViewItemBase::Clicked);
|
||||
|
||||
// Use dummy QWidget to retain width when not expanded (QDockWidget seems to ignore the titlebar
|
||||
// size hints and will shrink as small as possible if the body is hidden)
|
||||
hidden_body_ = new QWidget(this);
|
||||
// Use dummy QWidget to retain width when not expanded (QDockWidget seems to ignore the titlebar
|
||||
// size hints and will shrink as small as possible if the body is hidden)
|
||||
hidden_body_ = new QWidget(this);
|
||||
|
||||
// Default to hidden body, this also seems to fix an issue with clicks being intermittent
|
||||
// on the titlebar
|
||||
setWidget(hidden_body_);
|
||||
// Default to hidden body, this also seems to fix an issue with clicks being intermittent
|
||||
// on the titlebar
|
||||
setWidget(hidden_body_);
|
||||
|
||||
setAutoFillBackground(true);
|
||||
setAutoFillBackground(true);
|
||||
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
}
|
||||
|
||||
bool NodeParamViewItemBase::IsExpanded() const
|
||||
{
|
||||
return title_bar_->IsExpanded();
|
||||
return title_bar_->IsExpanded();
|
||||
}
|
||||
|
||||
QString NodeParamViewItemBase::GetTitleBarTextFromNode(Node *n)
|
||||
{
|
||||
if (n->GetLabel().isEmpty()) {
|
||||
return n->Name();
|
||||
} else {
|
||||
return tr("%1 (%2)").arg(n->GetLabel(), n->Name());
|
||||
}
|
||||
if (n->GetLabel().isEmpty()) {
|
||||
return n->Name();
|
||||
} else {
|
||||
return tr("%1 (%2)").arg(n->GetLabel(), n->Name());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBase::SetBody(QWidget *body)
|
||||
{
|
||||
body_ = body;
|
||||
body_->setParent(this);
|
||||
body_ = body;
|
||||
body_->setParent(this);
|
||||
|
||||
if (title_bar_->IsExpanded()) {
|
||||
setWidget(body_);
|
||||
}
|
||||
if (title_bar_->IsExpanded()) {
|
||||
setWidget(body_);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBase::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
super::paintEvent(event);
|
||||
super::paintEvent(event);
|
||||
|
||||
// Draw border if focused
|
||||
if (highlighted_) {
|
||||
QPainter p(this);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(palette().highlight().color());
|
||||
p.drawRect(rect().adjusted(0, 0, -1, -1));
|
||||
}
|
||||
// Draw border if focused
|
||||
if (highlighted_) {
|
||||
QPainter p(this);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setPen(palette().highlight().color());
|
||||
p.drawRect(rect().adjusted(0, 0, -1, -1));
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemBase::SetExpanded(bool e)
|
||||
{
|
||||
setWidget(e ? body_ : hidden_body_);
|
||||
title_bar_->SetExpanded(e);
|
||||
setWidget(e ? body_ : hidden_body_);
|
||||
title_bar_->SetExpanded(e);
|
||||
|
||||
emit ExpandedChanged(e);
|
||||
emit ExpandedChanged(e);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBase::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
super::changeEvent(e);
|
||||
super::changeEvent(e);
|
||||
}
|
||||
|
||||
void NodeParamViewItemBase::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
super::moveEvent(event);
|
||||
super::moveEvent(event);
|
||||
|
||||
emit Moved();
|
||||
emit Moved();
|
||||
}
|
||||
|
||||
void NodeParamViewItemBase::mousePressEvent(QMouseEvent *e)
|
||||
{
|
||||
super::mousePressEvent(e);
|
||||
super::mousePressEvent(e);
|
||||
|
||||
emit Clicked();
|
||||
emit Clicked();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,72 +26,76 @@
|
||||
#include "nodeparamviewitemtitlebar.h"
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewItemBase : public QDockWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeParamViewItemBase : public QDockWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewItemBase(QWidget* parent = nullptr);
|
||||
NodeParamViewItemBase(QWidget *parent = nullptr);
|
||||
|
||||
void SetHighlighted(bool e)
|
||||
{
|
||||
highlighted_ = e;
|
||||
void SetHighlighted(bool e)
|
||||
{
|
||||
highlighted_ = e;
|
||||
|
||||
update();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
bool IsHighlighted() const { return highlighted_; }
|
||||
bool IsHighlighted() const
|
||||
{
|
||||
return highlighted_;
|
||||
}
|
||||
|
||||
bool IsExpanded() const;
|
||||
bool IsExpanded() const;
|
||||
|
||||
static QString GetTitleBarTextFromNode(Node *n);
|
||||
static QString GetTitleBarTextFromNode(Node *n);
|
||||
|
||||
public slots:
|
||||
void SetExpanded(bool e);
|
||||
void SetExpanded(bool e);
|
||||
|
||||
void ToggleExpanded()
|
||||
{
|
||||
SetExpanded(!IsExpanded());
|
||||
}
|
||||
void ToggleExpanded()
|
||||
{
|
||||
SetExpanded(!IsExpanded());
|
||||
}
|
||||
|
||||
signals:
|
||||
void PinToggled(bool e);
|
||||
void PinToggled(bool e);
|
||||
|
||||
void ExpandedChanged(bool e);
|
||||
void ExpandedChanged(bool e);
|
||||
|
||||
void Moved();
|
||||
void Moved();
|
||||
|
||||
void Clicked();
|
||||
void Clicked();
|
||||
|
||||
protected:
|
||||
void SetBody(QWidget *body);
|
||||
void SetBody(QWidget *body);
|
||||
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
NodeParamViewItemTitleBar* title_bar() const
|
||||
{
|
||||
return title_bar_;
|
||||
}
|
||||
NodeParamViewItemTitleBar *title_bar() const
|
||||
{
|
||||
return title_bar_;
|
||||
}
|
||||
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
virtual void mousePressEvent(QMouseEvent *e) override;
|
||||
|
||||
protected slots:
|
||||
virtual void Retranslate(){}
|
||||
virtual void Retranslate()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
NodeParamViewItemTitleBar* title_bar_;
|
||||
NodeParamViewItemTitleBar *title_bar_;
|
||||
|
||||
QWidget *body_;
|
||||
QWidget *body_;
|
||||
|
||||
QWidget *hidden_body_;
|
||||
|
||||
bool highlighted_;
|
||||
QWidget *hidden_body_;
|
||||
|
||||
bool highlighted_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,78 +25,85 @@
|
||||
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamViewItemTitleBar::NodeParamViewItemTitleBar(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
draw_border_(true)
|
||||
namespace olive
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
|
||||
collapse_btn_ = new CollapseButton(this);
|
||||
connect(collapse_btn_, &QPushButton::clicked, this, &NodeParamViewItemTitleBar::ExpandedStateChanged);
|
||||
layout->addWidget(collapse_btn_);
|
||||
NodeParamViewItemTitleBar::NodeParamViewItemTitleBar(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, draw_border_(true)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
|
||||
lbl_ = new QLabel(this);
|
||||
layout->addWidget(lbl_);
|
||||
collapse_btn_ = new CollapseButton(this);
|
||||
connect(collapse_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewItemTitleBar::ExpandedStateChanged);
|
||||
layout->addWidget(collapse_btn_);
|
||||
|
||||
// Place next buttons on the far side
|
||||
layout->addStretch();
|
||||
lbl_ = new QLabel(this);
|
||||
layout->addWidget(lbl_);
|
||||
|
||||
add_fx_btn_ = new QPushButton(this);
|
||||
add_fx_btn_->setIcon(icon::AddEffect);
|
||||
add_fx_btn_->setFixedSize(add_fx_btn_->sizeHint().height(), add_fx_btn_->sizeHint().height());
|
||||
add_fx_btn_->setVisible(false);
|
||||
layout->addWidget(add_fx_btn_);
|
||||
connect(add_fx_btn_, &QPushButton::clicked, this, &NodeParamViewItemTitleBar::AddEffectButtonClicked);
|
||||
// Place next buttons on the far side
|
||||
layout->addStretch();
|
||||
|
||||
pin_btn_ = new QPushButton(QStringLiteral("P"), this);
|
||||
pin_btn_->setCheckable(true);
|
||||
pin_btn_->setFixedSize(pin_btn_->sizeHint().height(), pin_btn_->sizeHint().height());
|
||||
pin_btn_->setVisible(false);
|
||||
layout->addWidget(pin_btn_);
|
||||
connect(pin_btn_, &QPushButton::clicked, this, &NodeParamViewItemTitleBar::PinToggled);
|
||||
add_fx_btn_ = new QPushButton(this);
|
||||
add_fx_btn_->setIcon(icon::AddEffect);
|
||||
add_fx_btn_->setFixedSize(add_fx_btn_->sizeHint().height(),
|
||||
add_fx_btn_->sizeHint().height());
|
||||
add_fx_btn_->setVisible(false);
|
||||
layout->addWidget(add_fx_btn_);
|
||||
connect(add_fx_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewItemTitleBar::AddEffectButtonClicked);
|
||||
|
||||
enabled_checkbox_ = new QCheckBox(this);
|
||||
enabled_checkbox_->setVisible(false);
|
||||
layout->addWidget(enabled_checkbox_);
|
||||
connect(enabled_checkbox_, &QCheckBox::clicked, this, &NodeParamViewItemTitleBar::EnabledCheckBoxClicked);
|
||||
pin_btn_ = new QPushButton(QStringLiteral("P"), this);
|
||||
pin_btn_->setCheckable(true);
|
||||
pin_btn_->setFixedSize(pin_btn_->sizeHint().height(),
|
||||
pin_btn_->sizeHint().height());
|
||||
pin_btn_->setVisible(false);
|
||||
layout->addWidget(pin_btn_);
|
||||
connect(pin_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewItemTitleBar::PinToggled);
|
||||
|
||||
enabled_checkbox_ = new QCheckBox(this);
|
||||
enabled_checkbox_->setVisible(false);
|
||||
layout->addWidget(enabled_checkbox_);
|
||||
connect(enabled_checkbox_, &QCheckBox::clicked, this,
|
||||
&NodeParamViewItemTitleBar::EnabledCheckBoxClicked);
|
||||
}
|
||||
|
||||
void NodeParamViewItemTitleBar::SetExpanded(bool e)
|
||||
{
|
||||
draw_border_ = e;
|
||||
collapse_btn_->setChecked(e);
|
||||
draw_border_ = e;
|
||||
collapse_btn_->setChecked(e);
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeParamViewItemTitleBar::paintEvent(QPaintEvent *event)
|
||||
{
|
||||
QWidget::paintEvent(event);
|
||||
QWidget::paintEvent(event);
|
||||
|
||||
if (draw_border_) {
|
||||
QPainter p(this);
|
||||
if (draw_border_) {
|
||||
QPainter p(this);
|
||||
|
||||
// Draw bottom border using text color
|
||||
int bottom = height() - 1;
|
||||
p.setPen(palette().text().color());
|
||||
p.drawLine(0, bottom, width(), bottom);
|
||||
}
|
||||
// Draw bottom border using text color
|
||||
int bottom = height() - 1;
|
||||
p.setPen(palette().text().color());
|
||||
p.drawLine(0, bottom, width(), bottom);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewItemTitleBar::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mousePressEvent(event);
|
||||
QWidget::mousePressEvent(event);
|
||||
|
||||
emit Clicked();
|
||||
emit Clicked();
|
||||
}
|
||||
|
||||
void NodeParamViewItemTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
|
||||
collapse_btn_->click();
|
||||
collapse_btn_->click();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,79 +27,78 @@
|
||||
|
||||
#include "widget/collapsebutton/collapsebutton.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewItemTitleBar : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewItemTitleBar(QWidget* parent = nullptr);
|
||||
|
||||
bool IsExpanded() const
|
||||
{
|
||||
return collapse_btn_->isChecked();
|
||||
}
|
||||
class NodeParamViewItemTitleBar : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewItemTitleBar(QWidget *parent = nullptr);
|
||||
|
||||
bool IsExpanded() const
|
||||
{
|
||||
return collapse_btn_->isChecked();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetExpanded(bool e);
|
||||
void SetExpanded(bool e);
|
||||
|
||||
void SetText(const QString& s)
|
||||
{
|
||||
lbl_->setText(s);
|
||||
lbl_->setToolTip(s);
|
||||
lbl_->setMinimumWidth(1);
|
||||
}
|
||||
void SetText(const QString &s)
|
||||
{
|
||||
lbl_->setText(s);
|
||||
lbl_->setToolTip(s);
|
||||
lbl_->setMinimumWidth(1);
|
||||
}
|
||||
|
||||
void SetPinButtonVisible(bool e)
|
||||
{
|
||||
pin_btn_->setVisible(e);
|
||||
}
|
||||
void SetPinButtonVisible(bool e)
|
||||
{
|
||||
pin_btn_->setVisible(e);
|
||||
}
|
||||
|
||||
void SetAddEffectButtonVisible(bool e)
|
||||
{
|
||||
add_fx_btn_->setVisible(e);
|
||||
}
|
||||
void SetAddEffectButtonVisible(bool e)
|
||||
{
|
||||
add_fx_btn_->setVisible(e);
|
||||
}
|
||||
|
||||
void SetEnabledCheckBoxVisible(bool e)
|
||||
{
|
||||
enabled_checkbox_->setVisible(e);
|
||||
}
|
||||
void SetEnabledCheckBoxVisible(bool e)
|
||||
{
|
||||
enabled_checkbox_->setVisible(e);
|
||||
}
|
||||
|
||||
void SetEnabledCheckBoxChecked(bool e)
|
||||
{
|
||||
enabled_checkbox_->setChecked(e);
|
||||
}
|
||||
void SetEnabledCheckBoxChecked(bool e)
|
||||
{
|
||||
enabled_checkbox_->setChecked(e);
|
||||
}
|
||||
|
||||
signals:
|
||||
void ExpandedStateChanged(bool e);
|
||||
void ExpandedStateChanged(bool e);
|
||||
|
||||
void PinToggled(bool e);
|
||||
void PinToggled(bool e);
|
||||
|
||||
void AddEffectButtonClicked();
|
||||
void AddEffectButtonClicked();
|
||||
|
||||
void EnabledCheckBoxClicked(bool e);
|
||||
void EnabledCheckBoxClicked(bool e);
|
||||
|
||||
void Clicked();
|
||||
void Clicked();
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
virtual void paintEvent(QPaintEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
bool draw_border_;
|
||||
bool draw_border_;
|
||||
|
||||
QLabel* lbl_;
|
||||
QLabel *lbl_;
|
||||
|
||||
CollapseButton* collapse_btn_;
|
||||
CollapseButton *collapse_btn_;
|
||||
|
||||
QPushButton *pin_btn_;
|
||||
QPushButton *pin_btn_;
|
||||
|
||||
QPushButton *add_fx_btn_;
|
||||
|
||||
QCheckBox *enabled_checkbox_;
|
||||
QPushButton *add_fx_btn_;
|
||||
|
||||
QCheckBox *enabled_checkbox_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -27,268 +27,307 @@
|
||||
#include "node/nodeundo.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(bool right_align, QWidget *parent) :
|
||||
QWidget(parent)
|
||||
namespace olive
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
if (right_align) {
|
||||
// Automatically right aligns all buttons
|
||||
layout->addStretch();
|
||||
}
|
||||
NodeParamViewKeyframeControl::NodeParamViewKeyframeControl(bool right_align,
|
||||
QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setSpacing(0);
|
||||
|
||||
prev_key_btn_ = CreateNewToolButton(icon::TriLeft);
|
||||
prev_key_btn_->setIconSize(prev_key_btn_->iconSize() / 2);
|
||||
layout->addWidget(prev_key_btn_);
|
||||
if (right_align) {
|
||||
// Automatically right aligns all buttons
|
||||
layout->addStretch();
|
||||
}
|
||||
|
||||
toggle_key_btn_ = CreateNewToolButton(icon::Diamond);
|
||||
toggle_key_btn_->setCheckable(true);
|
||||
toggle_key_btn_->setIconSize(toggle_key_btn_->iconSize() / 2);
|
||||
layout->addWidget(toggle_key_btn_);
|
||||
prev_key_btn_ = CreateNewToolButton(icon::TriLeft);
|
||||
prev_key_btn_->setIconSize(prev_key_btn_->iconSize() / 2);
|
||||
layout->addWidget(prev_key_btn_);
|
||||
|
||||
next_key_btn_ = CreateNewToolButton(icon::TriRight);
|
||||
next_key_btn_->setIconSize(next_key_btn_->iconSize() / 2);
|
||||
layout->addWidget(next_key_btn_);
|
||||
toggle_key_btn_ = CreateNewToolButton(icon::Diamond);
|
||||
toggle_key_btn_->setCheckable(true);
|
||||
toggle_key_btn_->setIconSize(toggle_key_btn_->iconSize() / 2);
|
||||
layout->addWidget(toggle_key_btn_);
|
||||
|
||||
enable_key_btn_ = CreateNewToolButton(icon::Clock);
|
||||
enable_key_btn_->setCheckable(true);
|
||||
enable_key_btn_->setIconSize(enable_key_btn_->iconSize() / 4 * 3);
|
||||
layout->addWidget(enable_key_btn_);
|
||||
next_key_btn_ = CreateNewToolButton(icon::TriRight);
|
||||
next_key_btn_->setIconSize(next_key_btn_->iconSize() / 2);
|
||||
layout->addWidget(next_key_btn_);
|
||||
|
||||
connect(prev_key_btn_, &QPushButton::clicked, this, &NodeParamViewKeyframeControl::GoToPreviousKey);
|
||||
connect(next_key_btn_, &QPushButton::clicked, this, &NodeParamViewKeyframeControl::GoToNextKey);
|
||||
connect(toggle_key_btn_, &QPushButton::clicked, this, &NodeParamViewKeyframeControl::ToggleKeyframe);
|
||||
connect(enable_key_btn_, &QPushButton::toggled, this, &NodeParamViewKeyframeControl::ShowButtonsFromKeyframeEnable);
|
||||
connect(enable_key_btn_, &QPushButton::clicked, this, &NodeParamViewKeyframeControl::KeyframeEnableBtnClicked);
|
||||
enable_key_btn_ = CreateNewToolButton(icon::Clock);
|
||||
enable_key_btn_->setCheckable(true);
|
||||
enable_key_btn_->setIconSize(enable_key_btn_->iconSize() / 4 * 3);
|
||||
layout->addWidget(enable_key_btn_);
|
||||
|
||||
// Set defaults
|
||||
SetInput(NodeInput());
|
||||
ShowButtonsFromKeyframeEnable(false);
|
||||
connect(prev_key_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewKeyframeControl::GoToPreviousKey);
|
||||
connect(next_key_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewKeyframeControl::GoToNextKey);
|
||||
connect(toggle_key_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewKeyframeControl::ToggleKeyframe);
|
||||
connect(enable_key_btn_, &QPushButton::toggled, this,
|
||||
&NodeParamViewKeyframeControl::ShowButtonsFromKeyframeEnable);
|
||||
connect(enable_key_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewKeyframeControl::KeyframeEnableBtnClicked);
|
||||
|
||||
// Set defaults
|
||||
SetInput(NodeInput());
|
||||
ShowButtonsFromKeyframeEnable(false);
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::SetInput(const NodeInput& input)
|
||||
void NodeParamViewKeyframeControl::SetInput(const NodeInput &input)
|
||||
{
|
||||
if (input_.IsValid()) {
|
||||
disconnect(input_.node(), &Node::KeyframeEnableChanged, this, &NodeParamViewKeyframeControl::KeyframeEnableChanged);
|
||||
disconnect(input_.node(), &Node::KeyframeAdded, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
disconnect(input_.node(), &Node::KeyframeRemoved, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
disconnect(input_.node(), &Node::KeyframeTimeChanged, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
}
|
||||
if (input_.IsValid()) {
|
||||
disconnect(input_.node(), &Node::KeyframeEnableChanged, this,
|
||||
&NodeParamViewKeyframeControl::KeyframeEnableChanged);
|
||||
disconnect(input_.node(), &Node::KeyframeAdded, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
disconnect(input_.node(), &Node::KeyframeRemoved, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
disconnect(input_.node(), &Node::KeyframeTimeChanged, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
}
|
||||
|
||||
input_ = input;
|
||||
SetButtonsEnabled(input_.IsValid());
|
||||
input_ = input;
|
||||
SetButtonsEnabled(input_.IsValid());
|
||||
|
||||
// Pick up keyframing value
|
||||
enable_key_btn_->setChecked(input_.IsValid() && input_.IsKeyframing());
|
||||
// Pick up keyframing value
|
||||
enable_key_btn_->setChecked(input_.IsValid() && input_.IsKeyframing());
|
||||
|
||||
// Update buttons
|
||||
UpdateState();
|
||||
// Update buttons
|
||||
UpdateState();
|
||||
|
||||
if (input_.IsValid()) {
|
||||
connect(input_.node(), &Node::KeyframeEnableChanged, this, &NodeParamViewKeyframeControl::KeyframeEnableChanged);
|
||||
connect(input_.node(), &Node::KeyframeAdded, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
connect(input_.node(), &Node::KeyframeRemoved, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
connect(input_.node(), &Node::KeyframeTimeChanged, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
}
|
||||
if (input_.IsValid()) {
|
||||
connect(input_.node(), &Node::KeyframeEnableChanged, this,
|
||||
&NodeParamViewKeyframeControl::KeyframeEnableChanged);
|
||||
connect(input_.node(), &Node::KeyframeAdded, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
connect(input_.node(), &Node::KeyframeRemoved, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
connect(input_.node(), &Node::KeyframeTimeChanged, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::TimeTargetDisconnectEvent(ViewerOutput *v)
|
||||
{
|
||||
disconnect(v, &ViewerOutput::PlayheadChanged, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
disconnect(v, &ViewerOutput::PlayheadChanged, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::TimeTargetConnectEvent(ViewerOutput *v)
|
||||
{
|
||||
connect(v, &ViewerOutput::PlayheadChanged, this, &NodeParamViewKeyframeControl::UpdateState);
|
||||
UpdateState();
|
||||
connect(v, &ViewerOutput::PlayheadChanged, this,
|
||||
&NodeParamViewKeyframeControl::UpdateState);
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
QPushButton *NodeParamViewKeyframeControl::CreateNewToolButton(const QIcon& icon) const
|
||||
QPushButton *
|
||||
NodeParamViewKeyframeControl::CreateNewToolButton(const QIcon &icon) const
|
||||
{
|
||||
QPushButton* btn = new QPushButton();
|
||||
btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
btn->setIcon(icon);
|
||||
QPushButton *btn = new QPushButton();
|
||||
btn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
btn->setIcon(icon);
|
||||
|
||||
return btn;
|
||||
return btn;
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::SetButtonsEnabled(bool e)
|
||||
{
|
||||
prev_key_btn_->setEnabled(e);
|
||||
toggle_key_btn_->setEnabled(e);
|
||||
next_key_btn_->setEnabled(e);
|
||||
enable_key_btn_->setEnabled(e);
|
||||
prev_key_btn_->setEnabled(e);
|
||||
toggle_key_btn_->setEnabled(e);
|
||||
next_key_btn_->setEnabled(e);
|
||||
enable_key_btn_->setEnabled(e);
|
||||
}
|
||||
|
||||
rational NodeParamViewKeyframeControl::GetCurrentTimeAsNodeTime() const
|
||||
{
|
||||
return GetAdjustedTime(GetTimeTarget(), input_.node(), GetTimeTarget()->GetPlayhead(), Node::kTransformTowardsInput);
|
||||
return GetAdjustedTime(GetTimeTarget(), input_.node(),
|
||||
GetTimeTarget()->GetPlayhead(),
|
||||
Node::kTransformTowardsInput);
|
||||
}
|
||||
|
||||
rational NodeParamViewKeyframeControl::ConvertToViewerTime(const rational &r) const
|
||||
rational
|
||||
NodeParamViewKeyframeControl::ConvertToViewerTime(const rational &r) const
|
||||
{
|
||||
return GetAdjustedTime(input_.node(), GetTimeTarget(), r, Node::kTransformTowardsOutput);
|
||||
return GetAdjustedTime(input_.node(), GetTimeTarget(), r,
|
||||
Node::kTransformTowardsOutput);
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::ShowButtonsFromKeyframeEnable(bool e)
|
||||
{
|
||||
prev_key_btn_->setVisible(e);
|
||||
toggle_key_btn_->setVisible(e);
|
||||
next_key_btn_->setVisible(e);
|
||||
prev_key_btn_->setVisible(e);
|
||||
toggle_key_btn_->setVisible(e);
|
||||
next_key_btn_->setVisible(e);
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::ToggleKeyframe(bool e)
|
||||
{
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
|
||||
QVector<NodeKeyframe*> keys = input_.node()->GetKeyframesAtTime(input_, node_time);
|
||||
QVector<NodeKeyframe *> keys =
|
||||
input_.node()->GetKeyframesAtTime(input_, node_time);
|
||||
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
int nb_tracks = input_.node()->GetNumberOfKeyframeTracks(input_);
|
||||
int nb_tracks = input_.node()->GetNumberOfKeyframeTracks(input_);
|
||||
|
||||
if (e && keys.isEmpty()) {
|
||||
// Add a keyframe here (one for each track)
|
||||
for (int i=0;i<nb_tracks;i++) {
|
||||
NodeKeyframe* key = new NodeKeyframe(node_time,
|
||||
input_.node()->GetSplitValueAtTimeOnTrack(input_, node_time, i),
|
||||
input_.node()->GetBestKeyframeTypeForTimeOnTrack(input_, node_time, i),
|
||||
i,
|
||||
input_.element(),
|
||||
input_.input());
|
||||
if (e && keys.isEmpty()) {
|
||||
// Add a keyframe here (one for each track)
|
||||
for (int i = 0; i < nb_tracks; i++) {
|
||||
NodeKeyframe *key = new NodeKeyframe(
|
||||
node_time,
|
||||
input_.node()->GetSplitValueAtTimeOnTrack(input_, node_time, i),
|
||||
input_.node()->GetBestKeyframeTypeForTimeOnTrack(input_,
|
||||
node_time, i),
|
||||
i, input_.element(), input_.input());
|
||||
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(input_.node(), key));
|
||||
}
|
||||
} else if (!e && !keys.isEmpty()) {
|
||||
// Remove all keyframes at this time
|
||||
foreach (NodeKeyframe* key, keys) {
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(key));
|
||||
command->add_child(
|
||||
new NodeParamInsertKeyframeCommand(input_.node(), key));
|
||||
}
|
||||
} else if (!e && !keys.isEmpty()) {
|
||||
// Remove all keyframes at this time
|
||||
foreach (NodeKeyframe *key, keys) {
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(key));
|
||||
|
||||
if (input_.node()->GetKeyframeTracks(input_).size() == 1) {
|
||||
// If this was the last keyframe on this track, set the standard value to the value at this time too
|
||||
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(input_, key->track()),
|
||||
input_.node()->GetSplitValueAtTimeOnTrack(input_, node_time, key->track())));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (input_.node()->GetKeyframeTracks(input_).size() == 1) {
|
||||
// If this was the last keyframe on this track, set the standard value to the value at this time too
|
||||
command->add_child(new NodeParamSetStandardValueCommand(
|
||||
NodeKeyframeTrackReference(input_, key->track()),
|
||||
input_.node()->GetSplitValueAtTimeOnTrack(input_, node_time,
|
||||
key->track())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, tr("Toggled Keyframe"));
|
||||
Core::instance()->undo_stack()->push(command, tr("Toggled Keyframe"));
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::UpdateState()
|
||||
{
|
||||
if (!input_.IsValid() || !input_.IsKeyframing() || !GetTimeTarget()) {
|
||||
return;
|
||||
}
|
||||
if (!input_.IsValid() || !input_.IsKeyframing() || !GetTimeTarget()) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeKeyframe* earliest_key = input_.node()->GetEarliestKeyframe(input_);
|
||||
NodeKeyframe* latest_key = input_.node()->GetLatestKeyframe(input_);
|
||||
NodeKeyframe *earliest_key = input_.node()->GetEarliestKeyframe(input_);
|
||||
NodeKeyframe *latest_key = input_.node()->GetLatestKeyframe(input_);
|
||||
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
|
||||
prev_key_btn_->setEnabled(earliest_key && node_time > earliest_key->time());
|
||||
next_key_btn_->setEnabled(latest_key && node_time < latest_key->time());
|
||||
toggle_key_btn_->setChecked(input_.node()->HasKeyframeAtTime(input_, node_time));
|
||||
prev_key_btn_->setEnabled(earliest_key && node_time > earliest_key->time());
|
||||
next_key_btn_->setEnabled(latest_key && node_time < latest_key->time());
|
||||
toggle_key_btn_->setChecked(
|
||||
input_.node()->HasKeyframeAtTime(input_, node_time));
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::GoToPreviousKey()
|
||||
{
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
|
||||
NodeKeyframe* previous_key = input_.node()->GetClosestKeyframeBeforeTime(input_, node_time);
|
||||
NodeKeyframe *previous_key =
|
||||
input_.node()->GetClosestKeyframeBeforeTime(input_, node_time);
|
||||
|
||||
if (previous_key && GetTimeTarget()) {
|
||||
rational key_time = ConvertToViewerTime(previous_key->time());
|
||||
GetTimeTarget()->SetPlayhead(key_time);
|
||||
}
|
||||
if (previous_key && GetTimeTarget()) {
|
||||
rational key_time = ConvertToViewerTime(previous_key->time());
|
||||
GetTimeTarget()->SetPlayhead(key_time);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::GoToNextKey()
|
||||
{
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
rational node_time = GetCurrentTimeAsNodeTime();
|
||||
|
||||
NodeKeyframe* next_key = input_.node()->GetClosestKeyframeAfterTime(input_, node_time);
|
||||
NodeKeyframe *next_key =
|
||||
input_.node()->GetClosestKeyframeAfterTime(input_, node_time);
|
||||
|
||||
if (next_key && GetTimeTarget()) {
|
||||
rational key_time = ConvertToViewerTime(next_key->time());
|
||||
GetTimeTarget()->SetPlayhead(key_time);
|
||||
}
|
||||
if (next_key && GetTimeTarget()) {
|
||||
rational key_time = ConvertToViewerTime(next_key->time());
|
||||
GetTimeTarget()->SetPlayhead(key_time);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::KeyframeEnableBtnClicked(bool e)
|
||||
{
|
||||
if (e == input_.IsKeyframing()) {
|
||||
// No-op
|
||||
return;
|
||||
}
|
||||
if (e == input_.IsKeyframing()) {
|
||||
// No-op
|
||||
return;
|
||||
}
|
||||
|
||||
MultiUndoCommand* command = new MultiUndoCommand();
|
||||
MultiUndoCommand *command = new MultiUndoCommand();
|
||||
|
||||
QString command_name;
|
||||
QString command_name;
|
||||
|
||||
if (e) {
|
||||
// Enable keyframing
|
||||
command->add_child(new NodeParamSetKeyframingCommand(input_, true));
|
||||
if (e) {
|
||||
// Enable keyframing
|
||||
command->add_child(new NodeParamSetKeyframingCommand(input_, true));
|
||||
|
||||
// Create one keyframe across all tracks here
|
||||
const QVector<QVariant>& key_vals = input_.node()->GetSplitStandardValue(input_);
|
||||
// Create one keyframe across all tracks here
|
||||
const QVector<QVariant> &key_vals =
|
||||
input_.node()->GetSplitStandardValue(input_);
|
||||
|
||||
for (int i=0;i<key_vals.size();i++) {
|
||||
NodeKeyframe* key = new NodeKeyframe(GetCurrentTimeAsNodeTime(),
|
||||
key_vals.at(i),
|
||||
NodeKeyframe::kDefaultType,
|
||||
i,
|
||||
input_.element(),
|
||||
input_.input());
|
||||
for (int i = 0; i < key_vals.size(); i++) {
|
||||
NodeKeyframe *key =
|
||||
new NodeKeyframe(GetCurrentTimeAsNodeTime(), key_vals.at(i),
|
||||
NodeKeyframe::kDefaultType, i,
|
||||
input_.element(), input_.input());
|
||||
|
||||
command->add_child(new NodeParamInsertKeyframeCommand(input_.node(), key));
|
||||
}
|
||||
command->add_child(
|
||||
new NodeParamInsertKeyframeCommand(input_.node(), key));
|
||||
}
|
||||
|
||||
command_name = tr("Enabled Keyframing On %1 - %2").arg(input_.node()->GetLabelAndName(), input_.GetInputName());
|
||||
} else {
|
||||
// Confirm the user wants to clear all keyframes
|
||||
if (QMessageBox::warning(this,
|
||||
tr("Warning"),
|
||||
tr("Are you sure you want to disable keyframing on this value? This will clear all existing keyframes."),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
command_name =
|
||||
tr("Enabled Keyframing On %1 - %2")
|
||||
.arg(input_.node()->GetLabelAndName(), input_.GetInputName());
|
||||
} else {
|
||||
// Confirm the user wants to clear all keyframes
|
||||
if (QMessageBox::warning(
|
||||
this, tr("Warning"),
|
||||
tr("Are you sure you want to disable keyframing on this value? This will clear all existing keyframes."),
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
|
||||
// Store value at this time, we'll set this as the persistent value later
|
||||
const QVector<QVariant> &stored_vals =
|
||||
input_.node()->GetSplitValueAtTime(input_,
|
||||
GetCurrentTimeAsNodeTime());
|
||||
|
||||
// Store value at this time, we'll set this as the persistent value later
|
||||
const QVector<QVariant>& stored_vals = input_.node()->GetSplitValueAtTime(input_, GetCurrentTimeAsNodeTime());
|
||||
// Delete all keyframes
|
||||
foreach (const NodeKeyframeTrack &track,
|
||||
input_.node()->GetKeyframeTracks(input_)) {
|
||||
for (int i = track.size() - 1; i >= 0; i--) {
|
||||
command->add_child(
|
||||
new NodeParamRemoveKeyframeCommand(track.at(i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Delete all keyframes
|
||||
foreach (const NodeKeyframeTrack& track, input_.node()->GetKeyframeTracks(input_)) {
|
||||
for (int i=track.size()-1;i>=0;i--) {
|
||||
command->add_child(new NodeParamRemoveKeyframeCommand(track.at(i)));
|
||||
}
|
||||
}
|
||||
// Update standard value
|
||||
for (int i = 0; i < stored_vals.size(); i++) {
|
||||
command->add_child(new NodeParamSetStandardValueCommand(
|
||||
NodeKeyframeTrackReference(input_, i), stored_vals.at(i)));
|
||||
}
|
||||
|
||||
// Update standard value
|
||||
for (int i=0;i<stored_vals.size();i++) {
|
||||
command->add_child(new NodeParamSetStandardValueCommand(NodeKeyframeTrackReference(input_, i), stored_vals.at(i)));
|
||||
}
|
||||
// Disable keyframing
|
||||
command->add_child(
|
||||
new NodeParamSetKeyframingCommand(input_, false));
|
||||
|
||||
// Disable keyframing
|
||||
command->add_child(new NodeParamSetKeyframingCommand(input_, false));
|
||||
command_name = tr("Disabled Keyframing On %1 - %2")
|
||||
.arg(input_.node()->GetLabelAndName(),
|
||||
input_.GetInputName());
|
||||
} else {
|
||||
// Disable action has effectively been ignored
|
||||
enable_key_btn_->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
command_name = tr("Disabled Keyframing On %1 - %2").arg(input_.node()->GetLabelAndName(), input_.GetInputName());
|
||||
} else {
|
||||
// Disable action has effectively been ignored
|
||||
enable_key_btn_->setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
Core::instance()->undo_stack()->push(command, command_name);
|
||||
Core::instance()->undo_stack()->push(command, command_name);
|
||||
}
|
||||
|
||||
void NodeParamViewKeyframeControl::KeyframeEnableChanged(const NodeInput &input, bool e)
|
||||
void NodeParamViewKeyframeControl::KeyframeEnableChanged(const NodeInput &input,
|
||||
bool e)
|
||||
{
|
||||
if (input_ == input) {
|
||||
enable_key_btn_->setChecked(e);
|
||||
}
|
||||
if (input_ == input) {
|
||||
enable_key_btn_->setChecked(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,60 +27,59 @@
|
||||
#include "node/param.h"
|
||||
#include "widget/timetarget/timetarget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewKeyframeControl : public QWidget, public TimeTargetObject
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeParamViewKeyframeControl : public QWidget, public TimeTargetObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewKeyframeControl(bool right_align, QWidget* parent = nullptr);
|
||||
NodeParamViewKeyframeControl(QWidget* parent = nullptr) :
|
||||
NodeParamViewKeyframeControl(true, parent)
|
||||
{
|
||||
}
|
||||
NodeParamViewKeyframeControl(bool right_align, QWidget *parent = nullptr);
|
||||
NodeParamViewKeyframeControl(QWidget *parent = nullptr)
|
||||
: NodeParamViewKeyframeControl(true, parent)
|
||||
{
|
||||
}
|
||||
|
||||
const NodeInput& GetConnectedInput() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
const NodeInput &GetConnectedInput() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
|
||||
void SetInput(const NodeInput& input);
|
||||
void SetInput(const NodeInput &input);
|
||||
|
||||
protected:
|
||||
virtual void TimeTargetDisconnectEvent(ViewerOutput *v) override;
|
||||
virtual void TimeTargetConnectEvent(ViewerOutput *v) override;
|
||||
virtual void TimeTargetDisconnectEvent(ViewerOutput *v) override;
|
||||
virtual void TimeTargetConnectEvent(ViewerOutput *v) override;
|
||||
|
||||
private:
|
||||
QPushButton* CreateNewToolButton(const QIcon &icon) const;
|
||||
QPushButton *CreateNewToolButton(const QIcon &icon) const;
|
||||
|
||||
void SetButtonsEnabled(bool e);
|
||||
void SetButtonsEnabled(bool e);
|
||||
|
||||
rational GetCurrentTimeAsNodeTime() const;
|
||||
rational GetCurrentTimeAsNodeTime() const;
|
||||
|
||||
rational ConvertToViewerTime(const rational& r) const;
|
||||
rational ConvertToViewerTime(const rational &r) const;
|
||||
|
||||
QPushButton* prev_key_btn_;
|
||||
QPushButton* toggle_key_btn_;
|
||||
QPushButton* next_key_btn_;
|
||||
QPushButton* enable_key_btn_;
|
||||
QPushButton *prev_key_btn_;
|
||||
QPushButton *toggle_key_btn_;
|
||||
QPushButton *next_key_btn_;
|
||||
QPushButton *enable_key_btn_;
|
||||
|
||||
NodeInput input_;
|
||||
NodeInput input_;
|
||||
|
||||
private slots:
|
||||
void ShowButtonsFromKeyframeEnable(bool e);
|
||||
void ShowButtonsFromKeyframeEnable(bool e);
|
||||
|
||||
void ToggleKeyframe(bool e);
|
||||
void ToggleKeyframe(bool e);
|
||||
|
||||
void UpdateState();
|
||||
void UpdateState();
|
||||
|
||||
void GoToPreviousKey();
|
||||
void GoToPreviousKey();
|
||||
|
||||
void GoToNextKey();
|
||||
void GoToNextKey();
|
||||
|
||||
void KeyframeEnableBtnClicked(bool e);
|
||||
|
||||
void KeyframeEnableChanged(const NodeInput& input, bool e);
|
||||
void KeyframeEnableBtnClicked(bool e);
|
||||
|
||||
void KeyframeEnableChanged(const NodeInput &input, bool e);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,54 +25,58 @@
|
||||
#include "dialog/text/text.h"
|
||||
#include "ui/icons/icons.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeParamViewTextEdit::NodeParamViewTextEdit(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
namespace olive
|
||||
{
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
line_edit_ = new QPlainTextEdit();
|
||||
line_edit_->setUndoRedoEnabled(true);
|
||||
connect(line_edit_, &QPlainTextEdit::textChanged, this, &NodeParamViewTextEdit::InnerWidgetTextChanged);
|
||||
layout->addWidget(line_edit_);
|
||||
NodeParamViewTextEdit::NodeParamViewTextEdit(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QHBoxLayout *layout = new QHBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
edit_btn_ = new QPushButton();
|
||||
edit_btn_->setIcon(icon::ToolEdit);
|
||||
edit_btn_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
|
||||
layout->addWidget(edit_btn_);
|
||||
connect(edit_btn_, &QPushButton::clicked, this, &NodeParamViewTextEdit::ShowTextDialog);
|
||||
line_edit_ = new QPlainTextEdit();
|
||||
line_edit_->setUndoRedoEnabled(true);
|
||||
connect(line_edit_, &QPlainTextEdit::textChanged, this,
|
||||
&NodeParamViewTextEdit::InnerWidgetTextChanged);
|
||||
layout->addWidget(line_edit_);
|
||||
|
||||
edit_in_viewer_btn_ = new QPushButton(tr("Edit In Viewer"));
|
||||
edit_in_viewer_btn_->setIcon(icon::Pencil);
|
||||
layout->addWidget(edit_in_viewer_btn_);
|
||||
connect(edit_in_viewer_btn_, &QPushButton::clicked, this, &NodeParamViewTextEdit::RequestEditInViewer);
|
||||
edit_btn_ = new QPushButton();
|
||||
edit_btn_->setIcon(icon::ToolEdit);
|
||||
edit_btn_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
|
||||
layout->addWidget(edit_btn_);
|
||||
connect(edit_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewTextEdit::ShowTextDialog);
|
||||
|
||||
SetEditInViewerOnlyMode(false);
|
||||
edit_in_viewer_btn_ = new QPushButton(tr("Edit In Viewer"));
|
||||
edit_in_viewer_btn_->setIcon(icon::Pencil);
|
||||
layout->addWidget(edit_in_viewer_btn_);
|
||||
connect(edit_in_viewer_btn_, &QPushButton::clicked, this,
|
||||
&NodeParamViewTextEdit::RequestEditInViewer);
|
||||
|
||||
SetEditInViewerOnlyMode(false);
|
||||
}
|
||||
|
||||
void NodeParamViewTextEdit::SetEditInViewerOnlyMode(bool on)
|
||||
{
|
||||
line_edit_->setVisible(!on);
|
||||
edit_btn_->setVisible(!on);
|
||||
edit_in_viewer_btn_->setVisible(on);
|
||||
line_edit_->setVisible(!on);
|
||||
edit_btn_->setVisible(!on);
|
||||
edit_in_viewer_btn_->setVisible(on);
|
||||
}
|
||||
|
||||
void NodeParamViewTextEdit::ShowTextDialog()
|
||||
{
|
||||
TextDialog d(this->text(), this);
|
||||
if (d.exec() == QDialog::Accepted) {
|
||||
QString s = d.text();
|
||||
TextDialog d(this->text(), this);
|
||||
if (d.exec() == QDialog::Accepted) {
|
||||
QString s = d.text();
|
||||
|
||||
line_edit_->setPlainText(s);
|
||||
emit textEdited(s);
|
||||
}
|
||||
line_edit_->setPlainText(s);
|
||||
emit textEdited(s);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeParamViewTextEdit::InnerWidgetTextChanged()
|
||||
{
|
||||
emit textEdited(this->text());
|
||||
emit textEdited(this->text());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,60 +27,59 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewTextEdit : public QWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeParamViewTextEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewTextEdit(QWidget* parent = nullptr);
|
||||
NodeParamViewTextEdit(QWidget *parent = nullptr);
|
||||
|
||||
QString text() const
|
||||
{
|
||||
return line_edit_->toPlainText();
|
||||
}
|
||||
QString text() const
|
||||
{
|
||||
return line_edit_->toPlainText();
|
||||
}
|
||||
|
||||
void SetEditInViewerOnlyMode(bool on);
|
||||
void SetEditInViewerOnlyMode(bool on);
|
||||
|
||||
public slots:
|
||||
void setText(const QString &s)
|
||||
{
|
||||
line_edit_->blockSignals(true);
|
||||
line_edit_->setPlainText(s);
|
||||
line_edit_->blockSignals(false);
|
||||
}
|
||||
void setText(const QString &s)
|
||||
{
|
||||
line_edit_->blockSignals(true);
|
||||
line_edit_->setPlainText(s);
|
||||
line_edit_->blockSignals(false);
|
||||
}
|
||||
|
||||
void setTextPreservingCursor(const QString &s)
|
||||
{
|
||||
// Save cursor position
|
||||
int cursor_pos = line_edit_->textCursor().position();
|
||||
void setTextPreservingCursor(const QString &s)
|
||||
{
|
||||
// Save cursor position
|
||||
int cursor_pos = line_edit_->textCursor().position();
|
||||
|
||||
// Set text
|
||||
this->setText(s);
|
||||
// Set text
|
||||
this->setText(s);
|
||||
|
||||
// Get new text cursor
|
||||
QTextCursor c = line_edit_->textCursor();
|
||||
c.setPosition(cursor_pos);
|
||||
line_edit_->setTextCursor(c);
|
||||
}
|
||||
// Get new text cursor
|
||||
QTextCursor c = line_edit_->textCursor();
|
||||
c.setPosition(cursor_pos);
|
||||
line_edit_->setTextCursor(c);
|
||||
}
|
||||
|
||||
signals:
|
||||
void textEdited(const QString &);
|
||||
void textEdited(const QString &);
|
||||
|
||||
void RequestEditInViewer();
|
||||
void RequestEditInViewer();
|
||||
|
||||
private:
|
||||
QPlainTextEdit* line_edit_;
|
||||
QPlainTextEdit *line_edit_;
|
||||
|
||||
QPushButton* edit_btn_;
|
||||
QPushButton *edit_btn_;
|
||||
|
||||
QPushButton *edit_in_viewer_btn_;
|
||||
QPushButton *edit_in_viewer_btn_;
|
||||
|
||||
private slots:
|
||||
void ShowTextDialog();
|
||||
|
||||
void InnerWidgetTextChanged();
|
||||
void ShowTextDialog();
|
||||
|
||||
void InnerWidgetTextChanged();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,98 +27,99 @@
|
||||
#include "widget/slider/base/numericsliderbase.h"
|
||||
#include "widget/timetarget/timetarget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeParamViewScrollBlocker : public QObject
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeParamViewScrollBlocker : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event) override;
|
||||
virtual bool eventFilter(QObject *watched, QEvent *event) override;
|
||||
};
|
||||
|
||||
class NodeParamViewWidgetBridge : public QObject, public TimeTargetObject
|
||||
{
|
||||
Q_OBJECT
|
||||
class NodeParamViewWidgetBridge : public QObject, public TimeTargetObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeParamViewWidgetBridge(NodeInput input, QObject* parent);
|
||||
NodeParamViewWidgetBridge(NodeInput input, QObject *parent);
|
||||
|
||||
const QVector<QWidget*>& widgets() const
|
||||
{
|
||||
return widgets_;
|
||||
}
|
||||
const QVector<QWidget *> &widgets() const
|
||||
{
|
||||
return widgets_;
|
||||
}
|
||||
|
||||
// Set the timebase of certain Timebased widgets
|
||||
void SetTimebase(const rational& timebase);
|
||||
// Set the timebase of certain Timebased widgets
|
||||
void SetTimebase(const rational &timebase);
|
||||
|
||||
signals:
|
||||
void ArrayWidgetDoubleClicked();
|
||||
void ArrayWidgetDoubleClicked();
|
||||
|
||||
void WidgetsRecreated(const NodeInput& input);
|
||||
void WidgetsRecreated(const NodeInput &input);
|
||||
|
||||
void RequestEditTextInViewer();
|
||||
void RequestEditTextInViewer();
|
||||
|
||||
protected:
|
||||
virtual void TimeTargetDisconnectEvent(ViewerOutput *v) override;
|
||||
virtual void TimeTargetConnectEvent(ViewerOutput *v) override;
|
||||
virtual void TimeTargetDisconnectEvent(ViewerOutput *v) override;
|
||||
virtual void TimeTargetConnectEvent(ViewerOutput *v) override;
|
||||
|
||||
private:
|
||||
void CreateWidgets();
|
||||
void CreateWidgets();
|
||||
|
||||
void SetInputValue(const QVariant& value, int track);
|
||||
void SetInputValue(const QVariant &value, int track);
|
||||
|
||||
void SetInputValueInternal(const QVariant& value, int track, MultiUndoCommand *command, bool insert_on_all_tracks_if_no_key);
|
||||
void SetInputValueInternal(const QVariant &value, int track,
|
||||
MultiUndoCommand *command,
|
||||
bool insert_on_all_tracks_if_no_key);
|
||||
|
||||
void ProcessSlider(NumericSliderBase* slider, int slider_track, const QVariant& value);
|
||||
void ProcessSlider(NumericSliderBase* slider, const QVariant& value)
|
||||
{
|
||||
ProcessSlider(slider, widgets_.indexOf(slider), value);
|
||||
}
|
||||
void ProcessSlider(NumericSliderBase *slider, int slider_track,
|
||||
const QVariant &value);
|
||||
void ProcessSlider(NumericSliderBase *slider, const QVariant &value)
|
||||
{
|
||||
ProcessSlider(slider, widgets_.indexOf(slider), value);
|
||||
}
|
||||
|
||||
void SetProperty(const QString &key, const QVariant &value);
|
||||
void SetProperty(const QString &key, const QVariant &value);
|
||||
|
||||
template <typename T>
|
||||
void CreateSliders(int count, QWidget *parent);
|
||||
template <typename T> void CreateSliders(int count, QWidget *parent);
|
||||
|
||||
void UpdateWidgetValues();
|
||||
void UpdateWidgetValues();
|
||||
|
||||
rational GetCurrentTimeAsNodeTime() const;
|
||||
rational GetCurrentTimeAsNodeTime() const;
|
||||
|
||||
const NodeInput &GetOuterInput() const
|
||||
{
|
||||
return input_hierarchy_.first();
|
||||
}
|
||||
const NodeInput &GetOuterInput() const
|
||||
{
|
||||
return input_hierarchy_.first();
|
||||
}
|
||||
|
||||
const NodeInput &GetInnerInput() const
|
||||
{
|
||||
return input_hierarchy_.last();
|
||||
}
|
||||
const NodeInput &GetInnerInput() const
|
||||
{
|
||||
return input_hierarchy_.last();
|
||||
}
|
||||
|
||||
QString GetCommandName() const;
|
||||
QString GetCommandName() const;
|
||||
|
||||
NodeValue::Type GetDataType() const
|
||||
{
|
||||
return GetOuterInput().GetDataType();
|
||||
}
|
||||
NodeValue::Type GetDataType() const
|
||||
{
|
||||
return GetOuterInput().GetDataType();
|
||||
}
|
||||
|
||||
void UpdateProperties();
|
||||
void UpdateProperties();
|
||||
|
||||
QVector<NodeInput> input_hierarchy_;
|
||||
QVector<NodeInput> input_hierarchy_;
|
||||
|
||||
QVector<QWidget*> widgets_;
|
||||
QVector<QWidget *> widgets_;
|
||||
|
||||
NodeInputDragger dragger_;
|
||||
NodeInputDragger dragger_;
|
||||
|
||||
NodeParamViewScrollBlocker scroll_filter_;
|
||||
NodeParamViewScrollBlocker scroll_filter_;
|
||||
|
||||
private slots:
|
||||
void WidgetCallback();
|
||||
void WidgetCallback();
|
||||
|
||||
void InputValueChanged(const NodeInput& input, const TimeRange& range);
|
||||
void InputValueChanged(const NodeInput &input, const TimeRange &range);
|
||||
|
||||
void InputDataTypeChanged(const QString& input, NodeValue::Type type);
|
||||
|
||||
void PropertyChanged(const QString &input, const QString &key, const QVariant &value);
|
||||
void InputDataTypeChanged(const QString &input, NodeValue::Type type);
|
||||
|
||||
void PropertyChanged(const QString &input, const QString &key,
|
||||
const QVariant &value);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,141 +25,142 @@
|
||||
|
||||
#include "node/traverser.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeTableView::NodeTableView(QWidget* parent) :
|
||||
QTreeWidget(parent)
|
||||
namespace olive
|
||||
{
|
||||
setColumnCount(3);
|
||||
setHeaderLabels({tr("Type"),
|
||||
tr("Source"),
|
||||
tr("R/X"),
|
||||
tr("G/Y"),
|
||||
tr("B/Z"),
|
||||
tr("A/W")});
|
||||
|
||||
NodeTableView::NodeTableView(QWidget *parent)
|
||||
: QTreeWidget(parent)
|
||||
{
|
||||
setColumnCount(3);
|
||||
setHeaderLabels({ tr("Type"), tr("Source"), tr("R/X"), tr("G/Y"), tr("B/Z"),
|
||||
tr("A/W") });
|
||||
}
|
||||
|
||||
void NodeTableView::SelectNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
foreach (Node* n, nodes) {
|
||||
QTreeWidgetItem* top_item = new QTreeWidgetItem();
|
||||
top_item->setText(0, n->GetLabelAndName());
|
||||
top_item->setFirstColumnSpanned(true);
|
||||
this->addTopLevelItem(top_item);
|
||||
top_level_item_map_.insert(n, top_item);
|
||||
}
|
||||
foreach (Node *n, nodes) {
|
||||
QTreeWidgetItem *top_item = new QTreeWidgetItem();
|
||||
top_item->setText(0, n->GetLabelAndName());
|
||||
top_item->setFirstColumnSpanned(true);
|
||||
this->addTopLevelItem(top_item);
|
||||
top_level_item_map_.insert(n, top_item);
|
||||
}
|
||||
|
||||
SetTime(last_time_);
|
||||
SetTime(last_time_);
|
||||
}
|
||||
|
||||
void NodeTableView::DeselectNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
foreach (Node* n, nodes) {
|
||||
delete top_level_item_map_.take(n);
|
||||
}
|
||||
foreach (Node *n, nodes) {
|
||||
delete top_level_item_map_.take(n);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTableView::SetTime(const rational &time)
|
||||
{
|
||||
last_time_ = time;
|
||||
last_time_ = time;
|
||||
|
||||
NodeTraverser traverser;
|
||||
NodeTraverser traverser;
|
||||
|
||||
for (auto i=top_level_item_map_.constBegin(); i!=top_level_item_map_.constEnd(); i++) {
|
||||
Node* node = i.key();
|
||||
QTreeWidgetItem* item = i.value();
|
||||
for (auto 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));
|
||||
// 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--;
|
||||
}
|
||||
}
|
||||
// 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
|
||||
for (auto l=db.begin(); l!=db.end(); l++) {
|
||||
const NodeValueTable& table = l.value();
|
||||
// Update all inputs
|
||||
for (auto l = db.begin(); l != db.end(); l++) {
|
||||
const NodeValueTable &table = l.value();
|
||||
|
||||
if (!node->HasInputWithID(l.key())) {
|
||||
// Filters out table entries that aren't inputs (like "global")
|
||||
continue;
|
||||
}
|
||||
if (!node->HasInputWithID(l.key())) {
|
||||
// Filters out table entries that aren't inputs (like "global")
|
||||
continue;
|
||||
}
|
||||
|
||||
QTreeWidgetItem* input_item = nullptr;
|
||||
QTreeWidgetItem *input_item = nullptr;
|
||||
|
||||
for (int j=0; j<item->childCount(); j++) {
|
||||
QTreeWidgetItem* compare = item->child(j);
|
||||
for (int j = 0; j < item->childCount(); j++) {
|
||||
QTreeWidgetItem *compare = item->child(j);
|
||||
|
||||
if (compare->data(0, Qt::UserRole).toString() == l.key()) {
|
||||
input_item = compare;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (compare->data(0, Qt::UserRole).toString() == l.key()) {
|
||||
input_item = compare;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!input_item) {
|
||||
input_item = new QTreeWidgetItem();
|
||||
input_item->setText(0, node->GetInputName(l.key()));
|
||||
input_item->setData(0, Qt::UserRole, l.key());
|
||||
input_item->setFirstColumnSpanned(true);
|
||||
item->addChild(input_item);
|
||||
}
|
||||
if (!input_item) {
|
||||
input_item = new QTreeWidgetItem();
|
||||
input_item->setText(0, node->GetInputName(l.key()));
|
||||
input_item->setData(0, Qt::UserRole, l.key());
|
||||
input_item->setFirstColumnSpanned(true);
|
||||
item->addChild(input_item);
|
||||
}
|
||||
|
||||
// Create children if necessary
|
||||
while (input_item->childCount() < table.Count()) {
|
||||
input_item->addChild(new QTreeWidgetItem());
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// 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);
|
||||
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);
|
||||
// Create item
|
||||
QTreeWidgetItem *sub_item = input_item->child(j);
|
||||
|
||||
// Set data type name
|
||||
sub_item->setText(0, NodeValue::GetPrettyDataTypeName(value.type()));
|
||||
// Set data type name
|
||||
sub_item->setText(
|
||||
0, NodeValue::GetPrettyDataTypeName(value.type()));
|
||||
|
||||
// Determine source
|
||||
QString source_name;
|
||||
if (value.source()) {
|
||||
source_name = value.source()->GetLabelAndName();
|
||||
} else {
|
||||
source_name = tr("(unknown)");
|
||||
}
|
||||
sub_item->setText(1, source_name);
|
||||
// Determine source
|
||||
QString source_name;
|
||||
if (value.source()) {
|
||||
source_name = value.source()->GetLabelAndName();
|
||||
} else {
|
||||
source_name = tr("(unknown)");
|
||||
}
|
||||
sub_item->setText(1, source_name);
|
||||
|
||||
switch (value.type()) {
|
||||
case NodeValue::kVideoParams:
|
||||
case NodeValue::kAudioParams:
|
||||
// These types have no string representation
|
||||
break;
|
||||
case NodeValue::kTexture:
|
||||
{
|
||||
// NodeTraverser puts video params in here
|
||||
for (int k=0;k<VideoParams::kRGBAChannelCount;k++) {
|
||||
this->setItemWidget(sub_item, 2 + k, new QCheckBox());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
QVector<QVariant> split_values = value.to_split_value();
|
||||
for (int k=0;k<split_values.size();k++) {
|
||||
sub_item->setText(2 + k, NodeValue::ValueToString(value.type(), split_values.at(k), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (value.type()) {
|
||||
case NodeValue::kVideoParams:
|
||||
case NodeValue::kAudioParams:
|
||||
// These types have no string representation
|
||||
break;
|
||||
case NodeValue::kTexture: {
|
||||
// NodeTraverser puts video params in here
|
||||
for (int k = 0; k < VideoParams::kRGBAChannelCount; k++) {
|
||||
this->setItemWidget(sub_item, 2 + k, new QCheckBox());
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
QVector<QVariant> split_values = value.to_split_value();
|
||||
for (int k = 0; k < split_values.size(); k++) {
|
||||
sub_item->setText(2 + k, NodeValue::ValueToString(
|
||||
value.type(),
|
||||
split_values.at(k), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,25 +25,24 @@
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeTableView : public QTreeWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeTableView : public QTreeWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeTableView(QWidget* parent = nullptr);
|
||||
NodeTableView(QWidget *parent = nullptr);
|
||||
|
||||
void SelectNodes(const QVector<Node *> &nodes);
|
||||
void SelectNodes(const QVector<Node *> &nodes);
|
||||
|
||||
void DeselectNodes(const QVector<Node*>& nodes);
|
||||
void DeselectNodes(const QVector<Node *> &nodes);
|
||||
|
||||
void SetTime(const rational& time);
|
||||
void SetTime(const rational &time);
|
||||
|
||||
private:
|
||||
QMap<Node*, QTreeWidgetItem*> top_level_item_map_;
|
||||
|
||||
rational last_time_;
|
||||
QMap<Node *, QTreeWidgetItem *> top_level_item_map_;
|
||||
|
||||
rational last_time_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,17 +22,18 @@
|
||||
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeTableWidget::NodeTableWidget(QWidget* parent) :
|
||||
TimeBasedWidget(parent)
|
||||
namespace olive
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
view_ = new NodeTableView();
|
||||
layout->addWidget(view_);
|
||||
NodeTableWidget::NodeTableWidget(QWidget *parent)
|
||||
: TimeBasedWidget(parent)
|
||||
{
|
||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
view_ = new NodeTableView();
|
||||
layout->addWidget(view_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,32 +24,31 @@
|
||||
#include "nodetableview.h"
|
||||
#include "widget/timebased/timebasedwidget.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeTableWidget : public TimeBasedWidget
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeTableWidget : public TimeBasedWidget {
|
||||
public:
|
||||
NodeTableWidget(QWidget* parent = nullptr);
|
||||
NodeTableWidget(QWidget *parent = nullptr);
|
||||
|
||||
void SelectNodes(const QVector<Node*>& nodes)
|
||||
{
|
||||
view_->SelectNodes(nodes);
|
||||
}
|
||||
void SelectNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
view_->SelectNodes(nodes);
|
||||
}
|
||||
|
||||
void DeselectNodes(const QVector<Node*>& nodes)
|
||||
{
|
||||
view_->DeselectNodes(nodes);
|
||||
}
|
||||
void DeselectNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
view_->DeselectNodes(nodes);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void TimeChangedEvent(const rational &time) override
|
||||
{
|
||||
view_->SetTime(time);
|
||||
}
|
||||
virtual void TimeChangedEvent(const rational &time) override
|
||||
{
|
||||
view_->SetTime(time);
|
||||
}
|
||||
|
||||
private:
|
||||
NodeTableView* view_;
|
||||
|
||||
NodeTableView *view_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -22,250 +22,270 @@
|
||||
|
||||
#include <QEvent>
|
||||
|
||||
namespace olive {
|
||||
|
||||
NodeTreeView::NodeTreeView(QWidget *parent) :
|
||||
QTreeWidget(parent),
|
||||
only_show_keyframable_(false),
|
||||
show_keyframe_tracks_as_rows_(false),
|
||||
checkboxes_enabled_(false)
|
||||
namespace olive
|
||||
{
|
||||
connect(this, &NodeTreeView::itemChanged, this, &NodeTreeView::ItemCheckStateChanged);
|
||||
connect(this, &NodeTreeView::itemSelectionChanged, this, &NodeTreeView::SelectionChanged);
|
||||
|
||||
Retranslate();
|
||||
NodeTreeView::NodeTreeView(QWidget *parent)
|
||||
: QTreeWidget(parent)
|
||||
, only_show_keyframable_(false)
|
||||
, show_keyframe_tracks_as_rows_(false)
|
||||
, checkboxes_enabled_(false)
|
||||
{
|
||||
connect(this, &NodeTreeView::itemChanged, this,
|
||||
&NodeTreeView::ItemCheckStateChanged);
|
||||
connect(this, &NodeTreeView::itemSelectionChanged, this,
|
||||
&NodeTreeView::SelectionChanged);
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
bool NodeTreeView::IsNodeEnabled(Node *n) const
|
||||
{
|
||||
return !disabled_nodes_.contains(n);
|
||||
return !disabled_nodes_.contains(n);
|
||||
}
|
||||
|
||||
bool NodeTreeView::IsInputEnabled(const NodeKeyframeTrackReference &ref) const
|
||||
{
|
||||
return !disabled_inputs_.contains(ref);
|
||||
return !disabled_inputs_.contains(ref);
|
||||
}
|
||||
|
||||
void NodeTreeView::SetKeyframeTrackColor(const NodeKeyframeTrackReference &ref, const QColor &color)
|
||||
void NodeTreeView::SetKeyframeTrackColor(const NodeKeyframeTrackReference &ref,
|
||||
const QColor &color)
|
||||
{
|
||||
// Insert into hashmap
|
||||
keyframe_colors_.insert(ref, color);
|
||||
// Insert into hashmap
|
||||
keyframe_colors_.insert(ref, color);
|
||||
|
||||
// If we currently have an item for this, set it
|
||||
QTreeWidgetItem* item = item_map_.value(ref);
|
||||
if (item) {
|
||||
item->setForeground(0, color);
|
||||
}
|
||||
// If we currently have an item for this, set it
|
||||
QTreeWidgetItem *item = item_map_.value(ref);
|
||||
if (item) {
|
||||
item->setForeground(0, color);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTreeView::SetNodes(const QVector<Node *> &nodes)
|
||||
{
|
||||
nodes_ = nodes;
|
||||
nodes_ = nodes;
|
||||
|
||||
this->clear();
|
||||
item_map_.clear();
|
||||
this->clear();
|
||||
item_map_.clear();
|
||||
|
||||
foreach (Node* n, nodes_) {
|
||||
QTreeWidgetItem* node_item = new QTreeWidgetItem();
|
||||
node_item->setText(0, n->Name());
|
||||
if (checkboxes_enabled_) {
|
||||
node_item->setCheckState(0, disabled_nodes_.contains(n) ? Qt::Unchecked : Qt::Checked);
|
||||
}
|
||||
node_item->setData(0, kItemType, kItemTypeNode);
|
||||
node_item->setData(0, kItemNodePointer, QtUtils::PtrToValue(n));
|
||||
foreach (Node *n, nodes_) {
|
||||
QTreeWidgetItem *node_item = new QTreeWidgetItem();
|
||||
node_item->setText(0, n->Name());
|
||||
if (checkboxes_enabled_) {
|
||||
node_item->setCheckState(
|
||||
0, disabled_nodes_.contains(n) ? Qt::Unchecked : Qt::Checked);
|
||||
}
|
||||
node_item->setData(0, kItemType, kItemTypeNode);
|
||||
node_item->setData(0, kItemNodePointer, QtUtils::PtrToValue(n));
|
||||
|
||||
foreach (const QString& input, n->inputs()) {
|
||||
if (n->IsInputHidden(input) || (only_show_keyframable_ && !n->IsInputKeyframable(input))) {
|
||||
continue;
|
||||
}
|
||||
foreach (const QString &input, n->inputs()) {
|
||||
if (n->IsInputHidden(input) ||
|
||||
(only_show_keyframable_ && !n->IsInputKeyframable(input))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QTreeWidgetItem* input_item = nullptr;
|
||||
QTreeWidgetItem *input_item = nullptr;
|
||||
|
||||
int arr_sz = n->InputArraySize(input);
|
||||
for (int i=-1; i<arr_sz; i++) {
|
||||
NodeInput input_ref(n, input, i);
|
||||
const QVector<NodeKeyframeTrack>& key_tracks = n->GetKeyframeTracks(input_ref);
|
||||
int arr_sz = n->InputArraySize(input);
|
||||
for (int i = -1; i < arr_sz; i++) {
|
||||
NodeInput input_ref(n, input, i);
|
||||
const QVector<NodeKeyframeTrack> &key_tracks =
|
||||
n->GetKeyframeTracks(input_ref);
|
||||
|
||||
int this_element_track;
|
||||
int this_element_track;
|
||||
|
||||
if (show_keyframe_tracks_as_rows_
|
||||
&& (key_tracks.size() == 1 || (i == -1 && n->InputIsArray(input)))) {
|
||||
this_element_track = 0;
|
||||
} else {
|
||||
this_element_track = -1;
|
||||
}
|
||||
if (show_keyframe_tracks_as_rows_ &&
|
||||
(key_tracks.size() == 1 ||
|
||||
(i == -1 && n->InputIsArray(input)))) {
|
||||
this_element_track = 0;
|
||||
} else {
|
||||
this_element_track = -1;
|
||||
}
|
||||
|
||||
QTreeWidgetItem* element_item;
|
||||
QTreeWidgetItem *element_item;
|
||||
|
||||
if (input_item) {
|
||||
element_item = CreateItem(input_item, NodeKeyframeTrackReference(input_ref, this_element_track));
|
||||
} else {
|
||||
input_item = CreateItem(node_item, NodeKeyframeTrackReference(input_ref, this_element_track));
|
||||
element_item = input_item;
|
||||
}
|
||||
if (input_item) {
|
||||
element_item = CreateItem(
|
||||
input_item, NodeKeyframeTrackReference(
|
||||
input_ref, this_element_track));
|
||||
} else {
|
||||
input_item = CreateItem(node_item,
|
||||
NodeKeyframeTrackReference(
|
||||
input_ref, this_element_track));
|
||||
element_item = input_item;
|
||||
}
|
||||
|
||||
if (show_keyframe_tracks_as_rows_ && key_tracks.size() > 1 && (!n->InputIsArray(input) || i >= 0)) {
|
||||
CreateItemsForTracks(element_item, input_ref, key_tracks.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (show_keyframe_tracks_as_rows_ && key_tracks.size() > 1 &&
|
||||
(!n->InputIsArray(input) || i >= 0)) {
|
||||
CreateItemsForTracks(element_item, input_ref,
|
||||
key_tracks.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add at the end to prevent unnecessary signalling while we're setting these objects up
|
||||
if (node_item->childCount() > 0) {
|
||||
this->addTopLevelItem(node_item);
|
||||
} else {
|
||||
delete node_item;
|
||||
}
|
||||
}
|
||||
// Add at the end to prevent unnecessary signalling while we're setting these objects up
|
||||
if (node_item->childCount() > 0) {
|
||||
this->addTopLevelItem(node_item);
|
||||
} else {
|
||||
delete node_item;
|
||||
}
|
||||
}
|
||||
|
||||
expandAll();
|
||||
expandAll();
|
||||
}
|
||||
|
||||
void NodeTreeView::changeEvent(QEvent *e)
|
||||
{
|
||||
QTreeWidget::changeEvent(e);
|
||||
QTreeWidget::changeEvent(e);
|
||||
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTreeView::mouseDoubleClickEvent(QMouseEvent *e)
|
||||
{
|
||||
QTreeWidget::mouseDoubleClickEvent(e);
|
||||
QTreeWidget::mouseDoubleClickEvent(e);
|
||||
|
||||
NodeKeyframeTrackReference ref = GetSelectedInput();
|
||||
NodeKeyframeTrackReference ref = GetSelectedInput();
|
||||
|
||||
if (ref.input().IsValid()) {
|
||||
emit InputDoubleClicked(ref);
|
||||
}
|
||||
if (ref.input().IsValid()) {
|
||||
emit InputDoubleClicked(ref);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTreeView::Retranslate()
|
||||
{
|
||||
setHeaderLabel(tr("Nodes"));
|
||||
setHeaderLabel(tr("Nodes"));
|
||||
}
|
||||
|
||||
NodeKeyframeTrackReference NodeTreeView::GetSelectedInput()
|
||||
{
|
||||
QList<QTreeWidgetItem*> sel = selectedItems();
|
||||
QList<QTreeWidgetItem *> sel = selectedItems();
|
||||
|
||||
NodeKeyframeTrackReference selected_ref;
|
||||
NodeKeyframeTrackReference selected_ref;
|
||||
|
||||
if (!sel.isEmpty()) {
|
||||
QTreeWidgetItem* item = sel.first();
|
||||
if (!sel.isEmpty()) {
|
||||
QTreeWidgetItem *item = sel.first();
|
||||
|
||||
if (item->data(0, kItemType).toInt() == kItemTypeInput) {
|
||||
selected_ref = item->data(0, kItemInputReference).value<NodeKeyframeTrackReference>();
|
||||
} else {
|
||||
selected_ref = NodeKeyframeTrackReference(NodeInput(QtUtils::ValueToPtr<Node>(item->data(0, kItemNodePointer)), QString()));
|
||||
}
|
||||
}
|
||||
if (item->data(0, kItemType).toInt() == kItemTypeInput) {
|
||||
selected_ref = item->data(0, kItemInputReference)
|
||||
.value<NodeKeyframeTrackReference>();
|
||||
} else {
|
||||
selected_ref = NodeKeyframeTrackReference(NodeInput(
|
||||
QtUtils::ValueToPtr<Node>(item->data(0, kItemNodePointer)),
|
||||
QString()));
|
||||
}
|
||||
}
|
||||
|
||||
return selected_ref;
|
||||
return selected_ref;
|
||||
}
|
||||
|
||||
QTreeWidgetItem* NodeTreeView::CreateItem(QTreeWidgetItem *parent, const NodeKeyframeTrackReference& ref)
|
||||
QTreeWidgetItem *NodeTreeView::CreateItem(QTreeWidgetItem *parent,
|
||||
const NodeKeyframeTrackReference &ref)
|
||||
{
|
||||
QTreeWidgetItem* input_item = new QTreeWidgetItem(parent);
|
||||
QTreeWidgetItem *input_item = new QTreeWidgetItem(parent);
|
||||
|
||||
QString item_name;
|
||||
if (ref.track() == -1
|
||||
|| NodeValue::get_number_of_keyframe_tracks(ref.input().GetDataType()) == 1
|
||||
|| (ref.input().IsArray() && ref.input().element() == -1)) {
|
||||
if (ref.input().element() == -1) {
|
||||
item_name = ref.input().name();
|
||||
} else {
|
||||
item_name = QString::number(ref.input().element());
|
||||
}
|
||||
} else {
|
||||
switch (ref.track()) {
|
||||
case 0:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("R") : tr("X");
|
||||
break;
|
||||
case 1:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("G") : tr("Y");
|
||||
break;
|
||||
case 2:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("B") : tr("Z");
|
||||
break;
|
||||
case 3:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("A") : tr("W");
|
||||
break;
|
||||
default:
|
||||
item_name = QString::number(ref.track());
|
||||
}
|
||||
}
|
||||
input_item->setText(0, item_name);
|
||||
QString item_name;
|
||||
if (ref.track() == -1 ||
|
||||
NodeValue::get_number_of_keyframe_tracks(ref.input().GetDataType()) ==
|
||||
1 ||
|
||||
(ref.input().IsArray() && ref.input().element() == -1)) {
|
||||
if (ref.input().element() == -1) {
|
||||
item_name = ref.input().name();
|
||||
} else {
|
||||
item_name = QString::number(ref.input().element());
|
||||
}
|
||||
} else {
|
||||
switch (ref.track()) {
|
||||
case 0:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("R") : tr("X");
|
||||
break;
|
||||
case 1:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("G") : tr("Y");
|
||||
break;
|
||||
case 2:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("B") : tr("Z");
|
||||
break;
|
||||
case 3:
|
||||
item_name = UseRGBAOverXYZW(ref) ? tr("A") : tr("W");
|
||||
break;
|
||||
default:
|
||||
item_name = QString::number(ref.track());
|
||||
}
|
||||
}
|
||||
input_item->setText(0, item_name);
|
||||
|
||||
if (checkboxes_enabled_) {
|
||||
input_item->setCheckState(0, disabled_inputs_.contains(ref) ? Qt::Unchecked : Qt::Checked);
|
||||
}
|
||||
input_item->setData(0, kItemType, kItemTypeInput);
|
||||
input_item->setData(0, kItemInputReference, QVariant::fromValue(ref));
|
||||
if (checkboxes_enabled_) {
|
||||
input_item->setCheckState(
|
||||
0, disabled_inputs_.contains(ref) ? Qt::Unchecked : Qt::Checked);
|
||||
}
|
||||
input_item->setData(0, kItemType, kItemTypeInput);
|
||||
input_item->setData(0, kItemInputReference, QVariant::fromValue(ref));
|
||||
|
||||
if (keyframe_colors_.contains(ref)) {
|
||||
input_item->setForeground(0, keyframe_colors_.value(ref));
|
||||
}
|
||||
if (keyframe_colors_.contains(ref)) {
|
||||
input_item->setForeground(0, keyframe_colors_.value(ref));
|
||||
}
|
||||
|
||||
item_map_.insert(ref, input_item);
|
||||
item_map_.insert(ref, input_item);
|
||||
|
||||
return input_item;
|
||||
return input_item;
|
||||
}
|
||||
|
||||
void NodeTreeView::CreateItemsForTracks(QTreeWidgetItem *parent, const NodeInput& input, int track_count)
|
||||
void NodeTreeView::CreateItemsForTracks(QTreeWidgetItem *parent,
|
||||
const NodeInput &input, int track_count)
|
||||
{
|
||||
for (int j=0; j<track_count; j++) {
|
||||
CreateItem(parent, NodeKeyframeTrackReference(input, j));
|
||||
}
|
||||
for (int j = 0; j < track_count; j++) {
|
||||
CreateItem(parent, NodeKeyframeTrackReference(input, j));
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeTreeView::UseRGBAOverXYZW(const NodeKeyframeTrackReference &ref)
|
||||
{
|
||||
return ref.input().GetDataType() == NodeValue::kColor;
|
||||
return ref.input().GetDataType() == NodeValue::kColor;
|
||||
}
|
||||
|
||||
void NodeTreeView::ItemCheckStateChanged(QTreeWidgetItem *item, int column)
|
||||
{
|
||||
Q_UNUSED(column)
|
||||
Q_UNUSED(column)
|
||||
|
||||
switch (item->data(0, kItemType).toInt()) {
|
||||
case kItemTypeNode:
|
||||
{
|
||||
Node* n = QtUtils::ValueToPtr<Node>(item->data(0, kItemNodePointer));
|
||||
switch (item->data(0, kItemType).toInt()) {
|
||||
case kItemTypeNode: {
|
||||
Node *n = QtUtils::ValueToPtr<Node>(item->data(0, kItemNodePointer));
|
||||
|
||||
if (item->checkState(0) == Qt::Checked) {
|
||||
if (disabled_nodes_.contains(n)) {
|
||||
disabled_nodes_.removeOne(n);
|
||||
emit NodeEnableChanged(n, true);
|
||||
}
|
||||
} else if (!disabled_nodes_.contains(n)) {
|
||||
disabled_nodes_.append(n);
|
||||
emit NodeEnableChanged(n, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kItemTypeInput:
|
||||
{
|
||||
NodeKeyframeTrackReference i = item->data(0, kItemInputReference).value<NodeKeyframeTrackReference>();
|
||||
if (item->checkState(0) == Qt::Checked) {
|
||||
if (disabled_nodes_.contains(n)) {
|
||||
disabled_nodes_.removeOne(n);
|
||||
emit NodeEnableChanged(n, true);
|
||||
}
|
||||
} else if (!disabled_nodes_.contains(n)) {
|
||||
disabled_nodes_.append(n);
|
||||
emit NodeEnableChanged(n, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case kItemTypeInput: {
|
||||
NodeKeyframeTrackReference i = item->data(0, kItemInputReference)
|
||||
.value<NodeKeyframeTrackReference>();
|
||||
|
||||
if (item->checkState(0) == Qt::Checked) {
|
||||
if (disabled_inputs_.contains(i)) {
|
||||
disabled_inputs_.removeOne(i);
|
||||
emit InputEnableChanged(i, true);
|
||||
}
|
||||
} else if (!disabled_inputs_.contains(i)) {
|
||||
disabled_inputs_.append(i);
|
||||
emit InputEnableChanged(i, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (item->checkState(0) == Qt::Checked) {
|
||||
if (disabled_inputs_.contains(i)) {
|
||||
disabled_inputs_.removeOne(i);
|
||||
emit InputEnableChanged(i, true);
|
||||
}
|
||||
} else if (!disabled_inputs_.contains(i)) {
|
||||
disabled_inputs_.append(i);
|
||||
emit InputEnableChanged(i, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeTreeView::SelectionChanged()
|
||||
{
|
||||
emit InputSelectionChanged(GetSelectedInput());
|
||||
emit InputSelectionChanged(GetSelectedInput());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,93 +25,92 @@
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeTreeView : public QTreeWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeTreeView : public QTreeWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeTreeView(QWidget *parent = nullptr);
|
||||
NodeTreeView(QWidget *parent = nullptr);
|
||||
|
||||
bool IsNodeEnabled(Node* n) const;
|
||||
bool IsNodeEnabled(Node *n) const;
|
||||
|
||||
bool IsInputEnabled(const NodeKeyframeTrackReference& ref) const;
|
||||
bool IsInputEnabled(const NodeKeyframeTrackReference &ref) const;
|
||||
|
||||
void SetCheckBoxesEnabled(bool e)
|
||||
{
|
||||
checkboxes_enabled_ = e;
|
||||
}
|
||||
void SetCheckBoxesEnabled(bool e)
|
||||
{
|
||||
checkboxes_enabled_ = e;
|
||||
}
|
||||
|
||||
void SetKeyframeTrackColor(const NodeKeyframeTrackReference& ref, const QColor& color);
|
||||
void SetKeyframeTrackColor(const NodeKeyframeTrackReference &ref,
|
||||
const QColor &color);
|
||||
|
||||
void SetOnlyShowKeyframable(bool e)
|
||||
{
|
||||
only_show_keyframable_ = e;
|
||||
}
|
||||
void SetOnlyShowKeyframable(bool e)
|
||||
{
|
||||
only_show_keyframable_ = e;
|
||||
}
|
||||
|
||||
void SetShowKeyframeTracksAsRows(bool e)
|
||||
{
|
||||
show_keyframe_tracks_as_rows_ = e;
|
||||
}
|
||||
void SetShowKeyframeTracksAsRows(bool e)
|
||||
{
|
||||
show_keyframe_tracks_as_rows_ = e;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetNodes(const QVector<Node *> &nodes);
|
||||
void SetNodes(const QVector<Node *> &nodes);
|
||||
|
||||
signals:
|
||||
void NodeEnableChanged(Node* n, bool e);
|
||||
void NodeEnableChanged(Node *n, bool e);
|
||||
|
||||
void InputEnableChanged(const NodeKeyframeTrackReference& ref, bool e);
|
||||
void InputEnableChanged(const NodeKeyframeTrackReference &ref, bool e);
|
||||
|
||||
void InputSelectionChanged(const NodeKeyframeTrackReference& ref);
|
||||
void InputSelectionChanged(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void InputDoubleClicked(const NodeKeyframeTrackReference& ref);
|
||||
void InputDoubleClicked(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent* e) override;
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* e) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *e) override;
|
||||
|
||||
private:
|
||||
void Retranslate();
|
||||
void Retranslate();
|
||||
|
||||
NodeKeyframeTrackReference GetSelectedInput();
|
||||
NodeKeyframeTrackReference GetSelectedInput();
|
||||
|
||||
QTreeWidgetItem *CreateItem(QTreeWidgetItem* parent, const NodeKeyframeTrackReference& ref);
|
||||
QTreeWidgetItem *CreateItem(QTreeWidgetItem *parent,
|
||||
const NodeKeyframeTrackReference &ref);
|
||||
|
||||
void CreateItemsForTracks(QTreeWidgetItem* parent, const NodeInput& input, int track_count);
|
||||
void CreateItemsForTracks(QTreeWidgetItem *parent, const NodeInput &input,
|
||||
int track_count);
|
||||
|
||||
static bool UseRGBAOverXYZW(const NodeKeyframeTrackReference &ref);
|
||||
static bool UseRGBAOverXYZW(const NodeKeyframeTrackReference &ref);
|
||||
|
||||
enum ItemType {
|
||||
kItemTypeNode,
|
||||
kItemTypeInput
|
||||
};
|
||||
enum ItemType { kItemTypeNode, kItemTypeInput };
|
||||
|
||||
static const int kItemType = Qt::UserRole;
|
||||
static const int kItemInputReference = Qt::UserRole + 1;
|
||||
static const int kItemNodePointer = Qt::UserRole + 1;
|
||||
static const int kItemType = Qt::UserRole;
|
||||
static const int kItemInputReference = Qt::UserRole + 1;
|
||||
static const int kItemNodePointer = Qt::UserRole + 1;
|
||||
|
||||
QVector<Node*> nodes_;
|
||||
QVector<Node *> nodes_;
|
||||
|
||||
QVector<Node*> disabled_nodes_;
|
||||
QVector<Node *> disabled_nodes_;
|
||||
|
||||
QVector<NodeKeyframeTrackReference> disabled_inputs_;
|
||||
QVector<NodeKeyframeTrackReference> disabled_inputs_;
|
||||
|
||||
QHash<NodeKeyframeTrackReference, QTreeWidgetItem*> item_map_;
|
||||
QHash<NodeKeyframeTrackReference, QTreeWidgetItem *> item_map_;
|
||||
|
||||
bool only_show_keyframable_;
|
||||
bool only_show_keyframable_;
|
||||
|
||||
bool show_keyframe_tracks_as_rows_;
|
||||
bool show_keyframe_tracks_as_rows_;
|
||||
|
||||
QHash<NodeKeyframeTrackReference, QColor> keyframe_colors_;
|
||||
QHash<NodeKeyframeTrackReference, QColor> keyframe_colors_;
|
||||
|
||||
bool checkboxes_enabled_;
|
||||
bool checkboxes_enabled_;
|
||||
|
||||
private slots:
|
||||
void ItemCheckStateChanged(QTreeWidgetItem* item, int column);
|
||||
|
||||
void SelectionChanged();
|
||||
void ItemCheckStateChanged(QTreeWidgetItem *item, int column);
|
||||
|
||||
void SelectionChanged();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,82 +4,88 @@
|
||||
|
||||
#include "node/traverser.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QTreeWidget
|
||||
|
||||
NodeValueTree::NodeValueTree(QWidget *parent) :
|
||||
super(parent)
|
||||
NodeValueTree::NodeValueTree(QWidget *parent)
|
||||
: super(parent)
|
||||
{
|
||||
setColumnWidth(0, 0);
|
||||
setColumnCount(4);
|
||||
setColumnWidth(0, 0);
|
||||
setColumnCount(4);
|
||||
|
||||
QSizePolicy p = sizePolicy();
|
||||
p.setHorizontalStretch(1);
|
||||
setSizePolicy(p);
|
||||
QSizePolicy p = sizePolicy();
|
||||
p.setHorizontalStretch(1);
|
||||
setSizePolicy(p);
|
||||
|
||||
static const int kMinimumRows = 10;
|
||||
setMinimumHeight(fontMetrics().height() * kMinimumRows);
|
||||
static const int kMinimumRows = 10;
|
||||
setMinimumHeight(fontMetrics().height() * kMinimumRows);
|
||||
|
||||
Retranslate();
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
void NodeValueTree::SetNode(const NodeInput &input, const rational &time)
|
||||
{
|
||||
clear();
|
||||
clear();
|
||||
|
||||
NodeTraverser traverser;
|
||||
NodeTraverser traverser;
|
||||
|
||||
Node *connected_node = input.GetConnectedOutput();
|
||||
Node *connected_node = input.GetConnectedOutput();
|
||||
|
||||
NodeValueTable table = traverser.GenerateTable(connected_node, TimeRange(time, time));
|
||||
NodeValueTable table =
|
||||
traverser.GenerateTable(connected_node, TimeRange(time, time));
|
||||
|
||||
int index = traverser.GenerateRowValueElementIndex(input.node(), input.input(), input.element(), &table);
|
||||
int index = traverser.GenerateRowValueElementIndex(
|
||||
input.node(), input.input(), input.element(), &table);
|
||||
|
||||
for (int i=0; i<table.Count(); i++) {
|
||||
const NodeValue &value = table.at(i);
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(this);
|
||||
for (int i = 0; i < table.Count(); i++) {
|
||||
const NodeValue &value = table.at(i);
|
||||
QTreeWidgetItem *item = new QTreeWidgetItem(this);
|
||||
|
||||
Node::ValueHint hint({value.type()}, table.Count()-1-i, value.tag());
|
||||
Node::ValueHint hint({ value.type() }, table.Count() - 1 - i,
|
||||
value.tag());
|
||||
|
||||
QRadioButton *radio = new QRadioButton(this);
|
||||
radio->setProperty("input", QVariant::fromValue(input));
|
||||
radio->setProperty("hint", QVariant::fromValue(hint));
|
||||
if (i == index) {
|
||||
radio->setChecked(true);
|
||||
}
|
||||
connect(radio, &QRadioButton::clicked, this, &NodeValueTree::RadioButtonChecked);
|
||||
QRadioButton *radio = new QRadioButton(this);
|
||||
radio->setProperty("input", QVariant::fromValue(input));
|
||||
radio->setProperty("hint", QVariant::fromValue(hint));
|
||||
if (i == index) {
|
||||
radio->setChecked(true);
|
||||
}
|
||||
connect(radio, &QRadioButton::clicked, this,
|
||||
&NodeValueTree::RadioButtonChecked);
|
||||
|
||||
setItemWidget(item, 0, radio);
|
||||
item->setText(1, NodeValue::GetPrettyDataTypeName(value.type()));
|
||||
item->setText(2, NodeValue::ValueToString(value, false));
|
||||
item->setText(3, value.source()->GetLabelAndName());
|
||||
}
|
||||
setItemWidget(item, 0, radio);
|
||||
item->setText(1, NodeValue::GetPrettyDataTypeName(value.type()));
|
||||
item->setText(2, NodeValue::ValueToString(value, false));
|
||||
item->setText(3, value.source()->GetLabelAndName());
|
||||
}
|
||||
}
|
||||
|
||||
void NodeValueTree::changeEvent(QEvent *event)
|
||||
{
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
if (event->type() == QEvent::LanguageChange) {
|
||||
Retranslate();
|
||||
}
|
||||
|
||||
super::changeEvent(event);
|
||||
super::changeEvent(event);
|
||||
}
|
||||
|
||||
void NodeValueTree::Retranslate()
|
||||
{
|
||||
setHeaderLabels({QString(), tr("Type"), tr("Value"), tr("Source")});
|
||||
setHeaderLabels({ QString(), tr("Type"), tr("Value"), tr("Source") });
|
||||
}
|
||||
|
||||
void NodeValueTree::RadioButtonChecked(bool e)
|
||||
{
|
||||
if (e) {
|
||||
QRadioButton *btn = static_cast<QRadioButton*>(sender());
|
||||
Node::ValueHint hint = btn->property("hint").value<Node::ValueHint>();
|
||||
NodeInput input = btn->property("input").value<NodeInput>();
|
||||
if (e) {
|
||||
QRadioButton *btn = static_cast<QRadioButton *>(sender());
|
||||
Node::ValueHint hint = btn->property("hint").value<Node::ValueHint>();
|
||||
NodeInput input = btn->property("input").value<NodeInput>();
|
||||
|
||||
input.node()->SetValueHintForInput(input.input(), hint, input.element());
|
||||
}
|
||||
input.node()->SetValueHintForInput(input.input(), hint,
|
||||
input.element());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,25 +6,24 @@
|
||||
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeValueTree : public QTreeWidget
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeValueTree(QWidget *parent = nullptr);
|
||||
|
||||
void SetNode(const NodeInput &input, const rational &time);
|
||||
class NodeValueTree : public QTreeWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeValueTree(QWidget *parent = nullptr);
|
||||
|
||||
void SetNode(const NodeInput &input, const rational &time);
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *event) override;
|
||||
virtual void changeEvent(QEvent *event) override;
|
||||
|
||||
private:
|
||||
void Retranslate();
|
||||
void Retranslate();
|
||||
|
||||
private slots:
|
||||
void RadioButtonChecked(bool e);
|
||||
|
||||
void RadioButtonChecked(bool e);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
+1296
-1155
File diff suppressed because it is too large
Load Diff
+149
-143
@@ -33,7 +33,8 @@
|
||||
#include "widget/handmovableview/handmovableview.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief A widget for viewing and editing node graphs
|
||||
@@ -41,248 +42,253 @@ namespace olive {
|
||||
* This widget takes a NodeGraph object and constructs a QGraphicsScene representing its data, viewing and allowing
|
||||
* the user to make modifications to it.
|
||||
*/
|
||||
class NodeView : public HandMovableView
|
||||
{
|
||||
Q_OBJECT
|
||||
class NodeView : public HandMovableView {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeView(QWidget* parent = nullptr);
|
||||
NodeView(QWidget *parent = nullptr);
|
||||
|
||||
virtual ~NodeView() override;
|
||||
virtual ~NodeView() override;
|
||||
|
||||
void SetContexts(const QVector<Node *> &nodes);
|
||||
void SetContexts(const QVector<Node *> &nodes);
|
||||
|
||||
const QVector<Node*> &GetContexts() const
|
||||
{
|
||||
if (overlay_view_) {
|
||||
return overlay_view_->GetContexts();
|
||||
} else {
|
||||
return contexts_;
|
||||
}
|
||||
}
|
||||
const QVector<Node *> &GetContexts() const
|
||||
{
|
||||
if (overlay_view_) {
|
||||
return overlay_view_->GetContexts();
|
||||
} else {
|
||||
return contexts_;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsGroupOverlay() const
|
||||
{
|
||||
return overlay_view_;
|
||||
}
|
||||
bool IsGroupOverlay() const
|
||||
{
|
||||
return overlay_view_;
|
||||
}
|
||||
|
||||
void CloseContextsBelongingToProject(Project *project);
|
||||
void CloseContextsBelongingToProject(Project *project);
|
||||
|
||||
void ClearGraph();
|
||||
void ClearGraph();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Delete selected nodes from graph (user-friendly/undoable)
|
||||
*/
|
||||
void DeleteSelected();
|
||||
void DeleteSelected();
|
||||
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
void SelectAll();
|
||||
void DeselectAll();
|
||||
|
||||
void Select(const QVector<Node::ContextPair> &nodes, bool center_view_on_item);
|
||||
void Select(const QVector<Node::ContextPair> &nodes,
|
||||
bool center_view_on_item);
|
||||
|
||||
void CopySelected(bool cut);
|
||||
void Paste();
|
||||
void CopySelected(bool cut);
|
||||
void Paste();
|
||||
|
||||
void Duplicate();
|
||||
void Duplicate();
|
||||
|
||||
void SetColorLabel(int index);
|
||||
void SetColorLabel(int index);
|
||||
|
||||
void ZoomIn();
|
||||
void ZoomIn();
|
||||
|
||||
void ZoomOut();
|
||||
void ZoomOut();
|
||||
|
||||
const QVector<Node*> &GetCurrentContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
const QVector<Node *> &GetCurrentContexts() const
|
||||
{
|
||||
return contexts_;
|
||||
}
|
||||
|
||||
public slots:
|
||||
void SetMiniMapEnabled(bool e)
|
||||
{
|
||||
minimap_->setVisible(e);
|
||||
}
|
||||
void SetMiniMapEnabled(bool e)
|
||||
{
|
||||
minimap_->setVisible(e);
|
||||
}
|
||||
|
||||
void ShowAddMenu()
|
||||
{
|
||||
Menu *m = CreateAddMenu(nullptr);
|
||||
m->exec(QCursor::pos());
|
||||
delete m;
|
||||
}
|
||||
void ShowAddMenu()
|
||||
{
|
||||
Menu *m = CreateAddMenu(nullptr);
|
||||
m->exec(QCursor::pos());
|
||||
delete m;
|
||||
}
|
||||
|
||||
void CenterOnItemsBoundingRect();
|
||||
void CenterOnItemsBoundingRect();
|
||||
|
||||
void CenterOnNode(olive::Node *n);
|
||||
void CenterOnNode(olive::Node *n);
|
||||
|
||||
void LabelSelectedNodes();
|
||||
void LabelSelectedNodes();
|
||||
|
||||
signals:
|
||||
void NodesSelected(const QVector<Node*>& nodes);
|
||||
void NodesSelected(const QVector<Node *> &nodes);
|
||||
|
||||
void NodesDeselected(const QVector<Node*>& nodes);
|
||||
void NodesDeselected(const QVector<Node *> &nodes);
|
||||
|
||||
void NodeSelectionChanged(const QVector<Node*>& nodes);
|
||||
void NodeSelectionChangedWithContexts(const QVector<Node::ContextPair>& nodes);
|
||||
void NodeSelectionChanged(const QVector<Node *> &nodes);
|
||||
void
|
||||
NodeSelectionChangedWithContexts(const QVector<Node::ContextPair> &nodes);
|
||||
|
||||
void NodeGroupOpened(NodeGroup *group);
|
||||
void NodeGroupClosed();
|
||||
void NodeGroupOpened(NodeGroup *group);
|
||||
void NodeGroupClosed();
|
||||
|
||||
void EscPressed();
|
||||
void EscPressed();
|
||||
|
||||
protected:
|
||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
virtual void keyPressEvent(QKeyEvent *event) override;
|
||||
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent* event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent* event) override;
|
||||
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
virtual void dropEvent(QDropEvent *event) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
virtual void dragEnterEvent(QDragEnterEvent *event) override;
|
||||
virtual void dragMoveEvent(QDragMoveEvent *event) override;
|
||||
virtual void dropEvent(QDropEvent *event) override;
|
||||
virtual void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier, const QPointF &cursor_pos) override;
|
||||
virtual void ZoomIntoCursorPosition(QWheelEvent *event, double multiplier,
|
||||
const QPointF &cursor_pos) override;
|
||||
|
||||
virtual bool event(QEvent *event) override;
|
||||
virtual bool event(QEvent *event) override;
|
||||
|
||||
virtual bool eventFilter(QObject *object, QEvent *event) override;
|
||||
virtual bool eventFilter(QObject *object, QEvent *event) override;
|
||||
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
virtual void changeEvent(QEvent *e) override;
|
||||
|
||||
private:
|
||||
void DetachItemsFromCursor(bool delete_nodes_too = true);
|
||||
void DetachItemsFromCursor(bool delete_nodes_too = true);
|
||||
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
|
||||
void MoveAttachedNodesToCursor(const QPoint &p);
|
||||
void ProcessMovingAttachedNodes(const QPoint &pos);
|
||||
QVector<Node*> ProcessDroppingAttachedNodes(MultiUndoCommand *command, Node *select_context, const QPoint &pos);
|
||||
Node *GetContextAtMousePos(const QPoint &p);
|
||||
void MoveAttachedNodesToCursor(const QPoint &p);
|
||||
void ProcessMovingAttachedNodes(const QPoint &pos);
|
||||
QVector<Node *> ProcessDroppingAttachedNodes(MultiUndoCommand *command,
|
||||
Node *select_context,
|
||||
const QPoint &pos);
|
||||
Node *GetContextAtMousePos(const QPoint &p);
|
||||
|
||||
void ConnectSelectionChangedSignal();
|
||||
void DisconnectSelectionChangedSignal();
|
||||
void ConnectSelectionChangedSignal();
|
||||
void DisconnectSelectionChangedSignal();
|
||||
|
||||
void ZoomFromKeyboard(double multiplier);
|
||||
void ZoomFromKeyboard(double multiplier);
|
||||
|
||||
void ClearCreateEdgeInputIfNecessary();
|
||||
void ClearCreateEdgeInputIfNecessary();
|
||||
|
||||
QPointF GetEstimatedPositionForContext(NodeViewItem *item, Node *context) const;
|
||||
QPointF GetEstimatedPositionForContext(NodeViewItem *item,
|
||||
Node *context) const;
|
||||
|
||||
NodeViewItem *GetAssumedItemForSelectedNode(Node *node);
|
||||
bool GetAssumedPositionForSelectedNode(Node *node, Node::Position *pos);
|
||||
NodeViewItem *GetAssumedItemForSelectedNode(Node *node);
|
||||
bool GetAssumedPositionForSelectedNode(Node *node, Node::Position *pos);
|
||||
|
||||
Menu *CreateAddMenu(Menu *parent);
|
||||
Menu *CreateAddMenu(Menu *parent);
|
||||
|
||||
void PositionNewEdge(const QPoint &pos);
|
||||
void PositionNewEdge(const QPoint &pos);
|
||||
|
||||
void AddContext(Node *n);
|
||||
void AddContext(Node *n);
|
||||
|
||||
void RemoveContext(Node *n);
|
||||
void RemoveContext(Node *n);
|
||||
|
||||
bool IsItemAttachedToCursor(NodeViewItem *item) const;
|
||||
bool IsItemAttachedToCursor(NodeViewItem *item) const;
|
||||
|
||||
void ExpandItem(NodeViewItem *item);
|
||||
void ExpandItem(NodeViewItem *item);
|
||||
|
||||
void CollapseItem(NodeViewItem *item);
|
||||
void CollapseItem(NodeViewItem *item);
|
||||
|
||||
void EndEdgeDrag(bool cancel = false);
|
||||
void EndEdgeDrag(bool cancel = false);
|
||||
|
||||
void PostPaste(const QVector<Node*> &new_nodes, const Node::PositionMap &map);
|
||||
void PostPaste(const QVector<Node *> &new_nodes,
|
||||
const Node::PositionMap &map);
|
||||
|
||||
void ResizeOverlay();
|
||||
void ResizeOverlay();
|
||||
|
||||
NodeViewMiniMap *minimap_;
|
||||
NodeViewMiniMap *minimap_;
|
||||
|
||||
NodeViewContext *GetContextItemFromNodeItem(NodeViewItem *item);
|
||||
NodeViewContext *GetContextItemFromNodeItem(NodeViewItem *item);
|
||||
|
||||
struct AttachedItem {
|
||||
NodeViewItem* item;
|
||||
Node *node;
|
||||
QPointF original_pos;
|
||||
};
|
||||
struct AttachedItem {
|
||||
NodeViewItem *item;
|
||||
Node *node;
|
||||
QPointF original_pos;
|
||||
};
|
||||
|
||||
void SetAttachedItems(const QVector<AttachedItem> &items);
|
||||
QVector<AttachedItem> attached_items_;
|
||||
void SetAttachedItems(const QVector<AttachedItem> &items);
|
||||
QVector<AttachedItem> attached_items_;
|
||||
|
||||
NodeViewEdge* drop_edge_;
|
||||
NodeInput drop_input_;
|
||||
NodeViewEdge *drop_edge_;
|
||||
NodeInput drop_input_;
|
||||
|
||||
NodeViewEdge* create_edge_;
|
||||
NodeViewItem* create_edge_output_item_;
|
||||
NodeViewItem* create_edge_input_item_;
|
||||
NodeInput create_edge_input_;
|
||||
bool create_edge_already_exists_;
|
||||
bool create_edge_from_output_;
|
||||
NodeViewEdge *create_edge_;
|
||||
NodeViewItem *create_edge_output_item_;
|
||||
NodeViewItem *create_edge_input_item_;
|
||||
NodeInput create_edge_input_;
|
||||
bool create_edge_already_exists_;
|
||||
bool create_edge_from_output_;
|
||||
|
||||
QVector<NodeViewItem*> create_edge_expanded_items_;
|
||||
QVector<NodeViewItem *> create_edge_expanded_items_;
|
||||
|
||||
NodeViewScene scene_;
|
||||
NodeViewScene scene_;
|
||||
|
||||
QVector<Node*> selected_nodes_;
|
||||
QVector<Node *> selected_nodes_;
|
||||
|
||||
QVector<Node*> contexts_;
|
||||
QVector<Node*> last_set_filter_nodes_;
|
||||
QMap<Node*, QPointF> context_offsets_;
|
||||
QVector<Node *> contexts_;
|
||||
QVector<Node *> last_set_filter_nodes_;
|
||||
QMap<Node *, QPointF> context_offsets_;
|
||||
|
||||
QMap<NodeViewItem*, QPointF> dragging_items_;
|
||||
QMap<NodeViewItem *, QPointF> dragging_items_;
|
||||
|
||||
NodeView* overlay_view_;
|
||||
NodeView *overlay_view_;
|
||||
|
||||
double scale_;
|
||||
double scale_;
|
||||
|
||||
bool dont_emit_selection_signals_;
|
||||
bool dont_emit_selection_signals_;
|
||||
|
||||
static const double kMinimumScale;
|
||||
static const double kMinimumScale;
|
||||
|
||||
static const int kMaximumContexts;
|
||||
static const int kMaximumContexts;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for when the scene's selected items change
|
||||
*/
|
||||
void UpdateSelectionCache();
|
||||
void UpdateSelectionCache();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for when the user right clicks (or otherwise requests a context menu)
|
||||
*/
|
||||
void ShowContextMenu(const QPoint &pos);
|
||||
void ShowContextMenu(const QPoint &pos);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for when the user requests a new node from the add menu
|
||||
*/
|
||||
void CreateNodeSlot(QAction* action);
|
||||
void CreateNodeSlot(QAction *action);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Receiver for setting the direction from the context menu
|
||||
*/
|
||||
void ContextMenuSetDirection(QAction* action);
|
||||
void ContextMenuSetDirection(QAction *action);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Opens the selected node in a Viewer
|
||||
*/
|
||||
void OpenSelectedNodeInViewer();
|
||||
void OpenSelectedNodeInViewer();
|
||||
|
||||
void UpdateSceneBoundingRect();
|
||||
void UpdateSceneBoundingRect();
|
||||
|
||||
void RepositionMiniMap();
|
||||
void RepositionMiniMap();
|
||||
|
||||
void UpdateViewportOnMiniMap();
|
||||
void UpdateViewportOnMiniMap();
|
||||
|
||||
void MoveToScenePoint(const QPointF &pos);
|
||||
void MoveToScenePoint(const QPointF &pos);
|
||||
|
||||
void NodeRemovedFromGraph();
|
||||
void NodeRemovedFromGraph();
|
||||
|
||||
void GroupNodes();
|
||||
void GroupNodes();
|
||||
|
||||
void UngroupNodes();
|
||||
void UngroupNodes();
|
||||
|
||||
void ShowNodeProperties();
|
||||
void ShowNodeProperties();
|
||||
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
|
||||
void CloseOverlay();
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
|
||||
void CloseOverlay();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -25,43 +25,49 @@
|
||||
|
||||
#include "common/define.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeViewCommon {
|
||||
public:
|
||||
enum FlowDirection {
|
||||
kInvalidDirection = -1,
|
||||
kTopToBottom,
|
||||
kBottomToTop,
|
||||
kLeftToRight,
|
||||
kRightToLeft
|
||||
};
|
||||
enum FlowDirection {
|
||||
kInvalidDirection = -1,
|
||||
kTopToBottom,
|
||||
kBottomToTop,
|
||||
kLeftToRight,
|
||||
kRightToLeft
|
||||
};
|
||||
|
||||
static Qt::Orientation GetFlowOrientation(FlowDirection dir) {
|
||||
if (dir == kTopToBottom || dir == kBottomToTop) {
|
||||
return Qt::Vertical;
|
||||
} else {
|
||||
return Qt::Horizontal;
|
||||
}
|
||||
}
|
||||
static Qt::Orientation GetFlowOrientation(FlowDirection dir)
|
||||
{
|
||||
if (dir == kTopToBottom || dir == kBottomToTop) {
|
||||
return Qt::Vertical;
|
||||
} else {
|
||||
return Qt::Horizontal;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsFlowVertical(FlowDirection dir)
|
||||
{
|
||||
return dir == kTopToBottom || dir == kBottomToTop;
|
||||
}
|
||||
static bool IsFlowVertical(FlowDirection dir)
|
||||
{
|
||||
return dir == kTopToBottom || dir == kBottomToTop;
|
||||
}
|
||||
|
||||
static bool IsFlowHorizontal(FlowDirection dir)
|
||||
{
|
||||
return dir == kLeftToRight || dir == kRightToLeft;
|
||||
}
|
||||
|
||||
static bool DirectionsAreOpposing(FlowDirection a, FlowDirection b) {
|
||||
return ((a == NodeViewCommon::kLeftToRight && b == NodeViewCommon::kRightToLeft)
|
||||
|| (a == NodeViewCommon::kRightToLeft && b == NodeViewCommon::kLeftToRight)
|
||||
|| (a == NodeViewCommon::kTopToBottom && b == NodeViewCommon::kBottomToTop)
|
||||
|| (a == NodeViewCommon::kBottomToTop && b == NodeViewCommon::kTopToBottom));
|
||||
}
|
||||
static bool IsFlowHorizontal(FlowDirection dir)
|
||||
{
|
||||
return dir == kLeftToRight || dir == kRightToLeft;
|
||||
}
|
||||
|
||||
static bool DirectionsAreOpposing(FlowDirection a, FlowDirection b)
|
||||
{
|
||||
return ((a == NodeViewCommon::kLeftToRight &&
|
||||
b == NodeViewCommon::kRightToLeft) ||
|
||||
(a == NodeViewCommon::kRightToLeft &&
|
||||
b == NodeViewCommon::kLeftToRight) ||
|
||||
(a == NodeViewCommon::kTopToBottom &&
|
||||
b == NodeViewCommon::kBottomToTop) ||
|
||||
(a == NodeViewCommon::kBottomToTop &&
|
||||
b == NodeViewCommon::kTopToBottom));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -16,344 +16,379 @@
|
||||
#include "nodeviewitem.h"
|
||||
#include "ui/colorcoding.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QGraphicsRectItem
|
||||
|
||||
NodeViewContext::NodeViewContext(Node *context, QGraphicsItem *item) :
|
||||
super(item),
|
||||
context_(context)
|
||||
NodeViewContext::NodeViewContext(Node *context, QGraphicsItem *item)
|
||||
: super(item)
|
||||
, context_(context)
|
||||
{
|
||||
Block *block = dynamic_cast<Block*>(context_);
|
||||
if (block && block->track() && block->track()->sequence()) {
|
||||
rational timebase = block->track()->sequence()->GetVideoParams().frame_rate_as_time_base();
|
||||
lbl_ = QCoreApplication::translate("NodeViewContext",
|
||||
"%1 [%2] :: %3 - %4").arg(block->GetLabelAndName(),
|
||||
Track::Reference::TypeToTranslatedString(block->track()->type()),
|
||||
QString::fromStdString(Timecode::time_to_timecode(block->in(), timebase, Core::instance()->GetTimecodeDisplay())),
|
||||
QString::fromStdString(Timecode::time_to_timecode(block->out(), timebase, Core::instance()->GetTimecodeDisplay())));
|
||||
} else {
|
||||
lbl_ = context_->GetLabelAndName();
|
||||
}
|
||||
Block *block = dynamic_cast<Block *>(context_);
|
||||
if (block && block->track() && block->track()->sequence()) {
|
||||
rational timebase = block->track()
|
||||
->sequence()
|
||||
->GetVideoParams()
|
||||
.frame_rate_as_time_base();
|
||||
lbl_ =
|
||||
QCoreApplication::translate("NodeViewContext", "%1 [%2] :: %3 - %4")
|
||||
.arg(block->GetLabelAndName(),
|
||||
Track::Reference::TypeToTranslatedString(
|
||||
block->track()->type()),
|
||||
QString::fromStdString(Timecode::time_to_timecode(
|
||||
block->in(), timebase,
|
||||
Core::instance()->GetTimecodeDisplay())),
|
||||
QString::fromStdString(Timecode::time_to_timecode(
|
||||
block->out(), timebase,
|
||||
Core::instance()->GetTimecodeDisplay())));
|
||||
} else {
|
||||
lbl_ = context_->GetLabelAndName();
|
||||
}
|
||||
|
||||
const Node::PositionMap &map = context_->GetContextPositions();
|
||||
for (auto it=map.cbegin(); it!=map.cend(); it++) {
|
||||
AddChild(it.key());
|
||||
}
|
||||
const Node::PositionMap &map = context_->GetContextPositions();
|
||||
for (auto it = map.cbegin(); it != map.cend(); it++) {
|
||||
AddChild(it.key());
|
||||
}
|
||||
|
||||
connect(context_, &Node::NodeAddedToContext, this, &NodeViewContext::AddChild, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodePositionInContextChanged, this, &NodeViewContext::SetChildPosition, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodeRemovedFromContext, this, &NodeViewContext::RemoveChild, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodeAddedToContext, this,
|
||||
&NodeViewContext::AddChild, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodePositionInContextChanged, this,
|
||||
&NodeViewContext::SetChildPosition, Qt::DirectConnection);
|
||||
connect(context_, &Node::NodeRemovedFromContext, this,
|
||||
&NodeViewContext::RemoveChild, Qt::DirectConnection);
|
||||
}
|
||||
|
||||
NodeViewContext::~NodeViewContext()
|
||||
{
|
||||
// Delete edges before items, because the edge constructor references the items
|
||||
qDeleteAll(edges_);
|
||||
edges_.clear();
|
||||
// Delete edges before items, because the edge constructor references the items
|
||||
qDeleteAll(edges_);
|
||||
edges_.clear();
|
||||
}
|
||||
|
||||
void NodeViewContext::AddChild(Node *node)
|
||||
{
|
||||
if (!context_) {
|
||||
return;
|
||||
}
|
||||
if (!context_) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeViewItem *item = new NodeViewItem(node, context_, this);
|
||||
item->SetFlowDirection(flow_dir_);
|
||||
NodeViewItem *item = new NodeViewItem(node, context_, this);
|
||||
item->SetFlowDirection(flow_dir_);
|
||||
|
||||
AddNodeInternal(node, item);
|
||||
AddNodeInternal(node, item);
|
||||
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup*>(node)) {
|
||||
for (auto it=group->GetContextPositions().cbegin(); it!=group->GetContextPositions().cend(); it++) {
|
||||
// Use this item as the representative for all of these nodes too
|
||||
AddNodeInternal(it.key(), item);
|
||||
}
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup *>(node)) {
|
||||
for (auto it = group->GetContextPositions().cbegin();
|
||||
it != group->GetContextPositions().cend(); it++) {
|
||||
// Use this item as the representative for all of these nodes too
|
||||
AddNodeInternal(it.key(), item);
|
||||
}
|
||||
|
||||
connect(group, &NodeGroup::NodeAddedToContext, this, &NodeViewContext::GroupAddedNode);
|
||||
connect(group, &NodeGroup::NodeRemovedFromContext, this, &NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
connect(group, &NodeGroup::NodeAddedToContext, this,
|
||||
&NodeViewContext::GroupAddedNode);
|
||||
connect(group, &NodeGroup::NodeRemovedFromContext, this,
|
||||
&NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
|
||||
UpdateRect();
|
||||
UpdateRect();
|
||||
}
|
||||
|
||||
void NodeViewContext::SetChildPosition(Node *node, const QPointF &pos)
|
||||
{
|
||||
item_map_.value(node)->SetNodePosition(pos);
|
||||
item_map_.value(node)->SetNodePosition(pos);
|
||||
}
|
||||
|
||||
void NodeViewContext::RemoveChild(Node *node)
|
||||
{
|
||||
disconnect(node, &Node::InputConnected, this, &NodeViewContext::ChildInputConnected);
|
||||
disconnect(node, &Node::InputDisconnected, this, &NodeViewContext::ChildInputDisconnected);
|
||||
disconnect(node, &Node::InputConnected, this,
|
||||
&NodeViewContext::ChildInputConnected);
|
||||
disconnect(node, &Node::InputDisconnected, this,
|
||||
&NodeViewContext::ChildInputDisconnected);
|
||||
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup*>(node)) {
|
||||
disconnect(group, &NodeGroup::NodeAddedToContext, this, &NodeViewContext::GroupAddedNode);
|
||||
disconnect(group, &NodeGroup::NodeRemovedFromContext, this, &NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
if (NodeGroup *group = dynamic_cast<NodeGroup *>(node)) {
|
||||
disconnect(group, &NodeGroup::NodeAddedToContext, this,
|
||||
&NodeViewContext::GroupAddedNode);
|
||||
disconnect(group, &NodeGroup::NodeRemovedFromContext, this,
|
||||
&NodeViewContext::GroupRemovedNode);
|
||||
}
|
||||
|
||||
NodeViewItem *item = item_map_.take(node);
|
||||
NodeViewItem *item = item_map_.take(node);
|
||||
|
||||
// Remove from scene before emitting signal so that any drag functions that might be happening
|
||||
// now can be handled before the item is destroyed
|
||||
scene()->removeItem(item);
|
||||
// Remove from scene before emitting signal so that any drag functions that might be happening
|
||||
// now can be handled before the item is destroyed
|
||||
scene()->removeItem(item);
|
||||
|
||||
emit ItemAboutToBeDeleted(item);
|
||||
emit ItemAboutToBeDeleted(item);
|
||||
|
||||
// Delete edges first because the edge destructor will try to reference item (maybe that should
|
||||
// be changed...)
|
||||
QVector<NodeViewEdge*> edges_to_remove = item->GetAllEdgesRecursively();
|
||||
foreach (NodeViewEdge *edge, edges_to_remove) {
|
||||
if (node == item->GetNode() || edge->output() == node || edge->input().node() == node) {
|
||||
ChildInputDisconnected(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
// Delete edges first because the edge destructor will try to reference item (maybe that should
|
||||
// be changed...)
|
||||
QVector<NodeViewEdge *> edges_to_remove = item->GetAllEdgesRecursively();
|
||||
foreach (NodeViewEdge *edge, edges_to_remove) {
|
||||
if (node == item->GetNode() || edge->output() == node ||
|
||||
edge->input().node() == node) {
|
||||
ChildInputDisconnected(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this item is specifically for this node and the node is a group. If so, remove it for
|
||||
// all other entries in the map.
|
||||
if (item->GetNode() == node) {
|
||||
if (dynamic_cast<NodeGroup*>(item->GetNode())) {
|
||||
for (auto it=item_map_.begin(); it!=item_map_.end(); ) {
|
||||
if (it.value() == item) {
|
||||
it = item_map_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if this item is specifically for this node and the node is a group. If so, remove it for
|
||||
// all other entries in the map.
|
||||
if (item->GetNode() == node) {
|
||||
if (dynamic_cast<NodeGroup *>(item->GetNode())) {
|
||||
for (auto it = item_map_.begin(); it != item_map_.end();) {
|
||||
if (it.value() == item) {
|
||||
it = item_map_.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete item;
|
||||
}
|
||||
delete item;
|
||||
}
|
||||
|
||||
UpdateRect();
|
||||
UpdateRect();
|
||||
}
|
||||
|
||||
void NodeViewContext::ChildInputConnected(Node *output, const NodeInput &input)
|
||||
{
|
||||
// Add edge
|
||||
if (!input.IsHidden()) {
|
||||
if (NodeViewItem* output_item = item_map_.value(output)) {
|
||||
AddEdgeInternal(output, input, output_item, item_map_.value(input.node())->GetItemForInput(input));
|
||||
}
|
||||
}
|
||||
// Add edge
|
||||
if (!input.IsHidden()) {
|
||||
if (NodeViewItem *output_item = item_map_.value(output)) {
|
||||
AddEdgeInternal(
|
||||
output, input, output_item,
|
||||
item_map_.value(input.node())->GetItemForInput(input));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool NodeViewContext::ChildInputDisconnected(Node *output, const NodeInput &input)
|
||||
bool NodeViewContext::ChildInputDisconnected(Node *output,
|
||||
const NodeInput &input)
|
||||
{
|
||||
// Remove edge
|
||||
for (int i=0; i<edges_.size(); i++) {
|
||||
NodeViewEdge *e = edges_.at(i);
|
||||
if (e->output() == output && e->input() == input) {
|
||||
delete e;
|
||||
edges_.removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Remove edge
|
||||
for (int i = 0; i < edges_.size(); i++) {
|
||||
NodeViewEdge *e = edges_.at(i);
|
||||
if (e->output() == output && e->input() == input) {
|
||||
delete e;
|
||||
edges_.removeAt(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
qreal GetTextOffset(const QFontMetricsF &fm)
|
||||
{
|
||||
return fm.height()/2;
|
||||
return fm.height() / 2;
|
||||
}
|
||||
|
||||
void NodeViewContext::UpdateRect()
|
||||
{
|
||||
QFont f;
|
||||
QFontMetricsF fm(f);
|
||||
qreal lbl_offset = GetTextOffset(fm);
|
||||
QFont f;
|
||||
QFontMetricsF fm(f);
|
||||
qreal lbl_offset = GetTextOffset(fm);
|
||||
|
||||
QRectF cbr = childrenBoundingRect();
|
||||
QRectF rect = cbr;
|
||||
int pad = NodeViewItem::DefaultItemHeight();
|
||||
rect.adjust(-pad, - lbl_offset*2 - fm.height() - pad, pad, pad);
|
||||
setRect(rect);
|
||||
QRectF cbr = childrenBoundingRect();
|
||||
QRectF rect = cbr;
|
||||
int pad = NodeViewItem::DefaultItemHeight();
|
||||
rect.adjust(-pad, -lbl_offset * 2 - fm.height() - pad, pad, pad);
|
||||
setRect(rect);
|
||||
|
||||
last_titlebar_height_ = rect.y() + (cbr.y() - rect.y()) - pad;
|
||||
last_titlebar_height_ = rect.y() + (cbr.y() - rect.y()) - pad;
|
||||
}
|
||||
|
||||
void NodeViewContext::SetFlowDirection(NodeViewCommon::FlowDirection dir)
|
||||
{
|
||||
flow_dir_ = dir;
|
||||
flow_dir_ = dir;
|
||||
|
||||
foreach (NodeViewItem *item, item_map_) {
|
||||
item->SetFlowDirection(dir);
|
||||
}
|
||||
foreach (NodeViewItem *item, item_map_) {
|
||||
item->SetFlowDirection(dir);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewContext::SetCurvedEdges(bool e)
|
||||
{
|
||||
curved_edges_ = e;
|
||||
curved_edges_ = e;
|
||||
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
edge->SetCurved(e);
|
||||
}
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
edge->SetCurved(e);
|
||||
}
|
||||
}
|
||||
|
||||
int NodeViewContext::DeleteSelected(NodeViewDeleteCommand *command)
|
||||
{
|
||||
int count = 0;
|
||||
int count = 0;
|
||||
|
||||
// Delete any selected edges
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
if (edge->isSelected()) {
|
||||
command->AddEdge(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
// Delete any selected edges
|
||||
foreach (NodeViewEdge *edge, edges_) {
|
||||
if (edge->isSelected()) {
|
||||
command->AddEdge(edge->output(), edge->input());
|
||||
}
|
||||
}
|
||||
|
||||
// Delete any selected nodes
|
||||
foreach (NodeViewItem *node, item_map_) {
|
||||
if (node->isSelected()) {
|
||||
command->AddNode(node->GetNode(), context_);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
// Delete any selected nodes
|
||||
foreach (NodeViewItem *node, item_map_) {
|
||||
if (node->isSelected()) {
|
||||
command->AddNode(node->GetNode(), context_);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
return count;
|
||||
}
|
||||
|
||||
void NodeViewContext::Select(const QVector<Node *> &nodes)
|
||||
{
|
||||
foreach (Node *n, nodes) {
|
||||
if (NodeViewItem *item = item_map_.value(n)) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
}
|
||||
foreach (Node *n, nodes) {
|
||||
if (NodeViewItem *item = item_map_.value(n)) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QVector<NodeViewItem *> NodeViewContext::GetSelectedItems() const
|
||||
{
|
||||
QVector<NodeViewItem *> items;
|
||||
QVector<NodeViewItem *> items;
|
||||
|
||||
for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) {
|
||||
if (it.value()->isSelected()) {
|
||||
if (!items.contains(it.value())) {
|
||||
items.append(it.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = item_map_.cbegin(); it != item_map_.cend(); it++) {
|
||||
if (it.value()->isSelected()) {
|
||||
if (!items.contains(it.value())) {
|
||||
items.append(it.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return items;
|
||||
return items;
|
||||
}
|
||||
|
||||
QPointF NodeViewContext::MapScenePosToNodePosInContext(const QPointF &pos) const
|
||||
{
|
||||
for (auto it=item_map_.cbegin(); it!=item_map_.cend(); it++) {
|
||||
QPointF pos_inside_parent = it.value()->mapToParent(it.value()->mapFromScene(pos));
|
||||
return NodeViewItem::ScreenToNodePoint(pos_inside_parent, flow_dir_);
|
||||
}
|
||||
return QPointF(0, 0);
|
||||
for (auto it = item_map_.cbegin(); it != item_map_.cend(); it++) {
|
||||
QPointF pos_inside_parent =
|
||||
it.value()->mapToParent(it.value()->mapFromScene(pos));
|
||||
return NodeViewItem::ScreenToNodePoint(pos_inside_parent, flow_dir_);
|
||||
}
|
||||
return QPointF(0, 0);
|
||||
}
|
||||
|
||||
void NodeViewContext::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
||||
void NodeViewContext::paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget)
|
||||
{
|
||||
// Set pen and brush
|
||||
Color color = context_->color();
|
||||
QColor c = QtUtils::toQColor(color);
|
||||
QPen pen(c, 2);
|
||||
if (option->state & QStyle::State_Selected) {
|
||||
pen.setStyle(Qt::DotLine);
|
||||
}
|
||||
painter->setPen(pen);
|
||||
// Set pen and brush
|
||||
Color color = context_->color();
|
||||
QColor c = QtUtils::toQColor(color);
|
||||
QPen pen(c, 2);
|
||||
if (option->state & QStyle::State_Selected) {
|
||||
pen.setStyle(Qt::DotLine);
|
||||
}
|
||||
painter->setPen(pen);
|
||||
|
||||
QColor bg = c;
|
||||
bg.setAlpha(128);
|
||||
painter->setBrush(bg);
|
||||
QColor bg = c;
|
||||
bg.setAlpha(128);
|
||||
painter->setBrush(bg);
|
||||
|
||||
// Draw semi-transparent rect for whole item
|
||||
int rounded = painter->fontMetrics().height();
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
// Draw semi-transparent rect for whole item
|
||||
int rounded = painter->fontMetrics().height();
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
|
||||
// Draw solid background for titlebar
|
||||
QRectF titlebar_rect = rect();
|
||||
titlebar_rect.setHeight(last_titlebar_height_ - rect().top());
|
||||
painter->setClipRect(titlebar_rect);
|
||||
painter->setBrush(c);
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
painter->setClipping(false);
|
||||
// Draw solid background for titlebar
|
||||
QRectF titlebar_rect = rect();
|
||||
titlebar_rect.setHeight(last_titlebar_height_ - rect().top());
|
||||
painter->setClipRect(titlebar_rect);
|
||||
painter->setBrush(c);
|
||||
painter->drawRoundedRect(rect(), rounded, rounded);
|
||||
painter->setClipping(false);
|
||||
|
||||
// Draw titlebar text
|
||||
painter->setPen(ColorCoding::GetUISelectorColor(color));
|
||||
// Draw titlebar text
|
||||
painter->setPen(ColorCoding::GetUISelectorColor(color));
|
||||
|
||||
int offset = GetTextOffset(painter->fontMetrics());
|
||||
int offset = GetTextOffset(painter->fontMetrics());
|
||||
|
||||
QRectF text_rect = rect();
|
||||
text_rect.adjust(offset, offset, -offset, -offset);
|
||||
painter->drawText(text_rect, lbl_);
|
||||
QRectF text_rect = rect();
|
||||
text_rect.adjust(offset, offset, -offset, -offset);
|
||||
painter->drawText(text_rect, lbl_);
|
||||
}
|
||||
|
||||
QVariant NodeViewContext::itemChange(GraphicsItemChange change, const QVariant &value)
|
||||
QVariant NodeViewContext::itemChange(GraphicsItemChange change,
|
||||
const QVariant &value)
|
||||
{
|
||||
return super::itemChange(change, value);
|
||||
return super::itemChange(change, value);
|
||||
}
|
||||
|
||||
void NodeViewContext::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
||||
{
|
||||
bool clicked_inside_titlebar = (event->pos().y() < last_titlebar_height_);
|
||||
bool clicked_inside_titlebar = (event->pos().y() < last_titlebar_height_);
|
||||
|
||||
setFlag(ItemIsMovable, clicked_inside_titlebar);
|
||||
setFlag(ItemIsSelectable, clicked_inside_titlebar);
|
||||
setFlag(ItemIsMovable, clicked_inside_titlebar);
|
||||
setFlag(ItemIsSelectable, clicked_inside_titlebar);
|
||||
|
||||
super::mousePressEvent(event);
|
||||
super::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void NodeViewContext::AddNodeInternal(Node *node, NodeViewItem *item)
|
||||
{
|
||||
connect(node, &Node::InputConnected, this, &NodeViewContext::ChildInputConnected);
|
||||
connect(node, &Node::InputDisconnected, this, &NodeViewContext::ChildInputDisconnected);
|
||||
connect(node, &Node::InputConnected, this,
|
||||
&NodeViewContext::ChildInputConnected);
|
||||
connect(node, &Node::InputDisconnected, this,
|
||||
&NodeViewContext::ChildInputDisconnected);
|
||||
|
||||
item_map_.insert(node, item);
|
||||
item_map_.insert(node, item);
|
||||
|
||||
if (node == context_) {
|
||||
item->SetLabelAsOutput(true);
|
||||
}
|
||||
if (node == context_) {
|
||||
item->SetLabelAsOutput(true);
|
||||
}
|
||||
|
||||
for (auto it=node->output_connections().cbegin(); it!=node->output_connections().cend(); it++) {
|
||||
if (!it->second.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second.node())) {
|
||||
AddEdgeInternal(node, it->second, item, other_item->GetItemForInput(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = node->output_connections().cbegin();
|
||||
it != node->output_connections().cend(); it++) {
|
||||
if (!it->second.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second.node())) {
|
||||
AddEdgeInternal(node, it->second, item,
|
||||
other_item->GetItemForInput(it->second));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it=node->input_connections().cbegin(); it!=node->input_connections().cend(); it++) {
|
||||
if (!it->first.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second)) {
|
||||
AddEdgeInternal(it->second, it->first, other_item, item->GetItemForInput(it->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
for (auto it = node->input_connections().cbegin();
|
||||
it != node->input_connections().cend(); it++) {
|
||||
if (!it->first.IsHidden()) {
|
||||
if (NodeViewItem *other_item = item_map_.value(it->second)) {
|
||||
AddEdgeInternal(it->second, it->first, other_item,
|
||||
item->GetItemForInput(it->first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewContext::AddEdgeInternal(Node *output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to)
|
||||
void NodeViewContext::AddEdgeInternal(Node *output, const NodeInput &input,
|
||||
NodeViewItem *from, NodeViewItem *to)
|
||||
{
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
if (from == to) {
|
||||
return;
|
||||
}
|
||||
|
||||
NodeViewEdge* edge_ui = new NodeViewEdge(output, input, from, to, this);
|
||||
NodeViewEdge *edge_ui = new NodeViewEdge(output, input, from, to, this);
|
||||
|
||||
edge_ui->Adjust();
|
||||
edge_ui->SetCurved(curved_edges_);
|
||||
edge_ui->Adjust();
|
||||
edge_ui->SetCurved(curved_edges_);
|
||||
|
||||
edges_.append(edge_ui);
|
||||
edges_.append(edge_ui);
|
||||
}
|
||||
|
||||
void NodeViewContext::GroupAddedNode(Node *node)
|
||||
{
|
||||
NodeGroup *group = static_cast<NodeGroup*>(sender());
|
||||
NodeGroup *group = static_cast<NodeGroup *>(sender());
|
||||
|
||||
AddNodeInternal(node, item_map_.value(group));
|
||||
AddNodeInternal(node, item_map_.value(group));
|
||||
}
|
||||
|
||||
void NodeViewContext::GroupRemovedNode(Node *node)
|
||||
{
|
||||
NodeGroup *group = static_cast<NodeGroup*>(sender());
|
||||
NodeGroup *group = static_cast<NodeGroup *>(sender());
|
||||
|
||||
if (item_map_.value(node) == item_map_.value(group)) {
|
||||
item_map_.remove(node);
|
||||
}
|
||||
if (item_map_.value(node) == item_map_.value(group)) {
|
||||
item_map_.remove(node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,85 +9,88 @@
|
||||
#include "nodeviewcommon.h"
|
||||
#include "nodeviewedge.h"
|
||||
|
||||
namespace olive {
|
||||
|
||||
class NodeViewContext : public QObject, public QGraphicsRectItem
|
||||
namespace olive
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
class NodeViewContext : public QObject, public QGraphicsRectItem {
|
||||
Q_OBJECT
|
||||
public:
|
||||
NodeViewContext(Node *context, QGraphicsItem *item = nullptr);
|
||||
NodeViewContext(Node *context, QGraphicsItem *item = nullptr);
|
||||
|
||||
virtual ~NodeViewContext() override;
|
||||
virtual ~NodeViewContext() override;
|
||||
|
||||
Node *GetContext() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
Node *GetContext() const
|
||||
{
|
||||
return context_;
|
||||
}
|
||||
|
||||
void UpdateRect();
|
||||
void UpdateRect();
|
||||
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
void SetFlowDirection(NodeViewCommon::FlowDirection dir);
|
||||
|
||||
void SetCurvedEdges(bool e);
|
||||
void SetCurvedEdges(bool e);
|
||||
|
||||
int DeleteSelected(NodeViewDeleteCommand *command);
|
||||
int DeleteSelected(NodeViewDeleteCommand *command);
|
||||
|
||||
void Select(const QVector<Node*> &nodes);
|
||||
void Select(const QVector<Node *> &nodes);
|
||||
|
||||
QVector<NodeViewItem*> GetSelectedItems() const;
|
||||
QVector<NodeViewItem *> GetSelectedItems() const;
|
||||
|
||||
QPointF MapScenePosToNodePosInContext(const QPointF &pos) const;
|
||||
QPointF MapScenePosToNodePosInContext(const QPointF &pos) const;
|
||||
|
||||
NodeViewItem *GetItemFromMap(Node *node) const
|
||||
{
|
||||
return item_map_.value(node);
|
||||
}
|
||||
NodeViewItem *GetItemFromMap(Node *node) const
|
||||
{
|
||||
return item_map_.value(node);
|
||||
}
|
||||
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
virtual void paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget = nullptr) override;
|
||||
|
||||
public slots:
|
||||
void AddChild(Node *node);
|
||||
void AddChild(Node *node);
|
||||
|
||||
void SetChildPosition(Node *node, const QPointF &pos);
|
||||
void SetChildPosition(Node *node, const QPointF &pos);
|
||||
|
||||
void RemoveChild(Node *node);
|
||||
void RemoveChild(Node *node);
|
||||
|
||||
void ChildInputConnected(Node *output, const NodeInput& input);
|
||||
void ChildInputConnected(Node *output, const NodeInput &input);
|
||||
|
||||
bool ChildInputDisconnected(Node *output, const NodeInput& input);
|
||||
bool ChildInputDisconnected(Node *output, const NodeInput &input);
|
||||
|
||||
signals:
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
void ItemAboutToBeDeleted(NodeViewItem *item);
|
||||
|
||||
protected:
|
||||
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) override;
|
||||
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange change,
|
||||
const QVariant &value) override;
|
||||
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
|
||||
private:
|
||||
void AddNodeInternal(Node *node, NodeViewItem *item);
|
||||
void AddNodeInternal(Node *node, NodeViewItem *item);
|
||||
|
||||
void AddEdgeInternal(Node *output, const NodeInput& input, NodeViewItem *from, NodeViewItem *to);
|
||||
void AddEdgeInternal(Node *output, const NodeInput &input,
|
||||
NodeViewItem *from, NodeViewItem *to);
|
||||
|
||||
Node *context_;
|
||||
Node *context_;
|
||||
|
||||
QString lbl_;
|
||||
QString lbl_;
|
||||
|
||||
NodeViewCommon::FlowDirection flow_dir_;
|
||||
NodeViewCommon::FlowDirection flow_dir_;
|
||||
|
||||
bool curved_edges_;
|
||||
bool curved_edges_;
|
||||
|
||||
int last_titlebar_height_;
|
||||
int last_titlebar_height_;
|
||||
|
||||
QMap<Node*, NodeViewItem*> item_map_;
|
||||
QMap<Node *, NodeViewItem *> item_map_;
|
||||
|
||||
QVector<NodeViewEdge*> edges_;
|
||||
QVector<NodeViewEdge *> edges_;
|
||||
|
||||
private slots:
|
||||
void GroupAddedNode(Node *node);
|
||||
|
||||
void GroupRemovedNode(Node *node);
|
||||
void GroupAddedNode(Node *node);
|
||||
|
||||
void GroupRemovedNode(Node *node);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -30,226 +30,230 @@
|
||||
#include "nodeviewitem.h"
|
||||
#include "nodeviewscene.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
#define super QGraphicsPathItem
|
||||
|
||||
NodeViewEdge::NodeViewEdge(Node *output, const NodeInput &input,
|
||||
NodeViewItem* from_item, NodeViewItem* to_item,
|
||||
QGraphicsItem* parent) :
|
||||
super(parent),
|
||||
output_(output),
|
||||
input_(input),
|
||||
from_item_(from_item),
|
||||
to_item_(to_item)
|
||||
NodeViewItem *from_item, NodeViewItem *to_item,
|
||||
QGraphicsItem *parent)
|
||||
: super(parent)
|
||||
, output_(output)
|
||||
, input_(input)
|
||||
, from_item_(from_item)
|
||||
, to_item_(to_item)
|
||||
{
|
||||
Init();
|
||||
SetConnected(true);
|
||||
Init();
|
||||
SetConnected(true);
|
||||
|
||||
from_item_->AddEdge(this);
|
||||
to_item_->AddEdge(this);
|
||||
from_item_->AddEdge(this);
|
||||
to_item_->AddEdge(this);
|
||||
}
|
||||
|
||||
NodeViewEdge::NodeViewEdge(QGraphicsItem *parent) :
|
||||
QGraphicsPathItem(parent),
|
||||
from_item_(nullptr),
|
||||
to_item_(nullptr)
|
||||
NodeViewEdge::NodeViewEdge(QGraphicsItem *parent)
|
||||
: QGraphicsPathItem(parent)
|
||||
, from_item_(nullptr)
|
||||
, to_item_(nullptr)
|
||||
{
|
||||
Init();
|
||||
Init();
|
||||
}
|
||||
|
||||
NodeViewEdge::~NodeViewEdge()
|
||||
{
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
}
|
||||
|
||||
void NodeViewEdge::set_from_item(NodeViewItem *i)
|
||||
{
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
if (from_item_) {
|
||||
from_item_->RemoveEdge(this);
|
||||
}
|
||||
|
||||
from_item_ = i;
|
||||
from_item_ = i;
|
||||
|
||||
if (from_item_) {
|
||||
from_item_->AddEdge(this);
|
||||
}
|
||||
if (from_item_) {
|
||||
from_item_->AddEdge(this);
|
||||
}
|
||||
|
||||
Adjust();
|
||||
Adjust();
|
||||
}
|
||||
|
||||
void NodeViewEdge::set_to_item(NodeViewItem *i)
|
||||
{
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
if (to_item_) {
|
||||
to_item_->RemoveEdge(this);
|
||||
}
|
||||
|
||||
to_item_ = i;
|
||||
to_item_ = i;
|
||||
|
||||
if (to_item_) {
|
||||
to_item_->AddEdge(this);
|
||||
}
|
||||
if (to_item_) {
|
||||
to_item_->AddEdge(this);
|
||||
}
|
||||
|
||||
Adjust();
|
||||
Adjust();
|
||||
}
|
||||
|
||||
void NodeViewEdge::Adjust()
|
||||
{
|
||||
// Draw a line between the two
|
||||
SetPoints(from_item()->GetOutputPoint(), to_item()->GetInputPoint());
|
||||
// Draw a line between the two
|
||||
SetPoints(from_item()->GetOutputPoint(), to_item()->GetInputPoint());
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetConnected(bool c)
|
||||
{
|
||||
connected_ = c;
|
||||
connected_ = c;
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetHighlighted(bool e)
|
||||
{
|
||||
highlighted_ = e;
|
||||
highlighted_ = e;
|
||||
|
||||
update();
|
||||
update();
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetPoints(const QPointF &start, const QPointF &end)
|
||||
{
|
||||
cached_start_ = start;
|
||||
cached_end_ = end;
|
||||
cached_start_ = start;
|
||||
cached_end_ = end;
|
||||
|
||||
UpdateCurve();
|
||||
UpdateCurve();
|
||||
}
|
||||
|
||||
void NodeViewEdge::SetCurved(bool e)
|
||||
{
|
||||
curved_ = e;
|
||||
curved_ = e;
|
||||
|
||||
UpdateCurve();
|
||||
UpdateCurve();
|
||||
}
|
||||
|
||||
void NodeViewEdge::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *)
|
||||
void NodeViewEdge::paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option, QWidget *)
|
||||
{
|
||||
QPalette::ColorGroup group;
|
||||
QPalette::ColorRole role;
|
||||
QPalette::ColorGroup group;
|
||||
QPalette::ColorRole role;
|
||||
|
||||
if (connected_) {
|
||||
group = QPalette::Active;
|
||||
} else {
|
||||
group = QPalette::Disabled;
|
||||
}
|
||||
if (connected_) {
|
||||
group = QPalette::Active;
|
||||
} else {
|
||||
group = QPalette::Disabled;
|
||||
}
|
||||
|
||||
if (highlighted_ != bool(option->state & QStyle::State_Selected)) {
|
||||
role = QPalette::Highlight;
|
||||
} else {
|
||||
role = QPalette::Text;
|
||||
}
|
||||
if (highlighted_ != bool(option->state & QStyle::State_Selected)) {
|
||||
role = QPalette::Highlight;
|
||||
} else {
|
||||
role = QPalette::Text;
|
||||
}
|
||||
|
||||
// Draw main path
|
||||
QColor edge_color = qApp->palette().color(group, role);
|
||||
// Draw main path
|
||||
QColor edge_color = qApp->palette().color(group, role);
|
||||
|
||||
painter->setPen(QPen(edge_color, edge_width_));
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(path());
|
||||
painter->setPen(QPen(edge_color, edge_width_));
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
painter->drawPath(path());
|
||||
}
|
||||
|
||||
void NodeViewEdge::Init()
|
||||
{
|
||||
connected_ = false;
|
||||
highlighted_ = false;
|
||||
curved_ = true;
|
||||
connected_ = false;
|
||||
highlighted_ = false;
|
||||
curved_ = true;
|
||||
|
||||
setFlag(QGraphicsItem::ItemIsSelectable);
|
||||
setFlag(QGraphicsItem::ItemIsSelectable);
|
||||
|
||||
// Ensures this UI object is drawn behind other objects
|
||||
setZValue(-1);
|
||||
// Ensures this UI object is drawn behind other objects
|
||||
setZValue(-1);
|
||||
|
||||
// Use font metrics to set edge width for basic high DPI support
|
||||
edge_width_ = QFontMetrics(QFont()).height() / 12;
|
||||
// Use font metrics to set edge width for basic high DPI support
|
||||
edge_width_ = QFontMetrics(QFont()).height() / 12;
|
||||
}
|
||||
|
||||
void NodeViewEdge::UpdateCurve()
|
||||
{
|
||||
const QPointF &start = cached_start_;
|
||||
const QPointF &end = cached_end_;
|
||||
const QPointF &start = cached_start_;
|
||||
const QPointF &end = cached_end_;
|
||||
|
||||
QPainterPath path;
|
||||
path.moveTo(start);
|
||||
QPainterPath path;
|
||||
path.moveTo(start);
|
||||
|
||||
double angle = std::atan2(end.y() - start.y(), end.x() - start.x());
|
||||
double angle = std::atan2(end.y() - start.y(), end.x() - start.x());
|
||||
|
||||
if (curved_) {
|
||||
if (curved_) {
|
||||
double half_x = lerp(start.x(), end.x(), 0.5);
|
||||
double half_y = lerp(start.y(), end.y(), 0.5);
|
||||
|
||||
double half_x = lerp(start.x(), end.x(), 0.5);
|
||||
double half_y = lerp(start.y(), end.y(), 0.5);
|
||||
QPointF cp1, cp2;
|
||||
|
||||
QPointF cp1, cp2;
|
||||
NodeViewCommon::FlowDirection from_flow =
|
||||
from_item_ ? from_item_->GetFlowDirection() :
|
||||
NodeViewCommon::kInvalidDirection;
|
||||
NodeViewCommon::FlowDirection to_flow =
|
||||
to_item_ ? to_item_->GetFlowDirection() :
|
||||
NodeViewCommon::kInvalidDirection;
|
||||
|
||||
NodeViewCommon::FlowDirection from_flow = from_item_ ? from_item_->GetFlowDirection() : NodeViewCommon::kInvalidDirection;
|
||||
NodeViewCommon::FlowDirection to_flow = to_item_ ? to_item_->GetFlowDirection() : NodeViewCommon::kInvalidDirection;
|
||||
if (from_flow == NodeViewCommon::kInvalidDirection &&
|
||||
to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
// This is a technically unsupported scenario, but to avoid issues, we'll use a fallback
|
||||
from_flow = NodeViewCommon::kLeftToRight;
|
||||
to_flow = NodeViewCommon::kLeftToRight;
|
||||
} else if (from_flow == NodeViewCommon::kInvalidDirection) {
|
||||
from_flow = to_flow;
|
||||
} else if (to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
to_flow = from_flow;
|
||||
}
|
||||
|
||||
if (from_flow == NodeViewCommon::kInvalidDirection && to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
// This is a technically unsupported scenario, but to avoid issues, we'll use a fallback
|
||||
from_flow = NodeViewCommon::kLeftToRight;
|
||||
to_flow = NodeViewCommon::kLeftToRight;
|
||||
} else if (from_flow == NodeViewCommon::kInvalidDirection) {
|
||||
from_flow = to_flow;
|
||||
} else if (to_flow == NodeViewCommon::kInvalidDirection) {
|
||||
to_flow = from_flow;
|
||||
}
|
||||
if (NodeViewCommon::GetFlowOrientation(from_flow) == Qt::Horizontal) {
|
||||
cp1 = QPointF(half_x, start.y());
|
||||
} else {
|
||||
cp1 = QPointF(start.x(), half_y);
|
||||
}
|
||||
|
||||
if (NodeViewCommon::GetFlowOrientation(from_flow) == Qt::Horizontal) {
|
||||
cp1 = QPointF(half_x, start.y());
|
||||
} else {
|
||||
cp1 = QPointF(start.x(), half_y);
|
||||
}
|
||||
if (NodeViewCommon::GetFlowOrientation(to_flow) == Qt::Horizontal) {
|
||||
cp2 = QPointF(half_x, end.y());
|
||||
} else {
|
||||
cp2 = QPointF(end.x(), half_y);
|
||||
}
|
||||
|
||||
if (NodeViewCommon::GetFlowOrientation(to_flow) == Qt::Horizontal) {
|
||||
cp2 = QPointF(half_x, end.y());
|
||||
} else {
|
||||
cp2 = QPointF(end.x(), half_y);
|
||||
}
|
||||
path.cubicTo(cp1, cp2, end);
|
||||
|
||||
path.cubicTo(cp1, cp2, end);
|
||||
if (!qFuzzyCompare(start.x(), end.x())) {
|
||||
double continue_x = end.x() - std::cos(angle);
|
||||
|
||||
if (!qFuzzyCompare(start.x(), end.x())) {
|
||||
double continue_x = end.x() - std::cos(angle);
|
||||
double x1 = start.x();
|
||||
double x2 = cp1.x();
|
||||
double x3 = cp2.x();
|
||||
double x4 = end.x();
|
||||
double y1 = start.y();
|
||||
double y2 = cp1.y();
|
||||
double y3 = cp2.y();
|
||||
double y4 = end.y();
|
||||
|
||||
double x1 = start.x();
|
||||
double x2 = cp1.x();
|
||||
double x3 = cp2.x();
|
||||
double x4 = end.x();
|
||||
double y1 = start.y();
|
||||
double y2 = cp1.y();
|
||||
double y3 = cp2.y();
|
||||
double y4 = end.y();
|
||||
if (start.x() >= end.x()) {
|
||||
std::swap(x1, x4);
|
||||
std::swap(x2, x3);
|
||||
std::swap(y1, y4);
|
||||
std::swap(y2, y3);
|
||||
}
|
||||
|
||||
if (start.x() >= end.x()) {
|
||||
std::swap(x1, x4);
|
||||
std::swap(x2, x3);
|
||||
std::swap(y1, y4);
|
||||
std::swap(y2, y3);
|
||||
}
|
||||
double t = Bezier::CubicXtoT(continue_x, x1, x2, x3, x4);
|
||||
double y = Bezier::CubicTtoY(y1, y2, y3, y4, t);
|
||||
|
||||
double t = Bezier::CubicXtoT(continue_x, x1, x2, x3, x4);
|
||||
double y = Bezier::CubicTtoY(y1, y2, y3, y4, t);
|
||||
angle = std::atan2(end.y() - y, end.x() - continue_x);
|
||||
}
|
||||
|
||||
angle = std::atan2(end.y() - y, end.x() - continue_x);
|
||||
}
|
||||
} else {
|
||||
path.lineTo(end);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
path.lineTo(end);
|
||||
|
||||
}
|
||||
|
||||
setPath(mapFromScene(path));
|
||||
setPath(mapFromScene(path));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#include "nodeviewcommon.h"
|
||||
#include "node/node.h"
|
||||
|
||||
namespace olive {
|
||||
namespace olive
|
||||
{
|
||||
|
||||
class NodeViewItem;
|
||||
|
||||
@@ -36,49 +37,47 @@ class NodeViewItem;
|
||||
*
|
||||
* A fairly simple line widget use to visualize a connection between two node parameters (a NodeEdge).
|
||||
*/
|
||||
class NodeViewEdge : public QGraphicsPathItem
|
||||
{
|
||||
class NodeViewEdge : public QGraphicsPathItem {
|
||||
public:
|
||||
NodeViewEdge(Node *output, const NodeInput& input,
|
||||
NodeViewItem* from_item, NodeViewItem* to_item,
|
||||
QGraphicsItem* parent = nullptr);
|
||||
NodeViewEdge(Node *output, const NodeInput &input, NodeViewItem *from_item,
|
||||
NodeViewItem *to_item, QGraphicsItem *parent = nullptr);
|
||||
|
||||
NodeViewEdge(QGraphicsItem* parent = nullptr);
|
||||
NodeViewEdge(QGraphicsItem *parent = nullptr);
|
||||
|
||||
virtual ~NodeViewEdge() override;
|
||||
virtual ~NodeViewEdge() override;
|
||||
|
||||
Node *output() const
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
Node *output() const
|
||||
{
|
||||
return output_;
|
||||
}
|
||||
|
||||
const NodeInput& input() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
const NodeInput &input() const
|
||||
{
|
||||
return input_;
|
||||
}
|
||||
|
||||
int element() const
|
||||
{
|
||||
return element_;
|
||||
}
|
||||
int element() const
|
||||
{
|
||||
return element_;
|
||||
}
|
||||
|
||||
NodeViewItem* from_item() const
|
||||
{
|
||||
return from_item_;
|
||||
}
|
||||
NodeViewItem *from_item() const
|
||||
{
|
||||
return from_item_;
|
||||
}
|
||||
|
||||
NodeViewItem* to_item() const
|
||||
{
|
||||
return to_item_;
|
||||
}
|
||||
NodeViewItem *to_item() const
|
||||
{
|
||||
return to_item_;
|
||||
}
|
||||
|
||||
void set_from_item(NodeViewItem *i);
|
||||
void set_from_item(NodeViewItem *i);
|
||||
|
||||
void set_to_item(NodeViewItem *i);
|
||||
void set_to_item(NodeViewItem *i);
|
||||
|
||||
void Adjust();
|
||||
void Adjust();
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set the connected state of this line
|
||||
*
|
||||
* When the edge is not connected, it visually depicts this by coloring the line grey. When an edge is connected or
|
||||
@@ -88,59 +87,60 @@ public:
|
||||
* Using SetEdge() automatically sets this to true. Under most circumstances this should be left alone, and only
|
||||
* be set when an edge is being created/dragged.
|
||||
*/
|
||||
void SetConnected(bool c);
|
||||
void SetConnected(bool c);
|
||||
|
||||
bool IsConnected() const
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
bool IsConnected() const
|
||||
{
|
||||
return connected_;
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set highlighted state
|
||||
*
|
||||
* Changes color of edge.
|
||||
*/
|
||||
void SetHighlighted(bool e);
|
||||
void SetHighlighted(bool e);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set points to create curve from
|
||||
*/
|
||||
void SetPoints(const QPointF& start, const QPointF& end);
|
||||
void SetPoints(const QPointF &start, const QPointF &end);
|
||||
|
||||
/**
|
||||
/**
|
||||
* @brief Set whether edges should be drawn as curved or as straight lines
|
||||
*/
|
||||
void SetCurved(bool e);
|
||||
void SetCurved(bool e);
|
||||
|
||||
protected:
|
||||
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
|
||||
virtual void paint(QPainter *painter,
|
||||
const QStyleOptionGraphicsItem *option,
|
||||
QWidget *widget = nullptr) override;
|
||||
|
||||
private:
|
||||
void Init();
|
||||
void Init();
|
||||
|
||||
void UpdateCurve();
|
||||
void UpdateCurve();
|
||||
|
||||
Node *output_;
|
||||
Node *output_;
|
||||
|
||||
NodeInput input_;
|
||||
NodeInput input_;
|
||||
|
||||
int element_;
|
||||
int element_;
|
||||
|
||||
NodeViewItem* from_item_;
|
||||
NodeViewItem *from_item_;
|
||||
|
||||
NodeViewItem* to_item_;
|
||||
NodeViewItem *to_item_;
|
||||
|
||||
int edge_width_;
|
||||
int edge_width_;
|
||||
|
||||
bool connected_;
|
||||
bool connected_;
|
||||
|
||||
bool highlighted_;
|
||||
bool highlighted_;
|
||||
|
||||
bool curved_;
|
||||
|
||||
QPointF cached_start_;
|
||||
QPointF cached_end_;
|
||||
bool curved_;
|
||||
|
||||
QPointF cached_start_;
|
||||
QPointF cached_end_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user