merged fxrestructure
This commit is contained in:
+37
-37
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "audiomonitor.h"
|
||||
|
||||
#include "project/sequence.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
@@ -39,60 +39,60 @@ extern "C" {
|
||||
}
|
||||
|
||||
AudioMonitor::AudioMonitor(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
QWidget(parent)
|
||||
{
|
||||
clear_timer.setInterval(500);
|
||||
connect(&clear_timer, SIGNAL(timeout()), this, SLOT(clear()));
|
||||
clear_timer.setInterval(500);
|
||||
connect(&clear_timer, SIGNAL(timeout()), this, SLOT(clear()));
|
||||
}
|
||||
|
||||
void AudioMonitor::set_value(const QVector<double> &ivalues) {
|
||||
values = ivalues;
|
||||
update();
|
||||
values = ivalues;
|
||||
update();
|
||||
|
||||
QMetaObject::invokeMethod(&clear_timer, "start", Qt::QueuedConnection);
|
||||
QMetaObject::invokeMethod(&clear_timer, "start", Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void AudioMonitor::clear() {
|
||||
clear_timer.stop();
|
||||
clear_timer.stop();
|
||||
|
||||
values.fill(1);
|
||||
update();
|
||||
values.fill(1);
|
||||
update();
|
||||
}
|
||||
|
||||
void AudioMonitor::resizeEvent(QResizeEvent *e) {
|
||||
gradient = QLinearGradient(QPoint(0, rect().top()), QPoint(0, rect().bottom()));
|
||||
gradient.setColorAt(0, Qt::red);
|
||||
gradient.setColorAt(0.25, Qt::yellow);
|
||||
gradient.setColorAt(1, Qt::green);
|
||||
QWidget::resizeEvent(e);
|
||||
gradient = QLinearGradient(QPoint(0, rect().top()), QPoint(0, rect().bottom()));
|
||||
gradient.setColorAt(0, Qt::red);
|
||||
gradient.setColorAt(0.25, Qt::yellow);
|
||||
gradient.setColorAt(1, Qt::green);
|
||||
QWidget::resizeEvent(e);
|
||||
}
|
||||
|
||||
void AudioMonitor::paintEvent(QPaintEvent *) {
|
||||
if (olive::ActiveSequence != nullptr && values.size() > 0) {
|
||||
QPainter p(this);
|
||||
int channel_x = AUDIO_MONITOR_GAP;
|
||||
int channel_count = values.size();
|
||||
int channel_width = (width()/channel_count) - AUDIO_MONITOR_GAP;
|
||||
int i;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
QRect r(channel_x, AUDIO_MONITOR_PEAK_HEIGHT + AUDIO_MONITOR_GAP, channel_width, height());
|
||||
p.fillRect(r, gradient);
|
||||
if (olive::ActiveSequence != nullptr && values.size() > 0) {
|
||||
QPainter p(this);
|
||||
int channel_x = AUDIO_MONITOR_GAP;
|
||||
int channel_count = values.size();
|
||||
int channel_width = (width()/channel_count) - AUDIO_MONITOR_GAP;
|
||||
int i;
|
||||
for (i=0;i<channel_count;i++) {
|
||||
QRect r(channel_x, AUDIO_MONITOR_PEAK_HEIGHT + AUDIO_MONITOR_GAP, channel_width, height());
|
||||
p.fillRect(r, gradient);
|
||||
|
||||
bool peak = false;
|
||||
bool peak = false;
|
||||
|
||||
r.setHeight(qRound(r.height()*(values.at(i))));
|
||||
peak = (r.height() == 0);
|
||||
r.setHeight(qRound(r.height()*(values.at(i))));
|
||||
peak = (r.height() == 0);
|
||||
|
||||
QRect peak_rect(channel_x, 0, channel_width, AUDIO_MONITOR_PEAK_HEIGHT);
|
||||
if (peak) {
|
||||
p.fillRect(peak_rect, QColor(255, 0, 0));
|
||||
} else {
|
||||
p.fillRect(peak_rect, QColor(64, 0, 0));
|
||||
}
|
||||
QRect peak_rect(channel_x, 0, channel_width, AUDIO_MONITOR_PEAK_HEIGHT);
|
||||
if (peak) {
|
||||
p.fillRect(peak_rect, QColor(255, 0, 0));
|
||||
} else {
|
||||
p.fillRect(peak_rect, QColor(64, 0, 0));
|
||||
}
|
||||
|
||||
p.fillRect(r, QColor(0, 0, 0, 160));
|
||||
p.fillRect(r, QColor(0, 0, 0, 160));
|
||||
|
||||
channel_x += channel_width + AUDIO_MONITOR_GAP;
|
||||
}
|
||||
}
|
||||
channel_x += channel_width + AUDIO_MONITOR_GAP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+60
-9
@@ -24,28 +24,79 @@
|
||||
#include <QWidget>
|
||||
#include <QTimer>
|
||||
|
||||
/**
|
||||
* @brief The AudioMonitor class
|
||||
*
|
||||
* Used to show a visual representation of audio currently playing
|
||||
*/
|
||||
class AudioMonitor : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit AudioMonitor(QWidget *parent = 0);
|
||||
void set_value(const QVector<double>& values);
|
||||
/**
|
||||
* @brief AudioMonitor Constructor
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent object.
|
||||
*/
|
||||
explicit AudioMonitor(QWidget *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Set the current audio value
|
||||
*
|
||||
* The main interface for updating the audio monitor. Using this function will redraw the monitor with the values
|
||||
* specified.
|
||||
*
|
||||
* @param values
|
||||
*
|
||||
* An array of doubles between 0.0 and 1.0 to display the amplitude. 0.0 is no audio, 1.0 is full volume. Each array
|
||||
* entry is a channel and the audio monitor will automatically adjust to the channel count in the array.
|
||||
*/
|
||||
void set_value(const QVector<double>& values);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *);
|
||||
void resizeEvent(QResizeEvent *);
|
||||
/**
|
||||
* @brief Internal paint event
|
||||
*
|
||||
* Paints the
|
||||
*/
|
||||
void paintEvent(QPaintEvent *);
|
||||
|
||||
/**
|
||||
* @brief Internal resize event handler
|
||||
*
|
||||
* Triggers a repaint when the widget is resized.
|
||||
*/
|
||||
void resizeEvent(QResizeEvent *);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
private:
|
||||
QLinearGradient gradient;
|
||||
QVector<double> values;
|
||||
QTimer clear_timer;
|
||||
/**
|
||||
* @brief Internal gradient object from red to yellow to green
|
||||
*/
|
||||
QLinearGradient gradient;
|
||||
|
||||
/**
|
||||
* @brief Internal value storage
|
||||
*/
|
||||
QVector<double> values;
|
||||
|
||||
/**
|
||||
* @brief Internal timer to clear the audio monitor after a certain amount of time
|
||||
*
|
||||
* If it doesn't receive any values within a certain amount of time, it's assumed audio is no longer playing and the
|
||||
* monitor is cleared.
|
||||
*/
|
||||
QTimer clear_timer;
|
||||
|
||||
private slots:
|
||||
void clear();
|
||||
/**
|
||||
* @brief Slot to clear the audio monitor
|
||||
*/
|
||||
void clear();
|
||||
};
|
||||
|
||||
#endif // AUDIOMONITOR_H
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
#include "blur.h"
|
||||
|
||||
void olive::ui::blur(QImage& result, const QRect& rect, int radius, bool alphaOnly) {
|
||||
int tab[] = { 14, 10, 8, 6, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2 };
|
||||
int alpha = (radius < 1) ? 16 : (radius > 17) ? 1 : tab[radius-1];
|
||||
|
||||
int r1 = rect.top();
|
||||
int r2 = rect.bottom();
|
||||
int c1 = rect.left();
|
||||
int c2 = rect.right();
|
||||
|
||||
int bpl = result.bytesPerLine();
|
||||
int rgba[4];
|
||||
unsigned char* p;
|
||||
|
||||
int i1 = 0;
|
||||
int i2 = 3;
|
||||
|
||||
if (alphaOnly)
|
||||
i1 = i2 = (QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 3);
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r1) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += bpl;
|
||||
for (int j = r1; j < r2; j++, p += bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c1 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p += 4;
|
||||
for (int j = c1; j < c2; j++, p += 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int col = c1; col <= c2; col++) {
|
||||
p = result.scanLine(r2) + col * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= bpl;
|
||||
for (int j = r1; j < r2; j++, p -= bpl)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
|
||||
for (int row = r1; row <= r2; row++) {
|
||||
p = result.scanLine(row) + c2 * 4;
|
||||
for (int i = i1; i <= i2; i++)
|
||||
rgba[i] = p[i] << 4;
|
||||
|
||||
p -= 4;
|
||||
for (int j = c1; j < c2; j++, p -= 4)
|
||||
for (int i = i1; i <= i2; i++)
|
||||
p[i] = (rgba[i] += ((p[i] << 4) - rgba[i]) * alpha / 16) >> 4;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef BLUR_H
|
||||
#define BLUR_H
|
||||
|
||||
#include <QImage>
|
||||
#include <QRect>
|
||||
|
||||
namespace olive {
|
||||
namespace ui {
|
||||
/**
|
||||
* @brief Convenience function for blurring a QImage
|
||||
*
|
||||
* @param result
|
||||
*
|
||||
* QImage to blur
|
||||
*
|
||||
* @param rect
|
||||
*
|
||||
* The rectangle of the QImage to blur. Use QImage::rect() to blur the entire image.
|
||||
*
|
||||
* @param radius
|
||||
*
|
||||
* The blur radius - how much to blur the image.
|
||||
*
|
||||
* @param alphaOnly
|
||||
*
|
||||
* True if only the alpha channel should be blurred rather than the entire RGBA space.
|
||||
*/
|
||||
void blur(QImage& result, const QRect& rect, int radius, bool alphaOnly);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BLUR_H
|
||||
+4
-3
@@ -20,13 +20,14 @@
|
||||
|
||||
#include "checkboxex.h"
|
||||
|
||||
#include "project/undo.h"
|
||||
#include "undo/undostack.h"
|
||||
#include "undo/undo.h"
|
||||
|
||||
CheckboxEx::CheckboxEx(QWidget* parent) : QCheckBox(parent) {
|
||||
// connect(this, SIGNAL(clicked(bool)), this, SLOT(checkbox_command()));
|
||||
}
|
||||
|
||||
void CheckboxEx::checkbox_command() {
|
||||
CheckboxCommand* c = new CheckboxCommand(this);
|
||||
olive::UndoStack.push(c);
|
||||
CheckboxCommand* c = new CheckboxCommand(this);
|
||||
olive::UndoStack.push(c);
|
||||
}
|
||||
|
||||
+17
-11
@@ -33,7 +33,7 @@
|
||||
#include "ui/checkboxex.h"
|
||||
#include "ui/icons.h"
|
||||
|
||||
#include "debug.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
CollapsibleWidget::CollapsibleWidget(QWidget* parent) : QWidget(parent) {
|
||||
selected = false;
|
||||
@@ -52,8 +52,8 @@ CollapsibleWidget::CollapsibleWidget(QWidget* parent) : QWidget(parent) {
|
||||
header = new QLabel(title_bar);
|
||||
collapse_button = new QPushButton(title_bar);
|
||||
collapse_button->setIconSize(collapse_button->iconSize()*0.5);
|
||||
collapse_button->setStyleSheet("QPushButton { border: none; }");
|
||||
setText(tr("<untitled>"));
|
||||
collapse_button->setFlat(true);
|
||||
SetTitle(tr("<untitled>"));
|
||||
title_bar_layout->addWidget(collapse_button);
|
||||
title_bar_layout->addWidget(enabled_check);
|
||||
title_bar_layout->addWidget(header);
|
||||
@@ -80,35 +80,41 @@ void CollapsibleWidget::header_click(bool s, bool deselect) {
|
||||
if (deselect) emit deselect_others(this);
|
||||
}
|
||||
|
||||
bool CollapsibleWidget::is_focused() {
|
||||
bool CollapsibleWidget::IsFocused() {
|
||||
if (hasFocus()) return true;
|
||||
return title_bar->hasFocus();
|
||||
}
|
||||
|
||||
bool CollapsibleWidget::is_expanded() {
|
||||
bool CollapsibleWidget::IsExpanded() {
|
||||
return contents->isVisible();
|
||||
}
|
||||
|
||||
bool CollapsibleWidget::IsSelected()
|
||||
{
|
||||
return selected;
|
||||
}
|
||||
|
||||
void CollapsibleWidget::set_button_icon(bool open) {
|
||||
collapse_button->setIcon(open ? olive::icon::DownArrow : olive::icon::RightArrow);
|
||||
}
|
||||
|
||||
void CollapsibleWidget::setContents(QWidget* c) {
|
||||
void CollapsibleWidget::SetContents(QWidget* c) {
|
||||
bool existing = (contents != nullptr);
|
||||
contents = c;
|
||||
if (!existing) {
|
||||
layout->addWidget(contents);
|
||||
connect(enabled_check, SIGNAL(toggled(bool)), this, SLOT(on_enabled_change(bool)));
|
||||
connect(enabled_check, SIGNAL(toggled(bool)), contents, SLOT(setEnabled(bool)));
|
||||
connect(collapse_button, SIGNAL(clicked()), this, SLOT(on_visible_change()));
|
||||
}
|
||||
}
|
||||
|
||||
void CollapsibleWidget::setText(const QString &s) {
|
||||
header->setText(s);
|
||||
QString CollapsibleWidget::Title()
|
||||
{
|
||||
return header->text();
|
||||
}
|
||||
|
||||
void CollapsibleWidget::on_enabled_change(bool b) {
|
||||
contents->setEnabled(b);
|
||||
void CollapsibleWidget::SetTitle(const QString &s) {
|
||||
header->setText(s);
|
||||
}
|
||||
|
||||
void CollapsibleWidget::on_visible_change() {
|
||||
|
||||
+11
-10
@@ -35,7 +35,7 @@
|
||||
class CollapsibleWidgetHeader : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollapsibleWidgetHeader(QWidget* parent = 0);
|
||||
CollapsibleWidgetHeader(QWidget* parent = nullptr);
|
||||
bool selected;
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
@@ -48,17 +48,19 @@ class CollapsibleWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CollapsibleWidget(QWidget* parent = 0);
|
||||
void setContents(QWidget* c);
|
||||
void setText(const QString &);
|
||||
bool is_focused();
|
||||
bool is_expanded();
|
||||
|
||||
CollapsibleWidget(QWidget* parent = nullptr);
|
||||
void SetContents(QWidget* c);
|
||||
QString Title();
|
||||
void SetTitle(const QString &);
|
||||
bool IsFocused();
|
||||
bool IsExpanded();
|
||||
bool IsSelected();
|
||||
protected:
|
||||
CheckboxEx* enabled_check;
|
||||
bool selected;
|
||||
QWidget* contents;
|
||||
CollapsibleWidgetHeader* title_bar;
|
||||
QWidget* contents;
|
||||
private:
|
||||
bool selected;
|
||||
QLabel* header;
|
||||
QVBoxLayout* layout;
|
||||
QPushButton* collapse_button;
|
||||
@@ -71,7 +73,6 @@ signals:
|
||||
void visibleChanged();
|
||||
|
||||
private slots:
|
||||
void on_enabled_change(bool b);
|
||||
void on_visible_change();
|
||||
|
||||
public slots:
|
||||
|
||||
+15
-33
@@ -20,52 +20,34 @@
|
||||
|
||||
#include "colorbutton.h"
|
||||
|
||||
#include "project/undo.h"
|
||||
|
||||
#include <QColorDialog>
|
||||
|
||||
ColorButton::ColorButton(QWidget *parent)
|
||||
: QPushButton(parent), color(Qt::white) {
|
||||
set_button_color();
|
||||
connect(this, SIGNAL(clicked(bool)), this, SLOT(open_dialog()));
|
||||
: QPushButton(parent), color(Qt::white) {
|
||||
set_button_color();
|
||||
connect(this, SIGNAL(clicked(bool)), this, SLOT(open_dialog()));
|
||||
}
|
||||
|
||||
QColor ColorButton::get_color() {
|
||||
return color;
|
||||
return color;
|
||||
}
|
||||
|
||||
void ColorButton::set_color(QColor c) {
|
||||
previousColor = color;
|
||||
color = c;
|
||||
set_button_color();
|
||||
}
|
||||
|
||||
const QColor &ColorButton::getPreviousValue() {
|
||||
return previousColor;
|
||||
color = c;
|
||||
set_button_color();
|
||||
}
|
||||
|
||||
void ColorButton::set_button_color() {
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Button, color);
|
||||
setPalette(pal);
|
||||
QPalette pal = palette();
|
||||
pal.setColor(QPalette::Button, color);
|
||||
setPalette(pal);
|
||||
}
|
||||
|
||||
void ColorButton::open_dialog() {
|
||||
QColor new_color = QColorDialog::getColor(color, nullptr, tr("Set Color"));
|
||||
if (new_color.isValid() && color != new_color) {
|
||||
set_color(new_color);
|
||||
set_button_color();
|
||||
emit color_changed();
|
||||
}
|
||||
}
|
||||
|
||||
ColorCommand::ColorCommand(ColorButton* s, QColor o, QColor n)
|
||||
: sender(s), old_color(o), new_color(n) {}
|
||||
|
||||
void ColorCommand::undo() {
|
||||
sender->set_color(old_color);
|
||||
}
|
||||
|
||||
void ColorCommand::redo() {
|
||||
sender->set_color(new_color);
|
||||
QColor new_color = QColorDialog::getColor(color, nullptr, tr("Set Color"));
|
||||
if (new_color.isValid() && color != new_color) {
|
||||
set_color(new_color);
|
||||
set_button_color();
|
||||
emit color_changed(color);
|
||||
}
|
||||
}
|
||||
|
||||
+8
-21
@@ -26,31 +26,18 @@
|
||||
#include <QUndoCommand>
|
||||
|
||||
class ColorButton : public QPushButton {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorButton(QWidget* parent = 0);
|
||||
QColor get_color();
|
||||
void set_color(QColor c);
|
||||
const QColor& getPreviousValue();
|
||||
ColorButton(QWidget* parent = nullptr);
|
||||
QColor get_color();
|
||||
void set_color(QColor c);
|
||||
private:
|
||||
QColor color;
|
||||
QColor previousColor;
|
||||
void set_button_color();
|
||||
QColor color;
|
||||
void set_button_color();
|
||||
signals:
|
||||
void color_changed();
|
||||
void color_changed(const QColor& c);
|
||||
private slots:
|
||||
void open_dialog();
|
||||
};
|
||||
|
||||
class ColorCommand : public QUndoCommand {
|
||||
public:
|
||||
ColorCommand(ColorButton* s, QColor o, QColor n);
|
||||
void undo();
|
||||
void redo();
|
||||
private:
|
||||
ColorButton* sender;
|
||||
QColor old_color;
|
||||
QColor new_color;
|
||||
void open_dialog();
|
||||
};
|
||||
|
||||
#endif // COLORBUTTON_H
|
||||
|
||||
+12
-52
@@ -20,63 +20,23 @@
|
||||
|
||||
#include "comboboxex.h"
|
||||
|
||||
#include "project/undo.h"
|
||||
#include "panels/project.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <QWheelEvent>
|
||||
|
||||
|
||||
class ComboBoxExCommand : public QUndoCommand {
|
||||
public:
|
||||
ComboBoxExCommand(ComboBoxEx* obj, int old_index, int new_index) :
|
||||
combobox(obj), old_val(old_index), new_val(new_index), done(true), old_project_changed(olive::MainWindow->isWindowModified()) {}
|
||||
void undo() {
|
||||
combobox->setCurrentIndex(old_val);
|
||||
done = false;
|
||||
olive::MainWindow->setWindowModified(old_project_changed);
|
||||
}
|
||||
void redo() {
|
||||
if (!done) {
|
||||
combobox->setCurrentIndex(new_val);
|
||||
}
|
||||
olive::MainWindow->setWindowModified(true);
|
||||
}
|
||||
private:
|
||||
ComboBoxEx* combobox;
|
||||
int old_val;
|
||||
int new_val;
|
||||
bool done;
|
||||
bool old_project_changed;
|
||||
};
|
||||
|
||||
ComboBoxEx::ComboBoxEx(QWidget *parent) : QComboBox(parent), index(0) {
|
||||
connect(this, SIGNAL(activated(int)), this, SLOT(index_changed(int)));
|
||||
ComboBoxEx::ComboBoxEx(QWidget *parent) :
|
||||
QComboBox(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void ComboBoxEx::setCurrentIndexEx(int i) {
|
||||
index = i;
|
||||
setCurrentIndex(i);
|
||||
void ComboBoxEx::setScrollingEnabled(bool b)
|
||||
{
|
||||
scrolling_enabled_ = b;
|
||||
}
|
||||
|
||||
void ComboBoxEx::setCurrentTextEx(const QString &text) {
|
||||
setCurrentText(text);
|
||||
index = currentIndex();
|
||||
}
|
||||
|
||||
int ComboBoxEx::getPreviousIndex() {
|
||||
return previousIndex;
|
||||
}
|
||||
|
||||
void ComboBoxEx::index_changed(int i) {
|
||||
if (index != i) {
|
||||
previousIndex = index;
|
||||
// undo_stack.push(new ComboBoxExCommand(this, index, i));
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
|
||||
void ComboBoxEx::wheelEvent(QWheelEvent* e) {
|
||||
void ComboBoxEx::wheelEvent(QWheelEvent *e)
|
||||
{
|
||||
if (scrolling_enabled_) {
|
||||
QComboBox::wheelEvent(e);
|
||||
} else {
|
||||
e->ignore();
|
||||
}
|
||||
}
|
||||
|
||||
+6
-11
@@ -22,21 +22,16 @@
|
||||
#define COMBOBOXEX_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QDebug>
|
||||
|
||||
class ComboBoxEx : public QComboBox {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
ComboBoxEx(QWidget* parent = 0);
|
||||
void setCurrentIndexEx(int i);
|
||||
void setCurrentTextEx(const QString &text);
|
||||
int getPreviousIndex();
|
||||
private slots:
|
||||
void index_changed(int);
|
||||
ComboBoxEx(QWidget* parent = nullptr);
|
||||
void setScrollingEnabled(bool b);
|
||||
protected:
|
||||
virtual void wheelEvent(QWheelEvent* e) override;
|
||||
private:
|
||||
int index;
|
||||
int previousIndex;
|
||||
void wheelEvent(QWheelEvent* e);
|
||||
bool scrolling_enabled_;
|
||||
};
|
||||
|
||||
#endif // COMBOBOXEX_H
|
||||
|
||||
+312
@@ -0,0 +1,312 @@
|
||||
#include "effectui.h"
|
||||
|
||||
#include <QPoint>
|
||||
#include <QMenu>
|
||||
|
||||
#include "timeline/clip.h"
|
||||
#include "ui/menuhelper.h"
|
||||
#include "ui/keyframenavigator.h"
|
||||
#include "ui/clickablelabel.h"
|
||||
#include "panels/panels.h"
|
||||
|
||||
EffectUI::EffectUI(Effect* e) :
|
||||
effect_(e)
|
||||
{
|
||||
Q_ASSERT(e != nullptr);
|
||||
|
||||
QString effect_name;
|
||||
|
||||
// If this effect is actually a transition
|
||||
if (e->meta->type == EFFECT_TYPE_TRANSITION) {
|
||||
|
||||
Transition* t = static_cast<Transition*>(e);
|
||||
|
||||
// Since effects can have two clip attachments, find out which one is selected
|
||||
Clip* selected_clip = t->parent_clip;
|
||||
bool both_selected = false;
|
||||
|
||||
// Check if this is a shared transition
|
||||
if (t->secondary_clip != nullptr) {
|
||||
|
||||
// Check which clips are selected
|
||||
if (t->secondary_clip->IsSelected()) {
|
||||
|
||||
selected_clip = t->secondary_clip;
|
||||
|
||||
if (t->parent_clip->IsSelected()) {
|
||||
// Both clips are selected
|
||||
both_selected = true;
|
||||
}
|
||||
|
||||
} else if (!t->parent_clip->IsSelected()) {
|
||||
|
||||
// Neither are selected, but the naming scheme (no "opening" or "closing" modifier) will be the same
|
||||
both_selected = true;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// See if the transition is the clip's opening or closing transition and label it accordingly
|
||||
if (both_selected) {
|
||||
effect_name = t->name;
|
||||
} else if (selected_clip->opening_transition.get() == t) {
|
||||
effect_name = tr("%1 (Opening)").arg(t->name);
|
||||
} else {
|
||||
effect_name = tr("%1 (Closing)").arg(t->name);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Otherwise just set the title normally
|
||||
effect_name = e->name;
|
||||
|
||||
}
|
||||
|
||||
SetTitle(effect_name);
|
||||
|
||||
QWidget* ui = new QWidget(this);
|
||||
SetContents(ui);
|
||||
|
||||
layout_ = new QGridLayout(ui);
|
||||
layout_->setSpacing(4);
|
||||
|
||||
connect(title_bar,
|
||||
SIGNAL(customContextMenuRequested(const QPoint&)),
|
||||
this,
|
||||
SLOT(show_context_menu(const QPoint&)));
|
||||
|
||||
int maximum_column = 0;
|
||||
|
||||
widgets_.resize(e->row_count());
|
||||
|
||||
for (int i=0;i<e->row_count();i++) {
|
||||
EffectRow* row = e->row(i);
|
||||
|
||||
ClickableLabel* row_label = new ClickableLabel(row->name());
|
||||
connect(row_label, SIGNAL(clicked()), row, SLOT(FocusRow()));
|
||||
|
||||
labels_.append(row_label);
|
||||
|
||||
layout_->addWidget(row_label, i, 0);
|
||||
|
||||
widgets_[i].resize(row->FieldCount());
|
||||
|
||||
int column = 1;
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
EffectField* field = row->Field(j);
|
||||
|
||||
QWidget* widget = field->CreateWidget();
|
||||
|
||||
widgets_[i][j] = widget;
|
||||
|
||||
layout_->addWidget(widget, i, column, 1, field->GetColumnSpan());
|
||||
|
||||
column += field->GetColumnSpan();
|
||||
}
|
||||
|
||||
// Find maximum column to place keyframe controls
|
||||
maximum_column = qMax(row->FieldCount(), maximum_column);
|
||||
}
|
||||
|
||||
// Create keyframe controls
|
||||
maximum_column++;
|
||||
|
||||
keyframe_navigators_.resize(e->row_count());
|
||||
|
||||
for (int i=0;i<e->row_count();i++) {
|
||||
EffectRow* row = e->row(i);
|
||||
|
||||
KeyframeNavigator* nav;
|
||||
|
||||
if (row->IsKeyframable()) {
|
||||
|
||||
nav = new KeyframeNavigator();
|
||||
|
||||
nav->enable_keyframes(row->IsKeyframing());
|
||||
|
||||
AttachKeyframeNavigationToRow(row, nav);
|
||||
|
||||
layout_->addWidget(nav, i, maximum_column);
|
||||
|
||||
} else {
|
||||
|
||||
nav = nullptr;
|
||||
|
||||
}
|
||||
|
||||
keyframe_navigators_[i] = nav;
|
||||
|
||||
}
|
||||
|
||||
enabled_check->setChecked(e->IsEnabled());
|
||||
connect(enabled_check, SIGNAL(toggled(bool)), e, SLOT(SetEnabled(bool)));
|
||||
connect(enabled_check, SIGNAL(toggled(bool)), e, SLOT(FieldChanged()));
|
||||
}
|
||||
|
||||
void EffectUI::AddAdditionalEffect(Effect *e)
|
||||
{
|
||||
// Ensure this is the same kind of effect and will be fully compatible
|
||||
Q_ASSERT(e->meta == effect_->meta);
|
||||
|
||||
// Add multiple modifer to header label (but only once)
|
||||
if (additional_effects_.isEmpty()) {
|
||||
QString new_title = tr("%1 (multiple)").arg(Title());
|
||||
|
||||
SetTitle(new_title);
|
||||
}
|
||||
|
||||
// Add effect to list
|
||||
additional_effects_.append(e);
|
||||
|
||||
// Attach this UI's widgets to the additional effect
|
||||
for (int i=0;i<effect_->row_count();i++) {
|
||||
|
||||
EffectRow* row = effect_->row(i);
|
||||
|
||||
// Attach existing keyframe navigator to this effect's row
|
||||
AttachKeyframeNavigationToRow(e->row(i), keyframe_navigators_.at(i));
|
||||
|
||||
for (int j=0;j<row->FieldCount();j++) {
|
||||
|
||||
// Attach existing field widget to this effect's field
|
||||
e->row(i)->Field(j)->CreateWidget(Widget(i, j));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Effect *EffectUI::GetEffect()
|
||||
{
|
||||
return effect_;
|
||||
}
|
||||
|
||||
int EffectUI::GetRowY(int row, QWidget* mapToWidget) {
|
||||
|
||||
// Currently to get a Y value in the context of `mapToWidget`, we use `panel_effect_controls` as the base. Mapping
|
||||
// to global doesn't work for some reason, so this is the best reference point we have.
|
||||
|
||||
QLabel* row_label = labels_.at(row);
|
||||
|
||||
// Get center point of label (label->rect()->center()->y() - instead of y()+height/2 - produces an inaccurate result)
|
||||
return row_label->y()
|
||||
+ row_label->height() / 2
|
||||
+ mapToWidget->mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y()
|
||||
- title_bar->height();
|
||||
}
|
||||
|
||||
void EffectUI::UpdateFromEffect()
|
||||
{
|
||||
Effect* effect = GetEffect();
|
||||
|
||||
for (int j=0;j<effect->row_count();j++) {
|
||||
|
||||
EffectRow* row = effect->row(j);
|
||||
|
||||
for (int k=0;k<row->FieldCount();k++) {
|
||||
EffectField* field = row->Field(k);
|
||||
|
||||
// Check if this UI object is attached to one effect or many
|
||||
if (additional_effects_.isEmpty()) {
|
||||
|
||||
field->UpdateWidgetValue(Widget(j, k), field->Now());
|
||||
|
||||
} else {
|
||||
|
||||
bool same_value = true;
|
||||
|
||||
for (int i=0;i<additional_effects_.size();i++) {
|
||||
EffectField* previous_field = i > 0 ? additional_effects_.at(i-1)->row(j)->Field(k) : field;
|
||||
EffectField* additional_field = additional_effects_.at(i)->row(j)->Field(k);
|
||||
|
||||
if (additional_field->GetValueAt(additional_field->Now()) != previous_field->GetValueAt(previous_field->Now())) {
|
||||
same_value = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (same_value) {
|
||||
field->UpdateWidgetValue(Widget(j, k), field->Now());
|
||||
} else {
|
||||
field->UpdateWidgetValue(Widget(j, k), qSNaN());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool EffectUI::IsAttachedToClip(Clip *c)
|
||||
{
|
||||
if (GetEffect()->parent_clip == c) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (int i=0;i<additional_effects_.size();i++) {
|
||||
if (additional_effects_.at(i)->parent_clip == c) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
QWidget *EffectUI::Widget(int row, int field)
|
||||
{
|
||||
return widgets_.at(row).at(field);
|
||||
}
|
||||
|
||||
void EffectUI::AttachKeyframeNavigationToRow(EffectRow *row, KeyframeNavigator *nav)
|
||||
{
|
||||
if (nav == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
connect(nav, SIGNAL(goto_previous_key()), row, SLOT(GoToPreviousKeyframe()));
|
||||
connect(nav, SIGNAL(toggle_key()), row, SLOT(ToggleKeyframe()));
|
||||
connect(nav, SIGNAL(goto_next_key()), row, SLOT(GoToNextKeyframe()));
|
||||
connect(nav, SIGNAL(keyframe_enabled_changed(bool)), row, SLOT(SetKeyframingEnabled(bool)));
|
||||
connect(nav, SIGNAL(clicked()), row, SLOT(FocusRow()));
|
||||
connect(row, SIGNAL(KeyframingSetChanged(bool)), nav, SLOT(enable_keyframes(bool)));
|
||||
}
|
||||
|
||||
void EffectUI::show_context_menu(const QPoint& pos) {
|
||||
if (effect_->meta->type == EFFECT_TYPE_EFFECT) {
|
||||
QMenu menu;
|
||||
|
||||
Clip* c = effect_->parent_clip;
|
||||
|
||||
int index = c->IndexOfEffect(effect_);
|
||||
|
||||
QAction* cut_action = menu.addAction(tr("Cu&t"));
|
||||
connect(cut_action, SIGNAL(triggered(bool)), this, SIGNAL(CutRequested()));
|
||||
|
||||
QAction* copy_action = menu.addAction(tr("&Copy"));
|
||||
connect(copy_action, SIGNAL(triggered(bool)), this, SIGNAL(CopyRequested()));
|
||||
|
||||
olive::MenuHelper.create_effect_paste_action(&menu);
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
if (index > 0) {
|
||||
menu.addAction(tr("Move &Up"), this, SLOT(move_up()));
|
||||
}
|
||||
|
||||
if (index < c->effects.size() - 1) {
|
||||
menu.addAction(tr("Move &Down"), this, SLOT(move_down()));
|
||||
}
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(tr("D&elete"), this, SLOT(delete_self()));
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(tr("Load Settings From File"), this, SLOT(load_from_file()));
|
||||
|
||||
menu.addAction(tr("Save Settings to File"), this, SLOT(save_to_file()));
|
||||
|
||||
menu.exec(title_bar->mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
+199
@@ -0,0 +1,199 @@
|
||||
#ifndef EFFECTUI_H
|
||||
#define EFFECTUI_H
|
||||
|
||||
#include "collapsiblewidget.h"
|
||||
#include "effects/effect.h"
|
||||
|
||||
/**
|
||||
* @brief The EffectUI class
|
||||
*
|
||||
* EffectUI is a complete QWidget-based representation of an Effect that can be added to any Qt layout. It overrides
|
||||
* CollapsibleWidget (meaning the Effect can be collapsed to just a titlebar to save space). The titlebar is
|
||||
* automatically set to the Effect's name and the contents are composed of a grid layout (QGridLayout) corresponding
|
||||
* to the Effect's EffectRow and EffectField children.
|
||||
*
|
||||
* Many EffectUIs can be created from a single Effect, and many Effects can be attached to a single EffectUI (provided
|
||||
* the Effects are all the same type). Neither gains ownership of each other and deleting an EffectUI without any other
|
||||
* work is perfectly safe (deleting an Effect with an open EffectUI however, is not).
|
||||
*/
|
||||
class EffectUI : public CollapsibleWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief EffectUI Constructor
|
||||
*
|
||||
* Creates a QWidget-based UI representation of an Effect.
|
||||
*
|
||||
* @param e
|
||||
*
|
||||
* The Effect to make a UI of. It must be a valid object.
|
||||
*/
|
||||
EffectUI(Effect* e);
|
||||
|
||||
/**
|
||||
* @brief Attach additional effects to this UI
|
||||
*
|
||||
* Olive allows users to modify several effects (of the same type) with one UI representation. To do this, you can
|
||||
* add any amount of extra Effect objects using this function and the UI will attach all of its UI functions to that
|
||||
* Effect as well without creating any new QWidgets.
|
||||
*
|
||||
* @param e
|
||||
*
|
||||
* The Effect to add to this UI object.
|
||||
*/
|
||||
void AddAdditionalEffect(Effect* e);
|
||||
|
||||
/**
|
||||
* @brief Get the primary Effect that this UI object was created for
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The Effect object passed to the constrcutor whe creating this EffectUI.
|
||||
*/
|
||||
Effect* GetEffect();
|
||||
|
||||
/**
|
||||
* @brief Get the Y position of a given row
|
||||
*
|
||||
* Retrieve the on-screen Y position of the attached Effect's EffectRow at a given index. This is primarily used for
|
||||
* displaying UI elements that align with the the row's on-screen widgets (e.g. keyframes in the EffectControls
|
||||
* panel).
|
||||
*
|
||||
* The Y value provided is specifically the center point of the row's name label. It gets mapped to a provided
|
||||
* QWidget object so it can be used locally by that QWidget without further modification.
|
||||
*
|
||||
* @param row
|
||||
*
|
||||
* The index of the EffectRow to retrieve the Y position of.
|
||||
*
|
||||
* @param mapToWidget
|
||||
*
|
||||
* The widget to map the Y value to.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The row's Y position.
|
||||
*/
|
||||
int GetRowY(int row, QWidget *mapToWidget);
|
||||
|
||||
/**
|
||||
* @brief Update widgets with the current Effect's values.
|
||||
*
|
||||
* When the Timeline playhead moves, the current values in the Effect might change if its fields are keyframed.
|
||||
* In order to visually update these values on the UI, this function should be called. It will loop through all
|
||||
* fields of all attached effects and update them to the value at the current Timeline playhead.
|
||||
*
|
||||
* Currently this function is called by update_ui() which is also responsible for updating other parts of the UI
|
||||
* like the Timeline and Viewer so they all get updated together.
|
||||
*/
|
||||
void UpdateFromEffect();
|
||||
|
||||
/**
|
||||
* @brief Check if a given Clip has an Effect referenced by this EffectUI
|
||||
*
|
||||
* Olive allows users to modify several effects (of the same type) with one UI representation. The behavior is if
|
||||
* multiple clips are selected that have effects of the same type, all those Effects can be modified by the same
|
||||
* EffectUI object. However this behavior is undesirable if a single Clip has more than one of the same type of Effect
|
||||
* (e.g. two or more blurs). In this scenario, the user will most likely expect two separate UI objects for each of
|
||||
* these effects individually, rather than consolidating them into one UI object.
|
||||
*
|
||||
* To address this, EffectControls will check this function to determine if this EffectUI already references
|
||||
* an Effect of this type from this Clip. If it does, it's assumed a new EffectUI should be made rather than
|
||||
* consolidating that Effect into the same EffectUI.
|
||||
*
|
||||
* @param c
|
||||
*
|
||||
* The Clip to determine whether an Effect of this type is already referenced by this EffectUI.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* True is an Effect from this Clip is already attached to this EffectUI.
|
||||
*/
|
||||
bool IsAttachedToClip(Clip* c);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Cut signal
|
||||
*
|
||||
* Emitted when the user selects Cut from the right-click context menu.
|
||||
*/
|
||||
void CutRequested();
|
||||
|
||||
/**
|
||||
* @brief Copy signal
|
||||
*
|
||||
* Emitted when the user selects Copy from the right-click context menu.
|
||||
*/
|
||||
void CopyRequested();
|
||||
private:
|
||||
/**
|
||||
* @brief Retrieve the QWidget corresponding a specific EffectField
|
||||
*
|
||||
* Convenience function equivalent to widgets_.at(row).at(field).
|
||||
*
|
||||
* @param row
|
||||
*
|
||||
* EffectRow index to retrieve field QWidget from
|
||||
*
|
||||
* @param field
|
||||
*
|
||||
* EffectField index to retrieve QWidget from
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The QWidget at this row and field index.
|
||||
*/
|
||||
QWidget* Widget(int row, int field);
|
||||
|
||||
/**
|
||||
* @brief Internal reference to the Effect this object was constructed around.
|
||||
*/
|
||||
Effect* effect_;
|
||||
|
||||
/**
|
||||
* @brief Internal array of additional Effect objects attached to this UI.
|
||||
*/
|
||||
QVector<Effect*> additional_effects_;
|
||||
|
||||
/**
|
||||
* @brief Layout for UI widgets
|
||||
*/
|
||||
QGridLayout* layout_;
|
||||
|
||||
/**
|
||||
* @brief Grid array of QWidgets corresponding to the Effect's rows and fields
|
||||
*/
|
||||
QVector< QVector<QWidget*> > widgets_;
|
||||
|
||||
/**
|
||||
* @brief Array of QLabel objects corresponding to each row's name().
|
||||
*/
|
||||
QVector<QLabel*> labels_;
|
||||
|
||||
/**
|
||||
* @brief Array of KeyframeNavigator objects corresponding to each row.
|
||||
*/
|
||||
QVector<KeyframeNavigator*> keyframe_navigators_;
|
||||
|
||||
/**
|
||||
* @brief Attach a KeyframeNavigator object to an EffectRow.
|
||||
*
|
||||
* Internal function for connecting a KeyframeNavigator UI object to an EffectRow.
|
||||
*
|
||||
* @param row
|
||||
*
|
||||
* The EffectRow object.
|
||||
*
|
||||
* @param nav
|
||||
*
|
||||
* The KeyframeNavigator object.
|
||||
*/
|
||||
void AttachKeyframeNavigationToRow(EffectRow* row, KeyframeNavigator* nav);
|
||||
private slots:
|
||||
/**
|
||||
* @brief Slot for titlebar's right-click signal to show a context menu for extra Effect functions.
|
||||
*/
|
||||
void show_context_menu(const QPoint&);
|
||||
};
|
||||
|
||||
#endif // EFFECTUI_H
|
||||
+33
-38
@@ -27,54 +27,49 @@
|
||||
#include <QFileDialog>
|
||||
|
||||
EmbeddedFileChooser::EmbeddedFileChooser(QWidget* parent) : QWidget(parent) {
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
file_label = new QLabel(this);
|
||||
update_label();
|
||||
layout->addWidget(file_label);
|
||||
QPushButton* browse_button = new QPushButton("...", this);
|
||||
browse_button->setFixedWidth(25);
|
||||
layout->addWidget(browse_button);
|
||||
connect(browse_button, SIGNAL(clicked(bool)), this, SLOT(browse()));
|
||||
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||
layout->setMargin(0);
|
||||
file_label = new QLabel(this);
|
||||
update_label();
|
||||
layout->addWidget(file_label);
|
||||
QPushButton* browse_button = new QPushButton("...", this);
|
||||
browse_button->setFixedWidth(25);
|
||||
layout->addWidget(browse_button);
|
||||
connect(browse_button, SIGNAL(clicked(bool)), this, SLOT(browse()));
|
||||
}
|
||||
|
||||
const QString &EmbeddedFileChooser::getFilename() {
|
||||
return filename;
|
||||
}
|
||||
|
||||
const QString &EmbeddedFileChooser::getPreviousValue() {
|
||||
return old_filename;
|
||||
return filename;
|
||||
}
|
||||
|
||||
void EmbeddedFileChooser::setFilename(const QString &s) {
|
||||
old_filename = filename;
|
||||
filename = s;
|
||||
update_label();
|
||||
emit changed();
|
||||
filename = s;
|
||||
update_label();
|
||||
emit changed(filename);
|
||||
}
|
||||
|
||||
void EmbeddedFileChooser::update_label() {
|
||||
QString l = "<html>" + tr("File:") + " ";
|
||||
if (filename.isEmpty()) {
|
||||
l += "(none)";
|
||||
} else {
|
||||
bool file_exists = QFileInfo::exists(filename);
|
||||
if (!file_exists) l += "<font color='red'>";
|
||||
QString short_fn = filename.mid(filename.lastIndexOf('/')+1);
|
||||
if (short_fn.size() > 20) {
|
||||
l += "..." + short_fn.right(20);
|
||||
} else {
|
||||
l += short_fn;
|
||||
}
|
||||
if (!file_exists) l += "</font>";
|
||||
}
|
||||
l += "</html>";
|
||||
file_label->setText(l);
|
||||
QString l = "<html>" + tr("File:") + " ";
|
||||
if (filename.isEmpty()) {
|
||||
l += "(none)";
|
||||
} else {
|
||||
bool file_exists = QFileInfo::exists(filename);
|
||||
if (!file_exists) l += "<font color='red'>";
|
||||
QString short_fn = filename.mid(filename.lastIndexOf('/')+1);
|
||||
if (short_fn.size() > 20) {
|
||||
l += "..." + short_fn.right(20);
|
||||
} else {
|
||||
l += short_fn;
|
||||
}
|
||||
if (!file_exists) l += "</font>";
|
||||
}
|
||||
l += "</html>";
|
||||
file_label->setText(l);
|
||||
}
|
||||
|
||||
void EmbeddedFileChooser::browse() {
|
||||
QString fn = QFileDialog::getOpenFileName(this);
|
||||
if (!fn.isEmpty()) {
|
||||
setFilename(fn);
|
||||
}
|
||||
QString fn = QFileDialog::getOpenFileName(this);
|
||||
if (!fn.isEmpty()) {
|
||||
setFilename(fn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,22 +26,20 @@
|
||||
class QLabel;
|
||||
|
||||
class EmbeddedFileChooser : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
EmbeddedFileChooser(QWidget* parent = 0);
|
||||
EmbeddedFileChooser(QWidget* parent = 0);
|
||||
|
||||
const QString& getFilename();
|
||||
const QString& getPreviousValue();
|
||||
void setFilename(const QString& s);
|
||||
const QString& getFilename();
|
||||
void setFilename(const QString& s);
|
||||
signals:
|
||||
void changed();
|
||||
void changed(const QString& s);
|
||||
private:
|
||||
QLabel* file_label;
|
||||
QString filename;
|
||||
QString old_filename;
|
||||
void update_label();
|
||||
QLabel* file_label;
|
||||
QString filename;
|
||||
void update_label();
|
||||
private slots:
|
||||
void browse();
|
||||
void browse();
|
||||
};
|
||||
|
||||
#endif // EMBEDDEDFILECHOOSER_H
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@
|
||||
#include "focusfilter.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
#include "project/sequence.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "ui/timelineheader.h"
|
||||
|
||||
FocusFilter olive::FocusFilter;
|
||||
@@ -197,7 +197,7 @@ void FocusFilter::delete_function() {
|
||||
} else if (panel_sequence_viewer->headers->hasFocus()) {
|
||||
panel_sequence_viewer->headers->delete_markers();
|
||||
} else if (panel_effect_controls->is_focused()) {
|
||||
panel_effect_controls->delete_effects();
|
||||
panel_effect_controls->DeleteSelectedEffects();
|
||||
} else if (panel_project->is_focused()) {
|
||||
panel_project->delete_selected_media();
|
||||
} else if (panel_effect_controls->keyframe_focus()) {
|
||||
|
||||
+5
-10
@@ -22,19 +22,14 @@
|
||||
|
||||
#include <QFontDatabase>
|
||||
|
||||
FontCombobox::FontCombobox(QWidget* parent) : ComboBoxEx(parent) {
|
||||
addItems(QFontDatabase().families());
|
||||
FontCombobox::FontCombobox(QWidget* parent) : QComboBox(parent) {
|
||||
addItems(QFontDatabase().families());
|
||||
|
||||
value = currentText();
|
||||
value = currentText();
|
||||
|
||||
connect(this, SIGNAL(currentTextChanged(QString)), this, SLOT(updateInternals()));
|
||||
}
|
||||
|
||||
const QString& FontCombobox::getPreviousValue() {
|
||||
return previousValue;
|
||||
connect(this, SIGNAL(currentTextChanged(QString)), this, SLOT(updateInternals()));
|
||||
}
|
||||
|
||||
void FontCombobox::updateInternals() {
|
||||
previousValue = value;
|
||||
value = currentText();
|
||||
value = currentText();
|
||||
}
|
||||
|
||||
+6
-8
@@ -21,18 +21,16 @@
|
||||
#ifndef FONTCOMBOBOX_H
|
||||
#define FONTCOMBOBOX_H
|
||||
|
||||
#include "comboboxex.h"
|
||||
#include <QComboBox>
|
||||
|
||||
class FontCombobox : public ComboBoxEx {
|
||||
Q_OBJECT
|
||||
class FontCombobox : public QComboBox {
|
||||
Q_OBJECT
|
||||
public:
|
||||
FontCombobox(QWidget* parent = 0);
|
||||
const QString &getPreviousValue();
|
||||
FontCombobox(QWidget* parent = nullptr);
|
||||
private slots:
|
||||
void updateInternals();
|
||||
void updateInternals();
|
||||
private:
|
||||
QString previousValue;
|
||||
QString value;
|
||||
QString value;
|
||||
};
|
||||
|
||||
#endif // FONTCOMBOBOX_H
|
||||
|
||||
+49
-50
@@ -26,19 +26,18 @@
|
||||
#include <QMenu>
|
||||
#include <cfloat>
|
||||
|
||||
#include "io/config.h"
|
||||
#include "global/config.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "project/sequence.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "ui/keyframedrawing.h"
|
||||
#include "project/undo.h"
|
||||
#include "project/effect.h"
|
||||
#include "project/clip.h"
|
||||
#include "undo/undo.h"
|
||||
#include "undo/undostack.h"
|
||||
#include "effects/effect.h"
|
||||
#include "timeline/clip.h"
|
||||
#include "ui/rectangleselect.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#include "global/debug.h"
|
||||
|
||||
const double kGraphZoomSpeed = 0.05;
|
||||
const int kGraphSize = 100;
|
||||
@@ -120,15 +119,15 @@ void GraphView::set_view_to_selection() {
|
||||
double min_dbl = DBL_MAX;
|
||||
double max_dbl = DBL_MIN;
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
const EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i));
|
||||
const EffectKeyframe& key = row->Field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i));
|
||||
min_time = qMin(key.time, min_time);
|
||||
max_time = qMax(key.time, max_time);
|
||||
min_dbl = qMin(key.data.toDouble(), min_dbl);
|
||||
max_dbl = qMax(key.data.toDouble(), max_dbl);
|
||||
}
|
||||
|
||||
min_time -= row->parent_effect->parent_clip->clip_in();
|
||||
max_time -= row->parent_effect->parent_clip->clip_in();
|
||||
min_time -= row->GetParentEffect()->parent_clip->clip_in();
|
||||
max_time -= row->GetParentEffect()->parent_clip->clip_in();
|
||||
|
||||
set_view_to_rect(min_time, min_dbl, max_time, max_dbl);
|
||||
}
|
||||
@@ -142,9 +141,9 @@ void GraphView::set_view_to_all() {
|
||||
long max_time = LONG_MIN;
|
||||
double min_dbl = DBL_MAX;
|
||||
double max_dbl = DBL_MIN;
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
for (int j=0;j<row->field(i)->keyframes.size();j++) {
|
||||
const EffectKeyframe& key = row->field(i)->keyframes.at(j);
|
||||
for (int i=0;i<row->FieldCount();i++) {
|
||||
for (int j=0;j<row->Field(i)->keyframes.size();j++) {
|
||||
const EffectKeyframe& key = row->Field(i)->keyframes.at(j);
|
||||
min_time = qMin(key.time, min_time);
|
||||
max_time = qMax(key.time, max_time);
|
||||
min_dbl = qMin(key.data.toDouble(), min_dbl);
|
||||
@@ -153,8 +152,8 @@ void GraphView::set_view_to_all() {
|
||||
}
|
||||
}
|
||||
if (can_set) {
|
||||
min_time -= row->parent_effect->parent_clip->clip_in();
|
||||
max_time -= row->parent_effect->parent_clip->clip_in();
|
||||
min_time -= row->GetParentEffect()->parent_clip->clip_in();
|
||||
max_time -= row->GetParentEffect()->parent_clip->clip_in();
|
||||
|
||||
set_view_to_rect(min_time, min_dbl, max_time, max_dbl);
|
||||
}
|
||||
@@ -242,10 +241,10 @@ void GraphView::paintEvent(QPaintEvent *) {
|
||||
QPen line_pen;
|
||||
line_pen.setWidth(kBezierLineSize);
|
||||
|
||||
for (int i=row->fieldCount()-1;i>=0;i--) {
|
||||
EffectField* field = row->field(i);
|
||||
for (int i=row->FieldCount()-1;i>=0;i--) {
|
||||
EffectField* field = row->Field(i);
|
||||
|
||||
if (field->type == EFFECT_FIELD_DOUBLE && field_visibility.at(i)) {
|
||||
if (field->type() == EffectField::EFFECT_FIELD_DOUBLE && field_visibility.at(i)) {
|
||||
// sort keyframes by time
|
||||
QVector<int> sorted_keys = sort_keys_from_field(field);
|
||||
|
||||
@@ -259,15 +258,15 @@ void GraphView::paintEvent(QPaintEvent *) {
|
||||
int key_x = get_screen_x(key.time);
|
||||
int key_y = get_screen_y(key.data.toDouble());
|
||||
|
||||
line_pen.setColor(get_curve_color(i, row->fieldCount()));
|
||||
line_pen.setColor(get_curve_color(i, row->FieldCount()));
|
||||
p.setPen(line_pen);
|
||||
if (j == 0) {
|
||||
p.drawLine(0, key_y, key_x, key_y);
|
||||
} else {
|
||||
const EffectKeyframe& last_key = field->keyframes.at(sorted_keys.at(j-1));
|
||||
|
||||
double pre_handle = field->get_validated_keyframe_handle(sorted_keys.at(j), false);
|
||||
double last_post_handle = field->get_validated_keyframe_handle(sorted_keys.at(j-1), true);
|
||||
double pre_handle = field->GetValidKeyframeHandlePosition(sorted_keys.at(j), false);
|
||||
double last_post_handle = field->GetValidKeyframeHandlePosition(sorted_keys.at(j-1), true);
|
||||
|
||||
if (last_key.type == EFFECT_KEYFRAME_HOLD) {
|
||||
// hold
|
||||
@@ -385,9 +384,9 @@ void GraphView::mousePressEvent(QMouseEvent *event) {
|
||||
update_ui(false);
|
||||
click_add_proc = true;
|
||||
} else {
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
EffectField* field = row->field(i);
|
||||
if (field->type == EFFECT_FIELD_DOUBLE && field_visibility.at(i)) {
|
||||
for (int i=0;i<row->FieldCount();i++) {
|
||||
EffectField* field = row->Field(i);
|
||||
if (field->type() == EffectField::EFFECT_FIELD_DOUBLE && field_visibility.at(i)) {
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
const EffectKeyframe& key = field->keyframes.at(j);
|
||||
int key_x = get_screen_x(key.time);
|
||||
@@ -488,8 +487,8 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
selected_keys.resize(rect_select_offset);
|
||||
selected_keys_fields.resize(rect_select_offset);
|
||||
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
EffectField* f = row->field(i);
|
||||
for (int i=0;i<row->FieldCount();i++) {
|
||||
EffectField* f = row->Field(i);
|
||||
for (int j=0;j<f->keyframes.size();j++) {
|
||||
bool already_selected = false;
|
||||
for (int k=0;k<selected_keys.size();k++) {
|
||||
@@ -514,11 +513,11 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
switch (current_handle) {
|
||||
case kBezierHandleNone:
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].time = qRound(selected_keys_old_vals.at(i) + (double(event->pos().x() - start_x)/x_zoom));
|
||||
row->Field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].time = qRound(selected_keys_old_vals.at(i) + (double(event->pos().x() - start_x)/x_zoom));
|
||||
if (event->modifiers() & Qt::ShiftModifier) {
|
||||
row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].data = selected_keys_old_doubles.at(i);
|
||||
row->Field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].data = selected_keys_old_doubles.at(i);
|
||||
} else {
|
||||
row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].data = qRound(selected_keys_old_doubles.at(i) + (double(start_y - event->pos().y())/y_zoom));
|
||||
row->Field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)].data = qRound(selected_keys_old_doubles.at(i) + (double(start_y - event->pos().y())/y_zoom));
|
||||
}
|
||||
}
|
||||
moved_keys = true;
|
||||
@@ -551,7 +550,7 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
}
|
||||
}
|
||||
|
||||
EffectKeyframe& key = row->field(handle_field)->keyframes[handle_index];
|
||||
EffectKeyframe& key = row->Field(handle_field)->keyframes[handle_index];
|
||||
key.pre_handle_x = qMin(0.0, new_pre_handle_x);
|
||||
key.pre_handle_y = new_pre_handle_y;
|
||||
key.post_handle_x = qMax(0.0, new_post_handle_x);
|
||||
@@ -569,9 +568,9 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
|
||||
bool hovering_key = false;
|
||||
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
for (int j=0;j<row->field(i)->keyframes.size();j++) {
|
||||
const EffectKeyframe& key = row->field(i)->keyframes.at(j);
|
||||
for (int i=0;i<row->FieldCount();i++) {
|
||||
for (int j=0;j<row->Field(i)->keyframes.size();j++) {
|
||||
const EffectKeyframe& key = row->Field(i)->keyframes.at(j);
|
||||
int key_x = get_screen_x(key.time);
|
||||
int key_y = get_screen_y(key.data.toDouble());
|
||||
QRect test_rect(
|
||||
@@ -603,8 +602,8 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
}
|
||||
|
||||
if (!hovering_key) {
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
EffectField* f = row->field(i);
|
||||
for (int i=0;i<row->FieldCount();i++) {
|
||||
EffectField* f = row->Field(i);
|
||||
if (field_visibility.at(i)) {
|
||||
QVector<int> sorted_keys = sort_keys_from_field(f);
|
||||
|
||||
@@ -702,13 +701,13 @@ void GraphView::mouseMoveEvent(QMouseEvent *event) {
|
||||
|
||||
void GraphView::mouseReleaseEvent(QMouseEvent *) {
|
||||
if (click_add_proc) {
|
||||
olive::UndoStack.push(new KeyframeFieldSet(click_add_field, click_add_key));
|
||||
olive::UndoStack.push(new KeyframeAdd(click_add_field, click_add_key));
|
||||
} else if (moved_keys && selected_keys.size() > 0) {
|
||||
ComboAction* ca = new ComboAction();
|
||||
switch (current_handle) {
|
||||
case kBezierHandleNone:
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)];
|
||||
EffectKeyframe& key = row->Field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)];
|
||||
ca->append(new SetLong(&key.time, selected_keys_old_vals.at(i), key.time));
|
||||
ca->append(new SetQVariant(&key.data, selected_keys_old_doubles.at(i), key.data));
|
||||
}
|
||||
@@ -716,7 +715,7 @@ void GraphView::mouseReleaseEvent(QMouseEvent *) {
|
||||
case kBezierHandlePre:
|
||||
case kBezierHandlePost:
|
||||
{
|
||||
EffectKeyframe& key = row->field(handle_field)->keyframes[handle_index];
|
||||
EffectKeyframe& key = row->Field(handle_field)->keyframes[handle_index];
|
||||
ca->append(new SetDouble(&key.pre_handle_x, old_pre_handle_x, key.pre_handle_x));
|
||||
ca->append(new SetDouble(&key.pre_handle_y, old_pre_handle_y, key.pre_handle_y));
|
||||
ca->append(new SetDouble(&key.post_handle_x, old_post_handle_x, key.post_handle_x));
|
||||
@@ -831,11 +830,11 @@ void GraphView::set_row(EffectRow *r) {
|
||||
emit selection_changed(false, -1);
|
||||
row = r;
|
||||
if (row != nullptr) {
|
||||
field_visibility.resize(row->fieldCount());
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
field_visibility[i] = row->field(i)->is_enabled();
|
||||
field_visibility.resize(row->FieldCount());
|
||||
for (int i=0;i<row->FieldCount();i++) {
|
||||
field_visibility[i] = row->Field(i)->IsEnabled();
|
||||
}
|
||||
visible_in = row->parent_effect->parent_clip->timeline_in();
|
||||
visible_in = row->GetParentEffect()->parent_clip->timeline_in();
|
||||
set_view_to_all();
|
||||
} else {
|
||||
update();
|
||||
@@ -847,7 +846,7 @@ void GraphView::set_selected_keyframe_type(int type) {
|
||||
if (selected_keys.size() > 0) {
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)];
|
||||
EffectKeyframe& key = row->Field(selected_keys_fields.at(i))->keyframes[selected_keys.at(i)];
|
||||
ca->append(new SetInt(&key.type, type));
|
||||
}
|
||||
olive::UndoStack.push(ca);
|
||||
@@ -864,7 +863,7 @@ void GraphView::delete_selected_keys() {
|
||||
if (row != nullptr) {
|
||||
QVector<EffectField*> fields;
|
||||
for (int i=0;i<selected_keys_fields.size();i++) {
|
||||
fields.append(row->field(selected_keys_fields.at(i)));
|
||||
fields.append(row->Field(selected_keys_fields.at(i)));
|
||||
}
|
||||
delete_keyframes(fields, selected_keys);
|
||||
}
|
||||
@@ -874,8 +873,8 @@ void GraphView::select_all() {
|
||||
if (row != nullptr) {
|
||||
selected_keys.clear();
|
||||
selected_keys_fields.clear();
|
||||
for (int i=0;i<row->fieldCount();i++) {
|
||||
EffectField* field = row->field(i);
|
||||
for (int i=0;i<row->FieldCount();i++) {
|
||||
EffectField* field = row->Field(i);
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
selected_keys.append(j);
|
||||
selected_keys_fields.append(i);
|
||||
@@ -903,7 +902,7 @@ void GraphView::set_zoom(double xz, double yz) {
|
||||
|
||||
int GraphView::get_screen_x(double d) {
|
||||
if (row != nullptr) {
|
||||
d -= row->parent_effect->parent_clip->clip_in();
|
||||
d -= row->GetParentEffect()->parent_clip->clip_in();
|
||||
}
|
||||
return qRound((d*x_zoom) - x_scroll);
|
||||
}
|
||||
@@ -915,7 +914,7 @@ int GraphView::get_screen_y(double d) {
|
||||
long GraphView::get_value_x(int i) {
|
||||
long frame = qRound((i + x_scroll)/x_zoom);
|
||||
if (row != nullptr) {
|
||||
frame += row->parent_effect->parent_clip->clip_in();
|
||||
frame += row->GetParentEffect()->parent_clip->clip_in();
|
||||
}
|
||||
return frame;
|
||||
}
|
||||
@@ -931,7 +930,7 @@ void GraphView::selection_update() {
|
||||
int selected_key_type = -1;
|
||||
|
||||
for (int i=0;i<selected_keys.size();i++) {
|
||||
const EffectKeyframe& key = row->field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i));
|
||||
const EffectKeyframe& key = row->Field(selected_keys_fields.at(i))->keyframes.at(selected_keys.at(i));
|
||||
selected_keys_old_vals.append(key.time);
|
||||
selected_keys_old_doubles.append(key.data.toDouble());
|
||||
|
||||
|
||||
+2
-2
@@ -24,8 +24,8 @@
|
||||
#include <QWidget>
|
||||
#include <QVector>
|
||||
|
||||
#include "project/effectrow.h"
|
||||
#include "project/effectfield.h"
|
||||
#include "effects/effectrow.h"
|
||||
#include "effects/effectfields.h"
|
||||
|
||||
QColor get_curve_color(int index, int length);
|
||||
|
||||
|
||||
+18
-2
@@ -1,6 +1,9 @@
|
||||
#include "icons.h"
|
||||
|
||||
#include "oliveglobal.h"
|
||||
#include <QDebug>
|
||||
|
||||
#include "global/global.h"
|
||||
#include "global/config.h"
|
||||
|
||||
QIcon olive::icon::LeftArrow;
|
||||
QIcon olive::icon::RightArrow;
|
||||
@@ -27,14 +30,27 @@ QIcon olive::icon::CreateIconFromSVG(const QString &path)
|
||||
{
|
||||
QIcon icon;
|
||||
|
||||
QPainter p;
|
||||
|
||||
// Draw the icon as a solid color
|
||||
QPixmap normal(path);
|
||||
|
||||
if (olive::styling::UseDarkIcons()) {
|
||||
p.begin(&normal);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceIn);
|
||||
p.fillRect(normal.rect(), QColor(32, 32, 32));
|
||||
p.end();
|
||||
}
|
||||
|
||||
icon.addPixmap(normal, QIcon::Normal, QIcon::On);
|
||||
|
||||
// Create semi-transparent disabled icon
|
||||
QPixmap disabled(normal.size());
|
||||
disabled.fill(Qt::transparent);
|
||||
|
||||
// draw semi-transparent version of icon for the disabled variant
|
||||
QPainter p(&disabled);
|
||||
p.begin(&disabled);
|
||||
p.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
p.setOpacity(0.5);
|
||||
p.drawPixmap(0, 0, normal);
|
||||
p.end();
|
||||
|
||||
+26
-26
@@ -20,42 +20,42 @@
|
||||
|
||||
#include "keyframedrawing.h"
|
||||
|
||||
#include "project/effect.h"
|
||||
#include "project/clip.h"
|
||||
#include "effects/effect.h"
|
||||
#include "timeline/clip.h"
|
||||
|
||||
#define KEYFRAME_POINT_COUNT 4
|
||||
|
||||
// routine for drawing a keyframe onscreen
|
||||
void draw_keyframe(QPainter &p, int type, int x, int y, bool darker, int r, int g, int b) {
|
||||
if (darker) {
|
||||
r *= 0.625;
|
||||
g *= 0.625;
|
||||
b *= 0.625;
|
||||
}
|
||||
p.setPen(QColor(0, 0, 0));
|
||||
p.setBrush(QColor(r, g, b));
|
||||
if (darker) {
|
||||
r *= 0.625;
|
||||
g *= 0.625;
|
||||
b *= 0.625;
|
||||
}
|
||||
p.setPen(QColor(0, 0, 0));
|
||||
p.setBrush(QColor(r, g, b));
|
||||
|
||||
switch (type) {
|
||||
case EFFECT_KEYFRAME_LINEAR:
|
||||
{
|
||||
QPoint points[KEYFRAME_POINT_COUNT] = {QPoint(x-KEYFRAME_SIZE, y), QPoint(x, y-KEYFRAME_SIZE), QPoint(x+KEYFRAME_SIZE, y), QPoint(x, y+KEYFRAME_SIZE)};
|
||||
p.drawPolygon(points, KEYFRAME_POINT_COUNT);
|
||||
}
|
||||
break;
|
||||
case EFFECT_KEYFRAME_BEZIER:
|
||||
p.drawEllipse(QPoint(x, y), KEYFRAME_SIZE, KEYFRAME_SIZE);
|
||||
break;
|
||||
case EFFECT_KEYFRAME_HOLD:
|
||||
p.drawRect(QRect(x - KEYFRAME_SIZE, y - KEYFRAME_SIZE, KEYFRAME_SIZE*2, KEYFRAME_SIZE*2));
|
||||
break;
|
||||
}
|
||||
switch (type) {
|
||||
case EFFECT_KEYFRAME_LINEAR:
|
||||
{
|
||||
QPoint points[KEYFRAME_POINT_COUNT] = {QPoint(x-KEYFRAME_SIZE, y), QPoint(x, y-KEYFRAME_SIZE), QPoint(x+KEYFRAME_SIZE, y), QPoint(x, y+KEYFRAME_SIZE)};
|
||||
p.drawPolygon(points, KEYFRAME_POINT_COUNT);
|
||||
}
|
||||
break;
|
||||
case EFFECT_KEYFRAME_BEZIER:
|
||||
p.drawEllipse(QPoint(x, y), KEYFRAME_SIZE, KEYFRAME_SIZE);
|
||||
break;
|
||||
case EFFECT_KEYFRAME_HOLD:
|
||||
p.drawRect(QRect(x - KEYFRAME_SIZE, y - KEYFRAME_SIZE, KEYFRAME_SIZE*2, KEYFRAME_SIZE*2));
|
||||
break;
|
||||
}
|
||||
|
||||
p.setBrush(Qt::NoBrush);
|
||||
p.setBrush(Qt::NoBrush);
|
||||
}
|
||||
|
||||
// adjusts keyframe's internal time (in clip time) to timeline time
|
||||
long adjust_row_keyframe(EffectRow* row, long time, long visible_in) {
|
||||
return time
|
||||
- row->parent_effect->parent_clip->clip_in()
|
||||
+ (row->parent_effect->parent_clip->timeline_in() - visible_in);
|
||||
- row->GetParentEffect()->parent_clip->clip_in()
|
||||
+ (row->GetParentEffect()->parent_clip->timeline_in() - visible_in);
|
||||
}
|
||||
|
||||
@@ -24,10 +24,13 @@
|
||||
#include <QPushButton>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDebug>
|
||||
|
||||
#include "ui/icons.h"
|
||||
|
||||
KeyframeNavigator::KeyframeNavigator(QWidget *parent, bool addLeftPad) : QWidget(parent) {
|
||||
setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
|
||||
|
||||
key_controls = new QHBoxLayout(this);
|
||||
key_controls->setSpacing(0);
|
||||
key_controls->setMargin(0);
|
||||
@@ -60,7 +63,8 @@ KeyframeNavigator::KeyframeNavigator(QWidget *parent, bool addLeftPad) : QWidget
|
||||
connect(right_key_nav, SIGNAL(clicked(bool)), this, SIGNAL(goto_next_key()));
|
||||
connect(right_key_nav, SIGNAL(clicked(bool)), this, SIGNAL(clicked()));
|
||||
|
||||
keyframe_enable = new QPushButton(olive::icon::Clock, "", this);
|
||||
keyframe_enable = new QPushButton(this);
|
||||
keyframe_enable->setIcon(olive::icon::Clock);
|
||||
keyframe_enable->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
keyframe_enable->setIconSize(keyframe_enable->iconSize()*0.75);
|
||||
keyframe_enable->setCheckable(true);
|
||||
|
||||
+18
-16
@@ -28,26 +28,28 @@ class QPushButton;
|
||||
|
||||
class KeyframeNavigator : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyframeNavigator(QWidget* parent = 0, bool addLeftPad = true);
|
||||
~KeyframeNavigator();
|
||||
void enable_keyframes(bool);
|
||||
void enable_keyframe_toggle(bool);
|
||||
KeyframeNavigator(QWidget* parent = nullptr, bool addLeftPad = true);
|
||||
~KeyframeNavigator();
|
||||
|
||||
void enable_keyframe_toggle(bool);
|
||||
public slots:
|
||||
void enable_keyframes(bool);
|
||||
signals:
|
||||
void goto_previous_key();
|
||||
void toggle_key();
|
||||
void goto_next_key();
|
||||
void keyframe_enabled_changed(bool);
|
||||
void clicked();
|
||||
void goto_previous_key();
|
||||
void toggle_key();
|
||||
void goto_next_key();
|
||||
void keyframe_enabled_changed(bool);
|
||||
void clicked();
|
||||
private slots:
|
||||
void keyframe_ui_enabled(bool);
|
||||
void keyframe_ui_enabled(bool);
|
||||
private:
|
||||
QHBoxLayout* key_controls;
|
||||
QPushButton* left_key_nav;
|
||||
QPushButton* key_addremove;
|
||||
QPushButton* right_key_nav;
|
||||
QPushButton* keyframe_enable;
|
||||
QHBoxLayout* key_controls;
|
||||
QPushButton* left_key_nav;
|
||||
QPushButton* key_addremove;
|
||||
QPushButton* right_key_nav;
|
||||
QPushButton* keyframe_enable;
|
||||
};
|
||||
|
||||
#endif // KEYFRAMENAVIGATOR_H
|
||||
|
||||
+66
-62
@@ -20,29 +20,29 @@
|
||||
|
||||
#include "keyframeview.h"
|
||||
|
||||
#include "project/effect.h"
|
||||
#include <QMouseEvent>
|
||||
#include <QtMath>
|
||||
#include <QMenu>
|
||||
|
||||
#include "effects/effect.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/effectcontrols.h"
|
||||
#include "project/clip.h"
|
||||
#include "timeline/clip.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "ui/timelineheader.h"
|
||||
#include "project/undo.h"
|
||||
#include "undo/undo.h"
|
||||
#include "undo/undostack.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "project/sequence.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "panels/grapheditor.h"
|
||||
#include "ui/keyframedrawing.h"
|
||||
#include "ui/clickablelabel.h"
|
||||
#include "ui/resizablescrollbar.h"
|
||||
#include "ui/rectangleselect.h"
|
||||
#include "project/keyframe.h"
|
||||
#include "effects/keyframe.h"
|
||||
#include "ui/graphview.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QtMath>
|
||||
#include <QMenu>
|
||||
|
||||
KeyframeView::KeyframeView(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
visible_in(0),
|
||||
@@ -62,6 +62,11 @@ KeyframeView::KeyframeView(QWidget *parent) :
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&)));
|
||||
}
|
||||
|
||||
void KeyframeView::SetEffects(const QVector<EffectUI *> &open_effects)
|
||||
{
|
||||
open_effects_ = open_effects;
|
||||
}
|
||||
|
||||
void KeyframeView::show_context_menu(const QPoint& pos) {
|
||||
if (selected_fields.size() > 0) {
|
||||
QMenu menu(this);
|
||||
@@ -101,62 +106,61 @@ void KeyframeView::paintEvent(QPaintEvent*) {
|
||||
rowY.clear();
|
||||
rows.clear();
|
||||
|
||||
if (panel_effect_controls->selected_clips.size() > 0) {
|
||||
if (!open_effects_.isEmpty()) {
|
||||
visible_in = LONG_MAX;
|
||||
visible_out = 0;
|
||||
|
||||
for (int j=0;j<panel_effect_controls->selected_clips.size();j++) {
|
||||
ClipPtr c = olive::ActiveSequence->clips.at(panel_effect_controls->selected_clips.at(j));
|
||||
for (int i=0;i<open_effects_.size();i++) {
|
||||
Clip* c = open_effects_.at(i)->GetEffect()->parent_clip;
|
||||
visible_in = qMin(visible_in, c->timeline_in());
|
||||
visible_out = qMax(visible_out, c->timeline_out());
|
||||
}
|
||||
|
||||
for (int j=0;j<panel_effect_controls->selected_clips.size();j++) {
|
||||
ClipPtr c = olive::ActiveSequence->clips.at(panel_effect_controls->selected_clips.at(j));
|
||||
for (int i=0;i<c->effects.size();i++) {
|
||||
EffectPtr e = c->effects.at(i);
|
||||
if (e->container->is_expanded()) {
|
||||
for (int j=0;j<e->row_count();j++) {
|
||||
EffectRow* row = e->row(j);
|
||||
for (int j=0;j<open_effects_.size();j++) {
|
||||
|
||||
ClickableLabel* label = row->label;
|
||||
QWidget* contents = e->container->contents;
|
||||
EffectUI* container = open_effects_.at(j);
|
||||
Effect* e = container->GetEffect();
|
||||
|
||||
QVector<long> key_times;
|
||||
int keyframe_y = label->y() + (label->height()>>1) + mapFrom(panel_effect_controls, contents->mapTo(panel_effect_controls, contents->pos())).y() - e->container->title_bar->height()/* - y_scroll*/;
|
||||
for (int l=0;l<row->fieldCount();l++) {
|
||||
EffectField* f = row->field(l);
|
||||
for (int k=0;k<f->keyframes.size();k++) {
|
||||
if (!key_times.contains(f->keyframes.at(k).time)) {
|
||||
bool keyframe_selected = keyframeIsSelected(f, k);
|
||||
long keyframe_frame = adjust_row_keyframe(row, f->keyframes.at(k).time, visible_in);
|
||||
if (container->IsExpanded()) {
|
||||
for (int j=0;j<e->row_count();j++) {
|
||||
EffectRow* row = e->row(j);
|
||||
|
||||
// see if any other keyframes have this time
|
||||
int appearances = 0;
|
||||
for (int m=0;m<row->fieldCount();m++) {
|
||||
EffectField* compf = row->field(m);
|
||||
for (int n=0;n<compf->keyframes.size();n++) {
|
||||
if (f->keyframes.at(k).time == compf->keyframes.at(n).time) {
|
||||
appearances++;
|
||||
}
|
||||
int keyframe_y = container->GetRowY(j, this);
|
||||
|
||||
QVector<long> key_times;
|
||||
|
||||
for (int l=0;l<row->FieldCount();l++) {
|
||||
EffectField* f = row->Field(l);
|
||||
for (int k=0;k<f->keyframes.size();k++) {
|
||||
if (!key_times.contains(f->keyframes.at(k).time)) {
|
||||
bool keyframe_selected = keyframeIsSelected(f, k);
|
||||
long keyframe_frame = adjust_row_keyframe(row, f->keyframes.at(k).time, visible_in);
|
||||
|
||||
// see if any other keyframes have this time
|
||||
int appearances = 0;
|
||||
for (int m=0;m<row->FieldCount();m++) {
|
||||
EffectField* compf = row->Field(m);
|
||||
for (int n=0;n<compf->keyframes.size();n++) {
|
||||
if (f->keyframes.at(k).time == compf->keyframes.at(n).time) {
|
||||
appearances++;
|
||||
}
|
||||
}
|
||||
|
||||
if (appearances != row->fieldCount()) {
|
||||
QColor cc = get_curve_color(l, row->fieldCount());
|
||||
draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected, cc.red(), cc.green(), cc.blue());
|
||||
} else {
|
||||
draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected);
|
||||
}
|
||||
|
||||
key_times.append(f->keyframes.at(k).time);
|
||||
}
|
||||
|
||||
if (appearances != row->FieldCount()) {
|
||||
QColor cc = get_curve_color(l, row->FieldCount());
|
||||
draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected, cc.red(), cc.green(), cc.blue());
|
||||
} else {
|
||||
draw_keyframe(p, f->keyframes.at(k).type, getScreenPointFromFrame(panel_effect_controls->zoom, keyframe_frame) - x_scroll, keyframe_y, keyframe_selected);
|
||||
}
|
||||
|
||||
key_times.append(f->keyframes.at(k).time);
|
||||
}
|
||||
}
|
||||
|
||||
rows.append(row);
|
||||
rowY.append(keyframe_y);
|
||||
}
|
||||
|
||||
rows.append(row);
|
||||
rowY.append(keyframe_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,12 +254,12 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
if (mouse_y > rowY.at(i)-KEYFRAME_SIZE-KEYFRAME_SIZE && mouse_y < rowY.at(i)+KEYFRAME_SIZE+KEYFRAME_SIZE) {
|
||||
EffectRow* row = rows.at(i);
|
||||
|
||||
row->focus_row();
|
||||
row->FocusRow();
|
||||
|
||||
for (int k=0;k<row->fieldCount();k++) {
|
||||
EffectField* f = row->field(k);
|
||||
for (int k=0;k<row->FieldCount();k++) {
|
||||
EffectField* f = row->Field(k);
|
||||
for (int j=0;j<f->keyframes.size();j++) {
|
||||
long eval_keyframe_time = f->keyframes.at(j).time-row->parent_effect->parent_clip->clip_in()+(row->parent_effect->parent_clip->timeline_in()-visible_in);
|
||||
long eval_keyframe_time = f->keyframes.at(j).time-row->GetParentEffect()->parent_clip->clip_in()+(row->GetParentEffect()->parent_clip->timeline_in()-visible_in);
|
||||
if (eval_keyframe_time >= frame_min && eval_keyframe_time <= frame_max) {
|
||||
long eval_frame_diff = qAbs(eval_keyframe_time - drag_frame_start);
|
||||
if (keyframe_index == -1 || eval_frame_diff < frame_diff) {
|
||||
@@ -273,7 +277,7 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
bool already_selected = false;
|
||||
keys_selected = false;
|
||||
if (keyframe_index > -1) {
|
||||
already_selected = keyframeIsSelected(rows.at(row_index)->field(field_index), keyframe_index);
|
||||
already_selected = keyframeIsSelected(rows.at(row_index)->Field(field_index), keyframe_index);
|
||||
} else {
|
||||
select_rect = true;
|
||||
}
|
||||
@@ -283,14 +287,14 @@ void KeyframeView::mousePressEvent(QMouseEvent *event) {
|
||||
selected_keyframes.clear();
|
||||
}
|
||||
if (keyframe_index > -1) {
|
||||
selected_fields.append(rows.at(row_index)->field(field_index));
|
||||
selected_fields.append(rows.at(row_index)->Field(field_index));
|
||||
selected_keyframes.append(keyframe_index);
|
||||
|
||||
// find other field with keyframes at the same time
|
||||
long comp_time = rows.at(row_index)->field(field_index)->keyframes.at(keyframe_index).time;
|
||||
for (int i=0;i<rows.at(row_index)->fieldCount();i++) {
|
||||
long comp_time = rows.at(row_index)->Field(field_index)->keyframes.at(keyframe_index).time;
|
||||
for (int i=0;i<rows.at(row_index)->FieldCount();i++) {
|
||||
if (i != field_index) {
|
||||
EffectField* f = rows.at(row_index)->field(i);
|
||||
EffectField* f = rows.at(row_index)->Field(i);
|
||||
for (int j=0;j<f->keyframes.size();j++) {
|
||||
if (f->keyframes.at(j).time == comp_time) {
|
||||
selected_fields.append(f);
|
||||
@@ -353,8 +357,8 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
for (int i=0;i<rowY.size();i++) {
|
||||
if (rowY.at(i) >= min_row && rowY.at(i) <= max_row) {
|
||||
EffectRow* row = rows.at(i);
|
||||
for (int k=0;k<row->fieldCount();k++) {
|
||||
EffectField* field = row->field(k);
|
||||
for (int k=0;k<row->FieldCount();k++) {
|
||||
EffectField* field = row->Field(k);
|
||||
for (int j=0;j<field->keyframes.size();j++) {
|
||||
long keyframe_frame = adjust_row_keyframe(row, field->keyframes.at(j).time, visible_in);
|
||||
if (!keyframeIsSelected(field, j) && keyframe_frame >= min_frame && keyframe_frame <= max_frame) {
|
||||
@@ -376,7 +380,7 @@ void KeyframeView::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (panel_timeline->snapping) {
|
||||
for (int i=0;i<selected_keyframes.size();i++) {
|
||||
EffectField* field = selected_fields.at(i);
|
||||
Clip* c = field->parent_row->parent_effect->parent_clip;
|
||||
Clip* c = field->GetParentRow()->GetParentEffect()->parent_clip;
|
||||
long key_time = old_key_vals.at(i) + frame_diff - c->clip_in() + c->timeline_in();
|
||||
long key_eval = key_time;
|
||||
if (panel_timeline->snap_to_point(olive::ActiveSequence->playhead, &key_eval)) {
|
||||
|
||||
+44
-38
@@ -24,6 +24,8 @@
|
||||
#include <QWidget>
|
||||
#include <QPainter>
|
||||
|
||||
#include "ui/effectui.h"
|
||||
|
||||
class Clip;
|
||||
class Effect;
|
||||
class EffectRow;
|
||||
@@ -31,56 +33,60 @@ class EffectField;
|
||||
class TimelineHeader;
|
||||
|
||||
class KeyframeView : public QWidget {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyframeView(QWidget* parent = 0);
|
||||
KeyframeView(QWidget* parent = nullptr);
|
||||
|
||||
void delete_selected_keyframes();
|
||||
void SetEffects(const QVector<EffectUI*>& open_effects);
|
||||
|
||||
TimelineHeader* header;
|
||||
void delete_selected_keyframes();
|
||||
|
||||
long visible_in;
|
||||
long visible_out;
|
||||
TimelineHeader* header;
|
||||
|
||||
long visible_in;
|
||||
long visible_out;
|
||||
signals:
|
||||
void wheel_event_signal(QWheelEvent*);
|
||||
void wheel_event_signal(QWheelEvent*);
|
||||
public slots:
|
||||
void set_x_scroll(int);
|
||||
void set_y_scroll(int);
|
||||
void resize_move(double d);
|
||||
void set_x_scroll(int);
|
||||
void set_y_scroll(int);
|
||||
void resize_move(double d);
|
||||
private:
|
||||
QVector<EffectField*> selected_fields;
|
||||
QVector<int> selected_keyframes;
|
||||
QVector<int> rowY;
|
||||
QVector<EffectRow*> rows;
|
||||
QVector<long> old_key_vals;
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void wheelEvent(QWheelEvent* e);
|
||||
bool mousedown;
|
||||
bool dragging;
|
||||
bool keys_selected;
|
||||
bool select_rect;
|
||||
bool scroll_drag;
|
||||
QVector<EffectUI*> open_effects_;
|
||||
|
||||
bool keyframeIsSelected(EffectField *field, int keyframe);
|
||||
QVector<EffectField*> selected_fields;
|
||||
QVector<int> selected_keyframes;
|
||||
QVector<int> rowY;
|
||||
QVector<EffectRow*> rows;
|
||||
QVector<long> old_key_vals;
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
void mouseReleaseEvent(QMouseEvent *event);
|
||||
void paintEvent(QPaintEvent *event);
|
||||
void wheelEvent(QWheelEvent* e);
|
||||
bool mousedown;
|
||||
bool dragging;
|
||||
bool keys_selected;
|
||||
bool select_rect;
|
||||
bool scroll_drag;
|
||||
|
||||
long drag_frame_start;
|
||||
long last_frame_diff;
|
||||
int rect_select_x;
|
||||
int rect_select_y;
|
||||
int rect_select_w;
|
||||
int rect_select_h;
|
||||
int rect_select_offset;
|
||||
bool keyframeIsSelected(EffectField *field, int keyframe);
|
||||
|
||||
int x_scroll;
|
||||
int y_scroll;
|
||||
long drag_frame_start;
|
||||
long last_frame_diff;
|
||||
int rect_select_x;
|
||||
int rect_select_y;
|
||||
int rect_select_w;
|
||||
int rect_select_h;
|
||||
int rect_select_offset;
|
||||
|
||||
void update_keys();
|
||||
int x_scroll;
|
||||
int y_scroll;
|
||||
|
||||
void update_keys();
|
||||
private slots:
|
||||
void show_context_menu(const QPoint& pos);
|
||||
void menu_set_key_type(QAction*);
|
||||
void show_context_menu(const QPoint& pos);
|
||||
void menu_set_key_type(QAction*);
|
||||
};
|
||||
|
||||
#endif // KEYFRAMEVIEW_H
|
||||
|
||||
+67
-70
@@ -20,11 +20,12 @@
|
||||
|
||||
#include "labelslider.h"
|
||||
|
||||
#include "project/undo.h"
|
||||
#include "undo/undo.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "io/config.h"
|
||||
#include "io/math.h"
|
||||
#include "debug.h"
|
||||
#include "global/config.h"
|
||||
#include "global/math.h"
|
||||
#include "global/debug.h"
|
||||
#include "ui/styling.h"
|
||||
|
||||
#include <QMouseEvent>
|
||||
#include <QInputDialog>
|
||||
@@ -40,28 +41,33 @@ LabelSlider::LabelSlider(QWidget* parent) : QLabel(parent) {
|
||||
drag_proc = false;
|
||||
min_enabled = false;
|
||||
max_enabled = false;
|
||||
set_color();
|
||||
set_default_cursor();
|
||||
SetColor();
|
||||
SetDefaultCursor();
|
||||
internal_value = -1;
|
||||
set = false;
|
||||
display_type = LABELSLIDER_NORMAL;
|
||||
display_type = Normal;
|
||||
|
||||
set_default_value(0);
|
||||
SetDefault(0);
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(ShowContextMenu(const QPoint&)));
|
||||
}
|
||||
|
||||
void LabelSlider::set_frame_rate(double d) {
|
||||
void LabelSlider::SetFrameRate(double d) {
|
||||
frame_rate = d;
|
||||
}
|
||||
|
||||
void LabelSlider::set_display_type(int type) {
|
||||
display_type = type;
|
||||
setText(valueToString());
|
||||
void LabelSlider::SetDecimalPlaces(int places)
|
||||
{
|
||||
decimal_places = places;
|
||||
}
|
||||
|
||||
void LabelSlider::set_value(double v, bool userSet) {
|
||||
void LabelSlider::SetDisplayType(const DisplayType& type) {
|
||||
display_type = type;
|
||||
setText(ValueToString());
|
||||
}
|
||||
|
||||
void LabelSlider::SetValue(double v) {
|
||||
set = true;
|
||||
if (!qFuzzyCompare(v, internal_value)) {
|
||||
if (min_enabled && v < min_value) {
|
||||
@@ -72,30 +78,25 @@ void LabelSlider::set_value(double v, bool userSet) {
|
||||
internal_value = v;
|
||||
}
|
||||
|
||||
setText(valueToString());
|
||||
if (userSet) emit valueChanged();
|
||||
setText(ValueToString());
|
||||
}
|
||||
}
|
||||
|
||||
bool LabelSlider::is_set() {
|
||||
return set;
|
||||
}
|
||||
|
||||
bool LabelSlider::is_dragging() {
|
||||
bool LabelSlider::IsDragging() {
|
||||
return drag_proc;
|
||||
}
|
||||
|
||||
QString LabelSlider::valueToString() {
|
||||
QString LabelSlider::ValueToString() {
|
||||
double v = internal_value;
|
||||
if (qIsNaN(v)) {
|
||||
return "---";
|
||||
} else {
|
||||
switch (display_type) {
|
||||
case LABELSLIDER_FRAMENUMBER:
|
||||
case FrameNumber:
|
||||
return frame_to_timecode(long(v), olive::CurrentConfig.timecode_view, frame_rate);
|
||||
case LABELSLIDER_PERCENT:
|
||||
case Percent:
|
||||
return QString::number((v*100), 'f', decimal_places).append("%");
|
||||
case LABELSLIDER_DECIBEL:
|
||||
case Decibel:
|
||||
{
|
||||
QString db_str;
|
||||
|
||||
@@ -112,21 +113,20 @@ QString LabelSlider::valueToString() {
|
||||
|
||||
return db_str;
|
||||
}
|
||||
default:
|
||||
return QString::number(v, 'f', decimal_places);
|
||||
}
|
||||
return QString::number(v, 'f', decimal_places);
|
||||
}
|
||||
}
|
||||
|
||||
double LabelSlider::getPreviousValue() {
|
||||
return previous_value;
|
||||
}
|
||||
|
||||
void LabelSlider::set_previous_value() {
|
||||
previous_value = internal_value;
|
||||
}
|
||||
|
||||
void LabelSlider::set_color(QString c) {
|
||||
if (c.isEmpty()) c = "#ffc000";
|
||||
void LabelSlider::SetColor(QString c) {
|
||||
if (c.isEmpty()) {
|
||||
if (olive::styling::UseDarkIcons()) {
|
||||
c = "#0080ff";
|
||||
} else {
|
||||
c = "#ffc000";
|
||||
}
|
||||
}
|
||||
setStyleSheet("QLabel{color:" + c + ";text-decoration:underline;}QLabel:disabled{color:#808080;}");
|
||||
}
|
||||
|
||||
@@ -134,20 +134,20 @@ double LabelSlider::value() {
|
||||
return internal_value;
|
||||
}
|
||||
|
||||
void LabelSlider::set_default_value(double v) {
|
||||
void LabelSlider::SetDefault(double v) {
|
||||
default_value = v;
|
||||
if (!set) {
|
||||
set_value(v, false);
|
||||
SetValue(v);
|
||||
set = false;
|
||||
}
|
||||
}
|
||||
|
||||
void LabelSlider::set_minimum_value(double v) {
|
||||
void LabelSlider::SetMinimum(double v) {
|
||||
min_value = v;
|
||||
min_enabled = true;
|
||||
}
|
||||
|
||||
void LabelSlider::set_maximum_value(double v) {
|
||||
void LabelSlider::SetMaximum(double v) {
|
||||
max_value = v;
|
||||
max_enabled = true;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ void LabelSlider::mousePressEvent(QMouseEvent *ev) {
|
||||
if (ev->modifiers() & Qt::AltModifier) {
|
||||
|
||||
// reset to default
|
||||
reset_to_default_value();
|
||||
ResetToDefault();
|
||||
|
||||
} else {
|
||||
|
||||
@@ -171,7 +171,7 @@ void LabelSlider::mousePressEvent(QMouseEvent *ev) {
|
||||
if (qIsNaN(internal_value)) internal_value = 0;
|
||||
|
||||
// hide the cursor and store information about it for dragging
|
||||
set_active_cursor();
|
||||
SetActiveCursor();
|
||||
|
||||
drag_start = true;
|
||||
drag_start_x = cursor().pos().x();
|
||||
@@ -203,7 +203,7 @@ void LabelSlider::mouseMoveEvent(QMouseEvent* event) {
|
||||
// ctrl + drag drags in smaller increments
|
||||
if (event->modifiers() & Qt::ControlModifier) diff *= 0.01;
|
||||
|
||||
if (display_type == LABELSLIDER_PERCENT) {
|
||||
if (display_type == Percent) {
|
||||
// we'll also need to drag in smaller increments for a percent value
|
||||
|
||||
diff *= 0.01;
|
||||
@@ -212,7 +212,7 @@ void LabelSlider::mouseMoveEvent(QMouseEvent* event) {
|
||||
// determine what the new value will be
|
||||
double new_value;
|
||||
|
||||
if (display_type == LABELSLIDER_DECIBEL) {
|
||||
if (display_type == Decibel) {
|
||||
// we move in terms of dB for decibel display
|
||||
|
||||
new_value = db_to_amplitude(amplitude_to_db(internal_value) + diff);
|
||||
@@ -224,7 +224,8 @@ void LabelSlider::mouseMoveEvent(QMouseEvent* event) {
|
||||
}
|
||||
|
||||
// set internal value
|
||||
set_value(new_value, true);
|
||||
SetValue(new_value);
|
||||
emit valueChanged(internal_value);
|
||||
|
||||
// keep the cursor in the same location while dragging
|
||||
cursor().setPos(drag_start_x, drag_start_y);
|
||||
@@ -235,7 +236,7 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent*) {
|
||||
if (drag_start) {
|
||||
|
||||
// unhide cursor
|
||||
set_default_cursor();
|
||||
SetDefaultCursor();
|
||||
|
||||
drag_start = false;
|
||||
|
||||
@@ -244,55 +245,51 @@ void LabelSlider::mouseReleaseEvent(QMouseEvent*) {
|
||||
|
||||
drag_proc = false;
|
||||
|
||||
previous_value = drag_start_value;
|
||||
|
||||
emit valueChanged();
|
||||
emit valueChanged(internal_value);
|
||||
|
||||
} else {
|
||||
|
||||
prompt_for_value();
|
||||
ShowDialog();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LabelSlider::set_default_cursor() {
|
||||
void LabelSlider::SetDefaultCursor() {
|
||||
setCursor(Qt::SizeHorCursor);
|
||||
}
|
||||
|
||||
void LabelSlider::set_active_cursor() {
|
||||
void LabelSlider::SetActiveCursor() {
|
||||
setCursor(Qt::BlankCursor);
|
||||
}
|
||||
|
||||
void LabelSlider::show_context_menu(const QPoint &pos)
|
||||
void LabelSlider::ShowContextMenu(const QPoint &pos)
|
||||
{
|
||||
QMenu menu(this);
|
||||
|
||||
menu.addAction(tr("&Edit"), this, SLOT(prompt_for_value()));
|
||||
menu.addAction(tr("&Edit"), this, SLOT(ShowDialog()));
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(tr("&Reset to Default"), this, SLOT(reset_to_default_value()));
|
||||
menu.addAction(tr("&Reset to Default"), this, SLOT(ResetToDefault()));
|
||||
|
||||
menu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void LabelSlider::reset_to_default_value()
|
||||
void LabelSlider::ResetToDefault()
|
||||
{
|
||||
// if the value is not already default, and there is a default to set
|
||||
if (!qFuzzyCompare(internal_value, default_value)
|
||||
&& !qIsNaN(default_value)) {
|
||||
|
||||
// cache current value
|
||||
set_previous_value();
|
||||
|
||||
// set back to default
|
||||
set_value(default_value, true);
|
||||
SetValue(default_value);
|
||||
emit valueChanged(internal_value);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void LabelSlider::prompt_for_value()
|
||||
void LabelSlider::ShowDialog()
|
||||
{
|
||||
// if the user didn't actually drag, and just clicked in one place,
|
||||
// we instead present a dialog prompt for the user to enter a
|
||||
@@ -300,7 +297,7 @@ void LabelSlider::prompt_for_value()
|
||||
|
||||
double d = internal_value;
|
||||
|
||||
if (display_type == LABELSLIDER_FRAMENUMBER) {
|
||||
if (display_type == FrameNumber) {
|
||||
|
||||
// ask the user to enter a timecode
|
||||
QString s = QInputDialog::getText(
|
||||
@@ -308,7 +305,7 @@ void LabelSlider::prompt_for_value()
|
||||
tr("Set Value"),
|
||||
tr("New value:"),
|
||||
QLineEdit::Normal,
|
||||
valueToString()
|
||||
ValueToString()
|
||||
);
|
||||
if (s.isEmpty()) return;
|
||||
|
||||
@@ -322,9 +319,9 @@ void LabelSlider::prompt_for_value()
|
||||
|
||||
// value to show
|
||||
double shown_value = internal_value;
|
||||
if (display_type == LABELSLIDER_PERCENT) {
|
||||
if (display_type == Percent) {
|
||||
shown_value *= 100;
|
||||
} else if (display_type == LABELSLIDER_DECIBEL) {
|
||||
} else if (display_type == Decibel) {
|
||||
shown_value = amplitude_to_db(shown_value);
|
||||
}
|
||||
|
||||
@@ -333,7 +330,7 @@ void LabelSlider::prompt_for_value()
|
||||
if (min_enabled) {
|
||||
// if this field has a minimum value set, use it
|
||||
shown_minimum_value = min_value;
|
||||
} else if (display_type == LABELSLIDER_DECIBEL) {
|
||||
} else if (display_type == Decibel) {
|
||||
// minimum decibel amount is -96db
|
||||
shown_minimum_value = -96;
|
||||
} else {
|
||||
@@ -355,16 +352,16 @@ void LabelSlider::prompt_for_value()
|
||||
if (!ok) return;
|
||||
|
||||
// convert shown value back to internal value
|
||||
if (display_type == LABELSLIDER_PERCENT) {
|
||||
if (display_type == Percent) {
|
||||
d *= 0.01;
|
||||
} else if (display_type == LABELSLIDER_DECIBEL) {
|
||||
} else if (display_type == Decibel) {
|
||||
d = db_to_amplitude(d);
|
||||
}
|
||||
}
|
||||
|
||||
// if the value actually changed, trigger a change event
|
||||
if (!qFuzzyCompare(d, internal_value)) {
|
||||
set_previous_value();
|
||||
set_value(d, true);
|
||||
SetValue(d);
|
||||
emit valueChanged(internal_value);
|
||||
}
|
||||
}
|
||||
|
||||
+131
-160
@@ -1,20 +1,20 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
@@ -24,13 +24,6 @@
|
||||
#include <QLabel>
|
||||
#include <QUndoCommand>
|
||||
|
||||
enum LabelSliderDisplayType {
|
||||
LABELSLIDER_NORMAL,
|
||||
LABELSLIDER_FRAMENUMBER,
|
||||
LABELSLIDER_PERCENT,
|
||||
LABELSLIDER_DECIBEL
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The LabelSlider class
|
||||
*
|
||||
@@ -44,154 +37,132 @@ public:
|
||||
LabelSlider(QWidget* parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Set the display frame rate
|
||||
*
|
||||
* If the `display_type` is set to LABELSLIDER_FRAMENUMBER, this function sets how many frames per second the
|
||||
* timecode will be in.
|
||||
*
|
||||
* @param d
|
||||
*/
|
||||
void set_frame_rate(double d);
|
||||
* @brief Set the value
|
||||
* @param v
|
||||
*
|
||||
* Value to set to.
|
||||
*
|
||||
* @param userSet
|
||||
*
|
||||
* **TRUE** if this was called through a user action, **FALSE** if this was called through some other way. The
|
||||
* only difference is **TRUE** will emit a signal (valueChanged()) indicating that the value has changed, and
|
||||
* **FALSE** will not.
|
||||
*/
|
||||
void SetValue(double v);
|
||||
|
||||
/**
|
||||
* @brief Sets the way to display the value
|
||||
*
|
||||
* * `LABELSLIDER_NORMAL` - Shows the value as a normal number
|
||||
* * `LABELSLIDER_FRAMENUMBER` - Shows the number as a timecode according to `config.timecode_view`. By default,
|
||||
* will render hh:mm:ss:ff
|
||||
* * `LABELSLIDER_PERCENT` - Shows the number as a percentage. 1.0 becomes "100%", 0.5 becomes 50%, etc.
|
||||
* * `LABELSLIDER_DECIBLE` - Shows the number as a decibel. 1.0 becomes "0 dB", 2.0 becames roughly "6 dB", 0.5
|
||||
* becomes roughly "-6 dB", etc.
|
||||
*
|
||||
* @param type
|
||||
*
|
||||
* The display type to set to. Should be a member of `enum LabelSliderDisplayType`.
|
||||
*/
|
||||
void set_display_type(int type);
|
||||
* @brief Set the default value
|
||||
*
|
||||
* If a default value is set, alt+clicking the LabelSlider will return to the default value.
|
||||
*
|
||||
* @param v
|
||||
*
|
||||
* Value to set as default
|
||||
*/
|
||||
void SetDefault(double v);
|
||||
|
||||
/**
|
||||
* @brief Set the value
|
||||
* @param v
|
||||
*
|
||||
* Value to set to.
|
||||
*
|
||||
* @param userSet
|
||||
*
|
||||
* **TRUE** if this was called through a user action, **FALSE** if this was called through some other way. The
|
||||
* only difference is **TRUE** will emit a signal (valueChanged()) indicating that the value has changed, and
|
||||
* **FALSE** will not.
|
||||
*/
|
||||
void set_value(double v, bool userSet);
|
||||
|
||||
/**
|
||||
* @brief Set the default value
|
||||
*
|
||||
* If a default value is set, alt+clicking the LabelSlider will return to the default value.
|
||||
*
|
||||
* @param v
|
||||
*
|
||||
* Value to set as default
|
||||
*/
|
||||
void set_default_value(double v);
|
||||
|
||||
/**
|
||||
* @brief Set the minimum value
|
||||
*
|
||||
* If a minimum value is set, the value will never go below it. If the user manually sets a value lower than
|
||||
* the minimum, it will automatically snap to the minimum.
|
||||
*
|
||||
* @param v
|
||||
*
|
||||
* Value to set as minimum
|
||||
*/
|
||||
void set_minimum_value(double v);
|
||||
|
||||
/**
|
||||
* @brief Set the maximum value
|
||||
*
|
||||
* If a maximum value is set, the value will never go above it. If the user manually sets a value higher than
|
||||
* the maximum, it will automatically snap to the maximum.
|
||||
*
|
||||
* @param v
|
||||
*
|
||||
* Value to set as maximum
|
||||
*/
|
||||
void set_maximum_value(double v);
|
||||
|
||||
/**
|
||||
* @brief Returns the internal value as a double
|
||||
* @return The internal value. This will not respect the `display_type`, i.e. 100% will return as 1.0, 12dB will
|
||||
* return as 400%, and a timecode will return as a frame number.
|
||||
*/
|
||||
* @brief Returns the internal value as a double
|
||||
* @return The internal value. This will not respect the `display_type`, i.e. 100% will return as 1.0, 12dB will
|
||||
* return as 400%, and a timecode will return as a frame number.
|
||||
*/
|
||||
double value();
|
||||
|
||||
/**
|
||||
* @brief Returns whether a value has been set or not
|
||||
*
|
||||
* If a value has been entered by any means (i.e. if set_value() was called), this will be **TRUE**. If set_value()
|
||||
* has not been called and is_set() is **FALSE**, calling set_default_value() will automatically set the value
|
||||
* to the default value WITHOUT changing the is_set() state (i.e. it will still be **FALSE** and calling
|
||||
* set_default_value() again will change the current value again unless it's been changed through some other means
|
||||
* in that time).
|
||||
*
|
||||
* @return **TRUE** if a value has been set, **FALSE** if not.
|
||||
*/
|
||||
bool is_set();
|
||||
enum DisplayType {
|
||||
Normal,
|
||||
FrameNumber,
|
||||
Percent,
|
||||
Decibel
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Returns whether the user is currently dragging
|
||||
* @return **TRUE** if the user is dragging, **FALSE** if not.
|
||||
*/
|
||||
bool is_dragging();
|
||||
* @brief Sets the way to display the value
|
||||
*
|
||||
* * `LABELSLIDER_NORMAL` - Shows the value as a normal number
|
||||
* * `LABELSLIDER_FRAMENUMBER` - Shows the number as a timecode according to `config.timecode_view`. By default,
|
||||
* will render hh:mm:ss:ff
|
||||
* * `LABELSLIDER_PERCENT` - Shows the number as a percentage. 1.0 becomes "100%", 0.5 becomes 50%, etc.
|
||||
* * `LABELSLIDER_DECIBLE` - Shows the number as a decibel. 1.0 becomes "0 dB", 2.0 becames roughly "6 dB", 0.5
|
||||
* becomes roughly "-6 dB", etc.
|
||||
*
|
||||
* @param type
|
||||
*
|
||||
* The display type to set to.
|
||||
*/
|
||||
void SetDisplayType(const DisplayType& type);
|
||||
|
||||
/**
|
||||
* @brief Convert the internal value to a displayed string according to `display_type`
|
||||
* @return The internal value as a string
|
||||
*/
|
||||
QString valueToString();
|
||||
* @brief Returns whether the user is currently dragging
|
||||
* @return **TRUE** if the user is dragging, **FALSE** if not.
|
||||
*/
|
||||
bool IsDragging();
|
||||
|
||||
/**
|
||||
* @brief Returns whatever value was set before the last set_value()
|
||||
*
|
||||
* For various reasons (largely undo capabilities) it is helpful to retrieve whatever the value was before the
|
||||
* current one. If the user dragged the current value, this will return the value just before the user started
|
||||
* dragging.
|
||||
*
|
||||
* @return The previous value
|
||||
*/
|
||||
double getPreviousValue();
|
||||
* @brief Set the display color
|
||||
* @param c
|
||||
*
|
||||
* Color to set to
|
||||
*/
|
||||
void SetColor(QString c = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Updates previous value
|
||||
*
|
||||
* Called internally to store the current value as the previous value in anticipation of an upcoming value change.
|
||||
* Can also be called externally (mainly for dragged EffectGizmos) in anticipation of an external change.
|
||||
*/
|
||||
void set_previous_value();
|
||||
* @brief Set the display frame rate
|
||||
*
|
||||
* If the `display_type` is set to LABELSLIDER_FRAMENUMBER, this function sets how many frames per second the
|
||||
* timecode will be in.
|
||||
*
|
||||
* @param d
|
||||
*/
|
||||
void SetFrameRate(double d);
|
||||
|
||||
/**
|
||||
* @brief Set the display color
|
||||
* @param c
|
||||
*
|
||||
* Color to set to
|
||||
*/
|
||||
void set_color(QString c = nullptr);
|
||||
* @brief Set how many decimal places to show for a floating-point number
|
||||
*
|
||||
* Defaults to 1
|
||||
*/
|
||||
void SetDecimalPlaces(int places);
|
||||
public slots:
|
||||
/**
|
||||
* @brief Set the minimum value
|
||||
*
|
||||
* If a minimum value is set, the value will never go below it. If the user manually sets a value lower than
|
||||
* the minimum, it will automatically snap to the minimum.
|
||||
*
|
||||
* @param v
|
||||
*
|
||||
* Value to set as minimum
|
||||
*/
|
||||
void SetMinimum(double v);
|
||||
|
||||
/**
|
||||
* @brief Set how many decimal places to show for a floating-point number
|
||||
*
|
||||
* Defaults to 1
|
||||
*/
|
||||
int decimal_places;
|
||||
* @brief Set the maximum value
|
||||
*
|
||||
* If a maximum value is set, the value will never go above it. If the user manually sets a value higher than
|
||||
* the maximum, it will automatically snap to the maximum.
|
||||
*
|
||||
* @param v
|
||||
*
|
||||
* Value to set as maximum
|
||||
*/
|
||||
void SetMaximum(double v);
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *ev);
|
||||
void mouseMoveEvent(QMouseEvent *ev);
|
||||
void mouseReleaseEvent(QMouseEvent *ev);
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Convert the internal value to a displayed string according to `display_type`
|
||||
* @return The internal value as a string
|
||||
*/
|
||||
QString ValueToString();
|
||||
|
||||
double default_value;
|
||||
double internal_value;
|
||||
double drag_start_value;
|
||||
double previous_value;
|
||||
|
||||
int decimal_places;
|
||||
|
||||
bool min_enabled;
|
||||
double min_value;
|
||||
@@ -205,19 +176,19 @@ private:
|
||||
|
||||
bool set;
|
||||
|
||||
int display_type;
|
||||
DisplayType display_type;
|
||||
|
||||
double frame_rate;
|
||||
|
||||
/**
|
||||
* @brief Internal function to set the standard cursor (usually SizeHorCursor)
|
||||
*/
|
||||
void set_default_cursor();
|
||||
* @brief Internal function to set the standard cursor (usually SizeHorCursor)
|
||||
*/
|
||||
void SetDefaultCursor();
|
||||
|
||||
/**
|
||||
* @brief Internal function to set the cursor while dragging (usually NoCursor aka invisible)
|
||||
*/
|
||||
void set_active_cursor();
|
||||
* @brief Internal function to set the cursor while dragging (usually NoCursor aka invisible)
|
||||
*/
|
||||
void SetActiveCursor();
|
||||
private slots:
|
||||
/**
|
||||
* @brief Context menu slot to be connected to QWidget::customContextMenuRequested(const QPoint&)
|
||||
@@ -226,12 +197,12 @@ private slots:
|
||||
*
|
||||
* Current cursor position
|
||||
*/
|
||||
void show_context_menu(const QPoint& pos);
|
||||
void ShowContextMenu(const QPoint& pos);
|
||||
|
||||
/**
|
||||
* @brief Slot to reset current value to the default value
|
||||
*/
|
||||
void reset_to_default_value();
|
||||
void ResetToDefault();
|
||||
|
||||
/**
|
||||
* @brief Show prompt asking for value
|
||||
@@ -240,20 +211,20 @@ private slots:
|
||||
* Will show an input dialog asking for a new value to be entered manually. Asks for units in the selected
|
||||
* display type and converts them back to the internal value type.
|
||||
*/
|
||||
void prompt_for_value();
|
||||
void ShowDialog();
|
||||
signals:
|
||||
/**
|
||||
* @brief valueChanged signal
|
||||
*
|
||||
* Emitted if the value changed at it was instigated by the user.
|
||||
*/
|
||||
void valueChanged();
|
||||
* @brief valueChanged signal
|
||||
*
|
||||
* Emitted if the value changed at it was instigated by the user.
|
||||
*/
|
||||
void valueChanged(double d);
|
||||
|
||||
/**
|
||||
* @brief clicked signal
|
||||
*
|
||||
* Emitted if the user clicks on the LabelSlider in any way
|
||||
*/
|
||||
* @brief clicked signal
|
||||
*
|
||||
* Emitted if the user clicks on the LabelSlider in any way
|
||||
*/
|
||||
void clicked();
|
||||
};
|
||||
|
||||
|
||||
+1255
File diff suppressed because it is too large
Load Diff
+366
@@ -0,0 +1,366 @@
|
||||
/***
|
||||
|
||||
Olive - Non-Linear Video Editor
|
||||
Copyright (C) 2019 Olive Team
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
***/
|
||||
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
class Project;
|
||||
class EffectControls;
|
||||
class Viewer;
|
||||
class Timeline;
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent);
|
||||
virtual ~MainWindow() override;
|
||||
|
||||
/**
|
||||
* @brief Update window title
|
||||
*
|
||||
* Updates the window title to reflect the current project filename. Call if the project filename changes.
|
||||
*
|
||||
* NOTE: It's recommended to use update_project_filename() from Olive::Global to update the filename completely
|
||||
* instead of calling this function directly (update_project_filename() calls this function in the process).
|
||||
*/
|
||||
void updateTitle();
|
||||
|
||||
/**
|
||||
* @brief Load shortcut file.
|
||||
*
|
||||
* Loads a shortcut configuration from file and sets Olive to use them.
|
||||
*
|
||||
* @param fn
|
||||
*
|
||||
* URL of the shortcut file to be loaded
|
||||
*
|
||||
*/
|
||||
void load_shortcuts(const QString &fn);
|
||||
|
||||
/**
|
||||
* @brief Save shortcut file.
|
||||
*
|
||||
* Saves the current shortcut configuration to file. Only saves shortcuts that have been changed from default.
|
||||
*
|
||||
* @param fn
|
||||
*
|
||||
* URL to save the shortcut file to.
|
||||
*/
|
||||
void save_shortcuts(const QString &fn);
|
||||
|
||||
/**
|
||||
* @brief Load a CSS/QSS style from file to customize Olive's interface.
|
||||
*
|
||||
* @param fn
|
||||
*
|
||||
* URL to load the CSS file from.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* **TRUE** if CSS was successfully loaded.
|
||||
*/
|
||||
bool load_css_from_file(const QString& fn);
|
||||
|
||||
/**
|
||||
* @brief Set application's QStyle based on values from Config
|
||||
*/
|
||||
void Restyle();
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* @brief Toggles full screen mode.
|
||||
*
|
||||
* Toggles the main window between full screen and windowed modes.
|
||||
*/
|
||||
void toggle_full_screen();
|
||||
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted once when the main window has finished initializing
|
||||
*
|
||||
* Emitted the first time paintEvent runs. Connect this to functions that must be completed post-initialization.
|
||||
*/
|
||||
void finished_first_paint();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Close event
|
||||
*
|
||||
* Confirms whether the project can be closed, and if so performs various clean-up functions before the application
|
||||
* exits. It's preferable to call clean-up functions here rather than in the destructor because this will get called
|
||||
* first.
|
||||
*/
|
||||
virtual void closeEvent(QCloseEvent *) override;
|
||||
|
||||
/**
|
||||
* @brief Paint event
|
||||
*
|
||||
* Overridden to provide the finished_first_paint() signal.
|
||||
*/
|
||||
virtual void paintEvent(QPaintEvent *) override;
|
||||
|
||||
/**
|
||||
* @brief Change event
|
||||
*
|
||||
* Overridden to handle language changes (e->type() == QEvent::LanguageChange) by calling Retranslate().
|
||||
*
|
||||
* See documentation for QWidget::changeEvent() for more information.
|
||||
*
|
||||
* @param e
|
||||
* @return
|
||||
*/
|
||||
virtual void changeEvent(QEvent* e) override;
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief Maximizes the currently hovered panel.
|
||||
*
|
||||
* Saves the current state of the panels/dock widgets and removes all except the currently hovered panel,
|
||||
* effectively maximizing the panel to the entire window.
|
||||
*/
|
||||
void maximize_panel();
|
||||
|
||||
/**
|
||||
* @brief Reset panel layout to default.
|
||||
*
|
||||
* Resets the current panel layout to default. Doesn't save the current layout.
|
||||
*/
|
||||
void reset_layout();
|
||||
|
||||
/**
|
||||
* @brief Function to prepare File menu.
|
||||
*
|
||||
* Primarily used to populate the Open Recent Projects menu.
|
||||
*/
|
||||
void fileMenu_About_To_Be_Shown();
|
||||
|
||||
/**
|
||||
* @brief Function to prepare Edit menu.
|
||||
*
|
||||
* Primarily used to set the enabled state on Undo and Redo depending if there are undos/redos available.
|
||||
*/
|
||||
void editMenu_About_To_Be_Shown();
|
||||
|
||||
/**
|
||||
* @brief Function to prepare Window menu.
|
||||
*
|
||||
* Primarily used to set the checked state of menu items corresponding to the panels that are currently visible.
|
||||
*/
|
||||
void windowMenu_About_To_Be_Shown();
|
||||
|
||||
/**
|
||||
* @brief Function to prepare Playback menu.
|
||||
*
|
||||
* Primarily used to set the checked state on the "Loop" item.
|
||||
*/
|
||||
void playbackMenu_About_To_Be_Shown();
|
||||
|
||||
/**
|
||||
* @brief Function to prepare View menu.
|
||||
*
|
||||
* Primarily used to set the checked state of various options in the view menu (e.g. title safe area, timecode
|
||||
* units, etc.)
|
||||
*/
|
||||
void viewMenu_About_To_Be_Shown();
|
||||
|
||||
/**
|
||||
* @brief Function to prepare Tools menu.
|
||||
*
|
||||
* Primarily used to set the checked state on various settings available from the Tools menu.
|
||||
*/
|
||||
void toolMenu_About_To_Be_Shown();
|
||||
|
||||
/**
|
||||
* @brief Toggle whether a panel is visible or not.
|
||||
*
|
||||
* Assumes the sender() QAction has a pointer to a QDockWidget in its data variable. Casts it and toggles its
|
||||
* visibility.
|
||||
*/
|
||||
void toggle_panel_visibility();
|
||||
|
||||
/**
|
||||
* @brief Set panel lock
|
||||
*
|
||||
* @param locked
|
||||
*
|
||||
* If **TRUE** prevents panels from being moved around. Defaults to **FALSE**.
|
||||
*/
|
||||
void set_panels_locked(bool locked);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Internal function for setting the panel layout to a predetermined preset.
|
||||
*
|
||||
* Resets layout to default and optionally loads a layout from file. If loading from file, this function will
|
||||
* always load from `get_config_path() + "/layout"`.
|
||||
*
|
||||
* @param reset
|
||||
*
|
||||
* **TRUE** if this function should just reset the current layout. **FALSE** if it should load from the
|
||||
* aforementioned layout file.
|
||||
*/
|
||||
void setup_layout(bool reset);
|
||||
|
||||
/**
|
||||
* @brief Initialize menu bar menus and items.
|
||||
*
|
||||
* Internal initialization function for all menus and menu items in the main window. Called once from the
|
||||
* MainWindow() constructor.
|
||||
*/
|
||||
void setup_menus();
|
||||
|
||||
void Retranslate();
|
||||
|
||||
// file menu actions
|
||||
QMenu* file_menu;
|
||||
QMenu* new_menu;
|
||||
QAction* open_project;
|
||||
QMenu* open_recent;
|
||||
QAction* open_action;
|
||||
QAction* clear_open_recent_action;
|
||||
QAction* save_project;
|
||||
QAction* save_project_as;
|
||||
QAction* import_action;
|
||||
QAction* export_action;
|
||||
QAction* exit_action;
|
||||
|
||||
// edit menu actions
|
||||
QMenu* edit_menu;
|
||||
QAction* undo_action;
|
||||
QAction* redo_action;
|
||||
QAction* select_all_action;
|
||||
QAction* deselect_all_action;
|
||||
QAction* ripple_to_in_point_;
|
||||
QAction* ripple_to_out_point_;
|
||||
QAction* edit_to_in_point_;
|
||||
QAction* edit_to_out_point_;
|
||||
QAction* delete_inout_point_;
|
||||
QAction* ripple_delete_inout_point_;
|
||||
QAction* setedit_marker_;
|
||||
|
||||
// view menu actions
|
||||
QMenu* view_menu;
|
||||
QAction* zoom_in_;
|
||||
QAction* zoom_out_;
|
||||
QAction* increase_track_height_;
|
||||
QAction* decrease_track_height_;
|
||||
QAction* track_lines;
|
||||
QAction* frames_action;
|
||||
QAction* drop_frame_action;
|
||||
QAction* nondrop_frame_action;
|
||||
QAction* milliseconds_action;
|
||||
QAction* no_autoscroll;
|
||||
QAction* page_autoscroll;
|
||||
QAction* smooth_autoscroll;
|
||||
|
||||
QMenu* title_safe_area_menu;
|
||||
QAction* title_safe_off;
|
||||
QAction* title_safe_default;
|
||||
QAction* title_safe_43;
|
||||
QAction* title_safe_169;
|
||||
QAction* title_safe_custom;
|
||||
|
||||
QAction* full_screen;
|
||||
QAction* full_screen_viewer_;
|
||||
QAction* show_all;
|
||||
|
||||
// playback menu
|
||||
QMenu* playback_menu;
|
||||
|
||||
QAction* go_to_start_;
|
||||
QAction* previous_frame_;
|
||||
QAction* playpause_;
|
||||
QAction* play_in_to_out_;
|
||||
QAction* next_frame_;
|
||||
QAction* go_to_end_;
|
||||
QAction* go_to_prev_cut_;
|
||||
QAction* go_to_next_cut_;
|
||||
QAction* go_to_in_point_;
|
||||
QAction* go_to_out_point_;
|
||||
QAction* shuttle_left_;
|
||||
QAction* shuttle_stop_;
|
||||
QAction* shuttle_right_;
|
||||
QAction* loop_action_;
|
||||
|
||||
// window menu
|
||||
|
||||
QMenu* window_menu;
|
||||
|
||||
QAction* window_project_action;
|
||||
QAction* window_effectcontrols_action;
|
||||
QAction* window_timeline_action;
|
||||
QAction* window_graph_editor_action;
|
||||
QAction* window_footageviewer_action;
|
||||
QAction* window_sequenceviewer_action;
|
||||
|
||||
QAction* maximize_panel_;
|
||||
QAction* lock_panels_;
|
||||
QAction* reset_default_layout_;
|
||||
|
||||
// tools menu
|
||||
QMenu* tools_menu;
|
||||
|
||||
QAction* pointer_tool_action;
|
||||
QAction* edit_tool_action;
|
||||
QAction* ripple_tool_action;
|
||||
QAction* razor_tool_action;
|
||||
QAction* slip_tool_action;
|
||||
QAction* slide_tool_action;
|
||||
QAction* hand_tool_action;
|
||||
QAction* transition_tool_action;
|
||||
QAction* snap_toggle;
|
||||
QAction* selecting_also_seeks;
|
||||
QAction* edit_tool_also_seeks;
|
||||
QAction* edit_tool_selects_links;
|
||||
QAction* seek_to_end_of_pastes;
|
||||
QAction* scroll_wheel_zooms;
|
||||
QAction* invert_timeline_scroll_axes;
|
||||
QAction* rectified_waveforms;
|
||||
QAction* enable_drag_files_to_timeline;
|
||||
QAction* autoscale_by_default;
|
||||
QAction* enable_seek_to_import;
|
||||
QAction* enable_audio_scrubbing;
|
||||
QAction* enable_drop_on_media_to_replace;
|
||||
QAction* enable_hover_focus;
|
||||
QAction* set_name_and_marker;
|
||||
QAction* seek_also_selects;
|
||||
QAction* preferences_action_;
|
||||
QAction* clear_undo_action_;
|
||||
|
||||
// help menu
|
||||
QMenu* help_menu;
|
||||
QAction* action_search_;
|
||||
QAction* debug_log_;
|
||||
QAction* about_action_;
|
||||
|
||||
// used to store the panel state when one panel is maximized
|
||||
QByteArray temp_panel_state;
|
||||
|
||||
// used in paintEvent() to determine the first paintEvent() performed
|
||||
bool first_show;
|
||||
};
|
||||
|
||||
namespace olive {
|
||||
extern MainWindow* MainWindow;
|
||||
}
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
@@ -40,11 +40,11 @@ MediaIconService::MediaIconService() {
|
||||
void MediaIconService::SetMediaIcon(Media *media, int icon_type) {
|
||||
// if this icon is already part of the throbber animation loop, remove it
|
||||
if (throbber_items_.contains(media)) {
|
||||
// throbber_lock_.lock();
|
||||
throbber_lock_.lock();
|
||||
|
||||
throbber_items_.removeAll(media);
|
||||
|
||||
// throbber_lock_.unlock();
|
||||
throbber_lock_.unlock();
|
||||
|
||||
// if we aren't animating anything, no need to run the timer for now
|
||||
if (throbber_items_.empty()) {
|
||||
@@ -90,13 +90,13 @@ void MediaIconService::AnimationUpdate() {
|
||||
|
||||
QIcon throbber_ico = QIcon(throbber_pixmap_.copy(kThrobberSize*throbber_animation_frame_, 0, kThrobberSize, kThrobberSize));
|
||||
|
||||
// throbber_lock_.lock();
|
||||
throbber_lock_.lock();
|
||||
|
||||
for (int i=0;i<throbber_items_.size();i++) {
|
||||
olive::project_model.set_icon(throbber_items_.at(i), throbber_ico);
|
||||
}
|
||||
|
||||
// throbber_lock_.unlock();
|
||||
throbber_lock_.unlock();
|
||||
|
||||
throbber_animation_frame_++;
|
||||
}
|
||||
|
||||
+16
-16
@@ -28,33 +28,33 @@
|
||||
#include "project/media.h"
|
||||
|
||||
enum IconType {
|
||||
ICON_TYPE_VIDEO,
|
||||
ICON_TYPE_AUDIO,
|
||||
ICON_TYPE_IMAGE,
|
||||
ICON_TYPE_LOADING,
|
||||
ICON_TYPE_ERROR
|
||||
ICON_TYPE_VIDEO,
|
||||
ICON_TYPE_AUDIO,
|
||||
ICON_TYPE_IMAGE,
|
||||
ICON_TYPE_LOADING,
|
||||
ICON_TYPE_ERROR
|
||||
};
|
||||
|
||||
class MediaIconService : public QObject {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
MediaIconService();
|
||||
MediaIconService();
|
||||
public slots:
|
||||
void SetMediaIcon(Media* media, int icon_type);
|
||||
void SetMediaIcon(Media* media, int icon_type);
|
||||
signals:
|
||||
void IconChanged();
|
||||
void IconChanged();
|
||||
private slots:
|
||||
void AnimationUpdate();
|
||||
void AnimationUpdate();
|
||||
private:
|
||||
int throbber_animation_frame_;
|
||||
QVector<Media*> throbber_items_;
|
||||
QTimer throbber_animator_;
|
||||
QPixmap throbber_pixmap_;
|
||||
QMutex throbber_lock_;
|
||||
int throbber_animation_frame_;
|
||||
QVector<Media*> throbber_items_;
|
||||
QTimer throbber_animator_;
|
||||
QPixmap throbber_pixmap_;
|
||||
QMutex throbber_lock_;
|
||||
};
|
||||
|
||||
namespace olive {
|
||||
extern std::unique_ptr<MediaIconService> media_icon_service;
|
||||
extern std::unique_ptr<MediaIconService> media_icon_service;
|
||||
}
|
||||
|
||||
#endif // MEDIAICONSERVICE_H
|
||||
|
||||
+26
-17
@@ -20,21 +20,18 @@
|
||||
|
||||
#include "menuhelper.h"
|
||||
|
||||
#include "oliveglobal.h"
|
||||
|
||||
#include "ui/focusfilter.h"
|
||||
|
||||
#include "io/config.h"
|
||||
|
||||
#include "panels/panels.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QInputDialog>
|
||||
#include <QPushButton>
|
||||
#include <QStyleFactory>
|
||||
|
||||
#include "global/config.h"
|
||||
#include "project/clipboard.h"
|
||||
#include "ui/mainwindow.h"
|
||||
#include "global/global.h"
|
||||
#include "panels/panels.h"
|
||||
#include "ui/focusfilter.h"
|
||||
|
||||
MenuHelper olive::MenuHelper;
|
||||
|
||||
void MenuHelper::InitializeSharedMenus()
|
||||
@@ -125,15 +122,21 @@ void MenuHelper::make_clip_functions_menu(QMenu *parent) {
|
||||
parent->addAction(nest_);
|
||||
}
|
||||
|
||||
void MenuHelper::make_edit_functions_menu(QMenu *parent) {
|
||||
parent->addAction(cut_);
|
||||
parent->addAction(copy_);
|
||||
void MenuHelper::make_edit_functions_menu(QMenu *parent, bool objects_are_selected) {
|
||||
if (objects_are_selected) {
|
||||
parent->addAction(cut_);
|
||||
parent->addAction(copy_);
|
||||
}
|
||||
|
||||
parent->addAction(paste_);
|
||||
parent->addAction(paste_insert_);
|
||||
parent->addAction(duplicate_);
|
||||
parent->addAction(delete_);
|
||||
parent->addAction(ripple_delete_);
|
||||
parent->addAction(split_);
|
||||
|
||||
if (objects_are_selected) {
|
||||
parent->addAction(duplicate_);
|
||||
parent->addAction(delete_);
|
||||
parent->addAction(ripple_delete_);
|
||||
parent->addAction(split_);
|
||||
}
|
||||
}
|
||||
|
||||
void MenuHelper::set_bool_action_checked(QAction *a) {
|
||||
@@ -262,6 +265,12 @@ void MenuHelper::open_recent_from_menu() {
|
||||
olive::Global.get()->open_recent(index);
|
||||
}
|
||||
|
||||
void MenuHelper::create_effect_paste_action(QMenu *menu)
|
||||
{
|
||||
QAction* paste_action = menu->addAction(tr("&Paste"), panel_timeline, SLOT(paste(bool)));
|
||||
paste_action->setEnabled(clipboard.size() > 0 && clipboard_type == CLIPBOARD_TYPE_EFFECT);
|
||||
}
|
||||
|
||||
QMenu* MenuHelper::create_submenu(QMenuBar* parent,
|
||||
const QObject *receiver,
|
||||
const char *member) {
|
||||
|
||||
+15
-1
@@ -75,8 +75,13 @@ public:
|
||||
* @param parent
|
||||
*
|
||||
* The menu to add items to.
|
||||
*
|
||||
* @param objects_are_selected
|
||||
*
|
||||
* Some extra functions may be hidden in the event no clip is actually selected. Set this to **FALSE** to hide those
|
||||
* functions.
|
||||
*/
|
||||
void make_edit_functions_menu(QMenu* parent);
|
||||
void make_edit_functions_menu(QMenu* parent, bool objects_are_selected = true);
|
||||
|
||||
/**
|
||||
* @brief Sets the checked state of a menu item based on a Boolean variable.
|
||||
@@ -186,6 +191,15 @@ public slots:
|
||||
*/
|
||||
void open_recent_from_menu();
|
||||
|
||||
/**
|
||||
* @brief Create a "Paste" action on the specified menu that's enabled only if the clipboard contains effects
|
||||
*
|
||||
* @param menu
|
||||
*
|
||||
* Menu to add action to
|
||||
*/
|
||||
void create_effect_paste_action(QMenu *menu);
|
||||
|
||||
private:
|
||||
QAction* new_project_;
|
||||
QAction* new_sequence_;
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <QStyle>
|
||||
#include <QStyleOptionSlider>
|
||||
|
||||
#include "debug.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
#define RESIZE_HANDLE_SIZE 10
|
||||
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@
|
||||
#include <QWheelEvent>
|
||||
#include <QDebug>
|
||||
|
||||
#include "io/config.h"
|
||||
#include "global/config.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
|
||||
|
||||
+37
-37
@@ -25,65 +25,65 @@
|
||||
#include "panels/project.h"
|
||||
#include "project/media.h"
|
||||
#include "project/sourcescommon.h"
|
||||
#include "debug.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
SourceIconView::SourceIconView(QWidget *parent) : QListView(parent) {
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
setResizeMode(QListView::Adjust);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
setResizeMode(QListView::Adjust);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
|
||||
}
|
||||
|
||||
void SourceIconView::show_context_menu() {
|
||||
project_parent->sources_common->show_context_menu(this, selectedIndexes());
|
||||
project_parent->sources_common->show_context_menu(this, selectedIndexes());
|
||||
}
|
||||
|
||||
void SourceIconView::item_click(const QModelIndex& index) {
|
||||
if (selectedIndexes().size() == 1 && index.column() == 0) {
|
||||
project_parent->sources_common->item_click(project_parent->item_to_media(index), index);
|
||||
}
|
||||
if (selectedIndexes().size() == 1 && index.column() == 0) {
|
||||
project_parent->sources_common->item_click(project_parent->item_to_media(index), index);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceIconView::mousePressEvent(QMouseEvent* event) {
|
||||
project_parent->sources_common->mousePressEvent(event);
|
||||
if (!indexAt(event->pos()).isValid()) selectionModel()->clear();
|
||||
QListView::mousePressEvent(event);
|
||||
project_parent->sources_common->mousePressEvent(event);
|
||||
if (!indexAt(event->pos()).isValid()) selectionModel()->clear();
|
||||
QListView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void SourceIconView::dragEnterEvent(QDragEnterEvent *event) {
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QListView::dragEnterEvent(event);
|
||||
}
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QListView::dragEnterEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceIconView::dragMoveEvent(QDragMoveEvent *event) {
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QListView::dragMoveEvent(event);
|
||||
}
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QListView::dragMoveEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceIconView::dropEvent(QDropEvent* event) {
|
||||
QModelIndex drop_item = indexAt(event->pos());
|
||||
if (!drop_item.isValid()) drop_item = rootIndex();
|
||||
project_parent->sources_common->dropEvent(this, event, drop_item, selectedIndexes());
|
||||
QModelIndex drop_item = indexAt(event->pos());
|
||||
if (!drop_item.isValid()) drop_item = rootIndex();
|
||||
project_parent->sources_common->dropEvent(this, event, drop_item, selectedIndexes());
|
||||
}
|
||||
|
||||
void SourceIconView::mouseDoubleClickEvent(QMouseEvent *) {
|
||||
bool default_behavior = true;
|
||||
if (selectedIndexes().size() == 1) {
|
||||
Media* m = project_parent->item_to_media(selectedIndexes().at(0));
|
||||
if (m->get_type() == MEDIA_TYPE_FOLDER) {
|
||||
default_behavior = false;
|
||||
setRootIndex(selectedIndexes().at(0));
|
||||
emit changed_root();
|
||||
}
|
||||
}
|
||||
if (default_behavior) {
|
||||
bool default_behavior = true;
|
||||
if (selectedIndexes().size() == 1) {
|
||||
Media* m = project_parent->item_to_media(selectedIndexes().at(0));
|
||||
if (m->get_type() == MEDIA_TYPE_FOLDER) {
|
||||
default_behavior = false;
|
||||
setRootIndex(selectedIndexes().at(0));
|
||||
emit changed_root();
|
||||
}
|
||||
}
|
||||
if (default_behavior) {
|
||||
project_parent->sources_common->mouseDoubleClickEvent(selectedIndexes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+30
-30
@@ -26,13 +26,13 @@
|
||||
#include "panels/viewer.h"
|
||||
#include "panels/panels.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "project/undo.h"
|
||||
#include "project/sequence.h"
|
||||
#include "undo/undo.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "mainwindow.h"
|
||||
#include "io/config.h"
|
||||
#include "global/config.h"
|
||||
#include "project/media.h"
|
||||
#include "project/sourcescommon.h"
|
||||
#include "debug.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
#include <QDragEnterEvent>
|
||||
#include <QMimeData>
|
||||
@@ -46,30 +46,30 @@
|
||||
#include <QProcess>
|
||||
|
||||
SourceTable::SourceTable(QWidget* parent) : QTreeView(parent) {
|
||||
setSortingEnabled(true);
|
||||
setAcceptDrops(true);
|
||||
sortByColumn(0, Qt::AscendingOrder);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setDragDropMode(QAbstractItemView::DragDrop);
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
|
||||
setSortingEnabled(true);
|
||||
setAcceptDrops(true);
|
||||
sortByColumn(0, Qt::AscendingOrder);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setDragDropMode(QAbstractItemView::DragDrop);
|
||||
setSelectionMode(QAbstractItemView::ExtendedSelection);
|
||||
connect(this, SIGNAL(clicked(const QModelIndex&)), this, SLOT(item_click(const QModelIndex&)));
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu()));
|
||||
}
|
||||
|
||||
void SourceTable::show_context_menu() {
|
||||
project_parent->sources_common->show_context_menu(this, selectionModel()->selectedRows());
|
||||
project_parent->sources_common->show_context_menu(this, selectionModel()->selectedRows());
|
||||
}
|
||||
|
||||
void SourceTable::item_click(const QModelIndex& index) {
|
||||
if (selectionModel()->selectedRows().size() == 1 && index.column() == 0) {
|
||||
project_parent->sources_common->item_click(project_parent->item_to_media(index), index);
|
||||
}
|
||||
if (selectionModel()->selectedRows().size() == 1 && index.column() == 0) {
|
||||
project_parent->sources_common->item_click(project_parent->item_to_media(index), index);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTable::mousePressEvent(QMouseEvent* event) {
|
||||
project_parent->sources_common->mousePressEvent(event);
|
||||
QTreeView::mousePressEvent(event);
|
||||
project_parent->sources_common->mousePressEvent(event);
|
||||
QTreeView::mousePressEvent(event);
|
||||
}
|
||||
|
||||
void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) {
|
||||
@@ -77,21 +77,21 @@ void SourceTable::mouseDoubleClickEvent(QMouseEvent* ) {
|
||||
}
|
||||
|
||||
void SourceTable::dragEnterEvent(QDragEnterEvent *event) {
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QTreeView::dragEnterEvent(event);
|
||||
}
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QTreeView::dragEnterEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTable::dragMoveEvent(QDragMoveEvent *event) {
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QTreeView::dragMoveEvent(event);
|
||||
}
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
QTreeView::dragMoveEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void SourceTable::dropEvent(QDropEvent* event) {
|
||||
project_parent->sources_common->dropEvent(this, event, indexAt(event->pos()), selectionModel()->selectedRows());
|
||||
project_parent->sources_common->dropEvent(this, event, indexAt(event->pos()), selectionModel()->selectedRows());
|
||||
}
|
||||
|
||||
+10
-10
@@ -30,19 +30,19 @@ class Media;
|
||||
|
||||
class SourceTable : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
SourceTable(QWidget* parent = 0);
|
||||
Project* project_parent;
|
||||
SourceTable(QWidget* parent = 0);
|
||||
Project* project_parent;
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
void mouseDoubleClickEvent(QMouseEvent *);
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
void mouseDoubleClickEvent(QMouseEvent *);
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
private slots:
|
||||
void item_click(const QModelIndex& index);
|
||||
void show_context_menu();
|
||||
void item_click(const QModelIndex& index);
|
||||
void show_context_menu();
|
||||
};
|
||||
|
||||
#endif // SOURCETABLE_H
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "styling.h"
|
||||
|
||||
#include "global/config.h"
|
||||
|
||||
bool olive::styling::UseDarkIcons()
|
||||
{
|
||||
return olive::CurrentConfig.style == kOliveDefaultLight || olive::CurrentConfig.style == kNativeDarkIcons;
|
||||
}
|
||||
|
||||
QColor olive::styling::GetIconColor()
|
||||
{
|
||||
if (UseDarkIcons()) {
|
||||
return Qt::black;
|
||||
} else {
|
||||
return Qt::white;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool olive::styling::UseNativeUI()
|
||||
{
|
||||
return olive::CurrentConfig.style == kNativeLightIcons || olive::CurrentConfig.style == kNativeDarkIcons;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
#ifndef STYLING_H
|
||||
#define STYLING_H
|
||||
|
||||
#include <QColor>
|
||||
|
||||
namespace olive {
|
||||
namespace styling {
|
||||
|
||||
/**
|
||||
* @brief Officially supported styles to use in Olive
|
||||
*/
|
||||
enum Style {
|
||||
/**
|
||||
Qt Fusion-based cross-platform UI. The default styling of Olive. Can also be heavily customized with a CSS
|
||||
file.
|
||||
*/
|
||||
kOliveDefaultDark,
|
||||
|
||||
/**
|
||||
Qt Fusion-based cross-platform UI. The default styling of Olive. Can also be heavily customized with a CSS
|
||||
file. This will use the
|
||||
*/
|
||||
kOliveDefaultLight,
|
||||
|
||||
/**
|
||||
Use current OS's native styling (or at least Qt's default). Most UIs use a light theming, so this will
|
||||
automatically implement dark icons/UI elements.
|
||||
*/
|
||||
kNativeDarkIcons,
|
||||
|
||||
/**
|
||||
Use current OS's native styling (or at least Qt's default). Most UIs use a light theming, but in case one
|
||||
doesn't, this option will provide light icons for use with a dark theme.
|
||||
*/
|
||||
kNativeLightIcons
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Return whether to use dark icons or light icons
|
||||
* @return
|
||||
*
|
||||
* **TRUE** if icons should be dark.
|
||||
*/
|
||||
bool UseDarkIcons();
|
||||
|
||||
/**
|
||||
* @brief Return whether to use native UI or Fusion
|
||||
* @return
|
||||
*
|
||||
* **TRUE** if UI should use native styling
|
||||
*/
|
||||
bool UseNativeUI();
|
||||
|
||||
/**
|
||||
* @brief Return the current icon color based on Config::use_dark_icons.
|
||||
*
|
||||
* Also used by some other UI elements like the lines and text on the TimelineHeader
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* Either white or black depending on Config::use_dark_icons
|
||||
*/
|
||||
QColor GetIconColor();
|
||||
}
|
||||
}
|
||||
|
||||
#endif // STYLING_H
|
||||
+34
-31
@@ -21,42 +21,45 @@
|
||||
#include "texteditex.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QMenu>
|
||||
|
||||
TextEditEx::TextEditEx(QWidget *parent) : QTextEdit(parent) {
|
||||
setUndoRedoEnabled(false);
|
||||
connect(this, SIGNAL(textChanged()), this, SLOT(updateInternals()));
|
||||
connect(this, SIGNAL(updateSelf()), this, SLOT(updateText()));
|
||||
#include "dialogs/texteditdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
TextEditEx::TextEditEx(QWidget *parent, bool enable_rich_text) :
|
||||
QTextEdit(parent),
|
||||
enable_rich_text_(enable_rich_text)
|
||||
{
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(text_edit_menu()));
|
||||
|
||||
connect(this, SIGNAL(textChanged()), this, SLOT(queue_text_modified()));
|
||||
}
|
||||
|
||||
const QString& TextEditEx::getPlainTextEx() {
|
||||
return text;
|
||||
void TextEditEx::text_edit_menu() {
|
||||
QMenu menu;
|
||||
|
||||
menu.addAction(tr("&Edit Text"), this, SLOT(open_text_edit()));
|
||||
|
||||
menu.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void TextEditEx::setPlainTextEx(const QString &t) {
|
||||
previousText = text;
|
||||
text = t;
|
||||
emit updateSelf();
|
||||
void TextEditEx::open_text_edit() {
|
||||
const QString& current_text = (enable_rich_text_) ? toHtml() : toPlainText();
|
||||
|
||||
TextEditDialog ted(olive::MainWindow, current_text, enable_rich_text_);
|
||||
ted.exec();
|
||||
QString result = ted.get_string();
|
||||
if (!result.isEmpty()) {
|
||||
if (enable_rich_text_) {
|
||||
setHtml(result);
|
||||
} else {
|
||||
setPlainText(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const QString &TextEditEx::getPreviousValue() {
|
||||
return previousText;
|
||||
}
|
||||
|
||||
void TextEditEx::updateInternals() {
|
||||
previousText = text;
|
||||
text = toPlainText();
|
||||
}
|
||||
|
||||
void TextEditEx::updateText() {
|
||||
blockSignals(true);
|
||||
|
||||
int pos = textCursor().position();
|
||||
|
||||
setPlainText(text);
|
||||
|
||||
QTextCursor newCursor(document());
|
||||
newCursor.setPosition(pos);
|
||||
setTextCursor(newCursor);
|
||||
|
||||
blockSignals(false);
|
||||
void TextEditEx::queue_text_modified()
|
||||
{
|
||||
emit textModified(enable_rich_text_ ? toHtml() : toPlainText());
|
||||
}
|
||||
|
||||
+7
-10
@@ -24,20 +24,17 @@
|
||||
#include <QTextEdit>
|
||||
|
||||
class TextEditEx : public QTextEdit {
|
||||
Q_OBJECT
|
||||
Q_OBJECT
|
||||
public:
|
||||
TextEditEx(QWidget* parent = 0);
|
||||
void setPlainTextEx(const QString &text);
|
||||
const QString& getPreviousValue();
|
||||
const QString& getPlainTextEx();
|
||||
TextEditEx(QWidget* parent = nullptr, bool enable_rich_text = true);
|
||||
signals:
|
||||
void updateSelf();
|
||||
void textModified(const QString& s);
|
||||
private slots:
|
||||
void updateInternals();
|
||||
void updateText();
|
||||
void text_edit_menu();
|
||||
void open_text_edit();
|
||||
void queue_text_modified();
|
||||
private:
|
||||
QString previousText;
|
||||
QString text;
|
||||
bool enable_rich_text_;
|
||||
};
|
||||
|
||||
#endif // TEXTEDITEX_H
|
||||
|
||||
+332
-329
@@ -20,17 +20,6 @@
|
||||
|
||||
#include "timelineheader.h"
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "project/sequence.h"
|
||||
#include "project/undo.h"
|
||||
#include "project/media.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "io/config.h"
|
||||
#include "ui/menuhelper.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
@@ -38,6 +27,19 @@
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "panels/panels.h"
|
||||
#include "panels/timeline.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "undo/undo.h"
|
||||
#include "project/media.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "global/config.h"
|
||||
#include "global/global.h"
|
||||
#include "ui/menuhelper.h"
|
||||
#include "global/debug.h"
|
||||
#include "undo/undostack.h"
|
||||
|
||||
#define CLICK_RANGE 5
|
||||
#define PLAYHEAD_SIZE 6
|
||||
#define LINE_MIN_PADDING 50
|
||||
@@ -47,428 +49,429 @@
|
||||
#define TEXT_PADDING_FROM_LINE 4
|
||||
|
||||
bool center_scroll_to_playhead(QScrollBar* bar, double zoom, long playhead) {
|
||||
// returns true is the scroll was changed, false if not
|
||||
int target_scroll = qMin(bar->maximum(), qMax(0, getScreenPointFromFrame(zoom, playhead)-(bar->width()>>1)));
|
||||
if (target_scroll == bar->value()) {
|
||||
return false;
|
||||
}
|
||||
bar->setValue(target_scroll);
|
||||
return true;
|
||||
// returns true is the scroll was changed, false if not
|
||||
int target_scroll = qMin(bar->maximum(), qMax(0, getScreenPointFromFrame(zoom, playhead)-(bar->width()>>1)));
|
||||
if (target_scroll == bar->value()) {
|
||||
return false;
|
||||
}
|
||||
bar->setValue(target_scroll);
|
||||
return true;
|
||||
}
|
||||
|
||||
TimelineHeader::TimelineHeader(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
snapping(true),
|
||||
dragging(false),
|
||||
resizing_workarea(false),
|
||||
zoom(1),
|
||||
in_visible(0),
|
||||
fm(font()),
|
||||
dragging_markers(false),
|
||||
scroll(0)
|
||||
QWidget(parent),
|
||||
snapping(true),
|
||||
dragging(false),
|
||||
resizing_workarea(false),
|
||||
zoom(1),
|
||||
in_visible(0),
|
||||
fm(font()),
|
||||
dragging_markers(false),
|
||||
scroll(0)
|
||||
{
|
||||
height_actual = fm.height();
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
show_text(true);
|
||||
height_actual = fm.height();
|
||||
setCursor(Qt::ArrowCursor);
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::ClickFocus);
|
||||
show_text(true);
|
||||
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(show_context_menu(const QPoint &)));
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(show_context_menu(const QPoint &)));
|
||||
}
|
||||
|
||||
void TimelineHeader::set_scroll(int s) {
|
||||
scroll = s;
|
||||
update();
|
||||
scroll = s;
|
||||
update();
|
||||
}
|
||||
|
||||
long TimelineHeader::getHeaderFrameFromScreenPoint(int x) {
|
||||
return getFrameFromScreenPoint(zoom, x + scroll) + in_visible;
|
||||
return getFrameFromScreenPoint(zoom, x + scroll) + in_visible;
|
||||
}
|
||||
|
||||
int TimelineHeader::getHeaderScreenPointFromFrame(long frame) {
|
||||
return getScreenPointFromFrame(zoom, frame - in_visible) - scroll;
|
||||
return getScreenPointFromFrame(zoom, frame - in_visible) - scroll;
|
||||
}
|
||||
|
||||
void TimelineHeader::set_playhead(int mouse_x) {
|
||||
long frame = getHeaderFrameFromScreenPoint(mouse_x);
|
||||
if (snapping) panel_timeline->snap_to_timeline(&frame, false, true, true);
|
||||
if (frame != viewer->seq->playhead) {
|
||||
viewer->seek(frame);
|
||||
}
|
||||
long frame = getHeaderFrameFromScreenPoint(mouse_x);
|
||||
if (snapping) panel_timeline->snap_to_timeline(&frame, false, true, true);
|
||||
if (frame != viewer->seq->playhead) {
|
||||
viewer->seek(frame);
|
||||
}
|
||||
}
|
||||
|
||||
int TimelineHeader::get_marker_offset() {
|
||||
return (text_enabled) ? height()/2 : 0;
|
||||
return (text_enabled) ? height()/2 : 0;
|
||||
}
|
||||
|
||||
void TimelineHeader::set_visible_in(long i) {
|
||||
in_visible = i;
|
||||
update();
|
||||
in_visible = i;
|
||||
update();
|
||||
}
|
||||
|
||||
void TimelineHeader::set_in_point(long new_in) {
|
||||
long new_out = viewer->seq->workarea_out;
|
||||
if (new_out == new_in) {
|
||||
new_in--;
|
||||
} else if (new_out < new_in) {
|
||||
new_out = viewer->seq->getEndFrame();
|
||||
}
|
||||
long new_out = viewer->seq->workarea_out;
|
||||
if (new_out == new_in) {
|
||||
new_in--;
|
||||
} else if (new_out < new_in) {
|
||||
new_out = viewer->seq->getEndFrame();
|
||||
}
|
||||
|
||||
olive::UndoStack.push(new SetTimelineInOutCommand(viewer->seq, true, new_in, new_out));
|
||||
update_parents();
|
||||
olive::UndoStack.push(new SetTimelineInOutCommand(viewer->seq.get(), true, new_in, new_out));
|
||||
update_parents();
|
||||
}
|
||||
|
||||
void TimelineHeader::set_out_point(long new_out) {
|
||||
long new_in = viewer->seq->workarea_in;
|
||||
if (new_out == new_in) {
|
||||
new_out++;
|
||||
} else if (new_in > new_out || new_in < 0) {
|
||||
new_in = 0;
|
||||
}
|
||||
long new_in = viewer->seq->workarea_in;
|
||||
if (new_out == new_in) {
|
||||
new_out++;
|
||||
} else if (new_in > new_out || new_in < 0) {
|
||||
new_in = 0;
|
||||
}
|
||||
|
||||
olive::UndoStack.push(new SetTimelineInOutCommand(viewer->seq, true, new_in, new_out));
|
||||
update_parents();
|
||||
olive::UndoStack.push(new SetTimelineInOutCommand(viewer->seq.get(), true, new_in, new_out));
|
||||
update_parents();
|
||||
}
|
||||
|
||||
void TimelineHeader::set_scrollbar_max(QScrollBar* bar, long sequence_end_frame, int offset) {
|
||||
bar->setMaximum(qMax(0, getScreenPointFromFrame(zoom, sequence_end_frame) - offset));
|
||||
bar->setMaximum(qMax(0, getScreenPointFromFrame(zoom, sequence_end_frame) - offset));
|
||||
}
|
||||
|
||||
void TimelineHeader::show_text(bool enable) {
|
||||
text_enabled = enable;
|
||||
if (enable) {
|
||||
setFixedHeight(height_actual*2);
|
||||
} else {
|
||||
setFixedHeight(height_actual);
|
||||
}
|
||||
update();
|
||||
text_enabled = enable;
|
||||
if (enable) {
|
||||
setFixedHeight(height_actual*2);
|
||||
} else {
|
||||
setFixedHeight(height_actual);
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
void TimelineHeader::mousePressEvent(QMouseEvent* event) {
|
||||
if (viewer->seq != nullptr && event->buttons() & Qt::LeftButton) {
|
||||
if (resizing_workarea) {
|
||||
sequence_end = viewer->seq->getEndFrame();
|
||||
} else {
|
||||
/*int
|
||||
QPoint start(in_x, height()+2);
|
||||
QPainterPath path;
|
||||
path.moveTo(start + QPoint(1,0));
|
||||
path.lineTo(in_x-PLAYHEAD_SIZE, yoff);
|
||||
path.lineTo(in_x+PLAYHEAD_SIZE+1, yoff);*/
|
||||
if (viewer->seq != nullptr && event->buttons() & Qt::LeftButton) {
|
||||
if (resizing_workarea) {
|
||||
sequence_end = viewer->seq->getEndFrame();
|
||||
} else {
|
||||
/*int
|
||||
QPoint start(in_x, height()+2);
|
||||
QPainterPath path;
|
||||
path.moveTo(start + QPoint(1,0));
|
||||
path.lineTo(in_x-PLAYHEAD_SIZE, yoff);
|
||||
path.lineTo(in_x+PLAYHEAD_SIZE+1, yoff);*/
|
||||
|
||||
bool shift = (event->modifiers() & Qt::ShiftModifier);
|
||||
bool clicked_on_marker = false;
|
||||
int playhead_x = getHeaderScreenPointFromFrame(viewer->seq->playhead);
|
||||
bool shift = (event->modifiers() & Qt::ShiftModifier);
|
||||
bool clicked_on_marker = false;
|
||||
int playhead_x = getHeaderScreenPointFromFrame(viewer->seq->playhead);
|
||||
|
||||
if (event->pos().y() > get_marker_offset()
|
||||
&& (event->pos().x() < playhead_x-PLAYHEAD_SIZE
|
||||
|| event->pos().x() > playhead_x+PLAYHEAD_SIZE)) {
|
||||
for (int i=0;i<viewer->marker_ref->size();i++) {
|
||||
int marker_pos = getHeaderScreenPointFromFrame(viewer->marker_ref->at(i).frame);
|
||||
if (event->pos().x() > marker_pos - MARKER_SIZE && event->pos().x() < marker_pos + MARKER_SIZE) {
|
||||
bool found = false;
|
||||
for (int j=0;j<selected_markers.size();j++) {
|
||||
if (selected_markers.at(j) == i) {
|
||||
if (shift) {
|
||||
selected_markers.removeAt(j);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (!shift) {
|
||||
selected_markers.clear();
|
||||
}
|
||||
selected_markers.append(i);
|
||||
}
|
||||
clicked_on_marker = true;
|
||||
update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (event->pos().y() > get_marker_offset()
|
||||
&& (event->pos().x() < playhead_x-PLAYHEAD_SIZE
|
||||
|| event->pos().x() > playhead_x+PLAYHEAD_SIZE)) {
|
||||
for (int i=0;i<viewer->marker_ref->size();i++) {
|
||||
int marker_pos = getHeaderScreenPointFromFrame(viewer->marker_ref->at(i).frame);
|
||||
if (event->pos().x() > marker_pos - MARKER_SIZE && event->pos().x() < marker_pos + MARKER_SIZE) {
|
||||
bool found = false;
|
||||
for (int j=0;j<selected_markers.size();j++) {
|
||||
if (selected_markers.at(j) == i) {
|
||||
if (shift) {
|
||||
selected_markers.removeAt(j);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
if (!shift) {
|
||||
selected_markers.clear();
|
||||
}
|
||||
selected_markers.append(i);
|
||||
}
|
||||
clicked_on_marker = true;
|
||||
update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (clicked_on_marker) {
|
||||
selected_marker_original_times.resize(selected_markers.size());
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
selected_marker_original_times[i] = viewer->marker_ref->at(selected_markers.at(i)).frame;
|
||||
}
|
||||
drag_start = event->pos().x();
|
||||
dragging_markers = true;
|
||||
} else {
|
||||
if (selected_markers.size() > 0 && !shift) {
|
||||
selected_markers.clear();
|
||||
update();
|
||||
}
|
||||
set_playhead(event->pos().x());
|
||||
}
|
||||
}
|
||||
dragging = true;
|
||||
}
|
||||
if (clicked_on_marker) {
|
||||
selected_marker_original_times.resize(selected_markers.size());
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
selected_marker_original_times[i] = viewer->marker_ref->at(selected_markers.at(i)).frame;
|
||||
}
|
||||
drag_start = event->pos().x();
|
||||
dragging_markers = true;
|
||||
} else {
|
||||
if (selected_markers.size() > 0 && !shift) {
|
||||
selected_markers.clear();
|
||||
update();
|
||||
}
|
||||
set_playhead(event->pos().x());
|
||||
}
|
||||
}
|
||||
dragging = true;
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineHeader::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (viewer->seq != nullptr) {
|
||||
if (dragging) {
|
||||
if (resizing_workarea) {
|
||||
long frame = getHeaderFrameFromScreenPoint(event->pos().x());
|
||||
if (snapping) panel_timeline->snap_to_timeline(&frame, true, true, false);
|
||||
if (viewer->seq != nullptr) {
|
||||
if (dragging) {
|
||||
if (resizing_workarea) {
|
||||
long frame = getHeaderFrameFromScreenPoint(event->pos().x());
|
||||
if (snapping) panel_timeline->snap_to_timeline(&frame, true, true, false);
|
||||
|
||||
if (resizing_workarea_in) {
|
||||
temp_workarea_in = qMax(qMin(temp_workarea_out-1, frame), 0L);
|
||||
} else {
|
||||
temp_workarea_out = qMin(qMax(temp_workarea_in+1, frame), sequence_end);
|
||||
}
|
||||
if (resizing_workarea_in) {
|
||||
temp_workarea_in = qMax(qMin(temp_workarea_out-1, frame), 0L);
|
||||
} else {
|
||||
temp_workarea_out = qMin(qMax(temp_workarea_in+1, frame), sequence_end);
|
||||
}
|
||||
|
||||
update_parents();
|
||||
} else if (dragging_markers) {
|
||||
long frame_movement = getHeaderFrameFromScreenPoint(event->pos().x()) - getHeaderFrameFromScreenPoint(drag_start);
|
||||
update_parents();
|
||||
} else if (dragging_markers) {
|
||||
long frame_movement = getHeaderFrameFromScreenPoint(event->pos().x()) - getHeaderFrameFromScreenPoint(drag_start);
|
||||
|
||||
// snap markers
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
long fm = selected_marker_original_times.at(i) + frame_movement;
|
||||
if (snapping && panel_timeline->snap_to_timeline(&fm, true, false, true)) {
|
||||
frame_movement = fm - selected_marker_original_times.at(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// snap markers
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
long fm = selected_marker_original_times.at(i) + frame_movement;
|
||||
if (snapping && panel_timeline->snap_to_timeline(&fm, true, false, true)) {
|
||||
frame_movement = fm - selected_marker_original_times.at(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// validate markers (ensure none go below 0)
|
||||
long validator;
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
validator = selected_marker_original_times.at(i) + frame_movement;
|
||||
if (validator < 0) {
|
||||
frame_movement -= validator;
|
||||
}
|
||||
}
|
||||
// validate markers (ensure none go below 0)
|
||||
long validator;
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
validator = selected_marker_original_times.at(i) + frame_movement;
|
||||
if (validator < 0) {
|
||||
frame_movement -= validator;
|
||||
}
|
||||
}
|
||||
|
||||
// move markers
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
viewer->marker_ref[0][selected_markers.at(i)].frame = selected_marker_original_times.at(i) + frame_movement;
|
||||
}
|
||||
// move markers
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
viewer->marker_ref[0][selected_markers.at(i)].frame = selected_marker_original_times.at(i) + frame_movement;
|
||||
}
|
||||
|
||||
update_parents();
|
||||
} else {
|
||||
set_playhead(event->pos().x());
|
||||
}
|
||||
} else {
|
||||
resizing_workarea = false;
|
||||
unsetCursor();
|
||||
if (viewer->seq != nullptr && viewer->seq->using_workarea) {
|
||||
long min_frame = getHeaderFrameFromScreenPoint(event->pos().x() - CLICK_RANGE) - 1;
|
||||
long max_frame = getHeaderFrameFromScreenPoint(event->pos().x() + CLICK_RANGE) + 1;
|
||||
if (viewer->seq->workarea_in > min_frame && viewer->seq->workarea_in < max_frame) {
|
||||
resizing_workarea = true;
|
||||
resizing_workarea_in = true;
|
||||
} else if (viewer->seq->workarea_out > min_frame && viewer->seq->workarea_out < max_frame) {
|
||||
resizing_workarea = true;
|
||||
resizing_workarea_in = false;
|
||||
}
|
||||
if (resizing_workarea) {
|
||||
temp_workarea_in = viewer->seq->workarea_in;
|
||||
temp_workarea_out = viewer->seq->workarea_out;
|
||||
setCursor(Qt::SizeHorCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
update_parents();
|
||||
} else {
|
||||
set_playhead(event->pos().x());
|
||||
}
|
||||
} else {
|
||||
resizing_workarea = false;
|
||||
unsetCursor();
|
||||
if (viewer->seq != nullptr && viewer->seq->using_workarea) {
|
||||
long min_frame = getHeaderFrameFromScreenPoint(event->pos().x() - CLICK_RANGE) - 1;
|
||||
long max_frame = getHeaderFrameFromScreenPoint(event->pos().x() + CLICK_RANGE) + 1;
|
||||
if (viewer->seq->workarea_in > min_frame && viewer->seq->workarea_in < max_frame) {
|
||||
resizing_workarea = true;
|
||||
resizing_workarea_in = true;
|
||||
} else if (viewer->seq->workarea_out > min_frame && viewer->seq->workarea_out < max_frame) {
|
||||
resizing_workarea = true;
|
||||
resizing_workarea_in = false;
|
||||
}
|
||||
if (resizing_workarea) {
|
||||
temp_workarea_in = viewer->seq->workarea_in;
|
||||
temp_workarea_out = viewer->seq->workarea_out;
|
||||
setCursor(Qt::SizeHorCursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineHeader::mouseReleaseEvent(QMouseEvent*) {
|
||||
if (viewer->seq != nullptr) {
|
||||
dragging = false;
|
||||
if (resizing_workarea) {
|
||||
olive::UndoStack.push(new SetTimelineInOutCommand(viewer->seq, true, temp_workarea_in, temp_workarea_out));
|
||||
} else if (dragging_markers && selected_markers.size() > 0) {
|
||||
bool moved = false;
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
Marker* m = &viewer->marker_ref[0][selected_markers.at(i)];
|
||||
if (selected_marker_original_times.at(i) != m->frame) {
|
||||
ca->append(new MoveMarkerAction(m, selected_marker_original_times.at(i), m->frame));
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
if (moved) {
|
||||
olive::UndoStack.push(ca);
|
||||
} else {
|
||||
delete ca;
|
||||
}
|
||||
}
|
||||
if (viewer->seq != nullptr) {
|
||||
dragging = false;
|
||||
if (resizing_workarea) {
|
||||
olive::UndoStack.push(new SetTimelineInOutCommand(viewer->seq.get(), true, temp_workarea_in, temp_workarea_out));
|
||||
} else if (dragging_markers && selected_markers.size() > 0) {
|
||||
bool moved = false;
|
||||
ComboAction* ca = new ComboAction();
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
Marker* m = &viewer->marker_ref[0][selected_markers.at(i)];
|
||||
if (selected_marker_original_times.at(i) != m->frame) {
|
||||
ca->append(new MoveMarkerAction(m, selected_marker_original_times.at(i), m->frame));
|
||||
moved = true;
|
||||
}
|
||||
}
|
||||
if (moved) {
|
||||
olive::UndoStack.push(ca);
|
||||
} else {
|
||||
delete ca;
|
||||
}
|
||||
}
|
||||
|
||||
resizing_workarea = false;
|
||||
dragging = false;
|
||||
dragging_markers = false;
|
||||
panel_timeline->snapped = false;
|
||||
update_parents();
|
||||
}
|
||||
resizing_workarea = false;
|
||||
dragging = false;
|
||||
dragging_markers = false;
|
||||
panel_timeline->snapped = false;
|
||||
update_parents();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineHeader::focusOutEvent(QFocusEvent*) {
|
||||
selected_markers.clear();
|
||||
update();
|
||||
selected_markers.clear();
|
||||
update();
|
||||
}
|
||||
|
||||
void TimelineHeader::update_parents() {
|
||||
viewer->update_parents();
|
||||
viewer->update_parents();
|
||||
}
|
||||
|
||||
void TimelineHeader::update_zoom(double z) {
|
||||
zoom = z;
|
||||
update();
|
||||
zoom = z;
|
||||
update();
|
||||
}
|
||||
|
||||
double TimelineHeader::get_zoom() {
|
||||
return zoom;
|
||||
return zoom;
|
||||
}
|
||||
|
||||
void TimelineHeader::delete_markers() {
|
||||
if (selected_markers.size() > 0) {
|
||||
DeleteMarkerAction* dma = new DeleteMarkerAction(viewer->marker_ref);
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
dma->markers.append(selected_markers.at(i));
|
||||
}
|
||||
olive::UndoStack.push(dma);
|
||||
update_parents();
|
||||
}
|
||||
if (selected_markers.size() > 0) {
|
||||
DeleteMarkerAction* dma = new DeleteMarkerAction(viewer->marker_ref);
|
||||
for (int i=0;i<selected_markers.size();i++) {
|
||||
dma->markers.append(selected_markers.at(i));
|
||||
}
|
||||
olive::UndoStack.push(dma);
|
||||
update_parents();
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineHeader::paintEvent(QPaintEvent*) {
|
||||
if (viewer->seq != nullptr && zoom > 0) {
|
||||
QPainter p(this);
|
||||
int yoff = get_marker_offset();
|
||||
if (viewer->seq != nullptr && zoom > 0) {
|
||||
QPainter p(this);
|
||||
int yoff = get_marker_offset();
|
||||
|
||||
double interval = viewer->seq->frame_rate;
|
||||
int textWidth = 0;
|
||||
int lastTextBoundary = INT_MIN;
|
||||
double interval = viewer->seq->frame_rate;
|
||||
int textWidth = 0;
|
||||
int lastTextBoundary = INT_MIN;
|
||||
|
||||
int lastLineX = INT_MIN;
|
||||
int lastLineX = INT_MIN;
|
||||
|
||||
int sublineCount = 1;
|
||||
int sublineTest = qRound(interval*zoom);
|
||||
int sublineInterval = 1;
|
||||
while (sublineTest > SUBLINE_MIN_PADDING
|
||||
&& sublineInterval >= 1) {
|
||||
sublineCount *= 2;
|
||||
sublineInterval = (interval/sublineCount);
|
||||
sublineTest = qRound(sublineInterval*zoom);
|
||||
}
|
||||
sublineCount = qMin(sublineCount, qRound(interval));
|
||||
int sublineCount = 1;
|
||||
int sublineTest = qRound(interval*zoom);
|
||||
int sublineInterval = 1;
|
||||
while (sublineTest > SUBLINE_MIN_PADDING
|
||||
&& sublineInterval >= 1) {
|
||||
sublineCount *= 2;
|
||||
sublineInterval = (interval/sublineCount);
|
||||
sublineTest = qRound(sublineInterval*zoom);
|
||||
}
|
||||
sublineCount = qMin(sublineCount, qRound(interval));
|
||||
|
||||
int text_x, fullTextWidth;
|
||||
QString timecode;
|
||||
int text_x, fullTextWidth;
|
||||
QString timecode;
|
||||
|
||||
// find where to start drawing lines (lineX algorithm reversed if lineX = 0)
|
||||
int i = qFloor(double(scroll)/zoom/interval);
|
||||
// find where to start drawing lines (lineX algorithm reversed if lineX = 0)
|
||||
int i = qFloor(double(scroll)/zoom/interval);
|
||||
|
||||
while (true) {
|
||||
long frame = qRound(interval*i);
|
||||
int lineX = qRound(frame*zoom) - scroll;
|
||||
while (true) {
|
||||
long frame = qRound(interval*i);
|
||||
int lineX = qRound(frame*zoom) - scroll;
|
||||
|
||||
if (lineX > width()) break;
|
||||
if (lineX > width()) break;
|
||||
|
||||
// draw text
|
||||
bool draw_text = false;
|
||||
if (text_enabled && lineX-textWidth > lastTextBoundary) {
|
||||
timecode = frame_to_timecode(frame + in_visible, olive::CurrentConfig.timecode_view, viewer->seq->frame_rate);
|
||||
fullTextWidth = fm.width(timecode);
|
||||
textWidth = fullTextWidth>>1;
|
||||
// draw text
|
||||
bool draw_text = false;
|
||||
if (text_enabled && lineX-textWidth > lastTextBoundary) {
|
||||
timecode = frame_to_timecode(frame + in_visible, olive::CurrentConfig.timecode_view, viewer->seq->frame_rate);
|
||||
fullTextWidth = fm.width(timecode);
|
||||
textWidth = fullTextWidth>>1;
|
||||
|
||||
text_x = lineX;
|
||||
text_x = lineX;
|
||||
|
||||
// centers the text to that point on the timeline, LEFT aligns it if not
|
||||
if (olive::CurrentConfig.center_timeline_timecodes) {
|
||||
text_x -= textWidth;
|
||||
} else {
|
||||
text_x += TEXT_PADDING_FROM_LINE;
|
||||
}
|
||||
// centers the text to that point on the timeline, LEFT aligns it if not
|
||||
if (olive::CurrentConfig.center_timeline_timecodes) {
|
||||
text_x -= textWidth;
|
||||
} else {
|
||||
text_x += TEXT_PADDING_FROM_LINE;
|
||||
}
|
||||
|
||||
lastTextBoundary = lineX+textWidth;
|
||||
if (lastTextBoundary >= 0) {
|
||||
draw_text = true;
|
||||
}
|
||||
}
|
||||
lastTextBoundary = lineX+textWidth;
|
||||
if (lastTextBoundary >= 0) {
|
||||
draw_text = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (lineX > lastLineX+LINE_MIN_PADDING) {
|
||||
if (draw_text) {
|
||||
p.setPen(Qt::white);
|
||||
p.drawText(QRect(text_x, 0, fullTextWidth, yoff), timecode);
|
||||
}
|
||||
if (lineX > lastLineX+LINE_MIN_PADDING) {
|
||||
if (draw_text) {
|
||||
p.setPen(olive::styling::GetIconColor());
|
||||
p.drawText(QRect(text_x, 0, fullTextWidth, yoff), timecode);
|
||||
}
|
||||
|
||||
// draw line markers
|
||||
p.setPen(Qt::gray);
|
||||
p.drawLine(lineX, (!olive::CurrentConfig.center_timeline_timecodes && draw_text) ? 0 : yoff, lineX, height());
|
||||
// draw line markers
|
||||
p.setPen(Qt::gray);
|
||||
p.drawLine(lineX, (!olive::CurrentConfig.center_timeline_timecodes && draw_text) ? 0 : yoff, lineX, height());
|
||||
|
||||
// draw sub-line markers
|
||||
for (int j=1;j<sublineCount;j++) {
|
||||
int sublineX = lineX+(qRound(j*interval/sublineCount)*zoom);
|
||||
p.drawLine(sublineX, yoff, sublineX, yoff+(height()/4));
|
||||
}
|
||||
// draw sub-line markers
|
||||
for (int j=1;j<sublineCount;j++) {
|
||||
int sublineX = lineX+(qRound(j*interval/sublineCount)*zoom);
|
||||
p.drawLine(sublineX, yoff, sublineX, yoff+(height()/4));
|
||||
}
|
||||
|
||||
lastLineX = lineX;
|
||||
}
|
||||
lastLineX = lineX;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
// draw in/out selection
|
||||
int in_x;
|
||||
if (viewer->seq->using_workarea) {
|
||||
in_x = getHeaderScreenPointFromFrame((resizing_workarea ? temp_workarea_in : viewer->seq->workarea_in));
|
||||
int out_x = getHeaderScreenPointFromFrame((resizing_workarea ? temp_workarea_out : viewer->seq->workarea_out));
|
||||
p.fillRect(QRect(in_x, 0, out_x-in_x, height()), QColor(0, 192, 255, 128));
|
||||
p.setPen(Qt::white);
|
||||
p.drawLine(in_x, 0, in_x, height());
|
||||
p.drawLine(out_x, 0, out_x, height());
|
||||
}
|
||||
// draw in/out selection
|
||||
int in_x;
|
||||
if (viewer->seq->using_workarea) {
|
||||
in_x = getHeaderScreenPointFromFrame((resizing_workarea ? temp_workarea_in : viewer->seq->workarea_in));
|
||||
int out_x = getHeaderScreenPointFromFrame((resizing_workarea ? temp_workarea_out : viewer->seq->workarea_out));
|
||||
p.fillRect(QRect(in_x, 0, out_x-in_x, height()), QColor(0, 192, 255, 128));
|
||||
p.setPen(olive::styling::GetIconColor());
|
||||
p.drawLine(in_x, 0, in_x, height());
|
||||
p.drawLine(out_x, 0, out_x, height());
|
||||
}
|
||||
|
||||
// draw markers
|
||||
for (int i=0;i<viewer->marker_ref->size();i++) {
|
||||
const Marker& m = viewer->marker_ref->at(i);
|
||||
// draw markers
|
||||
for (int i=0;i<viewer->marker_ref->size();i++) {
|
||||
const Marker& m = viewer->marker_ref->at(i);
|
||||
|
||||
int marker_x = getHeaderScreenPointFromFrame(m.frame);
|
||||
int marker_x = getHeaderScreenPointFromFrame(m.frame);
|
||||
|
||||
bool selected = false;
|
||||
for (int j=0;j<selected_markers.size();j++) {
|
||||
if (selected_markers.at(j) == i) {
|
||||
selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool selected = false;
|
||||
for (int j=0;j<selected_markers.size();j++) {
|
||||
if (selected_markers.at(j) == i) {
|
||||
selected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
draw_marker(p, marker_x, yoff, height()-1, selected);
|
||||
}
|
||||
draw_marker(p, marker_x, yoff, height()-1, selected);
|
||||
}
|
||||
|
||||
// draw playhead triangle
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
in_x = getHeaderScreenPointFromFrame(viewer->seq->playhead);
|
||||
QPoint start(in_x, height()+2);
|
||||
QPainterPath path;
|
||||
path.moveTo(start + QPoint(1,0));
|
||||
path.lineTo(in_x-PLAYHEAD_SIZE, yoff);
|
||||
path.lineTo(in_x+PLAYHEAD_SIZE+1, yoff);
|
||||
path.lineTo(start);
|
||||
p.fillPath(path, Qt::red);
|
||||
}
|
||||
// draw playhead triangle
|
||||
p.setRenderHint(QPainter::Antialiasing);
|
||||
in_x = getHeaderScreenPointFromFrame(viewer->seq->playhead);
|
||||
QPoint start(in_x, height()+2);
|
||||
QPainterPath path;
|
||||
path.moveTo(start + QPoint(1,0));
|
||||
path.lineTo(in_x-PLAYHEAD_SIZE, yoff);
|
||||
path.lineTo(in_x+PLAYHEAD_SIZE+1, yoff);
|
||||
path.lineTo(start);
|
||||
p.fillPath(path, Qt::red);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineHeader::show_context_menu(const QPoint &pos) {
|
||||
QMenu menu(this);
|
||||
QMenu menu(this);
|
||||
|
||||
olive::MenuHelper.make_inout_menu(&menu);
|
||||
// Add items for setting the in/out points of a QMenu
|
||||
olive::MenuHelper.make_inout_menu(&menu);
|
||||
|
||||
menu.addSeparator();
|
||||
menu.addSeparator();
|
||||
|
||||
QAction* center_timecodes = menu.addAction(tr("Center Timecodes"), olive::MainWindow, SLOT(toggle_bool_action()));
|
||||
center_timecodes->setCheckable(true);
|
||||
center_timecodes->setChecked(olive::CurrentConfig.center_timeline_timecodes);
|
||||
center_timecodes->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.center_timeline_timecodes));
|
||||
QAction* center_timecodes = menu.addAction(tr("Center Timecodes"), &olive::MenuHelper, SLOT(toggle_bool_action()));
|
||||
center_timecodes->setCheckable(true);
|
||||
center_timecodes->setChecked(olive::CurrentConfig.center_timeline_timecodes);
|
||||
center_timecodes->setData(reinterpret_cast<quintptr>(&olive::CurrentConfig.center_timeline_timecodes));
|
||||
|
||||
menu.exec(mapToGlobal(pos));
|
||||
menu.exec(mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void TimelineHeader::resized_scroll_listener(double d) {
|
||||
update_zoom(zoom * d);
|
||||
update_zoom(zoom * d);
|
||||
}
|
||||
|
||||
+53
-58
@@ -20,32 +20,6 @@
|
||||
|
||||
#include "timelinewidget.h"
|
||||
|
||||
#include "oliveglobal.h"
|
||||
#include "panels/panels.h"
|
||||
#include "project/projectelements.h"
|
||||
|
||||
#include "rendering/audio.h"
|
||||
#include "io/config.h"
|
||||
#include "ui/sourcetable.h"
|
||||
#include "ui/sourceiconview.h"
|
||||
#include "project/undo.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "ui/resizablescrollbar.h"
|
||||
#include "dialogs/newsequencedialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui/rectangleselect.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "ui/cursors.h"
|
||||
#include "ui/menuhelper.h"
|
||||
#include "ui/focusfilter.h"
|
||||
#include "dialogs/clippropertiesdialog.h"
|
||||
#include "debug.h"
|
||||
|
||||
#include "project/effect.h"
|
||||
|
||||
#include "effects/internal/solideffect.h"
|
||||
#include "effects/internal/texteffect.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QColor>
|
||||
#include <QMouseEvent>
|
||||
@@ -61,6 +35,30 @@
|
||||
#include <QInputDialog>
|
||||
#include <QStatusBar>
|
||||
|
||||
#include "global/global.h"
|
||||
#include "panels/panels.h"
|
||||
#include "project/projectelements.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "global/config.h"
|
||||
#include "ui/sourcetable.h"
|
||||
#include "ui/sourceiconview.h"
|
||||
#include "undo/undo.h"
|
||||
#include "undo/undostack.h"
|
||||
#include "ui/viewerwidget.h"
|
||||
#include "ui/resizablescrollbar.h"
|
||||
#include "dialogs/newsequencedialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "ui/rectangleselect.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "ui/cursors.h"
|
||||
#include "ui/menuhelper.h"
|
||||
#include "ui/focusfilter.h"
|
||||
#include "dialogs/clippropertiesdialog.h"
|
||||
#include "global/debug.h"
|
||||
#include "effects/effect.h"
|
||||
#include "effects/internal/solideffect.h"
|
||||
#include "effects/internal/texteffect.h"
|
||||
|
||||
#define MAX_TEXT_WIDTH 20
|
||||
#define TRANSITION_BETWEEN_RANGE 40
|
||||
|
||||
@@ -90,8 +88,6 @@ void TimelineWidget::show_context_menu(const QPoint& pos) {
|
||||
|
||||
QMenu menu(this);
|
||||
|
||||
// TODO replace with Olive::MenuHelper::make_edit_functions_menu() without losing functionality
|
||||
|
||||
QAction* undoAction = menu.addAction(tr("&Undo"));
|
||||
QAction* redoAction = menu.addAction(tr("&Redo"));
|
||||
connect(undoAction, SIGNAL(triggered(bool)), olive::Global.get(), SLOT(undo()));
|
||||
@@ -103,13 +99,7 @@ void TimelineWidget::show_context_menu(const QPoint& pos) {
|
||||
// collect all the selected clips
|
||||
QVector<Clip*> selected_clips = olive::ActiveSequence->SelectedClips();
|
||||
|
||||
if (!selected_clips.isEmpty()) {
|
||||
// clips are selected
|
||||
menu.addAction(tr("C&ut"), &olive::FocusFilter, SLOT(cut()));
|
||||
menu.addAction(tr("Cop&y"), &olive::FocusFilter, SLOT(copy()));
|
||||
}
|
||||
|
||||
menu.addAction(tr("&Paste"), olive::Global.get(), SLOT(paste()));
|
||||
olive::MenuHelper.make_edit_functions_menu(&menu, !selected_clips.isEmpty());
|
||||
|
||||
if (selected_clips.isEmpty()) {
|
||||
// no clips are selected
|
||||
@@ -119,7 +109,7 @@ void TimelineWidget::show_context_menu(const QPoint& pos) {
|
||||
panel_timeline->cursor_track = getTrackFromScreenPoint(pos.y());
|
||||
|
||||
if (panel_timeline->can_ripple_empty_space(panel_timeline->cursor_frame, panel_timeline->cursor_track)) {
|
||||
QAction* ripple_delete_action = menu.addAction(tr("R&ipple Delete"));
|
||||
QAction* ripple_delete_action = menu.addAction(tr("R&ipple Delete Empty Space"));
|
||||
connect(ripple_delete_action, SIGNAL(triggered(bool)), panel_timeline, SLOT(ripple_delete_empty_space()));
|
||||
}
|
||||
|
||||
@@ -128,7 +118,9 @@ void TimelineWidget::show_context_menu(const QPoint& pos) {
|
||||
}
|
||||
|
||||
if (!selected_clips.isEmpty()) {
|
||||
|
||||
menu.addSeparator();
|
||||
|
||||
menu.addAction(tr("&Speed/Duration"), olive::Global.get(), SLOT(open_speed_dialog()));
|
||||
|
||||
QAction* autoscaleAction = menu.addAction(tr("Auto-s&cale"), this, SLOT(toggle_autoscale()));
|
||||
@@ -259,8 +251,7 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
}
|
||||
|
||||
if (event->source() == panel_footage_viewer->viewer_widget) {
|
||||
SequencePtr proposed_seq = panel_footage_viewer->seq;
|
||||
if (proposed_seq != olive::ActiveSequence) { // don't allow nesting the same sequence
|
||||
if (panel_footage_viewer->seq != olive::ActiveSequence) { // don't allow nesting the same sequence
|
||||
media_list.append(panel_footage_viewer->media);
|
||||
import_init = true;
|
||||
}
|
||||
@@ -278,9 +269,10 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
panel_project->process_file_list(file_list);
|
||||
|
||||
for (int i=0;i<panel_project->last_imported_media.size();i++) {
|
||||
Footage* f = panel_project->last_imported_media.at(i)->to_footage();
|
||||
|
||||
// waits for media to have a duration
|
||||
// TODO would be much nicer if this was multithreaded
|
||||
FootagePtr f = panel_project->last_imported_media.at(i)->to_footage();
|
||||
f->ready_lock.lock();
|
||||
f->ready_lock.unlock();
|
||||
|
||||
@@ -302,14 +294,14 @@ void TimelineWidget::dragEnterEvent(QDragEnterEvent *event) {
|
||||
event->acceptProposedAction();
|
||||
|
||||
long entry_point;
|
||||
SequencePtr seq = olive::ActiveSequence;
|
||||
Sequence* seq = olive::ActiveSequence.get();
|
||||
|
||||
if (seq == nullptr) {
|
||||
// if no sequence, we're going to create a new one using the clips as a reference
|
||||
entry_point = 0;
|
||||
|
||||
self_created_sequence = create_sequence_from_media(media_list);
|
||||
seq = self_created_sequence;
|
||||
seq = self_created_sequence.get();
|
||||
} else {
|
||||
entry_point = panel_timeline->getTimelineFrameFromScreenPoint(event->pos().x());
|
||||
panel_timeline->drag_frame_start = entry_point + getFrameFromScreenPoint(panel_timeline->zoom, 50);
|
||||
@@ -486,13 +478,13 @@ void insert_clips(ComboAction* ca) {
|
||||
|
||||
long ripple_length = (latest_new_point - earliest_new_point);
|
||||
|
||||
ripple_clips(ca, olive::ActiveSequence, earliest_new_point, ripple_length, ignore_clips);
|
||||
ripple_clips(ca, olive::ActiveSequence.get(), earliest_new_point, ripple_length, ignore_clips);
|
||||
|
||||
if (ripple_old_point) {
|
||||
// works for moving later clips earlier but not earlier to later
|
||||
long second_ripple_length = (earliest_old_point - latest_old_point);
|
||||
|
||||
ripple_clips(ca, olive::ActiveSequence, latest_old_point, second_ripple_length, ignore_clips);
|
||||
ripple_clips(ca, olive::ActiveSequence.get(), latest_old_point, second_ripple_length, ignore_clips);
|
||||
|
||||
if (earliest_old_point < earliest_new_point) {
|
||||
for (int i=0;i<panel_timeline->ghosts.size();i++) {
|
||||
@@ -515,11 +507,11 @@ void TimelineWidget::dropEvent(QDropEvent* event) {
|
||||
|
||||
ComboAction* ca = new ComboAction();
|
||||
|
||||
SequencePtr s = olive::ActiveSequence;
|
||||
Sequence* s = olive::ActiveSequence.get();
|
||||
|
||||
// if we're dropping into nothing, create a new sequences based on the clip being dragged
|
||||
if (s == nullptr) {
|
||||
s = self_created_sequence;
|
||||
s = self_created_sequence.get();
|
||||
panel_project->create_sequence_internal(ca, self_created_sequence, true, nullptr);
|
||||
self_created_sequence = nullptr;
|
||||
} else if (event->keyboardModifiers() & Qt::ControlModifier) {
|
||||
@@ -664,7 +656,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
if (hovered_clip >= 0) {
|
||||
Clip* clip = olive::ActiveSequence->clips.at(hovered_clip).get();
|
||||
|
||||
if (olive::ActiveSequence->IsClipSelected(clip, true)) {
|
||||
if (clip->IsSelected()) {
|
||||
|
||||
if (shift) {
|
||||
|
||||
@@ -767,7 +759,7 @@ void TimelineWidget::mousePressEvent(QMouseEvent *event) {
|
||||
Clip* link = olive::ActiveSequence->clips.at(clip->linked.at(i)).get();
|
||||
|
||||
// check if the clip is already selected
|
||||
if (!olive::ActiveSequence->IsClipSelected(link, true)) {
|
||||
if (!link->IsSelected()) {
|
||||
Selection ss;
|
||||
ss.in = link->timeline_in();
|
||||
ss.out = link->timeline_out();
|
||||
@@ -998,7 +990,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
panel_sequence_viewer->cue_recording(qMin(g.in, g.out), qMax(g.in, g.out), g.track);
|
||||
panel_timeline->creating = false;
|
||||
} else if (g.in != g.out) {
|
||||
ClipPtr c = std::make_shared<Clip>(olive::ActiveSequence);
|
||||
ClipPtr c = std::make_shared<Clip>(olive::ActiveSequence.get());
|
||||
c->set_media(nullptr, 0);
|
||||
c->set_timeline_in(qMin(g.in, g.out));
|
||||
c->set_timeline_out(qMax(g.in, g.out));
|
||||
@@ -1020,7 +1012,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
|
||||
QVector<ClipPtr> add;
|
||||
add.append(c);
|
||||
ca->append(new AddClipCommand(olive::ActiveSequence, add));
|
||||
ca->append(new AddClipCommand(olive::ActiveSequence.get(), add));
|
||||
|
||||
if (c->track() < 0 && olive::CurrentConfig.add_default_effects_to_clips) {
|
||||
// default video effects (before custom effects)
|
||||
@@ -1040,7 +1032,11 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
{
|
||||
c->set_name(tr("Bars"));
|
||||
EffectPtr e = Effect::Create(c.get(), Effect::GetInternalMeta(EFFECT_INTERNAL_SOLID, EFFECT_TYPE_EFFECT));
|
||||
e->row(0)->field(0)->set_combo_index(1);
|
||||
|
||||
// Auto-select bars
|
||||
SolidEffect* solid_effect = static_cast<SolidEffect*>(e.get());
|
||||
solid_effect->SetType(SolidEffect::SOLID_TYPE_BARS);
|
||||
|
||||
c->effects.append(e);
|
||||
}
|
||||
break;
|
||||
@@ -1137,7 +1133,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
if (panel_timeline->trim_type == TRIM_OUT) ripple_length = -ripple_length;
|
||||
|
||||
// finally, ripple everything
|
||||
ripple_clips(ca, olive::ActiveSequence, ripple_point, ripple_length, ignore_clips);
|
||||
ripple_clips(ca, olive::ActiveSequence.get(), ripple_point, ripple_length, ignore_clips);
|
||||
}
|
||||
|
||||
if (panel_timeline->tool == TIMELINE_TOOL_POINTER
|
||||
@@ -1153,7 +1149,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
if (g.old_in != g.in || g.old_out != g.out || g.track != g.old_track || g.clip_in != g.old_clip_in) {
|
||||
|
||||
// create copy of clip
|
||||
ClipPtr c(olive::ActiveSequence->clips.at(g.clip)->copy(olive::ActiveSequence));
|
||||
ClipPtr c = olive::ActiveSequence->clips.at(g.clip)->copy(olive::ActiveSequence.get());
|
||||
|
||||
c->set_timeline_in(g.in);
|
||||
c->set_timeline_out(g.out);
|
||||
@@ -1180,7 +1176,7 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
|
||||
panel_timeline->relink_clips_using_ids(old_clips, new_clips);
|
||||
|
||||
// add them
|
||||
ca->append(new AddClipCommand(olive::ActiveSequence, new_clips));
|
||||
ca->append(new AddClipCommand(olive::ActiveSequence.get(), new_clips));
|
||||
|
||||
}
|
||||
|
||||
@@ -2004,7 +2000,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
panel_timeline->cursor_track = getTrackFromScreenPoint(event->pos().y());
|
||||
|
||||
// if holding the mouse button down, let's scroll to that location
|
||||
if (event->buttons() != 0) {
|
||||
if (event->buttons() != 0 && panel_timeline->tool != TIMELINE_TOOL_HAND) {
|
||||
panel_timeline->scroll_to_frame(panel_timeline->cursor_frame);
|
||||
}
|
||||
|
||||
@@ -2069,7 +2065,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
|
||||
Clip* c = olive::ActiveSequence->clips.at(j).get();
|
||||
|
||||
if (c != nullptr && olive::ActiveSequence->IsClipSelected(c, false)) {
|
||||
if (c != nullptr && c->IsSelected(false)) {
|
||||
|
||||
// loop through linked clips
|
||||
for (int k=0;k<c->linked.size();k++) {
|
||||
@@ -2199,7 +2195,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
|
||||
// if a transition isn't selected, check if the whole clip is
|
||||
if (!add) {
|
||||
add = olive::ActiveSequence->IsClipSelected(c, true);
|
||||
add = c->IsSelected();
|
||||
}
|
||||
|
||||
if (add) {
|
||||
@@ -2338,7 +2334,7 @@ void TimelineWidget::mouseMoveEvent(QMouseEvent *event) {
|
||||
}
|
||||
|
||||
// store selections
|
||||
selection_command = new SetSelectionsCommand(olive::ActiveSequence);
|
||||
selection_command = new SetSelectionsCommand(olive::ActiveSequence.get());
|
||||
selection_command->old_data = olive::ActiveSequence->selections;
|
||||
|
||||
// ready to start moving clips
|
||||
@@ -2949,7 +2945,6 @@ void TimelineWidget::paintEvent(QPaintEvent*) {
|
||||
if (clip->media() != nullptr && clip->media()->get_type() == MEDIA_TYPE_FOOTAGE) {
|
||||
bool draw_checkerboard = false;
|
||||
QRect checkerboard_rect(clip_rect);
|
||||
FootagePtr m = clip->media()->to_footage();
|
||||
FootageStream* ms = clip->media_stream();
|
||||
if (ms == nullptr) {
|
||||
draw_checkerboard = true;
|
||||
|
||||
+3
-3
@@ -28,11 +28,11 @@
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include "project/sequence.h"
|
||||
#include "project/clip.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "timeline/clip.h"
|
||||
#include "project/footage.h"
|
||||
#include "project/media.h"
|
||||
#include "project/undo.h"
|
||||
#include "undo/undo.h"
|
||||
#include "timelinetools.h"
|
||||
|
||||
class Timeline;
|
||||
|
||||
@@ -14,7 +14,7 @@ UpdateNotification::UpdateNotification()
|
||||
|
||||
void UpdateNotification::check()
|
||||
{
|
||||
#if defined(_WIN32) || defined(__APPLE__)
|
||||
#if defined(GITHASH) && defined(UPDATEMSG)
|
||||
QNetworkAccessManager* manager = new QNetworkAccessManager();
|
||||
|
||||
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(finished_slot(QNetworkReply *)));
|
||||
|
||||
+50
-50
@@ -28,67 +28,67 @@
|
||||
|
||||
#include "viewerwidget.h"
|
||||
#include "panels/viewer.h"
|
||||
#include "project/sequence.h"
|
||||
#include "debug.h"
|
||||
#include "timeline/sequence.h"
|
||||
#include "global/debug.h"
|
||||
|
||||
// enforces aspect ratio
|
||||
ViewerContainer::ViewerContainer(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
fit(true),
|
||||
child(nullptr)
|
||||
QWidget(parent),
|
||||
fit(true),
|
||||
child(nullptr)
|
||||
{
|
||||
horizontal_scrollbar = new QScrollBar(Qt::Horizontal, this);
|
||||
vertical_scrollbar = new QScrollBar(Qt::Vertical, this);
|
||||
horizontal_scrollbar = new QScrollBar(Qt::Horizontal, this);
|
||||
vertical_scrollbar = new QScrollBar(Qt::Vertical, this);
|
||||
|
||||
horizontal_scrollbar->setVisible(false);
|
||||
vertical_scrollbar->setVisible(false);
|
||||
horizontal_scrollbar->setVisible(false);
|
||||
vertical_scrollbar->setVisible(false);
|
||||
|
||||
horizontal_scrollbar->setSingleStep(20);
|
||||
vertical_scrollbar->setSingleStep(20);
|
||||
horizontal_scrollbar->setSingleStep(20);
|
||||
vertical_scrollbar->setSingleStep(20);
|
||||
|
||||
child = new ViewerWidget(this);
|
||||
child->container = this;
|
||||
child = new ViewerWidget(this);
|
||||
child->container = this;
|
||||
|
||||
connect(horizontal_scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scroll_changed()));
|
||||
connect(vertical_scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scroll_changed()));
|
||||
connect(horizontal_scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scroll_changed()));
|
||||
connect(vertical_scrollbar, SIGNAL(valueChanged(int)), this, SLOT(scroll_changed()));
|
||||
}
|
||||
|
||||
ViewerContainer::~ViewerContainer() {}
|
||||
|
||||
void ViewerContainer::dragScrollPress(const QPoint &p) {
|
||||
drag_start_x = p.x();
|
||||
drag_start_y = p.y();
|
||||
drag_start_x = p.x();
|
||||
drag_start_y = p.y();
|
||||
|
||||
horiz_start = horizontal_scrollbar->value();
|
||||
vert_start = vertical_scrollbar->value();
|
||||
horiz_start = horizontal_scrollbar->value();
|
||||
vert_start = vertical_scrollbar->value();
|
||||
}
|
||||
|
||||
void ViewerContainer::dragScrollMove(const QPoint &p) {
|
||||
int this_x = p.x();
|
||||
int this_y = p.y();
|
||||
int this_x = p.x();
|
||||
int this_y = p.y();
|
||||
|
||||
horizontal_scrollbar->setValue(horiz_start + (drag_start_x-this_x));
|
||||
vertical_scrollbar->setValue(vert_start + (drag_start_y-this_y));
|
||||
horizontal_scrollbar->setValue(horiz_start + (drag_start_x-this_x));
|
||||
vertical_scrollbar->setValue(vert_start + (drag_start_y-this_y));
|
||||
}
|
||||
|
||||
void ViewerContainer::parseWheelEvent(QWheelEvent *event) {
|
||||
if (event->modifiers() & Qt::AltModifier) {
|
||||
QApplication::sendEvent(horizontal_scrollbar, event);
|
||||
} else {
|
||||
QApplication::sendEvent(vertical_scrollbar, event);
|
||||
}
|
||||
if (event->modifiers() & Qt::AltModifier) {
|
||||
QApplication::sendEvent(horizontal_scrollbar, event);
|
||||
} else {
|
||||
QApplication::sendEvent(vertical_scrollbar, event);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerContainer::adjust() {
|
||||
if (viewer->seq != nullptr) {
|
||||
if (child->waveform) {
|
||||
child->move(0, 0);
|
||||
child->resize(size());
|
||||
} else {
|
||||
horizontal_scrollbar->setVisible(false);
|
||||
vertical_scrollbar->setVisible(false);
|
||||
if (viewer->seq != nullptr) {
|
||||
if (child->waveform) {
|
||||
child->move(0, 0);
|
||||
child->resize(size());
|
||||
} else {
|
||||
horizontal_scrollbar->setVisible(false);
|
||||
vertical_scrollbar->setVisible(false);
|
||||
|
||||
int zoomed_width = qRound(double(viewer->seq->width)*zoom);
|
||||
int zoomed_width = qRound(double(viewer->seq->width)*zoom);
|
||||
int zoomed_height = qRound(double(viewer->seq->height)*zoom);
|
||||
|
||||
if (fit || zoomed_width > width() || zoomed_height > height()) {
|
||||
@@ -147,28 +147,28 @@ void ViewerContainer::adjust() {
|
||||
child->move(zoomed_x, zoomed_y);
|
||||
child->resize(zoomed_width, zoomed_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerContainer::adjust_scrollbars() {
|
||||
horizontal_scrollbar->move(0, height()-horizontal_scrollbar->height());
|
||||
horizontal_scrollbar->setFixedWidth(qMax(0, width()-vertical_scrollbar->width()));
|
||||
horizontal_scrollbar->setPageStep(width());
|
||||
horizontal_scrollbar->move(0, height()-horizontal_scrollbar->height());
|
||||
horizontal_scrollbar->setFixedWidth(qMax(0, width()-vertical_scrollbar->width()));
|
||||
horizontal_scrollbar->setPageStep(width());
|
||||
|
||||
vertical_scrollbar->move(width() - vertical_scrollbar->width(), 0);
|
||||
vertical_scrollbar->setFixedHeight(qMax(0, height()-horizontal_scrollbar->height()));
|
||||
vertical_scrollbar->setPageStep(height());
|
||||
vertical_scrollbar->move(width() - vertical_scrollbar->width(), 0);
|
||||
vertical_scrollbar->setFixedHeight(qMax(0, height()-horizontal_scrollbar->height()));
|
||||
vertical_scrollbar->setPageStep(height());
|
||||
}
|
||||
|
||||
void ViewerContainer::resizeEvent(QResizeEvent *event) {
|
||||
event->accept();
|
||||
adjust();
|
||||
event->accept();
|
||||
adjust();
|
||||
}
|
||||
|
||||
void ViewerContainer::scroll_changed() {
|
||||
child->set_scroll(
|
||||
double(horizontal_scrollbar->value())/double(horizontal_scrollbar->maximum()),
|
||||
double(vertical_scrollbar->value())/double(vertical_scrollbar->maximum())
|
||||
);
|
||||
child->set_scroll(
|
||||
double(horizontal_scrollbar->value())/double(horizontal_scrollbar->maximum()),
|
||||
double(vertical_scrollbar->value())/double(vertical_scrollbar->maximum())
|
||||
);
|
||||
}
|
||||
|
||||
+10
-17
@@ -46,11 +46,11 @@ extern "C" {
|
||||
#include "project/projectelements.h"
|
||||
#include "rendering/renderfunctions.h"
|
||||
#include "rendering/audio.h"
|
||||
#include "io/config.h"
|
||||
#include "debug.h"
|
||||
#include "io/math.h"
|
||||
#include "global/config.h"
|
||||
#include "global/debug.h"
|
||||
#include "global/math.h"
|
||||
#include "ui/collapsiblewidget.h"
|
||||
#include "project/undo.h"
|
||||
#include "undo/undo.h"
|
||||
#include "project/media.h"
|
||||
#include "ui/viewercontainer.h"
|
||||
#include "rendering/cacher.h"
|
||||
@@ -91,7 +91,7 @@ ViewerWidget::~ViewerWidget() {
|
||||
}
|
||||
|
||||
void ViewerWidget::delete_function() {
|
||||
close_active_clips(viewer->seq);
|
||||
close_active_clips(viewer->seq.get());
|
||||
}
|
||||
|
||||
void ViewerWidget::set_waveform_scroll(int s) {
|
||||
@@ -168,7 +168,7 @@ void ViewerWidget::save_frame() {
|
||||
fn += selected_ext;
|
||||
}
|
||||
|
||||
renderer->start_render(context(), viewer->seq, fn);
|
||||
renderer->start_render(context(), viewer->seq.get(), fn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,11 +228,11 @@ void ViewerWidget::frame_update() {
|
||||
update();
|
||||
} else {
|
||||
doneCurrent();
|
||||
renderer->start_render(context(), viewer->seq);
|
||||
renderer->start_render(context(), viewer->seq.get());
|
||||
}
|
||||
|
||||
// render the audio
|
||||
compose_audio(viewer, viewer->seq, viewer->get_playback_speed(), viewer->WaitingForPlayWake());
|
||||
compose_audio(viewer, viewer->seq.get(), viewer->get_playback_speed(), viewer->WaitingForPlayWake());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ void ViewerWidget::seek_from_click(int x) {
|
||||
void ViewerWidget::context_destroy() {
|
||||
makeCurrent();
|
||||
if (viewer->seq != nullptr) {
|
||||
close_active_clips(viewer->seq);
|
||||
close_active_clips(viewer->seq.get());
|
||||
}
|
||||
renderer->delete_ctx();
|
||||
doneCurrent();
|
||||
@@ -310,8 +310,6 @@ void ViewerWidget::move_gizmos(QMouseEvent *event, bool done) {
|
||||
|
||||
drag_start_x = event->pos().x();
|
||||
drag_start_y = event->pos().y();
|
||||
|
||||
gizmos->field_changed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,10 +326,6 @@ void ViewerWidget::mousePressEvent(QMouseEvent* event) {
|
||||
gizmo_y_mvmt = 0;
|
||||
|
||||
selected_gizmo = get_gizmo_from_mouse(event->pos().x(), event->pos().y());
|
||||
|
||||
if (selected_gizmo != nullptr) {
|
||||
selected_gizmo->set_previous_value();
|
||||
}
|
||||
}
|
||||
dragging = true;
|
||||
}
|
||||
@@ -574,7 +568,6 @@ void ViewerWidget::paintGL() {
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
// double ar_diff = (double(viewer->seq->width)/double(viewer->seq->height)/(double(width())/double(height())));
|
||||
double zoom_factor = container->zoom/(double(width())/double(viewer->seq->width));
|
||||
double zoom_size = (zoom_factor*2.0) - 2.0;
|
||||
double zoom_left = -zoom_size*x_scroll - 1.0;
|
||||
@@ -619,7 +612,7 @@ void ViewerWidget::paintGL() {
|
||||
|
||||
if (renderer->did_texture_fail() && !viewer->playing) {
|
||||
doneCurrent();
|
||||
renderer->start_render(context(), viewer->seq);
|
||||
renderer->start_render(context(), viewer->seq.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -30,9 +30,9 @@
|
||||
#include <QWaitCondition>
|
||||
#include <QOpenGLFunctions>
|
||||
|
||||
#include "project/clip.h"
|
||||
#include "timeline/clip.h"
|
||||
#include "project/footage.h"
|
||||
#include "project/effect.h"
|
||||
#include "effects/effect.h"
|
||||
#include "ui/viewerwindow.h"
|
||||
#include "ui/viewercontainer.h"
|
||||
#include "rendering/renderthread.h"
|
||||
|
||||
Reference in New Issue
Block a user