change: change code style to Linux style except indent.

This commit is contained in:
Mike Solar
2025-08-03 22:50:34 +08:00
parent 1df31fbdfe
commit c4f47b6217
788 changed files with 77112 additions and 68888 deletions
+352 -330
View File
@@ -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 &params)
{
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;
}
}
+54 -52
View File
@@ -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 &params);
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_;
};
}
+54 -47
View File
@@ -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());
}
}
+38 -21
View File
@@ -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_;
};
}
+12 -11
View File
@@ -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();
}
}
}
+10 -11
View File
@@ -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();
};
}
+17 -16
View File
@@ -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);
}
}
}
+6 -7
View File
@@ -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);
};
}
+42 -36
View File
@@ -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()));
}
}
+21 -21
View File
@@ -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;
}
}
+12 -13
View File
@@ -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_;
};
}
+32 -29
View File
@@ -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());
}
}
+11 -12
View File
@@ -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();
};
}
+58 -51
View File
@@ -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));
}
}
+15 -15
View File
@@ -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_;
};
}
+33 -30
View File
@@ -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);
}
}
+13 -13
View File
@@ -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_;
};
}
+123 -112
View File
@@ -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());
}
}
}
+22 -20
View File
@@ -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();
};
}
+123 -127
View File
@@ -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 -25
View File
@@ -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();
};
}
+32 -29
View File
@@ -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();
}
}
+20 -20
View File
@@ -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_;
};
}
+297 -266
View File
@@ -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();
}
}
+66 -69
View File
@@ -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);
};
}
+86 -81
View File
@@ -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 &center, const QPoint &p) const
ColorWheelWidget::Triangle
ColorWheelWidget::GetTriangleFromCoords(const QPoint &center,
const QPoint &p) const
{
return GetTriangleFromCoords(center, p.y(), p.x());
return GetTriangleFromCoords(center, p.y(), p.x());
}
ColorWheelWidget::Triangle ColorWheelWidget::GetTriangleFromCoords(const QPoint &center, qreal y, qreal x) const
ColorWheelWidget::Triangle
ColorWheelWidget::GetTriangleFromCoords(const QPoint &center, 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;
}
}
+26 -25
View File
@@ -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 &center, const QPoint& p) const;
Triangle GetTriangleFromCoords(const QPoint &center, qreal y, qreal x) const;
Triangle GetTriangleFromCoords(const QPoint &center, const QPoint &p) const;
Triangle GetTriangleFromCoords(const QPoint &center, 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
+65 -58
View File
@@ -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_;
};
}
+224 -205
View File
@@ -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());
}
}
+57 -56
View File
@@ -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();
};
}
+35 -31
View File
@@ -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;}"));
}
}
}
+27 -28
View File
@@ -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);
};
}
+80 -77
View File
@@ -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();
}
}
+22 -23
View File
@@ -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;
};
}
+124 -136
View File
@@ -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)
}
}
+32 -24
View File
@@ -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);
};
}
+19 -13
View File
@@ -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 &current, const QModelIndex &previous)
void HistoryWidget::currentRowChanged(const QModelIndex &current,
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);
}
}
+10 -10
View File
@@ -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 &current, const QModelIndex &previous);
void indexChanged(int i);
void currentRowChanged(const QModelIndex &current,
const QModelIndex &previous);
};
}
File diff suppressed because it is too large Load Diff
+101 -83
View File
@@ -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);
};
}
+26 -21
View File
@@ -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_);
}
}
+23 -19
View File
@@ -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_;
};
}
+240 -225
View File
@@ -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_);
}
}
+133 -130
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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"));
}
}
+83 -84
View File
@@ -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();
};
}
+113 -95
View File
@@ -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;
}
}
+15 -16
View File
@@ -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_;
};
}
+122 -99
View File
@@ -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);
}
}
+30 -27
View File
@@ -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 -27
View File
@@ -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_);
}
}
}
}
+13 -14
View File
@@ -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
+107 -93
View File
@@ -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()));
}
}
}
+41 -42
View File
@@ -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);
};
}
+409 -343
View File
@@ -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)
{
}
+126 -120
View File
@@ -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);
};
}
+105 -104
View File
@@ -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));
}
}
}
}
}
}
}
}
+10 -11
View File
@@ -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_;
};
}
+10 -9
View File
@@ -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_);
}
}
+17 -18
View File
@@ -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_;
};
}
+185 -165
View File
@@ -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());
}
}
+49 -50
View File
@@ -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();
};
}
+49 -43
View File
@@ -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());
}
}
}
+10 -11
View File
@@ -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);
};
}
File diff suppressed because it is too large Load Diff
+149 -143
View File
@@ -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();
};
}
+36 -30
View File
@@ -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));
}
};
}
+247 -212
View File
@@ -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);
}
}
}
+45 -42
View File
@@ -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);
};
}
+138 -134
View File
@@ -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));
}
}
+58 -58
View File
@@ -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