reimplemented goto prev/next cut, about dialog, and action search dialog
This commit is contained in:
@@ -28,6 +28,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "dialog/about/about.h"
|
||||
#include "dialog/sequence/sequence.h"
|
||||
#include "panel/panelmanager.h"
|
||||
#include "panel/project/project.h"
|
||||
@@ -160,6 +161,12 @@ void Core::SetSnapping(const bool &b)
|
||||
emit SnappingChanged(snapping_);
|
||||
}
|
||||
|
||||
void Core::DialogAboutShow()
|
||||
{
|
||||
AboutDialog a(main_window_);
|
||||
a.exec();
|
||||
}
|
||||
|
||||
void Core::DialogImportShow()
|
||||
{
|
||||
// Open dialog for user to select files
|
||||
|
||||
@@ -114,6 +114,11 @@ public slots:
|
||||
*/
|
||||
void SetSnapping(const bool& b);
|
||||
|
||||
/**
|
||||
* @brief Show an About dialog
|
||||
*/
|
||||
void DialogAboutShow();
|
||||
|
||||
/**
|
||||
* @brief Open the import footage dialog and import the files selected (runs ImportFiles())
|
||||
*/
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
add_subdirectory(about)
|
||||
add_subdirectory(actionsearch)
|
||||
add_subdirectory(sequence)
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# 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/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
dialog/about/about.h
|
||||
dialog/about/about.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,65 @@
|
||||
/***
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "about.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QLabel>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
AboutDialog::AboutDialog(QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("About %1").arg(QApplication::applicationName()));
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
//layout->setSpacing(20);
|
||||
|
||||
// Construct About text
|
||||
QLabel* label =
|
||||
new QLabel(QString("<html><head/><body>"
|
||||
"<p><img src=\":/icons/olive-splash.png\"/></p>"
|
||||
"<p><a href=\"https://www.olivevideoeditor.org/\">"
|
||||
"<span style=\" text-decoration: underline; color:#007af4;\">"
|
||||
"https://www.olivevideoeditor.org/"
|
||||
"</span></a></p>"
|
||||
"<p><b>%1</b></p>" // AppName (version identifier)
|
||||
"<p>%2</p>" // First statement
|
||||
"<p>%3</p>" // Second statement
|
||||
"</body></html>").arg(QApplication::applicationName(),
|
||||
tr("Olive is a non-linear video editor. This software is free and "
|
||||
"protected by the GNU GPL."),
|
||||
tr("Olive Team is obliged to inform users that Olive source code is "
|
||||
"available for download from its website.")),this);
|
||||
|
||||
// Set text formatting
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
label->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
label->setCursor(Qt::IBeamCursor);
|
||||
label->setWordWrap(true);
|
||||
layout->addWidget(label);
|
||||
|
||||
QDialogButtonBox* buttons = new QDialogButtonBox(QDialogButtonBox::Ok, this);
|
||||
buttons->setCenterButtons(true);
|
||||
layout->addWidget(buttons);
|
||||
|
||||
connect(buttons, SIGNAL(accepted()), this, SLOT(accept()));
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/***
|
||||
|
||||
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 ABOUTDIALOG_H
|
||||
#define ABOUTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
/**
|
||||
* @brief The AboutDialog class
|
||||
*
|
||||
* The About dialog (accessible through Help > About). Contains license and version information. This can be run from
|
||||
* anywhere
|
||||
*/
|
||||
class AboutDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief AboutDialog Constructor
|
||||
*
|
||||
* Creates About dialog.
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent object. Usually this will be MainWindow.
|
||||
*/
|
||||
explicit AboutDialog(QWidget *parent = nullptr);
|
||||
};
|
||||
|
||||
#endif // ABOUTDIALOG_H
|
||||
@@ -0,0 +1,22 @@
|
||||
# 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/>.
|
||||
|
||||
set(OLIVE_SOURCES
|
||||
${OLIVE_SOURCES}
|
||||
dialog/actionsearch/actionsearch.h
|
||||
dialog/actionsearch/actionsearch.cpp
|
||||
PARENT_SCOPE
|
||||
)
|
||||
@@ -0,0 +1,253 @@
|
||||
/***
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "actionsearch.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
#include <QMenuBar>
|
||||
#include <QLabel>
|
||||
|
||||
ActionSearch::ActionSearch(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
menu_bar_(nullptr)
|
||||
{
|
||||
// ActionSearch requires a parent widget
|
||||
Q_ASSERT(parent != nullptr);
|
||||
|
||||
// Set styling (object name is required for CSS specific to this object)
|
||||
setObjectName("ASDiag");
|
||||
setStyleSheet("#ASDiag{border: 2px solid #808080;}");
|
||||
|
||||
// Size proportionally to the parent (usually MainWindow).
|
||||
resize(parent->width()/3, parent->height()/3);
|
||||
|
||||
// Show dialog as a "popup", which will make the dialog close if the user clicks out of it.
|
||||
setWindowFlags(Qt::Popup);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
|
||||
// Construct the main entry text field.
|
||||
ActionSearchEntry* entry_field = new ActionSearchEntry(this);
|
||||
|
||||
// Set the main entry field font size to 1.2x its standard font size.
|
||||
QFont entry_field_font = entry_field->font();
|
||||
entry_field_font.setPointSize(qRound(entry_field_font.pointSize()*1.2));
|
||||
entry_field->setFont(entry_field_font);
|
||||
|
||||
// Set placeholder text for the main entry field
|
||||
entry_field->setPlaceholderText(tr("Search for action..."));
|
||||
|
||||
// Connect signals/slots
|
||||
connect(entry_field, SIGNAL(textChanged(const QString&)), this, SLOT(search_update(const QString &)));
|
||||
connect(entry_field, SIGNAL(returnPressed()), this, SLOT(perform_action()));
|
||||
|
||||
// moveSelectionUp() and moveSelectionDown() are emitted when the user pressed up or down on the text field.
|
||||
// We override it here to select the upper or lower item in the list.
|
||||
connect(entry_field, SIGNAL(moveSelectionUp()), this, SLOT(move_selection_up()));
|
||||
connect(entry_field, SIGNAL(moveSelectionDown()), this, SLOT(move_selection_down()));
|
||||
layout->addWidget(entry_field);
|
||||
|
||||
// Construct list of actions
|
||||
list_widget = new ActionSearchList(this);
|
||||
|
||||
// Set list's font to 1.2x its standard font size
|
||||
QFont list_widget_font = list_widget->font();
|
||||
list_widget_font.setPointSize(qRound(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()));
|
||||
|
||||
// Instantly focus on the entry field to allow for fully keyboard operation (if this popup was initiated by keyboard
|
||||
// shortcut for example).
|
||||
entry_field->setFocus();
|
||||
}
|
||||
|
||||
void ActionSearch::SetMenuBar(QMenuBar *menu_bar)
|
||||
{
|
||||
menu_bar_ = menu_bar;
|
||||
}
|
||||
|
||||
void ActionSearch::search_update(const QString &s, const QString &p, QMenu *parent)
|
||||
{
|
||||
// Do nothing if there's no menu bar to work with
|
||||
if (menu_bar_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// This function is recursive, using the `parent` parameter to loop through a menu's items. It functions in two
|
||||
// modes - the parent being NULL, meaning it'll get MainWindow's menubar and loop over its menus, and the parent
|
||||
// referring to a menu at which point it'll loop over its actions (and call itself recursively if it finds any
|
||||
// submenus).
|
||||
|
||||
if (parent == nullptr) {
|
||||
|
||||
// If parent is NULL, we'll pull from the MainWindow's menubar and call this recursively on all of its submenus
|
||||
// (and their submenus).
|
||||
|
||||
// We'll clear all the current items in the list since if we're here, we're just starting.
|
||||
list_widget->clear();
|
||||
|
||||
QList<QAction*> menus = menu_bar_->actions();
|
||||
|
||||
// Loop through all menus from the menubar and run this function on each one.
|
||||
for (int i=0;i<menus.size();i++) {
|
||||
QMenu* menu = menus.at(i)->menu();
|
||||
|
||||
search_update(s, p, menu);
|
||||
}
|
||||
|
||||
// Once we're here, all the recursion/item retrieval is complete. We auto-select the first item for better
|
||||
// keyboard-exclusive functionality.
|
||||
if (list_widget->count() > 0) {
|
||||
list_widget->item(0)->setSelected(true);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Parent was not NULL, so we loop over the actions in the menu we were given in `parent`.
|
||||
|
||||
// The list shows a '>' delimited hierarchy of the menus in which this action came from. We construct it here by
|
||||
// adding the current menu's text to the existing hierarchy (passed in `p`).
|
||||
QString menu_text;
|
||||
if (!p.isEmpty()) menu_text += p + " > ";
|
||||
menu_text += parent->title().replace("&", ""); // Strip out any &s used in menu action names
|
||||
|
||||
// Loop over the menu's actions
|
||||
QList<QAction*> actions = parent->actions();
|
||||
for (int i=0;i<actions.size();i++) {
|
||||
|
||||
QAction* a = actions.at(i);
|
||||
|
||||
// Ignore separator actions
|
||||
if (!a->isSeparator()) {
|
||||
|
||||
if (a->menu() != nullptr) {
|
||||
|
||||
// If the action is a menu, run this function recursively on it
|
||||
search_update(s, menu_text, a->menu());
|
||||
|
||||
} else {
|
||||
|
||||
// This is a valid non-separator non-menu action, so check it against the currently entered string.
|
||||
|
||||
// Strip out all &s from the action's name
|
||||
QString comp = a->text().replace("&", "");
|
||||
|
||||
// See if the action's name contains any of the currently entered string
|
||||
if (comp.contains(s, Qt::CaseInsensitive)) {
|
||||
|
||||
// If so, we add it to the list widget.
|
||||
QListWidgetItem* item = new QListWidgetItem(QString("%1\n(%2)").arg(comp, menu_text), list_widget);
|
||||
|
||||
// Add a pointer to the original QAction in the item's data
|
||||
item->setData(Qt::UserRole+1, reinterpret_cast<quintptr>(a));
|
||||
|
||||
list_widget->addItem(item);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActionSearch::perform_action() {
|
||||
|
||||
// Loop over all the items in the list and if we find one that's selected, we trigger it.
|
||||
QList<QListWidgetItem*> selected_items = list_widget->selectedItems();
|
||||
if (list_widget->count() > 0 && selected_items.size() > 0) {
|
||||
|
||||
QListWidgetItem* item = selected_items.at(0);
|
||||
|
||||
// Get QAction pointer from item's data
|
||||
QAction* a = reinterpret_cast<QAction*>(item->data(Qt::UserRole+1).value<quintptr>());
|
||||
|
||||
a->trigger();
|
||||
|
||||
}
|
||||
|
||||
// Close this popup
|
||||
accept();
|
||||
|
||||
}
|
||||
|
||||
void ActionSearch::move_selection_up() {
|
||||
|
||||
// Here we loop over all the items to find the currently selected one, and then select the one above it. We start
|
||||
// iterating at 1 (instead of 0) to efficiently ignore the first item (since the selection can't go below the very
|
||||
// bottom item).
|
||||
|
||||
int lim = list_widget->count();
|
||||
for (int i=1;i<lim;i++) {
|
||||
if (list_widget->item(i)->isSelected()) {
|
||||
list_widget->item(i-1)->setSelected(true);
|
||||
list_widget->scrollToItem(list_widget->item(i-1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActionSearch::move_selection_down() {
|
||||
|
||||
// Here we loop over all the items to find the currently selected one, and then select the one below it. We limit it
|
||||
// one entry before count() to efficiently ignore the item at the end (since the selection can't go below the very
|
||||
// bottom item).
|
||||
|
||||
int lim = list_widget->count()-1;
|
||||
for (int i=0;i<lim;i++) {
|
||||
if (list_widget->item(i)->isSelected()) {
|
||||
list_widget->item(i+1)->setSelected(true);
|
||||
list_widget->scrollToItem(list_widget->item(i+1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ActionSearchEntry::ActionSearchEntry(QWidget *parent) : QLineEdit(parent) {}
|
||||
|
||||
void ActionSearchEntry::keyPressEvent(QKeyEvent * event) {
|
||||
|
||||
// Listen for up/down, otherwise pass the key event to the base class.
|
||||
|
||||
switch (event->key()) {
|
||||
case Qt::Key_Up:
|
||||
emit moveSelectionUp();
|
||||
break;
|
||||
case Qt::Key_Down:
|
||||
emit moveSelectionDown();
|
||||
break;
|
||||
default:
|
||||
QLineEdit::keyPressEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ActionSearchList::ActionSearchList(QWidget *parent) : QListWidget(parent) {}
|
||||
|
||||
void ActionSearchList::mouseDoubleClickEvent(QMouseEvent *) {
|
||||
|
||||
// Indiscriminately emit a signal on any double click
|
||||
emit dbl_click();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/***
|
||||
|
||||
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 ACTIONSEARCH_H
|
||||
#define ACTIONSEARCH_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QListWidget>
|
||||
#include <QMenu>
|
||||
#include <QMenuBar>
|
||||
|
||||
class ActionSearchList;
|
||||
|
||||
/**
|
||||
* @brief The ActionSearch class
|
||||
*
|
||||
* A popup window (accessible through Help > Action Search) that allows users to search for a menu command by typing
|
||||
* rather than browsing through the menu bar. This can be created from anywhere provided olive::MainWindow is valid.
|
||||
*/
|
||||
class ActionSearch : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief ActionSearch Constructor
|
||||
*
|
||||
* Create ActionSearch popup.
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow.
|
||||
*/
|
||||
ActionSearch(QWidget* parent);
|
||||
|
||||
/**
|
||||
* @brief Set the menu bar to use in this action search
|
||||
*/
|
||||
void SetMenuBar(QMenuBar* menu_bar);
|
||||
private slots:
|
||||
/**
|
||||
* @brief Update the list of actions according to a search query
|
||||
*
|
||||
* This function adds/removes actions in the action list according to a given search query entered by the user.
|
||||
*
|
||||
* To loop over the menubar and all of its menus and submenus, this function will call itself recursively. As such
|
||||
* some of its parameters do not need to be set externally, as these will be set by the function itself as it calls
|
||||
* itself.
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The search text. This is the only parameter that should be set externally.
|
||||
*
|
||||
* @param p
|
||||
*
|
||||
* The current parent hierarchy. In most cases, this should be left as nullptr when called externally.
|
||||
* search_update() will fill this automatically as it needs while calling itself recursively.
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* The current menu to loop over. In most cases, this should be left as nullptr when called externally.
|
||||
* search_update() will fill this automatically as it needs while calling itself recursively.
|
||||
*/
|
||||
void search_update(const QString& s, const QString &p = nullptr, QMenu *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Perform the currently selected action
|
||||
*
|
||||
* Usually triggered by pressing Enter on the ActionSearchEntry field, this will trigger whatever action is currently
|
||||
* highlighted and then close this popup. If no entries are highlighted (i.e. the list is empty), no action is
|
||||
* triggered and the popup closes anyway.
|
||||
*/
|
||||
void perform_action();
|
||||
|
||||
/**
|
||||
* @brief Move selection up
|
||||
*
|
||||
* A slot for pressing up on the ActionSearchEntry field. Moves the selection in the list up once. If the
|
||||
* selection is already at the top of the list, this is a no-op.
|
||||
*/
|
||||
void move_selection_up();
|
||||
|
||||
/**
|
||||
* @brief Move selection down
|
||||
*
|
||||
* A slot for pressing down on the ActionSearchEntry field. Moves the selection in the list down once. If the
|
||||
* selection is already at the bottom of the list, this is a no-op.
|
||||
*/
|
||||
void move_selection_down();
|
||||
private:
|
||||
/**
|
||||
* @brief Main widget that shows the list of commands
|
||||
*/
|
||||
ActionSearchList* list_widget;
|
||||
|
||||
/**
|
||||
* @brief Attached menu bar object
|
||||
*/
|
||||
QMenuBar* menu_bar_;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ActionSearchList class
|
||||
*
|
||||
* Simple wrapper around QListWidget that emits a signal when an item is double clicked that ActionSearch connects
|
||||
* to a slot that triggers the currently selected action.
|
||||
*/
|
||||
class ActionSearchList : public QListWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief ActionSearchList Constructor
|
||||
* @param parent
|
||||
*
|
||||
* Usually ActionSearch.
|
||||
*/
|
||||
ActionSearchList(QWidget* parent);
|
||||
protected:
|
||||
/**
|
||||
* @brief Override of QListWidget's double click event that emits a signal.
|
||||
*/
|
||||
void mouseDoubleClickEvent(QMouseEvent *);
|
||||
signals:
|
||||
/**
|
||||
* @brief Signal emitted when a QListWidget item is double clicked.
|
||||
*/
|
||||
void dbl_click();
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The ActionSearchEntry class
|
||||
*
|
||||
* Simple wrapper around QLineEdit that emits signals when the up or down arrow keys are pressed so that ActionSearch
|
||||
* can connect them to moving the current selection up or down.
|
||||
*/
|
||||
class ActionSearchEntry : public QLineEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief ActionSearchEntry
|
||||
* @param parent
|
||||
*
|
||||
* Usually ActionSearch.
|
||||
*/
|
||||
ActionSearchEntry(QWidget* parent);
|
||||
protected:
|
||||
/**
|
||||
* @brief Override of QLineEdit's key press event that listens for up/down key presses.
|
||||
* @param event
|
||||
*/
|
||||
void keyPressEvent(QKeyEvent * event);
|
||||
signals:
|
||||
/**
|
||||
* @brief Emitted when the user presses the up arrow key.
|
||||
*/
|
||||
void moveSelectionUp();
|
||||
|
||||
/**
|
||||
* @brief Emitted when the user presses the down arrow key.
|
||||
*/
|
||||
void moveSelectionDown();
|
||||
};
|
||||
|
||||
#endif // ACTIONSEARCH_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,432 @@
|
||||
/***
|
||||
|
||||
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 PREFERENCESDIALOG_H
|
||||
#define PREFERENCESDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include <QKeySequenceEdit>
|
||||
#include <QMenuBar>
|
||||
#include <QLineEdit>
|
||||
#include <QComboBox>
|
||||
#include <QRadioButton>
|
||||
#include <QTreeWidget>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QMenu>
|
||||
#include <QCheckBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QSpinBox>
|
||||
#include <OpenColorIO/OpenColorIO.h>
|
||||
namespace OCIO = OCIO_NAMESPACE::v1;
|
||||
|
||||
#include "timeline/sequence.h"
|
||||
|
||||
class KeySequenceEditor;
|
||||
|
||||
/**
|
||||
* @brief The PreferencesDialog class
|
||||
*
|
||||
* A dialog for the global application settings. Mostly an interface for Config. Can be loaded from any part of the
|
||||
* application.
|
||||
*/
|
||||
class PreferencesDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief PreferencesDialog Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent. Usually MainWindow.
|
||||
*/
|
||||
explicit PreferencesDialog(QWidget *parent = nullptr);
|
||||
|
||||
private slots:
|
||||
/**
|
||||
* @brief Override of accept to save preferences to Config.
|
||||
*/
|
||||
virtual void accept() override;
|
||||
|
||||
/**
|
||||
* @brief Reset all selected shortcuts in keyboard_tree to their defaults
|
||||
*/
|
||||
void reset_default_shortcut();
|
||||
|
||||
/**
|
||||
* @brief Reset all shortcuts indiscriminately to their defaults
|
||||
*
|
||||
* This is safe to call directly as it'll ask the user if they wish to do so before it resets.
|
||||
*/
|
||||
void reset_all_shortcuts();
|
||||
|
||||
/**
|
||||
* @brief Shows/hides shortcut entries according to a shortcut query.
|
||||
*
|
||||
* This function can be directly connected to QLineEdit::textChanged() for simplicity.
|
||||
*
|
||||
* @param s
|
||||
*
|
||||
* The search query to compare shortcut names to.
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* This is used as the function calls itself recursively to traverse the menu item hierarchy. This should be left as
|
||||
* nullptr when called externally.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* Value used as function calls itself recursively to determine if a menu parent has any children that are not hidden.
|
||||
* If so, TRUE is returned so the parent is shown too (even if it doesn't match the search query). If not, FALSE is
|
||||
* returned so the parent is hidden.
|
||||
*/
|
||||
bool refine_shortcut_list(const QString &s, QTreeWidgetItem* parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief Show a file dialog to load an external shortcut preset from file
|
||||
*/
|
||||
void load_shortcut_file();
|
||||
|
||||
/**
|
||||
* @brief Show a file dialog to save an external shortcut preset from file
|
||||
*/
|
||||
void save_shortcut_file();
|
||||
|
||||
/**
|
||||
* @brief Delete all previews (waveform and thumbnail cache)
|
||||
*/
|
||||
void delete_all_previews();
|
||||
|
||||
// Browse for file functionns
|
||||
/**
|
||||
* @brief Show a file dialog to browse for an external CSS file to load for styling the application.
|
||||
*/
|
||||
void browse_css_file();
|
||||
void browse_ocio_config();
|
||||
|
||||
// OCIO function
|
||||
void update_ocio_view_menu();
|
||||
void update_ocio_view_menu(OCIO::ConstConfigRcPtr config);
|
||||
void update_ocio_config(const QString&);
|
||||
|
||||
/**
|
||||
* @brief Shows a NewSequenceDialog attached to default_sequence
|
||||
*/
|
||||
void edit_default_sequence_settings();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* @brief Create and arrange all UI widgets
|
||||
*/
|
||||
void setup_ui();
|
||||
|
||||
/**
|
||||
* @brief Populate keyboard shortcut panel with keyboard shortcuts from the menu bar
|
||||
*
|
||||
* @param menu
|
||||
*
|
||||
* A reference to the main application's menu bar. Usually MainWindow::menuBar().
|
||||
*/
|
||||
void setup_kbd_shortcuts(QMenuBar* menu);
|
||||
|
||||
/**
|
||||
* @brief Internal function called by setup_kbd_shortcuts() to traverse down the menu bar's hierarchy and populate the
|
||||
* shortcut panel.
|
||||
*
|
||||
* This function will call itself recursively as it finds submenus belong to the menu provided. It will also create
|
||||
* QTreeWidgetItems as children of the parent item provided, either using them as parents themselves for submenus
|
||||
* or attaching a KeySequenceEditor to them for shortcut editing.
|
||||
*
|
||||
* @param menu
|
||||
*
|
||||
* The current menu to traverse down.
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* The parent item to add QTreeWidgetItems to.
|
||||
*/
|
||||
void setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent);
|
||||
|
||||
enum PreviewDeleteTypes {
|
||||
DELETE_NONE,
|
||||
DELETE_THUMBNAILS,
|
||||
DELETE_WAVEFORMS,
|
||||
DELETE_BOTH
|
||||
};
|
||||
|
||||
// used to delete previews
|
||||
// type can be: 't' for thumbnails, 'w' for waveforms, or 1 for all
|
||||
/**
|
||||
* @brief Delete disk cached preview files (thumbnails, waveforms, etc.)
|
||||
*
|
||||
* @param type
|
||||
*
|
||||
* The types of previews to delete.
|
||||
*/
|
||||
void delete_previews(PreviewDeleteTypes type);
|
||||
|
||||
void populate_ocio_menus(OCIO::ConstConfigRcPtr config);
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the CSS filename
|
||||
*/
|
||||
QLineEdit* custom_css_fn;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the list of extensions to detect image sequences from
|
||||
*/
|
||||
QLineEdit* imgSeqFormatEdit;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the recording channels
|
||||
*/
|
||||
QComboBox* recordingComboBox;
|
||||
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing keyboard shortcuts
|
||||
*/
|
||||
QTreeWidget* keyboard_tree;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the upcoming queue size
|
||||
*/
|
||||
QDoubleSpinBox* upcoming_queue_spinbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the upcoming queue type
|
||||
*/
|
||||
QComboBox* upcoming_queue_type;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the previous queue size
|
||||
*/
|
||||
QDoubleSpinBox* previous_queue_spinbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the previous queue type
|
||||
*/
|
||||
QComboBox* previous_queue_type;
|
||||
|
||||
/**
|
||||
* @brief UI widget for editing the size of textboxes in the EffectControls panel
|
||||
*/
|
||||
QSpinBox* effect_textbox_lines_field;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the output audio device
|
||||
*/
|
||||
QComboBox* audio_output_devices;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the input audio device
|
||||
*/
|
||||
QComboBox* audio_input_devices;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the audio sampling rates
|
||||
*/
|
||||
QComboBox* audio_sample_rate;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the UI language
|
||||
*/
|
||||
QComboBox* language_combobox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the resolution of the thumbnails to generate
|
||||
*/
|
||||
QSpinBox* thumbnail_res_spinbox;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the resolution of the waveforms to generate
|
||||
*/
|
||||
QSpinBox* waveform_res_spinbox;
|
||||
|
||||
QCheckBox* enable_color_management;
|
||||
QLineEdit* ocio_config_file;
|
||||
QComboBox* ocio_default_input;
|
||||
QComboBox* ocio_display;
|
||||
QComboBox* ocio_view;
|
||||
QComboBox* ocio_look;
|
||||
QComboBox* playback_bit_depth;
|
||||
QComboBox* export_bit_depth;
|
||||
|
||||
/**
|
||||
* @brief UI widget for selecting the current UI style
|
||||
*/
|
||||
QComboBox* ui_style;
|
||||
|
||||
/**
|
||||
* @brief Stored default Sequence object
|
||||
*
|
||||
* Default Sequence settings are loaded into an actual Sequence object that can be loaded into NewSequenceDialog
|
||||
* for the sake of familiarity with the user.
|
||||
*/
|
||||
Sequence default_sequence;
|
||||
|
||||
/**
|
||||
* @brief List of keyboard shortcut actions that can be triggered (links with key_shortcut_items and
|
||||
* key_shortcut_fields)
|
||||
*/
|
||||
QVector<QAction*> key_shortcut_actions;
|
||||
|
||||
/**
|
||||
* @brief List of keyboard shortcut items in keyboard_tree corresponding to existing actions (links with
|
||||
* key_shortcut_actions and key_shortcut_fields)
|
||||
*/
|
||||
QVector<QTreeWidgetItem*> key_shortcut_items;
|
||||
|
||||
/**
|
||||
* @brief List of keyboard shortcut editing fields in keyboard_tree corresponding to existing actions (links with
|
||||
* key_shortcut_actions and key_shortcut_fields)
|
||||
*/
|
||||
QVector<KeySequenceEditor*> key_shortcut_fields;
|
||||
|
||||
/**
|
||||
* @brief Tests an OpenColorIO configuration file to determine whether it's valid and throws a messagebox if not
|
||||
*
|
||||
* @param url
|
||||
*
|
||||
* URL to the OpenColorIO configuration file.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* A OCIO::ConstConfigRcPtr config pointer if the configuration file is valid, nullptr if not.
|
||||
*/
|
||||
OCIO::ConstConfigRcPtr TestOCIOConfig(const QString& url);
|
||||
|
||||
/**
|
||||
* @brief Add an automated QCheckBox+boolean value pair
|
||||
*
|
||||
* Many preferences are simple true/false (or on/off) options. Rather than adding a QCheckBox for each one and
|
||||
* manually setting its checked value to the configuration setting (and vice versa when saving), this convenience
|
||||
* function will add it to an automated set of checkboxes, automatically setting the checked state to the current
|
||||
* setting, and then saving the new checked state back to the setting when the user accepts the changes (clicks OK).
|
||||
*
|
||||
* @param ui
|
||||
*
|
||||
* A valid QCheckBox item. This function does not take ownership of the QWidget or place it in a layout anywhere.
|
||||
*
|
||||
* @param value
|
||||
*
|
||||
* A pointer to the Boolean value this QCheckBox should be shared with. The QCheckBox widget's checked state will be
|
||||
* set to the value of this pointer.
|
||||
*
|
||||
* @param restart_required
|
||||
*
|
||||
* Defaults to FALSE, set this to TRUE if changing this setting should prompt the user for a restart of Olive before
|
||||
* the setting change takes effect.
|
||||
*/
|
||||
void AddBoolPair(QCheckBox* ui, bool* value, bool restart_required = false);
|
||||
|
||||
/**
|
||||
* @brief Internal array managed by AddBoolPair(). Do not access this directly.
|
||||
*/
|
||||
QVector<QCheckBox*> bool_ui;
|
||||
|
||||
/**
|
||||
* @brief Internal array managed by AddBoolPair(). Do not access this directly.
|
||||
*/
|
||||
QVector<bool*> bool_value;
|
||||
|
||||
/**
|
||||
* @brief Internal array managed by AddBoolPair(). Do not access this directly.
|
||||
*/
|
||||
QVector<bool> bool_restart_required;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief The KeySequenceEditor class
|
||||
*
|
||||
* Simple derived class of QKeySequenceEdit that attaches to a QAction and provides functions for transferring
|
||||
* keyboard shortcuts to and from it.
|
||||
*/
|
||||
class KeySequenceEditor : public QKeySequenceEdit {
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief KeySequenceEditor Constructor
|
||||
*
|
||||
* @param parent
|
||||
*
|
||||
* QWidget parent.
|
||||
*
|
||||
* @param a
|
||||
*
|
||||
* The QAction to link to. This cannot be changed throughout the lifetime of a KeySequenceEditor.
|
||||
*/
|
||||
KeySequenceEditor(QWidget *parent, QAction* a);
|
||||
|
||||
/**
|
||||
* @brief Sets the attached QAction's shortcut to the shortcut entered in this field.
|
||||
*
|
||||
* This is not done automatically in case the user cancels out of the Preferences dialog, in which case the
|
||||
* expectation is that the changes made will not be saved. Therefore, this needs to be triggered manually when
|
||||
* PreferencesDialog saves.
|
||||
*/
|
||||
void set_action_shortcut();
|
||||
|
||||
/**
|
||||
* @brief Set this shortcut back to the QAction's default shortcut
|
||||
*
|
||||
* Each QAction contains the default shortcut in its `property("default")` and can be used to restore the default
|
||||
* "hard-coded" shortcut with this function.
|
||||
*
|
||||
* This function does not save the default shortcut back into the QAction, it simply loads the default shortcut from
|
||||
* the QAction into this edit field. To save it into the QAction, it's necessary to call set_action_shortcut() after
|
||||
* calling this function.
|
||||
*/
|
||||
void reset_to_default();
|
||||
|
||||
/**
|
||||
* @brief Return attached QAction's unique ID
|
||||
*
|
||||
* Each of Olive's menu actions has a unique string ID (that, unlike the text, is not translated) for matching with
|
||||
* an external shortcut configuration file. The ID is stored in the QAction's `property("id")`. This function returns
|
||||
* that ID.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* The QAction's unique ID.
|
||||
*/
|
||||
QString action_name();
|
||||
|
||||
/**
|
||||
* @brief Serialize this shortcut entry into a string that can be saved to a file
|
||||
*
|
||||
* @return
|
||||
*
|
||||
* A string serialization of this shortcut. The format is "[ID]\t[SEQUENCE]" where [ID] is the attached QAction's
|
||||
* unique identifier and [SEQUENCE] is the current keyboard shortcut in the field (NOT necessarily the shortcut in
|
||||
* the QAction). If the entered shortcut is the same as the QAction's default shortcut, the return value is empty
|
||||
* because a default shortcut does not need to be saved to a file.
|
||||
*/
|
||||
QString export_shortcut();
|
||||
private:
|
||||
/**
|
||||
* @brief Internal reference to the linked QAction
|
||||
*/
|
||||
QAction* action;
|
||||
};
|
||||
|
||||
#endif // PREFERENCESDIALOG_H
|
||||
@@ -36,6 +36,11 @@ void PanelManager::DeleteAllPanels()
|
||||
focus_history_.clear();
|
||||
}
|
||||
|
||||
const QList<PanelWidget *> &PanelManager::panels()
|
||||
{
|
||||
return focus_history_;
|
||||
}
|
||||
|
||||
PanelWidget *PanelManager::CurrentlyFocused() const
|
||||
{
|
||||
if (focus_history_.isEmpty()) {
|
||||
|
||||
@@ -47,8 +47,20 @@ class PanelManager : public QObject
|
||||
public:
|
||||
PanelManager(QObject* parent);
|
||||
|
||||
/**
|
||||
* @brief Destroy all panels
|
||||
*
|
||||
* Should only be used on application exit to cleanly free all panels.
|
||||
*/
|
||||
void DeleteAllPanels();
|
||||
|
||||
/**
|
||||
* @brief Get a list of all existing panels
|
||||
*
|
||||
* Panels are ordered from most recently focused to least recently focused.
|
||||
*/
|
||||
const QList<PanelWidget*>& panels();
|
||||
|
||||
/**
|
||||
* @brief Return the currently focused widget, or nullptr if nothing is focused
|
||||
*/
|
||||
|
||||
@@ -119,6 +119,16 @@ void TimelinePanel::EditToOut()
|
||||
view_->EditToOut();
|
||||
}
|
||||
|
||||
void TimelinePanel::GoToPrevCut()
|
||||
{
|
||||
view_->GoToPrevCut();
|
||||
}
|
||||
|
||||
void TimelinePanel::GoToNextCut()
|
||||
{
|
||||
view_->GoToNextCut();
|
||||
}
|
||||
|
||||
void TimelinePanel::changeEvent(QEvent *e)
|
||||
{
|
||||
if (e->type() == QEvent::LanguageChange) {
|
||||
|
||||
@@ -55,6 +55,10 @@ public:
|
||||
|
||||
virtual void EditToOut() override;
|
||||
|
||||
virtual void GoToPrevCut() override;
|
||||
|
||||
virtual void GoToNextCut() override;
|
||||
|
||||
public slots:
|
||||
void SetTimebase(const rational& timebase);
|
||||
|
||||
|
||||
@@ -69,6 +69,21 @@ void ViewerPanel::GoToEnd()
|
||||
viewer_->GoToEnd();
|
||||
}
|
||||
|
||||
void ViewerPanel::ShuttleLeft()
|
||||
{
|
||||
viewer_->ShuttleLeft();
|
||||
}
|
||||
|
||||
void ViewerPanel::ShuttleStop()
|
||||
{
|
||||
viewer_->ShuttleStop();
|
||||
}
|
||||
|
||||
void ViewerPanel::ShuttleRight()
|
||||
{
|
||||
viewer_->ShuttleRight();
|
||||
}
|
||||
|
||||
void ViewerPanel::SetTimebase(const rational &timebase)
|
||||
{
|
||||
viewer_->SetTimebase(timebase);
|
||||
|
||||
@@ -48,6 +48,12 @@ public:
|
||||
|
||||
virtual void GoToEnd() override;
|
||||
|
||||
virtual void ShuttleLeft() override;
|
||||
|
||||
virtual void ShuttleStop() override;
|
||||
|
||||
virtual void ShuttleRight() override;
|
||||
|
||||
void SetTimebase(const rational& timebase);
|
||||
|
||||
void ConnectViewerNode(ViewerOutput* node);
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/***
|
||||
|
||||
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/>.
|
||||
|
||||
***/
|
||||
|
||||
#include "undostack.h"
|
||||
|
||||
OliveUndoStack olive::undo_stack;
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
/***
|
||||
|
||||
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 UNDOSTACK_H
|
||||
#define UNDOSTACK_H
|
||||
|
||||
|
||||
@@ -96,6 +96,16 @@ public:
|
||||
|
||||
virtual void EditToOut(){}
|
||||
|
||||
virtual void ShuttleLeft(){}
|
||||
|
||||
virtual void ShuttleStop(){}
|
||||
|
||||
virtual void ShuttleRight(){}
|
||||
|
||||
virtual void GoToPrevCut(){}
|
||||
|
||||
virtual void GoToNextCut(){}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Set panel's title
|
||||
|
||||
@@ -238,6 +238,69 @@ void TimelineView::EditToOut()
|
||||
RippleEditTo(olive::timeline::kTrimOut, true);
|
||||
}
|
||||
|
||||
void TimelineView::GoToPrevCut()
|
||||
{
|
||||
if (timeline_node_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (playhead_ == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t closest_cut = 0;
|
||||
|
||||
foreach (TrackOutput* track, timeline_node_->Tracks()) {
|
||||
int64_t this_track_closest_cut = 0;
|
||||
|
||||
foreach (Block* block, track->Blocks()) {
|
||||
int64_t block_out_ts = olive::time_to_timestamp(block->out(), timebase_);
|
||||
|
||||
if (block_out_ts < playhead_) {
|
||||
this_track_closest_cut = block_out_ts;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closest_cut = qMax(closest_cut, this_track_closest_cut);
|
||||
}
|
||||
|
||||
UserSetTime(closest_cut);
|
||||
}
|
||||
|
||||
void TimelineView::GoToNextCut()
|
||||
{
|
||||
if (timeline_node_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int64_t closest_cut = INT64_MAX;
|
||||
|
||||
foreach (TrackOutput* track, timeline_node_->Tracks()) {
|
||||
int64_t this_track_closest_cut = olive::time_to_timestamp(track->in(), timebase_);
|
||||
|
||||
if (this_track_closest_cut <= playhead_) {
|
||||
this_track_closest_cut = INT64_MAX;
|
||||
}
|
||||
|
||||
foreach (Block* block, track->Blocks()) {
|
||||
int64_t block_in_ts = olive::time_to_timestamp(block->in(), timebase_);
|
||||
|
||||
if (block_in_ts > playhead_) {
|
||||
this_track_closest_cut = block_in_ts;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
closest_cut = qMin(closest_cut, this_track_closest_cut);
|
||||
}
|
||||
|
||||
if (closest_cut < INT64_MAX) {
|
||||
UserSetTime(closest_cut);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineView::SetTime(const int64_t time)
|
||||
{
|
||||
playhead_ = time;
|
||||
@@ -456,11 +519,16 @@ void TimelineView::RippleEditTo(olive::timeline::MovementMode mode, bool insert_
|
||||
|
||||
if (mode == olive::timeline::kTrimIn && !insert_gaps) {
|
||||
int64_t new_time = olive::time_to_timestamp(closest_point_to_playhead, timebase_);
|
||||
SetTime(new_time);
|
||||
emit TimeChanged(new_time);
|
||||
UserSetTime(new_time);
|
||||
}
|
||||
}
|
||||
|
||||
void TimelineView::UserSetTime(const int64_t &time)
|
||||
{
|
||||
SetTime(time);
|
||||
emit TimeChanged(time);
|
||||
}
|
||||
|
||||
void TimelineView::BlockChanged()
|
||||
{
|
||||
TimelineViewRect* rect = block_items_[static_cast<Block*>(sender())];
|
||||
|
||||
@@ -64,6 +64,10 @@ public:
|
||||
|
||||
void EditToOut();
|
||||
|
||||
void GoToPrevCut();
|
||||
|
||||
void GoToNextCut();
|
||||
|
||||
public slots:
|
||||
void SetTimebase(const rational& timebase);
|
||||
|
||||
@@ -358,6 +362,8 @@ private:
|
||||
|
||||
void RippleEditTo(olive::timeline::MovementMode mode, bool insert_gaps);
|
||||
|
||||
void UserSetTime(const int64_t& time);
|
||||
|
||||
QGraphicsScene scene_;
|
||||
|
||||
double scale_;
|
||||
|
||||
@@ -31,7 +31,8 @@
|
||||
|
||||
ViewerWidget::ViewerWidget(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
viewer_node_(nullptr)
|
||||
viewer_node_(nullptr),
|
||||
playback_speed_(0)
|
||||
{
|
||||
// Set up main layout
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
@@ -181,6 +182,24 @@ void ViewerWidget::UpdateTextureFromNode(const rational& time)
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::PlayInternal(int speed)
|
||||
{
|
||||
Q_ASSERT(speed != 0);
|
||||
|
||||
if (time_base_.isNull()) {
|
||||
qWarning() << "ViewerWidget can't play with an invalid timebase";
|
||||
return;
|
||||
}
|
||||
|
||||
start_msec_ = QDateTime::currentMSecsSinceEpoch();
|
||||
start_timestamp_ = ruler_->GetTime();
|
||||
playback_speed_ = speed;
|
||||
|
||||
playback_timer_.start();
|
||||
|
||||
controls_->ShowPauseButton();
|
||||
}
|
||||
|
||||
void ViewerWidget::RulerTimeChange(int64_t i)
|
||||
{
|
||||
Pause();
|
||||
@@ -190,17 +209,7 @@ void ViewerWidget::RulerTimeChange(int64_t i)
|
||||
|
||||
void ViewerWidget::Play()
|
||||
{
|
||||
if (time_base_.isNull()) {
|
||||
qWarning() << "ViewerWidget can't play with an invalid timebase";
|
||||
return;
|
||||
}
|
||||
|
||||
start_msec_ = QDateTime::currentMSecsSinceEpoch();
|
||||
start_timestamp_ = ruler_->GetTime();
|
||||
|
||||
playback_timer_.start();
|
||||
|
||||
controls_->ShowPauseButton();
|
||||
PlayInternal(1);
|
||||
}
|
||||
|
||||
void ViewerWidget::Pause()
|
||||
@@ -208,6 +217,8 @@ void ViewerWidget::Pause()
|
||||
playback_timer_.stop();
|
||||
|
||||
controls_->ShowPlayButton();
|
||||
|
||||
playback_speed_ = 0;
|
||||
}
|
||||
|
||||
void ViewerWidget::GoToStart()
|
||||
@@ -238,13 +249,55 @@ void ViewerWidget::GoToEnd()
|
||||
qWarning() << "No end frame support yet";
|
||||
}
|
||||
|
||||
void ViewerWidget::ShuttleLeft()
|
||||
{
|
||||
int current_speed = playback_speed_;
|
||||
|
||||
if (current_speed != 0) {
|
||||
Pause();
|
||||
}
|
||||
|
||||
current_speed--;
|
||||
|
||||
if (current_speed != 0) {
|
||||
PlayInternal(current_speed);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::ShuttleStop()
|
||||
{
|
||||
Pause();
|
||||
}
|
||||
|
||||
void ViewerWidget::ShuttleRight()
|
||||
{
|
||||
int current_speed = playback_speed_;
|
||||
|
||||
if (current_speed != 0) {
|
||||
Pause();
|
||||
}
|
||||
|
||||
current_speed++;
|
||||
|
||||
if (current_speed != 0) {
|
||||
PlayInternal(current_speed);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewerWidget::PlaybackTimerUpdate()
|
||||
{
|
||||
int64_t real_time = QDateTime::currentMSecsSinceEpoch() - start_msec_;
|
||||
|
||||
int64_t frames_since_start = qRound(static_cast<double>(real_time) / (time_base_dbl_ * 1000));
|
||||
|
||||
SetTime(start_timestamp_ + frames_since_start);
|
||||
int64_t current_time = start_timestamp_ + frames_since_start * playback_speed_;
|
||||
|
||||
if (current_time < 0) {
|
||||
current_time = 0;
|
||||
Pause();
|
||||
}
|
||||
|
||||
SetTime(current_time);
|
||||
}
|
||||
|
||||
void ViewerWidget::ViewerNodeChangedBetween(const rational &start, const rational &end)
|
||||
|
||||
@@ -86,6 +86,12 @@ public slots:
|
||||
|
||||
void GoToEnd();
|
||||
|
||||
void ShuttleLeft();
|
||||
|
||||
void ShuttleStop();
|
||||
|
||||
void ShuttleRight();
|
||||
|
||||
signals:
|
||||
void TimeChanged(const rational&);
|
||||
|
||||
@@ -97,6 +103,8 @@ private:
|
||||
|
||||
void UpdateTextureFromNode(const rational &time);
|
||||
|
||||
void PlayInternal(int speed);
|
||||
|
||||
ViewerGLWidget* gl_widget_;
|
||||
|
||||
PlaybackControls* controls_;
|
||||
@@ -116,6 +124,8 @@ private:
|
||||
|
||||
ViewerOutput* viewer_node_;
|
||||
|
||||
int playback_speed_;
|
||||
|
||||
private slots:
|
||||
void RulerTimeChange(int64_t);
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <QEvent>
|
||||
|
||||
#include "core.h"
|
||||
#include "dialog/actionsearch/actionsearch.h"
|
||||
#include "panel/panelmanager.h"
|
||||
#include "tool/tool.h"
|
||||
#include "ui/style/style.h"
|
||||
@@ -169,8 +170,8 @@ MainMenu::MainMenu(QMainWindow *parent) :
|
||||
|
||||
playback_menu_->addSeparator();
|
||||
|
||||
playback_prevcut_item_ = playback_menu_->AddItem("prevcut", nullptr, nullptr, "Up");
|
||||
playback_nextcut_item_ = playback_menu_->AddItem("nextcut", nullptr, nullptr, "Down");
|
||||
playback_prevcut_item_ = playback_menu_->AddItem("prevcut", this, SLOT(GoToPrevCutTriggered()), "Up");
|
||||
playback_nextcut_item_ = playback_menu_->AddItem("nextcut", this, SLOT(GoToNextCutTriggered()), "Down");
|
||||
|
||||
playback_menu_->addSeparator();
|
||||
|
||||
@@ -179,9 +180,9 @@ MainMenu::MainMenu(QMainWindow *parent) :
|
||||
|
||||
playback_menu_->addSeparator();
|
||||
|
||||
playback_shuttleleft_item_ = playback_menu_->AddItem("decspeed", nullptr, nullptr, "J");
|
||||
playback_shuttlestop_item_ = playback_menu_->AddItem("pause", nullptr, nullptr, "K");
|
||||
playback_shuttleright_item_ = playback_menu_->AddItem("incspeed", nullptr, nullptr, "L");
|
||||
playback_shuttleleft_item_ = playback_menu_->AddItem("decspeed", this, SLOT(ShuttleLeftTriggered()), "J");
|
||||
playback_shuttlestop_item_ = playback_menu_->AddItem("pause", this, SLOT(ShuttleStopTriggered()), "K");
|
||||
playback_shuttleright_item_ = playback_menu_->AddItem("incspeed", this, SLOT(ShuttleRightTriggered()), "L");
|
||||
|
||||
playback_menu_->addSeparator();
|
||||
|
||||
@@ -193,7 +194,7 @@ MainMenu::MainMenu(QMainWindow *parent) :
|
||||
//
|
||||
window_menu_ = new Menu(this, this, SLOT(WindowMenuAboutToShow()));
|
||||
window_menu_separator_ = window_menu_->addSeparator();
|
||||
window_maximize_panel_item_ = window_menu_->AddItem("maximizepanel", nullptr, nullptr, "`");
|
||||
window_maximize_panel_item_ = window_menu_->AddItem("maximizepanel", parent, SLOT(ToggleMaximizedPanel()), "`");
|
||||
window_lock_layout_item_ = window_menu_->AddItem("lockpanels", olive::panel_manager, SLOT(SetPanelsLocked(bool)));
|
||||
window_lock_layout_item_->setCheckable(true);
|
||||
window_menu_->addSeparator();
|
||||
@@ -294,11 +295,11 @@ MainMenu::MainMenu(QMainWindow *parent) :
|
||||
// HELP MENU
|
||||
//
|
||||
help_menu_ = new Menu(this);
|
||||
help_action_search_item_ = help_menu_->AddItem("actionsearch", nullptr, nullptr, "/");
|
||||
help_action_search_item_ = help_menu_->AddItem("actionsearch", this, SLOT(ActionSearchTriggered()), "/");
|
||||
help_menu_->addSeparator();
|
||||
help_debug_log_item_ = help_menu_->AddItem("debuglog", nullptr, nullptr);
|
||||
help_menu_->addSeparator();
|
||||
help_about_item_ = help_menu_->AddItem("about", nullptr, nullptr);
|
||||
help_about_item_ = help_menu_->AddItem("about", &olive::core, SLOT(DialogAboutShow()));
|
||||
|
||||
Retranslate();
|
||||
}
|
||||
@@ -427,6 +428,38 @@ void MainMenu::EditToOutTriggered()
|
||||
olive::panel_manager->CurrentlyFocused()->EditToOut();
|
||||
}
|
||||
|
||||
void MainMenu::ActionSearchTriggered()
|
||||
{
|
||||
ActionSearch as(parentWidget());
|
||||
as.SetMenuBar(this);
|
||||
as.exec();
|
||||
}
|
||||
|
||||
void MainMenu::ShuttleLeftTriggered()
|
||||
{
|
||||
olive::panel_manager->CurrentlyFocused()->ShuttleLeft();
|
||||
}
|
||||
|
||||
void MainMenu::ShuttleStopTriggered()
|
||||
{
|
||||
olive::panel_manager->CurrentlyFocused()->ShuttleStop();
|
||||
}
|
||||
|
||||
void MainMenu::ShuttleRightTriggered()
|
||||
{
|
||||
olive::panel_manager->CurrentlyFocused()->ShuttleRight();
|
||||
}
|
||||
|
||||
void MainMenu::GoToPrevCutTriggered()
|
||||
{
|
||||
olive::panel_manager->CurrentlyFocused()->GoToPrevCut();
|
||||
}
|
||||
|
||||
void MainMenu::GoToNextCutTriggered()
|
||||
{
|
||||
olive::panel_manager->CurrentlyFocused()->GoToNextCut();
|
||||
}
|
||||
|
||||
void MainMenu::Retranslate()
|
||||
{
|
||||
// MenuShared is not a QWidget and therefore does not receive a LanguageEvent, we use MainMenu's to update it
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <QMainWindow>
|
||||
#include <QMenuBar>
|
||||
|
||||
#include "dialog/actionsearch/actionsearch.h"
|
||||
#include "widget/menu/menu.h"
|
||||
|
||||
/**
|
||||
@@ -106,6 +107,15 @@ private slots:
|
||||
void EditToInTriggered();
|
||||
void EditToOutTriggered();
|
||||
|
||||
void ActionSearchTriggered();
|
||||
|
||||
void ShuttleLeftTriggered();
|
||||
void ShuttleStopTriggered();
|
||||
void ShuttleRightTriggered();
|
||||
|
||||
void GoToPrevCutTriggered();
|
||||
void GoToNextCutTriggered();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Set strings based on the current application language.
|
||||
@@ -201,6 +211,7 @@ private:
|
||||
QAction* help_action_search_item_;
|
||||
QAction* help_debug_log_item_;
|
||||
QAction* help_about_item_;
|
||||
|
||||
};
|
||||
|
||||
#endif // MAINMENU_H
|
||||
|
||||
@@ -64,6 +64,37 @@ void olive::MainWindow::SetFullscreen(bool fullscreen)
|
||||
}
|
||||
}
|
||||
|
||||
void olive::MainWindow::ToggleMaximizedPanel()
|
||||
{
|
||||
qDebug() << "Hello!";
|
||||
|
||||
if (premaximized_state_.isEmpty()) {
|
||||
// Assume nothing is maximized at the moment
|
||||
|
||||
// Find the currently focused panel
|
||||
PanelWidget* currently_focused = olive::panel_manager->CurrentlyFocused();
|
||||
|
||||
// If this panel is not actually on the main window, this is a no-op
|
||||
if (currently_focused->isFloating()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Save the current state so it can be restored later
|
||||
premaximized_state_ = saveState();
|
||||
|
||||
// For every other panel that is on the main window, hide it
|
||||
foreach (PanelWidget* panel, olive::panel_manager->panels()) {
|
||||
if (!panel->isFloating() && panel != currently_focused) {
|
||||
panel->setVisible(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Assume we are currently maximized, restore the state
|
||||
restoreState(premaximized_state_);
|
||||
premaximized_state_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
void olive::MainWindow::ProjectOpen(Project* p)
|
||||
{
|
||||
// FIXME Use settings data to create panels and restore state if they exist
|
||||
|
||||
@@ -38,12 +38,13 @@ public:
|
||||
public slots:
|
||||
void ProjectOpen(Project *p);
|
||||
void SetFullscreen(bool fullscreen);
|
||||
void ToggleMaximizedPanel();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent* e) override;
|
||||
|
||||
private:
|
||||
Qt::WindowStates old_window_state_;
|
||||
QByteArray premaximized_state_;
|
||||
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user