Merge branch 'master' of https://github.com/olive-editor/olive into project_icons

This commit is contained in:
Pablo Gil
2019-01-10 11:36:11 +01:00
24 changed files with 621 additions and 317 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ Source: olive-editor
Section: video
Priority: optional
Maintainer: Olive Team <itsmattkc@gmail.com>
Build-Depends: debhelper (>=9), build-essential, qt5-default, qtmultimedia5-dev, libqt5opengl5-dev, libqt5multimedia5-plugins, libavformat-dev, libavcodec-dev, libavutil-dev, libswscale-dev, libswresample-dev, libavfilter-dev, libpostproc-dev
Build-Depends: debhelper (>=9), build-essential, qt5-default, qtmultimedia5-dev, libqt5opengl5-dev, libqt5multimedia5-plugins, libavformat-dev, libavcodec-dev, libavutil-dev, libswscale-dev, libswresample-dev, libavfilter-dev, libpostproc-dev, git
Standards-Version: 3.9.6
Homepage: https://olivevideoeditor.org/
+2 -2
View File
@@ -21,7 +21,7 @@ ActionSearch::ActionSearch(QWidget *parent) :
ActionSearchEntry* entry_field = new ActionSearchEntry();
QFont entry_field_font = entry_field->font();
entry_field_font.setPointSize(entry_field_font.pointSize()*2);
entry_field_font.setPointSize(entry_field_font.pointSize()*1.2);
entry_field->setFont(entry_field_font);
entry_field->setPlaceholderText("Search for action...");
connect(entry_field, SIGNAL(textChanged(const QString&)), this, SLOT(search_update(const QString &)));
@@ -32,7 +32,7 @@ ActionSearch::ActionSearch(QWidget *parent) :
list_widget = new ActionSearchList();
QFont list_widget_font = list_widget->font();
list_widget_font.setPointSize(list_widget_font.pointSize()*1.5);
list_widget_font.setPointSize(list_widget_font.pointSize()*1.2);
list_widget->setFont(list_widget_font);
layout->addWidget(list_widget);
connect(list_widget, SIGNAL(dbl_click()), this, SLOT(perform_action()));
+95 -10
View File
@@ -19,6 +19,8 @@
#include <QTreeWidgetItem>
#include <QList>
#include <QDoubleSpinBox>
#include <QFileDialog>
#include <QMessageBox>
#include "debug.h"
@@ -32,6 +34,22 @@ void KeySequenceEditor::set_action_shortcut() {
action->setShortcut(keySequence());
}
void KeySequenceEditor::reset_to_default() {
setKeySequence(action->property("default").toString());
}
QString KeySequenceEditor::action_name() {
return action->text().replace("&", "");
}
QString KeySequenceEditor::export_shortcut() {
QString ks = keySequence().toString();
if (ks != action->property("default")) {
return action->text().replace("&", "") + "\t" + keySequence().toString();
}
return 0;
}
PreferencesDialog::PreferencesDialog(QWidget *parent) :
QDialog(parent)
{
@@ -51,7 +69,7 @@ void PreferencesDialog::setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem*
for (int i=0;i<actions.size();i++) {
QAction* a = actions.at(i);
if (!a->isSeparator()) {
if (!a->isSeparator() && a->property("keyignore").isNull()) {
QTreeWidgetItem* item = new QTreeWidgetItem();
item->setText(0, a->text().replace("&", ""));
@@ -61,7 +79,6 @@ void PreferencesDialog::setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem*
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
setup_kbd_shortcut_worker(a->menu(), item);
} else {
item->setData(0, Qt::UserRole + 1, reinterpret_cast<quintptr>(a));
key_shortcut_items.append(item);
key_shortcut_actions.append(a);
}
@@ -112,11 +129,14 @@ void PreferencesDialog::reset_default_shortcut() {
QList<QTreeWidgetItem*> items = keyboard_tree->selectedItems();
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* item = keyboard_tree->selectedItems().at(i);
const QVariant& data = item->data(0, Qt::UserRole + 1);
if (!data.isNull()) {
QAction* a = reinterpret_cast<QAction*>(data.value<quintptr>());
QKeySequence ks(a->property("default").toString());
static_cast<QKeySequenceEdit*>(keyboard_tree->itemWidget(item, 1))->setKeySequence(ks);
static_cast<KeySequenceEditor*>(keyboard_tree->itemWidget(item, 1))->reset_to_default();
}
}
void PreferencesDialog::reset_all_shortcuts() {
if (QMessageBox::question(this, "Confirm Reset All Shortcuts", "Are you sure you wish to reset all keyboard shortcuts to their defaults?", QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes) {
for (int i=0;i<key_shortcut_fields.size();i++) {
key_shortcut_fields.at(i)->reset_to_default();
}
}
}
@@ -159,6 +179,58 @@ bool PreferencesDialog::refine_shortcut_list(const QString &s, QTreeWidgetItem*
return all_children_are_hidden;
}
return true;
}
void PreferencesDialog::load_shortcut_file() {
QString fn = QFileDialog::getOpenFileName(this, "Import Keyboard Shortcuts");
if (!fn.isEmpty()) {
QFile f(fn);
if (f.exists() && f.open(QFile::ReadOnly)) {
QByteArray ba = f.readAll();
f.close();
for (int i=0;i<key_shortcut_fields.size();i++) {
int index = ba.indexOf(key_shortcut_fields.at(i)->action_name());
if (index == 0 || (index > 0 && ba.at(index-1) == '\n')) {
while (index < ba.size() && ba.at(index) != '\t') index++;
QString ks;
index++;
while (index < ba.size() && ba.at(index) != '\n') {
ks.append(ba.at(index));
index++;
}
dout << "set" << key_shortcut_fields.at(i)->action_name() << "to" << ks;
key_shortcut_fields.at(i)->setKeySequence(ks);
} else {
key_shortcut_fields.at(i)->reset_to_default();
}
}
} else {
QMessageBox::critical(this, "Error saving shortcuts", "Failed to open file for reading");
}
}
}
void PreferencesDialog::save_shortcut_file() {
QString fn = QFileDialog::getSaveFileName(this, "Export Keyboard Shortcuts");
if (!fn.isEmpty()) {
QFile f(fn);
if (f.open(QFile::WriteOnly)) {
bool start = true;
for (int i=0;i<key_shortcut_fields.size();i++) {
QString s = key_shortcut_fields.at(i)->export_shortcut();
if (!s.isEmpty()) {
if (!start) f.write("\n");
f.write(s.toUtf8());
start = false;
}
}
QMessageBox::information(this, "Export Shortcuts", "Shortcuts exported successfully");
f.close();
} else {
QMessageBox::critical(this, "Error saving shortcuts", "Failed to open file for writing");
}
}
}
void PreferencesDialog::setup_ui() {
@@ -250,11 +322,24 @@ void PreferencesDialog::setup_ui() {
shortcut_layout->addWidget(keyboard_tree);
QHBoxLayout* reset_shortcut_layout = new QHBoxLayout();
QPushButton* import_shortcut_button = new QPushButton("Import");
reset_shortcut_layout->addWidget(import_shortcut_button);
connect(import_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(load_shortcut_file()));
QPushButton* export_shortcut_button = new QPushButton("Export");
reset_shortcut_layout->addWidget(export_shortcut_button);
connect(export_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(save_shortcut_file()));
reset_shortcut_layout->addStretch();
reset_shortcut_button = new QPushButton("Reset to Default");
reset_shortcut_layout->addWidget(reset_shortcut_button);
connect(reset_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_default_shortcut()));
QPushButton* reset_selected_shortcut_button = new QPushButton("Reset Selected");
reset_shortcut_layout->addWidget(reset_selected_shortcut_button);
connect(reset_selected_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_default_shortcut()));
QPushButton* reset_all_shortcut_button = new QPushButton("Reset All");
reset_shortcut_layout->addWidget(reset_all_shortcut_button);
connect(reset_all_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(reset_all_shortcuts()));
shortcut_layout->addLayout(reset_shortcut_layout);
+6 -2
View File
@@ -18,6 +18,9 @@ class KeySequenceEditor : public QKeySequenceEdit {
public:
KeySequenceEditor(QWidget *parent, QAction* a);
void set_action_shortcut();
void reset_to_default();
QString action_name();
QString export_shortcut();
private:
QAction* action;
};
@@ -35,7 +38,10 @@ public:
private slots:
void save();
void reset_default_shortcut();
void reset_all_shortcuts();
bool refine_shortcut_list(const QString &, QTreeWidgetItem* parent = NULL);
void load_shortcut_file();
void save_shortcut_file();
private:
void setup_ui();
@@ -55,8 +61,6 @@ private:
QVector<QAction*> key_shortcut_actions;
QVector<QTreeWidgetItem*> key_shortcut_items;
QVector<KeySequenceEditor*> key_shortcut_fields;
QPushButton* reset_shortcut_button;
};
#endif // PREFERENCESDIALOG_H
+4 -1
View File
@@ -24,7 +24,7 @@ TextEffect::TextEffect(Clip *c, const EffectMeta* em) :
Effect(c, em)
{
enable_superimpose = true;
enable_shader = true;
//enable_shader = true;
text_val = add_row("Text")->add_field(EFFECT_FIELD_STRING, "text", 2);
@@ -189,6 +189,9 @@ void TextEffect::redraw(double timecode) {
}
void TextEffect::shadow_enable(bool e) {
enable_shader = e;
close();
shadow_color->set_enabled(e);
shadow_distance->set_enabled(e);
shadow_softness->set_enabled(e);
+62
View File
@@ -0,0 +1,62 @@
#include "voideffect.h"
#include <QXmlStreamReader>
#include <QLabel>
#include <QFile>
#include "ui/collapsiblewidget.h"
#include "debug.h"
VoidEffect::VoidEffect(Clip *c, const QString& n) : Effect(c, NULL) {
name = n;
QString display_name;
if (n.isEmpty()) {
display_name = "(unknown)";
} else {
display_name = n;
}
EffectRow* row = add_row("Missing Effect", false, false);
row->add_widget(new QLabel(display_name));
container->setText(display_name);
}
void VoidEffect::load(QXmlStreamReader &stream) {
QString tag = stream.name().toString();
qint64 start_index = stream.characterOffset();
qint64 end_index = start_index;
while (!stream.atEnd() && !(stream.name() == tag && stream.isEndElement())) {
end_index = stream.characterOffset();
stream.readNext();
}
qint64 passage_length = end_index - start_index;
if (passage_length > 0) {
// store xml data verbatim
QFile* device = static_cast<QFile*>(stream.device());
QFile passage_get(device->fileName());
if (passage_get.open(QFile::ReadOnly)) {
passage_get.seek(start_index);
bytes = passage_get.read(passage_length);
int passage_end = bytes.lastIndexOf('>')+1;
bytes.remove(passage_end, bytes.size()-passage_end);
passage_get.close();
}
}
}
void VoidEffect::save(QXmlStreamWriter &stream) {
if (!name.isEmpty()) {
stream.writeAttribute("name", name);
stream.writeAttribute("enabled", QString::number(is_enabled()));
// force xml writer to expand <effect> tag, ignored when loading
stream.writeStartElement("void");
stream.writeEndElement();
if (!bytes.isEmpty()) {
// write stored data
QIODevice* device = stream.device();
device->write(bytes);
}
}
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef VOIDEFFECT_H
#define VOIDEFFECT_H
/* VoidEffect is a placeholder used when Olive is unable to find an effect
* requested by a loaded project. It displays a missing effect so the user knows
* an effect is missing, and stores the XML project data verbatim so that it
* isn't lost if the user saves over the project.
*/
#include "project/effect.h"
class VoidEffect : public Effect {
public:
VoidEffect(Clip* c, const QString& n);
void load(QXmlStreamReader &stream) override;
void save(QXmlStreamWriter &stream) override;
private:
QByteArray bytes;
};
#endif // VOIDEFFECT_H
+12 -2
View File
@@ -43,7 +43,9 @@ Config::Config()
previous_queue_size(3),
previous_queue_type(FRAME_QUEUE_TYPE_FRAMES),
upcoming_queue_size(0.5),
upcoming_queue_type(FRAME_QUEUE_TYPE_SECONDS)
upcoming_queue_type(FRAME_QUEUE_TYPE_SECONDS),
loop(true),
pause_at_out_point(true)
{}
void Config::load(QString path) {
@@ -150,7 +152,13 @@ void Config::load(QString path) {
} else if (stream.name() == "UpcomingFrameQueueType") {
stream.readNext();
upcoming_queue_type = stream.text().toInt();
}
} else if (stream.name() == "Loop") {
stream.readNext();
loop = (stream.text() == "1");
} else if (stream.name() == "PauseAtOutPoint") {
stream.readNext();
pause_at_out_point = (stream.text() == "1");
}
}
}
if (stream.hasError()) {
@@ -206,6 +214,8 @@ void Config::save(QString path) {
stream.writeTextElement("PreviousFrameQueueType", QString::number(previous_queue_type));
stream.writeTextElement("UpcomingFrameQueueSize", QString::number(upcoming_queue_size));
stream.writeTextElement("UpcomingFrameQueueType", QString::number(upcoming_queue_type));
stream.writeTextElement("Loop", QString::number(loop));
stream.writeTextElement("PauseAtOutPoint", QString::number(pause_at_out_point));
stream.writeEndElement(); // configuration
stream.writeEndDocument(); // doc
+2
View File
@@ -58,6 +58,8 @@ struct Config {
int previous_queue_type;
double upcoming_queue_size;
int upcoming_queue_type;
bool loop;
bool pause_at_out_point;
void load(QString path);
void save(QString path);
+31 -43
View File
@@ -2,6 +2,7 @@
#include "mainwindow.h"
#include "panels/panels.h"
#include "panels/effectcontrols.h"
#include "panels/project.h"
#include "project/footage.h"
#include "io/config.h"
@@ -13,6 +14,7 @@
#include "io/previewgenerator.h"
#include "dialogs/loaddialog.h"
#include "project/media.h"
#include "effects/internal/voideffect.h"
#include "debug.h"
#include <QFile>
@@ -32,7 +34,7 @@ LoadThread::LoadThread(LoadDialog* l, bool a) : ld(l), autorecovery(a), cancelle
connect(this, SIGNAL(success()), this, SLOT(success_func()));
connect(this, SIGNAL(error()), this, SLOT(error_func()));
connect(this, SIGNAL(start_create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*)), this, SLOT(create_dual_transition(const TransitionData*,Clip*,Clip*,const EffectMeta*)));
connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const EffectMeta*, long, bool)));
connect(this, SIGNAL(start_create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)), this, SLOT(create_effect_ui(QXmlStreamReader*, Clip*, int, const QString*, const EffectMeta*, long, bool)));
}
const EffectMeta* get_meta_from_name(const QString& name) {
@@ -62,26 +64,8 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) {
}
}
// backwards compatibility with 180820
if (stream.name() == "effect" && effect_id != -1) {
switch (effect_id) {
case 0: effect_name = (c->track < 0) ? "Transform" : "Volume"; break;
case 1: effect_name = (c->track < 0) ? "Shake" : "Pan"; break;
case 2: effect_name = (c->track < 0) ? "Text" : "Noise"; break;
case 3: effect_name = (c->track < 0) ? "Solid" : "Tone"; break;
case 4: effect_name = "Invert"; break;
case 5: effect_name = "Chroma Key"; break;
case 6: effect_name = "Gaussian Blur"; break;
case 7: effect_name = "Crop"; break;
case 8: effect_name = "Flip"; break;
case 9: effect_name = "Box Blur"; break;
case 10: effect_name = "Wave"; break;
case 11: effect_name = "Temperature"; break;
}
}
// wait for effects to be loaded
effects_loaded.lock();
panel_effect_controls->effects_loaded.lock();
const EffectMeta* meta = NULL;
@@ -90,26 +74,21 @@ void LoadThread::load_effect(QXmlStreamReader& stream, Clip* c) {
meta = get_meta_from_name(effect_name);
}
effects_loaded.unlock();
panel_effect_controls->effects_loaded.unlock();
if (meta == NULL) {
dout << "[WARNING] An effect used by this project is missing. It was not loaded.";
QString tag = stream.name().toString();
int type;
if (tag == "opening") {
type = TA_OPENING_TRANSITION;
} else if (tag == "closing") {
type = TA_CLOSING_TRANSITION;
} else {
QString tag = stream.name().toString();
int type;
if (tag == "opening") {
type = TA_OPENING_TRANSITION;
} else if (tag == "closing") {
type = TA_CLOSING_TRANSITION;
} else {
type = TA_NO_TRANSITION;
}
emit start_create_effect_ui(&stream, c, type, meta, effect_length, effect_enabled);
waitCond.wait(&mutex);
type = TA_NO_TRANSITION;
}
emit start_create_effect_ui(&stream, c, type, &effect_name, meta, effect_length, effect_enabled);
waitCond.wait(&mutex);
}
void LoadThread::read_next(QXmlStreamReader &stream) {
@@ -183,7 +162,7 @@ bool LoadThread::load_worker(QFile& f, QXmlStreamReader& stream, int type) {
internal_proj_url = stream.readElementText();
internal_proj_dir = QFileInfo(internal_proj_url).absoluteDir();
} else {
while (!cancelled && !(stream.name() == root_search && stream.isEndElement())) {
while (!cancelled && !stream.atEnd() && !(stream.name() == root_search && stream.isEndElement())) {
read_next(stream);
if (stream.name() == child_search && stream.isStartElement()) {
switch (type) {
@@ -603,7 +582,7 @@ void LoadThread::run() {
xml_error = false;
if (show_err) emit error();
} else if (stream.hasError()) {
error_str = stream.errorString();
error_str = stream.errorString() + " - Line: " + QString::number(stream.lineNumber()) + " Col:" + QString::number(stream.columnNumber());
xml_error = true;
emit error();
cont = false;
@@ -678,6 +657,7 @@ void LoadThread::create_effect_ui(
QXmlStreamReader* stream,
Clip* c,
int type,
const QString* effect_name,
const EffectMeta* meta,
long effect_length,
bool effect_enabled)
@@ -705,11 +685,19 @@ void LoadThread::create_effect_ui(
if (cancelled) return;
if (type == TA_NO_TRANSITION) {
Effect* e = create_effect(c, meta);
e->set_enabled(effect_enabled);
e->load(*stream);
if (meta == NULL) {
// create void effect
VoidEffect* ve = new VoidEffect(c, *effect_name);
ve->set_enabled(effect_enabled);
ve->load(*stream);
c->effects.append(ve);
} else {
Effect* e = create_effect(c, meta);
e->set_enabled(effect_enabled);
e->load(*stream);
c->effects.append(e);
c->effects.append(e);
}
} else {
int transition_index = create_transition(c, NULL, meta);
Transition* t = c->sequence->transitions.at(transition_index);
+2 -2
View File
@@ -25,13 +25,13 @@ public:
signals:
void success();
void error();
void start_create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const EffectMeta* meta, long effect_length, bool effect_enabled);
void start_create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled);
void start_create_dual_transition(const TransitionData* td, Clip* primary, Clip* secondary, const EffectMeta* meta);
void report_progress(int p);
private slots:
void error_func();
void success_func();
void create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const EffectMeta* meta, long effect_length, bool effect_enabled);
void create_effect_ui(QXmlStreamReader* stream, Clip* c, int type, const QString *effect_name, const EffectMeta* meta, long effect_length, bool effect_enabled);
void create_dual_transition(const TransitionData* td, Clip* primary, Clip* secondary, const EffectMeta* meta);
private:
LoadDialog* ld;
+125 -68
View File
@@ -248,6 +248,84 @@ void MainWindow::make_inout_menu(QMenu *parent) {
parent->addAction("Clear In/Out Point", this, SLOT(clear_inout()), QKeySequence("G"));
}
void kbd_shortcut_processor(QByteArray& file, QMenu* menu, bool save, bool first) {
QList<QAction*> actions = menu->actions();
for (int i=0;i<actions.size();i++) {
QAction* a = actions.at(i);
if (a->menu() != NULL) {
kbd_shortcut_processor(file, a->menu(), save, first);
} else if (!a->isSeparator()) {
if (save) {
// saving custom shortcuts
if (!a->property("default").isNull()) {
QKeySequence defks(a->property("default").toString());
if (a->shortcut() != defks) {
// custom shortcut
if (!file.isEmpty()) file.append('\n');
file.append(a->text().replace("&", ""));
file.append('\t');
file.append(a->shortcut().toString());
}
}
} else {
// loading custom shortcuts
if (first) {
// store default shortcut
a->setProperty("default", a->shortcut().toString());
} else {
// restore default shortcut
a->setShortcut(a->property("default").toString());
}
QString comp_str = a->text().replace("&", "");
int shortcut_index = file.indexOf(comp_str);
if (shortcut_index == 0 || (shortcut_index > 0 && file.at(shortcut_index-1) == '\n')) {
shortcut_index += comp_str.size() + 1;
QString shortcut;
while (shortcut_index < file.size() && file.at(shortcut_index) != '\n') {
shortcut.append(file.at(shortcut_index));
shortcut_index++;
}
QKeySequence ks(shortcut);
if (!ks.isEmpty()) {
a->setShortcut(ks);
}
}
}
}
}
}
void MainWindow::load_shortcuts(const QString& fn, bool first) {
QByteArray shortcut_bytes;
QFile shortcut_path(fn);
if (shortcut_path.exists() && shortcut_path.open(QFile::ReadOnly)) {
shortcut_bytes = shortcut_path.readAll();
shortcut_path.close();
}
QList<QAction*> menus = menuBar()->actions();
for (int i=0;i<menus.size();i++) {
QMenu* menu = menus.at(i)->menu();
kbd_shortcut_processor(shortcut_bytes, menu, false, first);
}
}
void MainWindow::save_shortcuts(const QString& fn) {
// save main menu actions
QList<QAction*> menus = menuBar()->actions();
QByteArray shortcut_file;
for (int i=0;i<menus.size();i++) {
QMenu* menu = menus.at(i)->menu();
kbd_shortcut_processor(shortcut_file, menu, true, false);
}
QFile shortcut_file_io(fn);
if (shortcut_file_io.open(QFile::WriteOnly)) {
shortcut_file_io.write(shortcut_file);
shortcut_file_io.close();
} else {
dout << "[ERROR] Failed to save shortcut file";
}
}
void MainWindow::show_about() {
AboutDialog a(this);
a.exec();
@@ -319,7 +397,7 @@ void MainWindow::export_dialog() {
}
void MainWindow::ripple_delete() {
panel_timeline->delete_selection(sequence->selections, true);
if (sequence != NULL) panel_timeline->delete_selection(sequence->selections, true);
}
void MainWindow::editMenu_About_To_Be_Shown() {
@@ -442,47 +520,6 @@ bool MainWindow::can_close_project() {
return true;
}
void kbd_shortcut_processor(QByteArray& file, QMenu* menu, bool save) {
QList<QAction*> actions = menu->actions();
for (int i=0;i<actions.size();i++) {
QAction* a = actions.at(i);
if (a->menu() != NULL) {
kbd_shortcut_processor(file, a->menu(), save);
} else if (!a->isSeparator()) {
if (save) {
// saving custom shortcuts
if (!a->property("default").isNull()) {
QKeySequence defks(a->property("default").toString());
if (a->shortcut() != defks) {
// custom shortcut
if (!file.isEmpty()) file.append('\n');
file.append(a->text().replace("&", ""));
file.append('\t');
file.append(a->shortcut().toString());
}
}
} else {
// loading custom shortcuts
a->setProperty("default", a->shortcut().toString());
QString comp_str = a->text().replace("&", "");
int shortcut_index = file.indexOf(comp_str);
if (shortcut_index == 0 || (shortcut_index > 0 && file.at(shortcut_index-1) == '\n')) {
shortcut_index += comp_str.size() + 1;
QString shortcut;
while (shortcut_index < file.size() && file.at(shortcut_index) != '\n') {
shortcut.append(file.at(shortcut_index));
shortcut_index++;
}
QKeySequence ks(shortcut);
if (!ks.isEmpty()) {
a->setShortcut(ks);
}
}
}
}
}
}
void MainWindow::setup_menus() {
QMenuBar* menuBar = new QMenuBar(this);
setMenuBar(menuBar);
@@ -497,8 +534,13 @@ void MainWindow::setup_menus() {
file_menu->addAction("&Open Project", this, SLOT(open_project()), QKeySequence("Ctrl+O"));
clear_open_recent_action = new QAction("Clear Recent List");
connect(clear_open_recent_action, SIGNAL(triggered()), panel_project, SLOT(clear_recent_projects()));
open_recent = file_menu->addMenu("Open Recent");
open_recent->addAction(clear_open_recent_action);
file_menu->addAction("&Save Project", this, SLOT(save_project()), QKeySequence("Ctrl+S"));
file_menu->addAction("Save Project &As", this, SLOT(save_project_as()), QKeySequence("Ctrl+Shift+S"));
@@ -642,6 +684,9 @@ void MainWindow::setup_menus() {
playback_menu->addSeparator();
playback_menu->addAction("Go to Previous Cut", this, SLOT(prev_cut()), QKeySequence("Up"));
playback_menu->addAction("Go to Next Cut", this, SLOT(next_cut()), QKeySequence("Down"));
playback_menu->addSeparator();
playback_menu->addAction("Go to In Point", this, SLOT(go_to_in()), QKeySequence("Shift+I"));
playback_menu->addAction("Go to Out Point", this, SLOT(go_to_out()), QKeySequence("Shift+O"));
// INITIALIZE WINDOW MENU
@@ -769,6 +814,14 @@ void MainWindow::setup_menus() {
set_name_and_marker->setCheckable(true);
set_name_and_marker->setData(reinterpret_cast<quintptr>(&config.set_name_with_marker));
loop_action = tools_menu->addAction("Loop", this, SLOT(toggle_bool_action()));
loop_action->setCheckable(true);
loop_action->setData(reinterpret_cast<quintptr>(&config.loop));
pause_at_out_point_action = tools_menu->addAction("Pause At Out Point", this, SLOT(toggle_bool_action()));
pause_at_out_point_action->setCheckable(true);
pause_at_out_point_action->setData(reinterpret_cast<quintptr>(&config.pause_at_out_point));
tools_menu->addSeparator();
no_autoscroll = tools_menu->addAction("No Auto-Scroll", this, SLOT(set_autoscroll()));
@@ -795,21 +848,13 @@ void MainWindow::setup_menus() {
QMenu* help_menu = menuBar->addMenu("&Help");
help_menu->addAction("A&ction Search", this, SLOT(show_action_search()));
help_menu->addAction("A&ction Search", this, SLOT(show_action_search()), QKeySequence("/"));
help_menu->addSeparator();
help_menu->addAction("&About...", this, SLOT(show_about()));
QFile shortcut_path(get_config_path() + "/shortcuts");
if (shortcut_path.exists() && shortcut_path.open(QFile::ReadOnly)) {
QList<QAction*> menus = menuBar->actions();
QByteArray shortcut_bytes = shortcut_path.readAll();
for (int i=0;i<menus.size();i++) {
QMenu* menu = menus.at(i)->menu();
kbd_shortcut_processor(shortcut_bytes, menu, false);
}
}
load_shortcuts(get_config_path() + "/shortcuts", true);
}
void MainWindow::set_bool_action_checked(QAction *a) {
@@ -862,20 +907,7 @@ void MainWindow::closeEvent(QCloseEvent *e) {
dout << "[ERROR] Failed to save layout";
}
// save main menu actions
QList<QAction*> menus = menuBar()->actions();
QByteArray shortcut_file;
for (int i=0;i<menus.size();i++) {
QMenu* menu = menus.at(i)->menu();
kbd_shortcut_processor(shortcut_file, menu, true);
}
QFile shortcut_file_io(config_dir + "/shortcuts");
if (shortcut_file_io.open(QFile::WriteOnly)) {
shortcut_file_io.write(shortcut_file);
shortcut_file_io.close();
} else {
dout << "[ERROR] Failed to save shortcut file";
}
save_shortcuts(config_dir + "/shortcuts");
}
stop_audio();
@@ -931,6 +963,28 @@ void MainWindow::reset_layout() {
setup_layout(true);
}
void MainWindow::go_to_in() {
if (panel_timeline->focused()
|| panel_sequence_viewer->is_focused()
|| panel_effect_controls->keyframe_focus()
|| panel_graph_editor->view_is_focused()) {
panel_sequence_viewer->go_to_in();
} else if (panel_footage_viewer->is_focused()) {
panel_footage_viewer->go_to_in();
}
}
void MainWindow::go_to_out() {
if (panel_timeline->focused()
|| panel_sequence_viewer->is_focused()
|| panel_effect_controls->keyframe_focus()
|| panel_graph_editor->view_is_focused()) {
panel_sequence_viewer->go_to_out();
} else if (panel_footage_viewer->is_focused()) {
panel_footage_viewer->go_to_out();
}
}
void MainWindow::go_to_start() {
if (panel_timeline->focused()
|| panel_sequence_viewer->is_focused()
@@ -1066,6 +1120,8 @@ void MainWindow::toolMenu_About_To_Be_Shown() {
set_bool_action_checked(enable_drop_on_media_to_replace);
set_bool_action_checked(enable_hover_focus);
set_bool_action_checked(set_name_and_marker);
set_bool_action_checked(loop_action);
set_bool_action_checked(pause_at_out_point_action);
set_int_action_checked(no_autoscroll, config.autoscroll);
set_int_action_checked(page_autoscroll, config.autoscroll);
@@ -1103,12 +1159,13 @@ void MainWindow::fileMenu_About_To_Be_Shown() {
open_recent->setEnabled(true);
for (int i=0;i<recent_projects.size();i++) {
QAction* action = open_recent->addAction(recent_projects.at(i));
action->setProperty("keyignore", true);
action->setData(i);
connect(action, SIGNAL(triggered()), this, SLOT(load_recent_project()));
}
open_recent->addSeparator();
QAction* clear_action = open_recent->addAction("Clear Recent List");
connect(clear_action, SIGNAL(triggered()), panel_project, SLOT(clear_recent_projects()));
open_recent->addAction(clear_open_recent_action);
} else {
open_recent->setEnabled(false);
}
+8
View File
@@ -20,6 +20,9 @@ public:
void make_new_menu(QMenu* parent);
void make_inout_menu(QMenu* parent);
void load_shortcuts(const QString &fn, bool first = false);
void save_shortcuts(const QString &fn);
QString appName;
public slots:
@@ -56,6 +59,8 @@ private slots:
bool save_project_as();
bool save_project();
void go_to_in();
void go_to_out();
void go_to_start();
void prev_frame();
void playpause();
@@ -131,6 +136,7 @@ private:
// file menu actions
QMenu* open_recent;
QAction* clear_open_recent_action;
// view menu actions
QAction* track_lines;
@@ -172,6 +178,8 @@ private:
QAction* enable_drop_on_media_to_replace;
QAction* enable_hover_focus;
QAction* set_name_and_marker;
QAction* loop_action;
QAction* pause_at_out_point_action;
// edit menu actions
QAction* undo_action;
+4 -2
View File
@@ -119,7 +119,8 @@ SOURCES += \
ui/rectangleselect.cpp \
dialogs/actionsearch.cpp \
ui/embeddedfilechooser.cpp \
effects/internal/fillleftrighteffect.cpp
effects/internal/fillleftrighteffect.cpp \
effects/internal/voideffect.cpp
HEADERS += \
mainwindow.h \
@@ -208,7 +209,8 @@ HEADERS += \
ui/rectangleselect.h \
dialogs/actionsearch.h \
ui/embeddedfilechooser.h \
effects/internal/fillleftrighteffect.h
effects/internal/fillleftrighteffect.h \
effects/internal/voideffect.h
FORMS +=
@@ -9,10 +9,14 @@
<summary xml:lang="pt_BR">Editor de vídeo não-linear</summary>
<summary xml:lang="es">Editor de video no lineal</summary>
<summary xml:lang="ru">Нелинейный видеоредактор</summary>
<summary xml:lang="uk">Нелінійний відеоредактор</summary>
<summary xml:lang="uk_UA">Нелінійний відеоредактор</summary>
<description><p>Olive is a free non-linear video editor aiming to provide a fully-featured alternative to high-end professional video editing software.</p></description>
<description xml:lang="pt_BR"><p>Olive é um editor de vídeo não-linear com o objetivo de fornecer uma alternativa completa para softwares profissionais de edição de vídeo.</p></description>
<description xml:lang="es"><p>Olive es un editor de video no lineal libre que apunta a brindar una alternativa completa al software de edición de video profesional.</p></description>
<description xml:lang="ru"><p>Olive — свободный нелинейный видеоредактор, задуманный как полноценная замена закрытым коммерческим продуктам.</p></description>
<description xml:lang="uk"><p>Olive — вільний нелінійний відеоредактор, задуманий як повноцінна заміна закритим комерційним продуктам.</p></description>
<description xml:lang="uk_UA"><p>Olive — вільний нелінійний відеоредактор, задуманий як повноцінна заміна закритим комерційним продуктам.</p></description>
<url type="homepage">https://www.olivevideoeditor.org</url>
<url type="donation">https://www.patreon.com/olivevideoeditor</url>
<url type="bugtracker">https://github.com/olive-editor/olive/issues</url>
-1
View File
@@ -41,7 +41,6 @@ EffectControls::EffectControls(QWidget *parent) :
setup_ui();
init_effects();
clear_effects(false);
headers->viewer = panel_sequence_viewer;
headers->snapping = false;
+3
View File
@@ -3,6 +3,7 @@
#include <QDockWidget>
#include <QUndoCommand>
#include <QMutex>
struct Clip;
class QMenu;
@@ -50,6 +51,8 @@ public:
ResizableScrollBar* horizontalScrollBar;
QScrollBar* verticalScrollBar;
QMutex effects_loaded;
public slots:
void update_keyframes();
private slots:
+1
View File
@@ -152,6 +152,7 @@ void alloc_panels(QWidget* parent) {
panel_project = new Project(parent);
panel_project->setObjectName("proj_root");
panel_effect_controls = new EffectControls(parent);
init_effects();
panel_effect_controls->setObjectName("fx_controls");
panel_timeline = new Timeline(parent);
panel_timeline->setObjectName("timeline");
+44 -12
View File
@@ -248,11 +248,19 @@ void Viewer::seek(long p) {
}
void Viewer::go_to_start() {
if (seq != NULL) seek(0);
}
void Viewer::go_to_end() {
if (seq != NULL) seek(seq->getEndFrame());
}
void Viewer::go_to_in() {
if (seq != NULL) {
if (seq->using_workarea && seq->playhead != seq->workarea_in) {
if (seq->using_workarea) {
seek(seq->workarea_in);
} else {
seek(0);
go_to_start();
}
}
}
@@ -265,12 +273,12 @@ void Viewer::next_frame() {
if (seq != NULL) seek(seq->playhead+1);
}
void Viewer::go_to_end() {
void Viewer::go_to_out() {
if (seq != NULL) {
if (seq->using_workarea && seq->playhead != seq->workarea_out) {
if (seq->using_workarea) {
seek(seq->workarea_out);
} else {
seek(seq->getEndFrame());
go_to_end();
}
}
}
@@ -307,6 +315,12 @@ void Viewer::play() {
if (panel_footage_viewer->playing) panel_footage_viewer->pause();
if (seq != NULL) {
if (!is_recording_cued()
&& seq->playhead >= get_seq_out()
&& (config.loop || !main_sequence)) {
seek(get_seq_in());
}
reset_all_audio();
if (is_recording_cued() && !start_recording()) {
dout << "[ERROR] Failed to record audio";
@@ -455,6 +469,18 @@ void Viewer::set_sb_max() {
headers->set_scrollbar_max(horizontal_bar, seq->getEndFrame(), headers->width());
}
long Viewer::get_seq_in() {
return (seq->using_workarea)
? seq->workarea_in
: 0;
}
long Viewer::get_seq_out() {
return (seq->using_workarea && previous_playhead < seq->workarea_out)
? seq->workarea_out
: seq->getEndFrame();
}
void Viewer::setup_ui() {
QWidget* contents = new QWidget();
@@ -499,7 +525,7 @@ void Viewer::setup_ui() {
goToStartIcon.addFile(QStringLiteral(":/icons/prev.png"), QSize(), QIcon::Normal, QIcon::Off);
goToStartIcon.addFile(QStringLiteral(":/icons/prev-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off);
btnSkipToStart->setIcon(goToStartIcon);
connect(btnSkipToStart, SIGNAL(clicked(bool)), this, SLOT(go_to_start()));
connect(btnSkipToStart, SIGNAL(clicked(bool)), this, SLOT(go_to_in()));
playback_control_layout->addWidget(btnSkipToStart);
btnRewind = new QPushButton(playback_controls);
@@ -530,7 +556,7 @@ void Viewer::setup_ui() {
nextIcon.addFile(QStringLiteral(":/icons/next.png"), QSize(), QIcon::Normal, QIcon::Off);
nextIcon.addFile(QStringLiteral(":/icons/next-disabled.png"), QSize(), QIcon::Disabled, QIcon::Off);
btnSkipToEnd->setIcon(nextIcon);
connect(btnSkipToEnd, SIGNAL(clicked(bool)), this, SLOT(go_to_end()));
connect(btnSkipToEnd, SIGNAL(clicked(bool)), this, SLOT(go_to_out()));
playback_control_layout->addWidget(btnSkipToEnd);
lower_control_layout->addWidget(playback_controls);
@@ -637,17 +663,23 @@ void Viewer::update_playhead() {
}
void Viewer::timer_update() {
long previous_playhead = seq->playhead;
previous_playhead = seq->playhead;
seq->playhead = qRound(playhead_start + ((QDateTime::currentMSecsSinceEpoch()-start_msecs) * 0.001 * seq->frame_rate));
update_parents();
long end_frame = (seq->using_workarea && previous_playhead < seq->workarea_out) ? seq->workarea_out : seq->getEndFrame();
if ((!recording
long end_frame = get_seq_out();
if (!recording
&& playing
&& seq->playhead >= end_frame
&& previous_playhead < end_frame)
|| (recording && recording_start != recording_end && seq->playhead >= recording_end)) {
&& previous_playhead < end_frame) {
if (!config.pause_at_out_point && config.loop) {
seek(get_seq_in());
play();
} else if (config.pause_at_out_point || !main_sequence) {
pause();
}
} else if (recording && recording_start != recording_end && seq->playhead >= recording_end) {
pause();
}
}
+7
View File
@@ -72,9 +72,11 @@ public:
public slots:
void play_wake();
void go_to_start();
void go_to_in();
void previous_frame();
void toggle_play();
void next_frame();
void go_to_out();
void go_to_end();
private slots:
@@ -94,6 +96,9 @@ private:
void set_zoom_value(double d);
void set_sb_max();
long get_seq_in();
long get_seq_out();
QIcon playIcon;
void setup_ui();
@@ -112,6 +117,8 @@ private:
bool cue_recording_internal;
QTimer recording_flasher;
long previous_playhead;
};
#endif // VIEWER_H
+178 -165
View File
@@ -45,7 +45,6 @@
#include <QMenu>
QVector<EffectMeta> effects;
QMutex effects_loaded;
Effect* create_effect(Clip* c, const EffectMeta* em) {
if (!em->filename.isEmpty()) {
@@ -245,7 +244,7 @@ void init_effects() {
}
EffectInit::EffectInit() {
effects_loaded.lock();
panel_effect_controls->effects_loaded.lock();
}
void EffectInit::run() {
@@ -253,7 +252,7 @@ void EffectInit::run() {
load_internal_effects();
load_shader_effects();
load_vst_effects();
effects_loaded.unlock();
panel_effect_controls->effects_loaded.unlock();
dout << "[INFO] Finished initializing effects";
}
@@ -281,191 +280,193 @@ Effect::Effect(Clip* c, const EffectMeta *em) :
connect(container->title_bar, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(show_context_menu(const QPoint&)));
// set up UI from effect file
container->setText(em->name);
if (em != NULL) {
// set up UI from effect file
container->setText(em->name);
if (!em->filename.isEmpty()) {
QFile effect_file(em->filename);
if (effect_file.open(QFile::ReadOnly)) {
QXmlStreamReader reader(&effect_file);
if (!em->filename.isEmpty()) {
QFile effect_file(em->filename);
if (effect_file.open(QFile::ReadOnly)) {
QXmlStreamReader reader(&effect_file);
while (!reader.atEnd()) {
if (reader.name() == "row" && reader.isStartElement()) {
QString row_name;
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "name") {
row_name = attr.value().toString();
while (!reader.atEnd()) {
if (reader.name() == "row" && reader.isStartElement()) {
QString row_name;
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "name") {
row_name = attr.value().toString();
}
}
}
if (!row_name.isEmpty()) {
EffectRow* row = add_row(row_name);
while (!reader.atEnd() && !(reader.name() == "row" && reader.isEndElement())) {
reader.readNext();
if (reader.name() == "field" && reader.isStartElement()) {
int type = EFFECT_TYPE_VIDEO;
QString id;
if (!row_name.isEmpty()) {
EffectRow* row = add_row(row_name);
while (!reader.atEnd() && !(reader.name() == "row" && reader.isEndElement())) {
reader.readNext();
if (reader.name() == "field" && reader.isStartElement()) {
int type = EFFECT_TYPE_VIDEO;
QString id;
// get field type
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "type") {
QString comp = attr.value().toString().toUpper();
if (comp == "DOUBLE") {
type = EFFECT_FIELD_DOUBLE;
} else if (comp == "BOOL") {
type = EFFECT_FIELD_BOOL;
} else if (comp == "COLOR") {
type = EFFECT_FIELD_COLOR;
} else if (comp == "COMBO") {
type = EFFECT_FIELD_COMBO;
} else if (comp == "FONT") {
type = EFFECT_FIELD_FONT;
} else if (comp == "STRING") {
type = EFFECT_FIELD_STRING;
} else if (comp == "FILE") {
type = EFFECT_FIELD_FILE;
// get field type
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "type") {
QString comp = attr.value().toString().toUpper();
if (comp == "DOUBLE") {
type = EFFECT_FIELD_DOUBLE;
} else if (comp == "BOOL") {
type = EFFECT_FIELD_BOOL;
} else if (comp == "COLOR") {
type = EFFECT_FIELD_COLOR;
} else if (comp == "COMBO") {
type = EFFECT_FIELD_COMBO;
} else if (comp == "FONT") {
type = EFFECT_FIELD_FONT;
} else if (comp == "STRING") {
type = EFFECT_FIELD_STRING;
} else if (comp == "FILE") {
type = EFFECT_FIELD_FILE;
}
} else if (attr.name() == "id") {
id = attr.value().toString();
}
} else if (attr.name() == "id") {
id = attr.value().toString();
}
}
if (id.isEmpty()) {
dout << "[ERROR] Couldn't load field from" << em->filename << "- ID cannot be empty.";
} else if (type > -1) {
EffectField* field = row->add_field(type, id);
connect(field, SIGNAL(changed()), this, SLOT(field_changed()));
switch (type) {
case EFFECT_FIELD_DOUBLE:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_double_default_value(attr.value().toDouble());
} else if (attr.name() == "min") {
field->set_double_minimum_value(attr.value().toDouble());
} else if (attr.name() == "max") {
field->set_double_maximum_value(attr.value().toDouble());
if (id.isEmpty()) {
dout << "[ERROR] Couldn't load field from" << em->filename << "- ID cannot be empty.";
} else if (type > -1) {
EffectField* field = row->add_field(type, id);
connect(field, SIGNAL(changed()), this, SLOT(field_changed()));
switch (type) {
case EFFECT_FIELD_DOUBLE:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_double_default_value(attr.value().toDouble());
} else if (attr.name() == "min") {
field->set_double_minimum_value(attr.value().toDouble());
} else if (attr.name() == "max") {
field->set_double_maximum_value(attr.value().toDouble());
}
}
}
break;
case EFFECT_FIELD_COLOR:
{
QColor color;
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "r") {
color.setRed(attr.value().toInt());
} else if (attr.name() == "g") {
color.setGreen(attr.value().toInt());
} else if (attr.name() == "b") {
color.setBlue(attr.value().toInt());
} else if (attr.name() == "rf") {
color.setRedF(attr.value().toFloat());
} else if (attr.name() == "gf") {
color.setGreenF(attr.value().toFloat());
} else if (attr.name() == "bf") {
color.setBlueF(attr.value().toFloat());
} else if (attr.name() == "hex") {
color.setNamedColor(attr.value().toString());
break;
case EFFECT_FIELD_COLOR:
{
QColor color;
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "r") {
color.setRed(attr.value().toInt());
} else if (attr.name() == "g") {
color.setGreen(attr.value().toInt());
} else if (attr.name() == "b") {
color.setBlue(attr.value().toInt());
} else if (attr.name() == "rf") {
color.setRedF(attr.value().toFloat());
} else if (attr.name() == "gf") {
color.setGreenF(attr.value().toFloat());
} else if (attr.name() == "bf") {
color.setBlueF(attr.value().toFloat());
} else if (attr.name() == "hex") {
color.setNamedColor(attr.value().toString());
}
}
field->set_color_value(color);
}
field->set_color_value(color);
}
break;
case EFFECT_FIELD_STRING:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_string_value(attr.value().toString());
break;
case EFFECT_FIELD_STRING:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_string_value(attr.value().toString());
}
}
}
break;
case EFFECT_FIELD_BOOL:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_bool_value(attr.value() == "1");
break;
case EFFECT_FIELD_BOOL:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_bool_value(attr.value() == "1");
}
}
}
break;
case EFFECT_FIELD_COMBO:
{
int combo_index = 0;
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
combo_index = attr.value().toInt();
break;
break;
case EFFECT_FIELD_COMBO:
{
int combo_index = 0;
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
combo_index = attr.value().toInt();
break;
}
}
}
while (!reader.atEnd() && !(reader.name() == "field" && reader.isEndElement())) {
reader.readNext();
if (reader.name() == "option" && reader.isStartElement()) {
while (!reader.atEnd() && !(reader.name() == "field" && reader.isEndElement())) {
reader.readNext();
field->add_combo_item(reader.text().toString(), 0);
if (reader.name() == "option" && reader.isStartElement()) {
reader.readNext();
field->add_combo_item(reader.text().toString(), 0);
}
}
field->set_combo_index(combo_index);
}
field->set_combo_index(combo_index);
}
break;
case EFFECT_FIELD_FONT:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_font_name(attr.value().toString());
break;
case EFFECT_FIELD_FONT:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "default") {
field->set_font_name(attr.value().toString());
}
}
}
break;
case EFFECT_FIELD_FILE:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "filename") {
field->set_filename(attr.value().toString());
break;
case EFFECT_FIELD_FILE:
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "filename") {
field->set_filename(attr.value().toString());
}
}
break;
}
break;
}
}
}
}
}
} else if (reader.name() == "shader" && reader.isStartElement()) {
enable_shader = true;
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "vert") {
vertPath = attr.value().toString();
} else if (attr.name() == "frag") {
fragPath = attr.value().toString();
}
}
}/* else if (reader.name() == "superimpose" && reader.isStartElement()) {
enable_superimpose = true;
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "script") {
QFile script_file(get_effects_dir() + "/" + attr.value().toString());
if (script_file.open(QFile::ReadOnly)) {
script = script_file.readAll();
} else {
dout << "[ERROR] Failed to open superimpose script file for" << em->filename;
enable_superimpose = false;
} else if (reader.name() == "shader" && reader.isStartElement()) {
enable_shader = true;
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "vert") {
vertPath = attr.value().toString();
} else if (attr.name() == "frag") {
fragPath = attr.value().toString();
}
break;
}
}
}*/
reader.readNext();
}
}/* else if (reader.name() == "superimpose" && reader.isStartElement()) {
enable_superimpose = true;
const QXmlStreamAttributes& attributes = reader.attributes();
for (int i=0;i<attributes.size();i++) {
const QXmlStreamAttribute& attr = attributes.at(i);
if (attr.name() == "script") {
QFile script_file(get_effects_dir() + "/" + attr.value().toString());
if (script_file.open(QFile::ReadOnly)) {
script = script_file.readAll();
} else {
dout << "[ERROR] Failed to open superimpose script file for" << em->filename;
enable_superimpose = false;
}
break;
}
}
}*/
reader.readNext();
}
effect_file.close();
} else {
dout << "[ERROR] Failed to open effect file" << em->filename;
effect_file.close();
} else {
dout << "[ERROR] Failed to open effect file" << em->filename;
}
}
}
}
@@ -793,16 +794,28 @@ void Effect::open() {
validate_meta_path();
bool glsl_compiled = true;
if (!vertPath.isEmpty()) {
if (!glslProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, meta->path + "/" + vertPath)) {
if (glslProgram->addShaderFromSourceFile(QOpenGLShader::Vertex, meta->path + "/" + vertPath)) {
dout << "[INFO] Vertex shader added successfully";
} else {
glsl_compiled = false;
dout << "[WARNING] Vertex shader could not be added";
}
}
if (!fragPath.isEmpty()) {
if (!glslProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, meta->path + "/" + fragPath)) {
if (glslProgram->addShaderFromSourceFile(QOpenGLShader::Fragment, meta->path + "/" + fragPath)) {
dout << "[INFO] Fragment shader added successfully";
} else {
glsl_compiled = false;
dout << "[WARNING] Fragment shader could not be added";
}
}
if (glsl_compiled) {
if (glslProgram->link()) {
dout << "[INFO] Shader program linked successfully";
} else {
dout << "[WARNING] Shader program failed to link";
}
}
if (glsl_compiled) glslProgram->link();
isOpen = true;
}
} else {
+1 -3
View File
@@ -41,8 +41,6 @@ void init_effects();
Effect* create_effect(Clip* c, const EffectMeta *em);
const EffectMeta* get_internal_meta(int internal_id, int type);
extern QMutex effects_loaded;
#define EFFECT_TYPE_INVALID 0
#define EFFECT_TYPE_VIDEO 1
#define EFFECT_TYPE_AUDIO 2
@@ -135,7 +133,7 @@ public:
Effect* copy(Clip* c);
void copy_field_keyframes(Effect *e);
void load(QXmlStreamReader& stream);
virtual void load(QXmlStreamReader& stream);
virtual void custom_load(QXmlStreamReader& stream);
virtual void save(QXmlStreamWriter& stream);
+3 -1
View File
@@ -31,7 +31,9 @@ EffectRow::EffectRow(Effect *parent, bool save, QGridLayout *uilayout, const QSt
column_count = 1;
if (parent_effect->meta->type != EFFECT_TYPE_TRANSITION && keyframable) {
if (parent_effect->meta != NULL
&& parent_effect->meta->type != EFFECT_TYPE_TRANSITION
&& keyframable) {
connect(label, SIGNAL(clicked()), this, SLOT(focus_row()));
keyframe_nav = new KeyframeNavigator();
+5 -2
View File
@@ -554,7 +554,10 @@ bool isLiveEditing() {
void TimelineWidget::mousePressEvent(QMouseEvent *event) {
if (sequence != NULL) {
int tool = panel_timeline->tool;
if (event->button() == Qt::RightButton) {
if (event->button() == Qt::MiddleButton) {
tool = TIMELINE_TOOL_HAND;
panel_timeline->creating = false;
} else if (event->button() == Qt::RightButton) {
tool = TIMELINE_TOOL_MENU;
panel_timeline->creating = false;
}
@@ -1155,12 +1158,12 @@ void TimelineWidget::mouseReleaseEvent(QMouseEvent *event) {
panel_timeline->rect_select_proc = false;
panel_timeline->transition_tool_init = false;
panel_timeline->transition_tool_proc = false;
panel_timeline->hand_moving = false;
pre_clips.clear();
post_clips.clear();
update_ui(true);
}
panel_timeline->hand_moving = false;
}
}