various UI reimplementations from 0.1.x

This commit is contained in:
itsmattkc
2019-09-26 03:49:49 +10:00
parent c19718a4a5
commit 56e3fd41e5
70 changed files with 2056 additions and 1483 deletions
+20
View File
@@ -20,6 +20,7 @@
#include "filefunctions.h"
#include <QCoreApplication>
#include <QCryptographicHash>
#include <QDateTime>
#include <QDir>
@@ -73,3 +74,22 @@ QString GetMediaCacheLocation()
return media_cache_dir.absolutePath();
}
QString GetConfigurationLocation()
{
if (IsPortable()) {
return GetApplicationPath();
} else {
return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
}
}
bool IsPortable()
{
return QFileInfo::exists(QDir(GetApplicationPath()).filePath("portable"));
}
QString GetApplicationPath()
{
return QCoreApplication::applicationDirPath();
}
+6
View File
@@ -23,6 +23,8 @@
#include <QString>
bool IsPortable();
QString GetUniqueFileIdentifier(const QString& filename);
QString GetMediaIndexLocation();
@@ -31,4 +33,8 @@ QString GetMediaIndexFilename(const QString& filename);
QString GetMediaCacheLocation();
QString GetConfigurationLocation();
QString GetApplicationPath();
#endif // FILEFUNCTIONS_H
+7
View File
@@ -22,6 +22,8 @@
#include <QtMath>
#include "config/config.h"
QString padded(int arg, int padding) {
return QString("%1").arg(arg, padding, 10, QChar('0'));
}
@@ -91,3 +93,8 @@ int64_t olive::time_to_timestamp(const rational &time, const rational &timebase)
{
return qRound64(time.toDouble() * timebase.flipped().toDouble());
}
olive::TimecodeDisplay olive::CurrentTimecodeDisplay()
{
return static_cast<olive::TimecodeDisplay>(Config::Current()["TimecodeDisplay"].toInt());
}
+2
View File
@@ -34,6 +34,8 @@ enum TimecodeDisplay {
kMilliseconds
};
TimecodeDisplay CurrentTimecodeDisplay();
/**
* @brief Convert a timestamp (according to a rational timebase) to a user-friendly string representation
*/
+1
View File
@@ -17,5 +17,6 @@
set(OLIVE_SOURCES
${OLIVE_SOURCES}
config/config.h
config/config.cpp
PARENT_SCOPE
)
+152
View File
@@ -0,0 +1,152 @@
/***
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 "config.h"
#include <QCoreApplication>
#include <QDebug>
#include <QDir>
#include <QMessageBox>
#include <QXmlStreamWriter>
#include "core.h"
#include "common/filefunctions.h"
Config Config::current_config_;
Config::Config()
{
SetDefaults();
}
QString Config::GetConfigFilePath()
{
return QDir(GetConfigurationLocation()).filePath("config.xml");
}
Config &Config::Current()
{
return current_config_;
}
void Config::SetDefaults()
{
config_map_.clear();
config_map_["TimecodeDisplay"] = olive::kTimecodeFrames;
config_map_["DefaultStillLength"] = QVariant::fromValue(rational(2));
}
void Config::Load()
{
QFile config_file(GetConfigFilePath());
if (!config_file.exists()) {
return;
}
if (!config_file.open(QFile::ReadOnly)) {
qWarning() << QCoreApplication::translate("Config", "Failed to load application settings. This session will use "
"defaults.");
return;
}
// Reset to defaults
current_config_.SetDefaults();
QXmlStreamReader reader(&config_file);
while (!reader.atEnd()) {
reader.readNext();
if (!reader.isStartElement()) {
continue;
}
QString key = reader.name().toString();
reader.readNext();
QString value = reader.text().toString();
if (key == "Configuration") {
// First element, ignore
} else if (key == "Version") {
if (!value.contains(".")) {
qDebug() << "This is a 0.1.x config file, upconvert";
}
} else {
current_config_[key] = value;
}
}
if (reader.hasError()) {
QMessageBox::critical(olive::core.main_window(),
QCoreApplication::translate("Config", "Error loading settings"),
QCoreApplication::translate("Config", "Failed to load application settings. This session will "
"use defaults."),
QMessageBox::Ok);
current_config_.SetDefaults();
}
config_file.close();
}
void Config::Save()
{
QFile config_file(GetConfigFilePath());
if (!config_file.open(QFile::WriteOnly)) {
QMessageBox::critical(olive::core.main_window(),
QCoreApplication::translate("Config", "Error saving settings"),
QCoreApplication::translate("Config", "Failed to save application settings. The application "
"may lack write permissions to this location."),
QMessageBox::Ok);
return;
}
QXmlStreamWriter writer(&config_file);
writer.writeStartDocument();
writer.writeStartElement("Configuration");
// Anything after the hyphen is considered "unimportant" information
writer.writeTextElement("Version", QCoreApplication::applicationVersion().split('-').first());
QMapIterator<QString, QVariant> iterator(current_config_.config_map_);
while (iterator.hasNext()) {
iterator.next();
writer.writeTextElement(iterator.key(), iterator.value().toString());
}
writer.writeEndElement(); // Configuration
writer.writeEndDocument();
config_file.close();
}
QVariant Config::operator[](const QString &key) const
{
return config_map_[key];
}
QVariant &Config::operator[](const QString &key)
{
return config_map_[key];
}
+25 -5
View File
@@ -21,14 +21,34 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <QMap>
#include <QString>
#include <QVariant>
#include "common/timecodefunctions.h"
/**
* @brief Temporary variables that will definitely be configurable but aren't yet
*/
class Config {
public:
static Config& Current();
const olive::TimecodeDisplay kTimecodeDisplay = olive::kTimecodeFrames;
void SetDefaults();
const rational kDefaultImageLength = 2;
static void Load();
static void Save();
QVariant operator[](const QString&) const;
QVariant& operator[](const QString&);
private:
Config();
QMap<QString, QVariant> config_map_;
static Config current_config_;
static QString GetConfigFilePath();
};
#endif // CONFIG_H
+15 -2
View File
@@ -25,11 +25,14 @@
#include <QDebug>
#include <QFileDialog>
#include <QFileInfo>
#include <QMessageBox>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QStyleFactory>
#include "config/config.h"
#include "dialog/about/about.h"
#include "dialog/sequence/sequence.h"
#include "dialog/preferences/preferences.h"
#include "panel/panelmanager.h"
#include "panel/project/project.h"
#include "project/item/footage/footage.h"
@@ -85,6 +88,9 @@ void Core::Start()
// Declare custom types for Qt signal/slot syste
DeclareTypesForQt();
// Load application config
Config::Load();
//
// Start GUI (FIXME CLI mode)
@@ -193,6 +199,12 @@ void Core::DialogImportShow()
}
}
void Core::DialogPreferencesShow()
{
PreferencesDialog pd(main_window_, main_window_->menuBar());
pd.exec();
}
void Core::CreateNewFolder()
{
// Locate the most recently focused Project panel (assume that's the panel the user wants to import into)
@@ -344,7 +356,8 @@ void Core::DeclareTypesForQt()
void Core::StartGUI(bool full_screen)
{
// Set UI style
olive::style::AppSetDefault();
qApp->setStyle(QStyleFactory::create("Fusion"));
StyleManager::SetStyle(StyleManager::DefaultStyle());
// Set up shared menus
olive::menu_shared.Initialize();
+5
View File
@@ -124,6 +124,11 @@ public slots:
*/
void DialogImportShow();
/**
* @brief Show Preferences dialog
*/
void DialogPreferencesShow();
/**
* @brief Create a new folder in the currently active project
*/
+1
View File
@@ -16,6 +16,7 @@
add_subdirectory(about)
add_subdirectory(actionsearch)
add_subdirectory(preferences)
add_subdirectory(sequence)
set(OLIVE_SOURCES
+26
View File
@@ -0,0 +1,26 @@
# 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/>.
add_subdirectory(tabs)
set(OLIVE_SOURCES
${OLIVE_SOURCES}
dialog/preferences/keysequenceeditor.h
dialog/preferences/keysequenceeditor.cpp
dialog/preferences/preferences.h
dialog/preferences/preferences.cpp
PARENT_SCOPE
)
@@ -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/>.
***/
#include "keysequenceeditor.h"
#include <QAction>
KeySequenceEditor::KeySequenceEditor(QWidget* parent, QAction* a)
: QKeySequenceEdit(parent), action(a) {
setKeySequence(action->shortcut());
}
void KeySequenceEditor::set_action_shortcut() {
action->setShortcut(keySequence());
}
void KeySequenceEditor::reset_to_default() {
setKeySequence(action->property("default").toString());
}
QString KeySequenceEditor::action_name() {
return action->property("id").toString();
}
QString KeySequenceEditor::export_shortcut() {
QString ks = keySequence().toString();
if (ks != action->property("default")) {
return action->property("id").toString() + "\t" + ks;
}
return nullptr;
}
+100
View File
@@ -0,0 +1,100 @@
/***
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 KEYSEQUENCEEDITOR_H
#define KEYSEQUENCEEDITOR_H
#include <QKeySequenceEdit>
/**
* @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 // KEYSEQUENCEEDITOR_H
File diff suppressed because it is too large Load Diff
+10 -330
View File
@@ -1,7 +1,7 @@
/***
Olive - Non-Linear Video Editor
Copyright (C) 2019 Olive Team
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
@@ -21,24 +21,12 @@
#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 <QDialog>
#include <QMenuBar>
#include <QTabWidget>
#include "timeline/sequence.h"
class KeySequenceEditor;
#include "tabs/preferencestab.h"
/**
* @brief The PreferencesDialog class
@@ -58,7 +46,7 @@ public:
*
* QWidget parent. Usually MainWindow.
*/
explicit PreferencesDialog(QWidget *parent = nullptr);
explicit PreferencesDialog(QWidget *parent, QMenuBar* main_menu_bar);
private slots:
/**
@@ -66,215 +54,12 @@ private slots:
*/
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:
void AddTab(PreferencesTab* tab, const QString& title);
/**
* @brief Create and arrange all UI widgets
*/
void setup_ui();
QTabWidget* tab_widget_;
/**
* @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;
QList<PreferencesTab*> tabs_;
/**
* @brief Stored default Sequence object
@@ -282,38 +67,7 @@ private:
* 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);
//Sequence default_sequence;
/**
* @brief Add an automated QCheckBox+boolean value pair
@@ -355,78 +109,4 @@ private:
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
@@ -0,0 +1,36 @@
# 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/preferences/tabs/preferencesgeneraltab.h
dialog/preferences/tabs/preferencesgeneraltab.cpp
dialog/preferences/tabs/preferencesbehaviortab.h
dialog/preferences/tabs/preferencesbehaviortab.cpp
dialog/preferences/tabs/preferencesappearancetab.h
dialog/preferences/tabs/preferencesappearancetab.cpp
dialog/preferences/tabs/preferencesplaybacktab.h
dialog/preferences/tabs/preferencesplaybacktab.cpp
dialog/preferences/tabs/preferencesaudiotab.h
dialog/preferences/tabs/preferencesaudiotab.cpp
dialog/preferences/tabs/preferenceskeyboardtab.h
dialog/preferences/tabs/preferenceskeyboardtab.cpp
dialog/preferences/tabs/preferencescolormanagementtab.h
dialog/preferences/tabs/preferencescolormanagementtab.cpp
dialog/preferences/tabs/preferencestab.h
dialog/preferences/tabs/preferencestab.cpp
PARENT_SCOPE
)
@@ -0,0 +1,51 @@
#include "preferencesappearancetab.h"
#include <QFileDialog>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
PreferencesAppearanceTab::PreferencesAppearanceTab()
{
QVBoxLayout* layout = new QVBoxLayout(this);
QGridLayout* appearance_layout = new QGridLayout();
layout->addLayout(appearance_layout);
int row = 0;
// Appearance -> Theme
appearance_layout->addWidget(new QLabel(tr("Theme")), row, 0);
style_ = new QComboBox();
style_list_ = StyleManager::ListInternal();
foreach (StyleDescriptor s, style_list_) {
style_->addItem(s.name(), s.path());
if (s.path() == Config::Current()["Style"]) {
style_->setCurrentIndex(style_->count()-1);
}
}
appearance_layout->addWidget(style_, row, 1, 1, 2);
row++;
layout->addStretch();
}
void PreferencesAppearanceTab::Accept()
{
QString style_path = style_->currentData().toString();
StyleManager::SetStyle(style_path);
Config::Current()["Style"] = style_path;
if (style_->currentIndex() < style_list_.size()) {
// This is an internal style, set accordingly
} else {
StyleManager::SetStyle(style_->currentData().toString());
}
}
@@ -0,0 +1,37 @@
#ifndef PREFERENCESAPPEARANCETAB_H
#define PREFERENCESAPPEARANCETAB_H
#include <QComboBox>
#include <QLineEdit>
#include "preferencestab.h"
#include "ui/style/style.h"
class PreferencesAppearanceTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesAppearanceTab();
virtual void Accept() override;
private:
/**
* @brief Show a file dialog to browse for an external CSS file to load for styling the application.
*/
void BrowseForCSS();
/**
* @brief UI widget for selecting the current UI style
*/
QComboBox* style_;
/**
* @brief List of internal styles
*/
QList<StyleDescriptor> style_list_;
QString custom_style_path_;
};
#endif // PREFERENCESAPPEARANCETAB_H
@@ -0,0 +1,93 @@
#include "preferencesaudiotab.h"
#include <QAudioDeviceInfo>
#include <QGridLayout>
#include <QLabel>
#include "config/config.h"
PreferencesAudioTab::PreferencesAudioTab()
{
QGridLayout* audio_tab_layout = new QGridLayout(this);
int row = 0;
// Audio -> Output Device
audio_tab_layout->addWidget(new QLabel(tr("Output Device:")), row, 0);
audio_output_devices = new QComboBox();
audio_output_devices->addItem(tr("Default"), "");
// list all available audio output devices
QList<QAudioDeviceInfo> devs = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
bool found_preferred_device = false;
for (int i=0;i<devs.size();i++) {
audio_output_devices->addItem(devs.at(i).deviceName(), devs.at(i).deviceName());
if (!found_preferred_device
&& devs.at(i).deviceName() == Config::Current()["AudioOutput"]) {
audio_output_devices->setCurrentIndex(audio_output_devices->count()-1);
found_preferred_device = true;
}
}
audio_tab_layout->addWidget(audio_output_devices, row, 1);
row++;
// Audio -> Input Device
audio_tab_layout->addWidget(new QLabel(tr("Input Device:")), row, 0);
audio_input_devices = new QComboBox();
audio_input_devices->addItem(tr("Default"), "");
// list all available audio input devices
devs = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
found_preferred_device = false;
for (int i=0;i<devs.size();i++) {
audio_input_devices->addItem(devs.at(i).deviceName(), devs.at(i).deviceName());
if (!found_preferred_device
&& devs.at(i).deviceName() == Config::Current()["AudioInput"]) {
audio_input_devices->setCurrentIndex(audio_input_devices->count()-1);
found_preferred_device = true;
}
}
audio_tab_layout->addWidget(audio_input_devices, row, 1);
row++;
// Audio -> Sample Rate
audio_tab_layout->addWidget(new QLabel(tr("Sample Rate:")), row, 0);
audio_sample_rate = new QComboBox();
/*combobox_audio_sample_rates(audio_sample_rate);
for (int i=0;i<audio_sample_rate->count();i++) {
if (audio_sample_rate->itemData(i).toInt() == olive::config.audio_rate) {
audio_sample_rate->setCurrentIndex(i);
break;
}
}*/
audio_tab_layout->addWidget(audio_sample_rate, row, 1);
row++;
// Audio -> Audio Recording
audio_tab_layout->addWidget(new QLabel(tr("Audio Recording:"), this), row, 0);
recordingComboBox = new QComboBox();
recordingComboBox->addItem(tr("Mono"));
recordingComboBox->addItem(tr("Stereo"));
// recordingComboBox->setCurrentIndex(olive::config.recording_mode - 1);
audio_tab_layout->addWidget(recordingComboBox, row, 1);
row++;
}
void PreferencesAudioTab::Accept()
{
}
@@ -0,0 +1,39 @@
#ifndef PREFERENCESAUDIOTAB_H
#define PREFERENCESAUDIOTAB_H
#include <QComboBox>
#include "preferencestab.h"
class PreferencesAudioTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesAudioTab();
virtual void Accept() override;
private:
/**
* @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 editing the recording channels
*/
QComboBox* recordingComboBox;
};
#endif // PREFERENCESAUDIOTAB_H
@@ -0,0 +1,47 @@
#include "preferencesbehaviortab.h"
#include <QCheckBox>
#include <QVBoxLayout>
PreferencesBehaviorTab::PreferencesBehaviorTab()
{
QVBoxLayout* layout = new QVBoxLayout(this);
behavior_tree_ = new QTreeWidget();
layout->addWidget(behavior_tree_);
behavior_tree_->setHeaderLabel(tr("Behavior"));
behavior_tree_->setRootIsDecorated(false);
AddItem(tr("Add Default Effects to New Clips"));
AddItem(tr("Automatically Seek to the Beginning When Playing at the End of a Sequence"));
AddItem(tr("Selecting Also Seeks"));
AddItem(tr("Edit Tool Also Seeks"));
AddItem(tr("Edit Tool Selects Links"));
AddItem(tr("Seek Also Selects"));
AddItem(tr("Seek to the End of Pastes"));
AddItem(tr("Scroll Wheel Zooms"));
AddItem(tr("Invert Timeline Scroll Axes"));
AddItem(tr("Enable Drag Files to Timeline"));
AddItem(tr("Auto-Scale By Default"));
AddItem(tr("Auto-Seek to Imported Clips"));
AddItem(tr("Audio Scrubbing"));
AddItem(tr("Drop Files on Media to Replace"));
AddItem(tr("Enable Hover Focus"));
AddItem(tr("Ask For Name When Setting Marker"));
//scroll_wheel_zooms->setToolTip(tr("Hold CTRL to toggle this setting"));
}
void PreferencesBehaviorTab::Accept()
{
}
void PreferencesBehaviorTab::AddItem(const QString &text, const QString& tooltip)
{
QTreeWidgetItem* item = new QTreeWidgetItem({text});
item->setToolTip(0, tooltip);
item->setCheckState(0, Qt::Unchecked);
behavior_tree_->addTopLevelItem(item);
}
@@ -0,0 +1,22 @@
#ifndef PREFERENCESBEHAVIORTAB_H
#define PREFERENCESBEHAVIORTAB_H
#include <QTreeWidget>
#include "preferencestab.h"
class PreferencesBehaviorTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesBehaviorTab();
virtual void Accept() override;
private:
void AddItem(const QString& text, const QString &tooltip = QString());
QTreeWidget* behavior_tree_;
};
#endif // PREFERENCESBEHAVIORTAB_H
@@ -0,0 +1,213 @@
#include "preferencescolormanagementtab.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QGridLayout>
#include <QGroupBox>
#include <QLabel>
#include <QMessageBox>
#include <QPushButton>
PreferencesColorManagementTab::PreferencesColorManagementTab()
{
QGridLayout* color_management_layout = new QGridLayout(this);
int row = 0;
QGroupBox* opencolorio_groupbox = new QGroupBox();
QGridLayout* opencolorio_groupbox_layout = new QGridLayout(opencolorio_groupbox);
// COLOR MANAGEMENT -> OpenColorIO Config File
opencolorio_groupbox_layout->addWidget(new QLabel(tr("OpenColorIO Config File:")), 0, 0);
ocio_config_file = new QLineEdit();
// ocio_config_file->setText(olive::config.ocio_config_path);
connect(ocio_config_file, SIGNAL(textChanged(const QString &)), this, SLOT(update_ocio_config(const QString&)));
opencolorio_groupbox_layout->addWidget(ocio_config_file, 0, 1, 1, 4);
QPushButton* ocio_config_browse_btn = new QPushButton(tr("Browse"));
connect(ocio_config_browse_btn, SIGNAL(clicked(bool)), this, SLOT(browse_ocio_config()));
opencolorio_groupbox_layout->addWidget(ocio_config_browse_btn, 0, 5);
// COLOR MANAGEMENT -> Default Input Color Space
ocio_default_input = new QComboBox();
opencolorio_groupbox_layout->addWidget(new QLabel(tr("Default Input Color Space:")), 1, 0);
opencolorio_groupbox_layout->addWidget(ocio_default_input, 1, 1, 1, 5);
// COLOR MANAGEMENT -> Display
ocio_display = new QComboBox();
connect(ocio_display, SIGNAL(currentIndexChanged(int)), this, SLOT(update_ocio_view_menu()));
opencolorio_groupbox_layout->addWidget(new QLabel(tr("Display:")), 2, 0);
opencolorio_groupbox_layout->addWidget(ocio_display, 2, 1);
// COLOR MANAGEMENT -> View
ocio_view = new QComboBox();
opencolorio_groupbox_layout->addWidget(new QLabel(tr("View:")), 2, 2);
opencolorio_groupbox_layout->addWidget(ocio_view, 2, 3);
// COLOR MANAGEMENT -> Look
ocio_look = new QComboBox();
opencolorio_groupbox_layout->addWidget(new QLabel(tr("Look:")), 2, 4);
opencolorio_groupbox_layout->addWidget(ocio_look, 2, 5);
color_management_layout->addWidget(opencolorio_groupbox, row, 0);
row++;
// COLOR MANAGEMENT -> Bit Depth
QGroupBox* bit_depth_groupbox = new QGroupBox(tr("Bit Depth"));
QGridLayout* bit_depth_groupbox_layout = new QGridLayout(bit_depth_groupbox);
// COLOR MANAGEMENT -> Bit Depth -> Playback
playback_bit_depth = new QComboBox();
/*for (int i=0;i<olive::pixel_formats.size();i++) {
playback_bit_depth->addItem(olive::pixel_formats.at(i).name, i);
}
playback_bit_depth->setCurrentIndex(olive::config.playback_bit_depth);*/
bit_depth_groupbox_layout->addWidget(new QLabel(tr("Playback (Offline):")), 0, 0);
bit_depth_groupbox_layout->addWidget(playback_bit_depth, 0, 1);
// COLOR MANAGEMENT -> Bit Depth -> Export
export_bit_depth = new QComboBox();
/*for (int i=0;i<olive::pixel_formats.size();i++) {
export_bit_depth->addItem(olive::pixel_formats.at(i).name, i);
}
export_bit_depth->setCurrentIndex(olive::config.export_bit_depth);*/
bit_depth_groupbox_layout->addWidget(new QLabel(tr("Export (Online):")), 0, 2);
bit_depth_groupbox_layout->addWidget(export_bit_depth, 0, 3);
color_management_layout->addWidget(bit_depth_groupbox, row, 0);
//row++;
populate_ocio_menus(OCIO::GetCurrentConfig());
}
void PreferencesColorManagementTab::Accept()
{
}
void PreferencesColorManagementTab::populate_ocio_menus(OCIO::ConstConfigRcPtr config)
{
if (!config) {
// Just clear everything
ocio_display->clear();
ocio_default_input->clear();
ocio_view->clear();
ocio_look->clear();
} else {
// Get input color spaces for setting the default input color space
ocio_default_input->clear();
for (int i=0;i<config->getNumColorSpaces();i++) {
QString colorspace = config->getColorSpaceNameByIndex(i);
ocio_default_input->addItem(colorspace);
/*if (colorspace == olive::config.ocio_default_input_colorspace) {
ocio_default_input->setCurrentIndex(i);
}*/
}
// Get current display name (if the config is empty, get the current default display)
/*QString current_display = olive::config.ocio_display;
if (current_display.isEmpty()) {
current_display = config->getDefaultDisplay();
}*/
// Populate the display menu
ocio_display->clear();
for (int i=0;i<config->getNumDisplays();i++) {
ocio_display->addItem(config->getDisplay(i));
// Check if this index is the currently selected
/*if (config->getDisplay(i) == current_display) {
ocio_display->setCurrentIndex(i);
}*/
}
update_ocio_view_menu(config);
// Populate the look menu
ocio_look->clear();
ocio_look->addItem(tr("(None)"), QString());
for (int i=0;i<config->getNumLooks();i++) {
const char* look = config->getLookNameByIndex(i);
ocio_look->addItem(look, look);
/*if (look == olive::config.ocio_look) {
ocio_look->setCurrentIndex(i+1);
}*/
}
}
}
OCIO::ConstConfigRcPtr PreferencesColorManagementTab::TestOCIOConfig(const QString &url)
{
// Check whether OCIO can load it
OCIO::ConstConfigRcPtr config;
try {
config = OCIO::Config::CreateFromFile(url.toUtf8());
} catch (OCIO::Exception& e) {
QMessageBox::critical(this,
tr("OpenColorIO Config Error"),
tr("Failed to set OpenColorIO configuration: %1").arg(e.what()),
QMessageBox::Ok);
}
return config;
}
void PreferencesColorManagementTab::update_ocio_view_menu(OCIO::ConstConfigRcPtr config)
{
// Get views for the current display set in `ocio_display`
QString display = ocio_display->currentText();
// Get current view
/*QString current_view = olive::config.ocio_view;
if (current_view.isEmpty()) {
current_view = config->getDefaultView(display.toUtf8());
}*/
// Populate the view menu
int ocio_view_count = config->getNumViews(display.toUtf8());
ocio_view->clear();
for (int i=0;i<ocio_view_count;i++) {
const char* view = config->getView(display.toUtf8(), i);
ocio_view->addItem(view);
/*if (current_view == view) {
ocio_view->setCurrentIndex(i);
}*/
}
}
void PreferencesColorManagementTab::update_ocio_config(const QString &s)
{
OCIO::ConstConfigRcPtr file_config;
if (!s.isEmpty() && QFileInfo::exists(s)) {
file_config = TestOCIOConfig(s);
}
populate_ocio_menus(file_config);
}
void PreferencesColorManagementTab::browse_ocio_config()
{
QString fn = QFileDialog::getOpenFileName(this, tr("Browse for OpenColorIO configuration"));
if (!fn.isEmpty()) {
ocio_config_file->setText(fn);
}
}
void PreferencesColorManagementTab::update_ocio_view_menu()
{
update_ocio_view_menu(OCIO::GetCurrentConfig());
}
@@ -0,0 +1,52 @@
#ifndef PREFERENCESCOLORMANAGEMENTTAB_H
#define PREFERENCESCOLORMANAGEMENTTAB_H
#include <QComboBox>
#include <QCheckBox>
#include <QLineEdit>
#include <OpenColorIO/OpenColorIO.h>
namespace OCIO = OCIO_NAMESPACE::v1;
#include "preferencestab.h"
class PreferencesColorManagementTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesColorManagementTab();
virtual void Accept() override;
private slots:
// OCIO function
void browse_ocio_config();
void update_ocio_view_menu();
void update_ocio_view_menu(OCIO::ConstConfigRcPtr config);
void update_ocio_config(const QString&);
private:
/**
* @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);
void populate_ocio_menus(OCIO::ConstConfigRcPtr config);
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;
};
#endif // PREFERENCESCOLORMANAGEMENTTAB_H
@@ -0,0 +1,110 @@
#include "preferencesgeneraltab.h"
#include <QGridLayout>
#include <QLabel>
#include <QComboBox>
#include <QCheckBox>
#include <QPushButton>
PreferencesGeneralTab::PreferencesGeneralTab()
{
QGridLayout* general_layout = new QGridLayout(this);
int row = 0;
// General -> Language
general_layout->addWidget(new QLabel(tr("Language:")), row, 0);
language_combobox = new QComboBox();
// add default language (en-US)
language_combobox->addItem(QLocale::languageToString(QLocale("en-US").language()));
/*
// add languages from file
QList<QString> translation_paths = get_language_paths();
// iterate through all language search paths
for (int j=0;j<translation_paths.size();j++) {
QDir translation_dir(translation_paths.at(j));
if (translation_dir.exists()) {
QStringList translation_files = translation_dir.entryList({"*.qm"}, QDir::Files | QDir::NoDotAndDotDot);
for (int i=0;i<translation_files.size();i++) {
// get path of translation relative to the application path
QString locale_full_path = translation_dir.filePath(translation_files.at(i));
QString locale_relative_path = QDir(get_app_path()).relativeFilePath(locale_full_path);
QFileInfo locale_file(translation_files.at(i));
QString locale_file_basename = locale_file.baseName();
QString locale_str = locale_file_basename.mid(locale_file_basename.lastIndexOf('_')+1);
language_combobox->addItem(QLocale(locale_str).nativeLanguageName(), locale_relative_path);
if (olive::config.language_file == locale_relative_path) {
language_combobox->setCurrentIndex(language_combobox->count() - 1);
}
}
}
}
*/
general_layout->addWidget(language_combobox, row, 1, 1, 4);
row++;
// General -> Thumbnail and Waveform Resolution
general_layout->addWidget(new QLabel(tr("Thumbnail Resolution:"), this), row, 0);
thumbnail_res_spinbox = new QSpinBox(this);
thumbnail_res_spinbox->setMinimum(0);
thumbnail_res_spinbox->setMaximum(INT_MAX);
//thumbnail_res_spinbox->setValue(olive::config.thumbnail_resolution);
general_layout->addWidget(thumbnail_res_spinbox, row, 1);
general_layout->addWidget(new QLabel(tr("Waveform Resolution:"), this), row, 2);
waveform_res_spinbox = new QSpinBox(this);
waveform_res_spinbox->setMinimum(0);
waveform_res_spinbox->setMaximum(INT_MAX);
//waveform_res_spinbox->setValue(olive::config.waveform_resolution);
general_layout->addWidget(waveform_res_spinbox, row, 3);
QPushButton* delete_preview_btn = new QPushButton(tr("Delete Previews"));
general_layout->addWidget(delete_preview_btn, row, 4);
//connect(delete_preview_btn, SIGNAL(clicked(bool)), this, SLOT(delete_all_previews()));
row++;
QHBoxLayout* misc_general = new QHBoxLayout();
// General -> Use Software Fallbacks When Possible
QCheckBox* use_software_fallbacks_checkbox = new QCheckBox(tr("Use Software Fallbacks When Possible"));
//AddBoolPair(use_software_fallbacks_checkbox, &olive::config.use_software_fallback, true);
misc_general->addWidget(use_software_fallbacks_checkbox);
// General -> Don't Use Proxies When Exporting
QCheckBox* dont_use_proxies_when_exporting = new QCheckBox(tr("Don't Use Proxies When Exporting"));
dont_use_proxies_when_exporting->setToolTip(tr("Use originals instead of proxies when exporting"));
//AddBoolPair(dont_use_proxies_when_exporting, &olive::config.dont_use_proxies_on_export);
misc_general->addWidget(dont_use_proxies_when_exporting);
// General -> Default Sequence Settings
QPushButton* default_sequence_settings = new QPushButton(tr("Default Sequence Settings"));
connect(default_sequence_settings, SIGNAL(clicked(bool)), this, SLOT(edit_default_sequence_settings()));
misc_general->addWidget(default_sequence_settings);
general_layout->addLayout(misc_general, row, 0, 1, 5);
row++;
}
void PreferencesGeneralTab::Accept()
{
}
void PreferencesGeneralTab::edit_default_sequence_settings()
{
/*NewSequenceDialog nsd(this, nullptr, &default_sequence);
nsd.SetNameEditable(false);
nsd.exec();*/
}
@@ -0,0 +1,41 @@
#ifndef PREFERENCESGENERALTAB_H
#define PREFERENCESGENERALTAB_H
#include <QComboBox>
#include <QSpinBox>
#include "preferencestab.h"
class PreferencesGeneralTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesGeneralTab();
virtual void Accept() override;
private slots:
/**
* @brief Shows a NewSequenceDialog attached to default_sequence
*/
void edit_default_sequence_settings();
private:
/**
* @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;
};
#endif // PREFERENCESGENERALTAB_H
@@ -0,0 +1,214 @@
#include "preferenceskeyboardtab.h"
#include <QFileDialog>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QMessageBox>
#include <QPushButton>
#include <QVBoxLayout>
PreferencesKeyboardTab::PreferencesKeyboardTab(QMenuBar *menubar)
{
QVBoxLayout* shortcut_layout = new QVBoxLayout(this);
QLineEdit* key_search_line = new QLineEdit();
key_search_line->setPlaceholderText(tr("Search for action or shortcut"));
connect(key_search_line, SIGNAL(textChanged(const QString &)), this, SLOT(refine_shortcut_list(const QString &)));
shortcut_layout->addWidget(key_search_line);
keyboard_tree = new QTreeWidget();
QTreeWidgetItem* tree_header = keyboard_tree->headerItem();
tree_header->setText(0, tr("Action"));
tree_header->setText(1, tr("Shortcut"));
shortcut_layout->addWidget(keyboard_tree);
QHBoxLayout* reset_shortcut_layout = new QHBoxLayout();
QPushButton* import_shortcut_button = new QPushButton(tr("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(tr("Export"));
reset_shortcut_layout->addWidget(export_shortcut_button);
connect(export_shortcut_button, SIGNAL(clicked(bool)), this, SLOT(save_shortcut_file()));
reset_shortcut_layout->addStretch();
QPushButton* reset_selected_shortcut_button = new QPushButton(tr("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(tr("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);
setup_kbd_shortcuts(menubar);
}
void PreferencesKeyboardTab::Accept()
{
}
void PreferencesKeyboardTab::setup_kbd_shortcuts(QMenuBar* menubar) {
QList<QAction*> menus = menubar->actions();
for (int i=0;i<menus.size();i++) {
QMenu* menu = menus.at(i)->menu();
QTreeWidgetItem* item = new QTreeWidgetItem(keyboard_tree);
item->setText(0, menu->title().replace("&", ""));
keyboard_tree->addTopLevelItem(item);
setup_kbd_shortcut_worker(menu, item);
}
for (int i=0;i<key_shortcut_items.size();i++) {
if (!key_shortcut_actions.at(i)->property("id").isNull()) {
KeySequenceEditor* editor = new KeySequenceEditor(keyboard_tree, key_shortcut_actions.at(i));
keyboard_tree->setItemWidget(key_shortcut_items.at(i), 1, editor);
key_shortcut_fields.append(editor);
}
}
}
void PreferencesKeyboardTab::setup_kbd_shortcut_worker(QMenu* menu, QTreeWidgetItem* parent) {
QList<QAction*> actions = menu->actions();
for (int i=0;i<actions.size();i++) {
QAction* a = actions.at(i);
if (!a->isSeparator() && a->property("keyignore").isNull()) {
QTreeWidgetItem* item = new QTreeWidgetItem(parent);
item->setText(0, a->text().replace("&", ""));
parent->addChild(item);
if (a->menu() != nullptr) {
item->setChildIndicatorPolicy(QTreeWidgetItem::ShowIndicator);
setup_kbd_shortcut_worker(a->menu(), item);
} else {
key_shortcut_items.append(item);
key_shortcut_actions.append(a);
}
}
}
}
void PreferencesKeyboardTab::reset_default_shortcut() {
QList<QTreeWidgetItem*> items = keyboard_tree->selectedItems();
for (int i=0;i<items.size();i++) {
QTreeWidgetItem* item = keyboard_tree->selectedItems().at(i);
static_cast<KeySequenceEditor*>(keyboard_tree->itemWidget(item, 1))->reset_to_default();
}
}
void PreferencesKeyboardTab::reset_all_shortcuts() {
if (QMessageBox::question(
this,
tr("Confirm Reset All Shortcuts"),
tr("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();
}
}
}
bool PreferencesKeyboardTab::refine_shortcut_list(const QString &s, QTreeWidgetItem* parent) {
if (parent == nullptr) {
for (int i=0;i<keyboard_tree->topLevelItemCount();i++) {
refine_shortcut_list(s, keyboard_tree->topLevelItem(i));
}
} else {
parent->setExpanded(!s.isEmpty());
bool all_children_are_hidden = !s.isEmpty();
for (int i=0;i<parent->childCount();i++) {
QTreeWidgetItem* item = parent->child(i);
if (item->childCount() > 0) {
all_children_are_hidden = refine_shortcut_list(s, item);
} else {
item->setHidden(false);
if (s.isEmpty()) {
all_children_are_hidden = false;
} else {
QString shortcut;
if (keyboard_tree->itemWidget(item, 1) != nullptr) {
shortcut = static_cast<QKeySequenceEdit*>(keyboard_tree->itemWidget(item, 1))->keySequence().toString();
}
if (item->text(0).contains(s, Qt::CaseInsensitive) || shortcut.contains(s, Qt::CaseInsensitive)) {
all_children_are_hidden = false;
} else {
item->setHidden(true);
}
}
}
}
if (parent->text(0).contains(s, Qt::CaseInsensitive)) all_children_are_hidden = false;
parent->setHidden(all_children_are_hidden);
return all_children_are_hidden;
}
return true;
}
void PreferencesKeyboardTab::load_shortcut_file() {
QString fn = QFileDialog::getOpenFileName(this, tr("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++;
}
key_shortcut_fields.at(i)->setKeySequence(ks);
} else {
key_shortcut_fields.at(i)->reset_to_default();
}
}
} else {
QMessageBox::critical(
this,
tr("Error saving shortcuts"),
tr("Failed to open file for reading")
);
}
}
}
void PreferencesKeyboardTab::save_shortcut_file() {
QString fn = QFileDialog::getSaveFileName(this, tr("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;
}
}
f.close();
QMessageBox::information(this, tr("Export Shortcuts"), tr("Shortcuts exported successfully"));
} else {
QMessageBox::critical(this, tr("Error saving shortcuts"), tr("Failed to open file for writing"));
}
}
}
@@ -0,0 +1,115 @@
#ifndef PREFERENCESKEYBOARDTAB_H
#define PREFERENCESKEYBOARDTAB_H
#include <QMenuBar>
#include <QTreeWidget>
#include "preferencestab.h"
#include "../keysequenceeditor.h"
class PreferencesKeyboardTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesKeyboardTab(QMenuBar* menubar);
virtual void Accept() override;
private slots:
/**
* @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 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);
private:
/**
* @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);
/**
* @brief UI widget for editing keyboard shortcuts
*/
QTreeWidget* keyboard_tree;
/**
* @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;
};
#endif // PREFERENCESKEYBOARDTAB_H
@@ -0,0 +1,14 @@
#include "preferencesplaybacktab.h"
#include <QGroupBox>
#include <QLabel>
#include <QVBoxLayout>
PreferencesPlaybackTab::PreferencesPlaybackTab()
{
}
void PreferencesPlaybackTab::Accept()
{
}
@@ -0,0 +1,20 @@
#ifndef PREFERENCESPLAYBACKTAB_H
#define PREFERENCESPLAYBACKTAB_H
#include <QComboBox>
#include <QDoubleSpinBox>
#include "preferencestab.h"
class PreferencesPlaybackTab : public PreferencesTab
{
Q_OBJECT
public:
PreferencesPlaybackTab();
virtual void Accept() override;
private:
};
#endif // PREFERENCESPLAYBACKTAB_H
@@ -0,0 +1,6 @@
#include "preferencestab.h"
PreferencesTab::PreferencesTab()
{
}
@@ -0,0 +1,16 @@
#ifndef PREFERENCESTAB_H
#define PREFERENCESTAB_H
#include <QWidget>
#include "config/config.h"
class PreferencesTab : public QWidget
{
public:
PreferencesTab();
virtual void Accept() = 0;
};
#endif // PREFERENCESTAB_H
+2
View File
@@ -57,6 +57,8 @@ int main(int argc, char *argv[]) {
QString app_version = "0.2.0";
#ifdef GITHASH
// Anything after the hyphen is considered "unimportant" information. Text BEFORE the hyphen is used in version
// checking project files and config files
app_version.append("-");
app_version.append(GITHASH);
#endif
+5 -1
View File
@@ -24,7 +24,6 @@
Folder::Folder()
{
set_icon(olive::icon::Folder);
}
Item::Type Folder::type() const
@@ -36,3 +35,8 @@ bool Folder::CanHaveChildren() const
{
return true;
}
QIcon Folder::icon()
{
return olive::icon::Folder;
}
+2
View File
@@ -38,6 +38,8 @@ public:
virtual bool CanHaveChildren() const override;
virtual QIcon icon() override;
private:
};
+32 -37
View File
@@ -43,8 +43,6 @@ void Footage::set_status(const Footage::Status &status)
{
status_ = status;
UpdateIcon();
UpdateTooltip();
}
@@ -116,6 +114,38 @@ void Footage::set_decoder(const QString &id)
decoder_ = id;
}
QIcon Footage::icon()
{
switch (status_) {
case kUnprobed:
case kUnindexed:
// FIXME Set a waiting icon
return QIcon();
case kReady:
if (HasStreamsOfType(Stream::kVideo)) {
// Prioritize the video icon
return olive::icon::Video;
} else if (HasStreamsOfType(Stream::kAudio)) {
// Otherwise assume it's audio only
return olive::icon::Audio;
} else if (HasStreamsOfType(Stream::kImage)) {
// Otherwise assume it's an image
return olive::icon::Image;
}
/* fall through */
case kInvalid:
return olive::icon::Error;
}
return QIcon();
}
void Footage::ClearStreams()
{
if (streams_.empty()) {
@@ -138,41 +168,6 @@ bool Footage::HasStreamsOfType(const Stream::Type type)
return false;
}
void Footage::UpdateIcon()
{
switch (status_) {
case kUnprobed:
case kUnindexed:
// FIXME Set a waiting icon
set_icon(QIcon());
break;
case kReady:
if (HasStreamsOfType(Stream::kVideo)) {
// Prioritize the video icon
set_icon(olive::icon::Video);
break;
} else if (HasStreamsOfType(Stream::kAudio)) {
// Otherwise assume it's audio only
set_icon(olive::icon::Audio);
break;
} else if (HasStreamsOfType(Stream::kImage)) {
// Otherwise assume it's an image
set_icon(olive::icon::Image);
break;
}
/* fall through */
case kInvalid:
set_icon(olive::icon::Error);
break;
}
}
void Footage::UpdateTooltip()
{
switch (status_) {
+2
View File
@@ -205,6 +205,8 @@ public:
*/
void set_decoder(const QString& id);
virtual QIcon icon() override;
private:
/**
* @brief Internal function to delete all Stream children and empty the array
-10
View File
@@ -101,16 +101,6 @@ void Item::set_tooltip(const QString &t)
tooltip_ = t;
}
const QIcon &Item::icon()
{
return icon_;
}
void Item::set_icon(const QIcon &icon)
{
icon_ = icon;
}
Item *Item::parent() const
{
return parent_;
+1 -4
View File
@@ -92,8 +92,7 @@ public:
const QString& tooltip() const;
void set_tooltip(const QString& t);
const QIcon& icon();
void set_icon(const QIcon& icon);
virtual QIcon icon() = 0;
Item *parent() const;
const Item* root() const;
@@ -111,8 +110,6 @@ private:
QString name_;
QIcon icon_;
QString tooltip_;
};
+5 -1
View File
@@ -25,7 +25,6 @@
Sequence::Sequence()
{
set_icon(olive::icon::Sequence);
}
Item::Type Sequence::type() const
@@ -33,6 +32,11 @@ Item::Type Sequence::type() const
return kSequence;
}
QIcon Sequence::icon()
{
return olive::icon::Sequence;
}
const int &Sequence::video_width()
{
return video_width_;
+2
View File
@@ -38,6 +38,8 @@ public:
*/
virtual Type type() const override;
virtual QIcon icon() override;
/* VIDEO GETTER/SETTER FUNCTIONS */
const int& video_width();
+1 -1
View File
@@ -123,7 +123,7 @@ QIcon olive::icon::Create(const QString& theme, const QString &name)
QIcon icon;
for (int i=0;i<ICON_SIZE_COUNT;i++) {
icon.addFile(QString(":/style/%1/png/%2.%3.png").arg(theme, name, QString::number(ICON_SIZES[i])),
icon.addFile(QString("%1/png/%2.%3.png").arg(theme, name, QString::number(ICON_SIZES[i])),
QSize(ICON_SIZES[i], ICON_SIZES[i]));
}
+1
View File
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/style/olive-dark">
<file>palette.ini</file>
<file>style.css</file>
<file>png/add-button.16.png</file>
<file>png/add-button.32.png</file>
+18
View File
@@ -0,0 +1,18 @@
[All]
AlternateBase=#353535
Base=#191919
BrightText=#FF0000
Button=#353535
ButtonText=#FFFFFF
Disabled-ButtonText=#808080
Highlight=#2A82DA
HighlightedText=#FFFFFF
Link=#2A82DA
Text=#FFFFFF
ToolTipBase=#191919
ToolTipText=#FFFFFF
Window=#353535
WindowText=#FFFFFF
[Disabled]
ButtonText=#808080
-50
View File
@@ -18,56 +18,6 @@
***/
/***
Olive Dark - Qt CSS Theme
A fairly basic CSS style for the Olive Video Editor/Qt Fusion.
The primary colors are:
Main: #353535
Text: #ffffff
Disabled Text: #808080
Highlight: #2a82da
Highlight Text: #ffffff
Dark: #191919
**/
/* Default widget colors */
QWidget, QMenu::separator {
/* Main */
background: #353535;
/* Text */
color: #ffffff;
/* Highlight */
selection-background-color: #2a82da;
/* Highlight Text */
selection-color: #ffffff;
}
/* Default disabled colors */
QWidget::disabled {
/* Disabled Text */
color: #808080;
}
/* Default link color */
a {
/* Highlight */
color: #2a82da;
}
/* All of these widgets' backgrounds are dark */
QTreeView, QListView, QLineEdit, QMenu, QProgressBar, QPushButton::checked, NodeView, QComboBox, QSpinBox {
/* Dark */
background: #191919;
}
/* Node styling */
NodeViewItemWidget {
qproperty-titlebarColor: #4040a0;
+1
View File
@@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/style/olive-light">
<file>palette.ini</file>
<file>style.css</file>
<file>png/add-button.16.png</file>
<file>png/add-button.32.png</file>
+17
View File
@@ -0,0 +1,17 @@
[All]
AlternateBase=#D0D0D0
Base=#F0F0F0
BrightText=#FF0000
Button=#D0D0D0
ButtonText=#000000
Highlight=#2A82DA
HighlightedText=#FFFFFF
Link=#2A82DA
Text=#000000
ToolTipBase=#FFFFFF
ToolTipText=#000000
Window=#D0D0D0
WindowText=#000000
[Disabled]
ButtonText=#D0D0D0
-50
View File
@@ -18,56 +18,6 @@
***/
/***
Olive Light - Qt CSS Theme
A fairly basic CSS style for the Olive Video Editor/Qt Fusion.
The primary colors are:
Main: #d0d0d0
Text: #000000
Disabled Text: #808080
Highlight: #2a82da
Highlight Text: #ffffff
Dark: #ffffff
**/
/* Default widget colors */
QWidget, QMenu::separator {
/* Main */
background: #d0d0d0;
/* Text */
color: #000000;
/* Highlight */
selection-background-color: #2a82da;
/* Highlight Text */
selection-color: #ffffff;
}
/* Default disabled colors */
QWidget::disabled {
/* Disabled Text */
color: #808080;
}
/* Default link color */
a {
/* Highlight */
color: #2a82da;
}
/* All of these widgets' backgrounds are dark */
QTreeView, QListView, QLineEdit, QMenu, QProgressBar, QPushButton::checked, NodeView, QComboBox, QSpinBox {
/* Dark */
background: #ffffff;
}
/* Node styling */
NodeViewItemWidget {
qproperty-titlebarColor: #a0a0ff;
+133 -9
View File
@@ -22,6 +22,7 @@
#include <QApplication>
#include <QFile>
#include <QFileInfo>
#include <QPalette>
#include <QStyle>
#include <QStyleFactory>
@@ -29,28 +30,151 @@
#include "ui/icons/icons.h"
void olive::style::AppSetDefault()
QList<StyleDescriptor> StyleManager::ListInternal()
{
// FIXME: Fixed theme, allow the user to set this in-app
SetOliveStyle("olive-dark");
QList<StyleDescriptor> style_list;
style_list.append(StyleDescriptor(tr("Olive Dark"), ":/style/olive-dark"));
style_list.append(StyleDescriptor(tr("Olive Light"), ":/style/olive-light"));
return style_list;
}
void olive::style::SetOliveStyle(const QString &style_name)
QPalette StyleManager::ParsePalette(const QString& ini_path)
{
qApp->setStyle(QStyleFactory::create("Fusion"));
QSettings ini(ini_path, QSettings::IniFormat);
QPalette palette;
ParsePaletteGroup(&ini, &palette, QPalette::All);
ParsePaletteGroup(&ini, &palette, QPalette::Active);
ParsePaletteGroup(&ini, &palette, QPalette::Inactive);
ParsePaletteGroup(&ini, &palette, QPalette::Disabled);
return palette;
}
void StyleManager::ParsePaletteGroup(QSettings *ini, QPalette *palette, QPalette::ColorGroup group)
{
QString group_name;
switch (group) {
case QPalette::All:
group_name = "All";
break;
case QPalette::Active:
group_name = "Active";
break;
case QPalette::Inactive:
group_name = "Inactive";
break;
case QPalette::Disabled:
group_name = "Disabled";
break;
default:
return;
}
ini->beginGroup(group_name);
QStringList keys = ini->childKeys();
foreach (QString k, keys) {
ParsePaletteColor(ini, palette, group, k);
}
ini->endGroup();
}
void StyleManager::ParsePaletteColor(QSettings *ini, QPalette *palette, QPalette::ColorGroup group, const QString &role_name)
{
QPalette::ColorRole role;
if (!QString::compare(role_name, "Window", Qt::CaseInsensitive)) {
role = QPalette::Window;
} else if (!QString::compare(role_name, "WindowText", Qt::CaseInsensitive)) {
role = QPalette::WindowText;
} else if (!QString::compare(role_name, "Base", Qt::CaseInsensitive)) {
role = QPalette::Base;
} else if (!QString::compare(role_name, "AlternateBase", Qt::CaseInsensitive)) {
role = QPalette::AlternateBase;
} else if (!QString::compare(role_name, "ToolTipBase", Qt::CaseInsensitive)) {
role = QPalette::ToolTipBase;
} else if (!QString::compare(role_name, "ToolTipText", Qt::CaseInsensitive)) {
role = QPalette::ToolTipText;
} else if (!QString::compare(role_name, "PlaceholderText", Qt::CaseInsensitive)) {
role = QPalette::PlaceholderText;
} else if (!QString::compare(role_name, "Text", Qt::CaseInsensitive)) {
role = QPalette::Text;
} else if (!QString::compare(role_name, "Button", Qt::CaseInsensitive)) {
role = QPalette::Button;
} else if (!QString::compare(role_name, "ButtonText", Qt::CaseInsensitive)) {
role = QPalette::ButtonText;
} else if (!QString::compare(role_name, "BrightText", Qt::CaseInsensitive)) {
role = QPalette::BrightText;
} else if (!QString::compare(role_name, "Highlight", Qt::CaseInsensitive)) {
role = QPalette::Highlight;
} else if (!QString::compare(role_name, "HighlightedText", Qt::CaseInsensitive)) {
role = QPalette::HighlightedText;
} else if (!QString::compare(role_name, "Link", Qt::CaseInsensitive)) {
role = QPalette::Link;
} else if (!QString::compare(role_name, "LinkVisited", Qt::CaseInsensitive)) {
role = QPalette::LinkVisited;
} else {
return;
}
palette->setColor(group, role, QColor(ini->value(role_name).toString()));
}
StyleDescriptor StyleManager::DefaultStyle()
{
return ListInternal().first();
}
void StyleManager::SetStyle(const StyleDescriptor &style)
{
SetStyle(style.path());
}
void StyleManager::SetStyle(const QString &style_path)
{
// Load all icons for this style (icons must be loaded first because the style change below triggers the icon change)
olive::icon::LoadAll(style_path);
// Set palette for this
QString palette_file = QString("%1/palette.ini").arg(style_path);
if (QFileInfo::exists(palette_file)) {
qApp->setPalette(ParsePalette(palette_file));
} else {
qApp->setPalette(qApp->style()->standardPalette());
}
// Set CSS style for this
QFile css_file(QString(":/style/%1/style.css").arg(style_name));
QFile css_file(QString("%1/style.css").arg(style_path));
if (css_file.open(QFile::ReadOnly | QFile::Text)) {
if (css_file.exists() && css_file.open(QFile::ReadOnly | QFile::Text)) {
// Read in entire CSS from file and set as the application stylesheet
QTextStream css_ts(&css_file);
qApp->setStyleSheet(css_ts.readAll());
css_file.close();
} else {
qApp->setStyleSheet(QString());
}
}
// Load all icons for this style
olive::icon::LoadAll(style_name);
StyleDescriptor::StyleDescriptor(const QString &name, const QString &path) :
name_(name),
path_(path)
{
}
const QString &StyleDescriptor::name() const
{
return name_;
}
const QString &StyleDescriptor::path() const
{
return path_;
}
+29 -13
View File
@@ -21,23 +21,39 @@
#ifndef STYLEMANAGER_H
#define STYLEMANAGER_H
#include <QSettings>
#include <QWidget>
namespace olive {
namespace style {
class StyleDescriptor {
public:
StyleDescriptor(const QString& name, const QString& path);
/**
* @brief Sets the application style to "Olive Default"
*
* This function should probably be replaced (or at least renamed) later as alternative styles are reimplemented.
* At the moment, this is a convenience function for setting to "Olive Default" which is a cross-platform default
* style used in Olive.
*/
void AppSetDefault();
const QString& name() const;
const QString& path() const;
void SetOliveStyle(const QString& style_name);
private:
QString name_;
QString path_;
};
}
}
class StyleManager : public QObject {
public:
StyleManager();
static StyleDescriptor DefaultStyle();
static void SetStyle(const StyleDescriptor& style);
static void SetStyle(const QString& style_path);
static QList<StyleDescriptor> ListInternal();
private:
static QPalette ParsePalette(const QString& ini_path);
static void ParsePaletteGroup(QSettings* ini, QPalette* palette, QPalette::ColorGroup group);
static void ParsePaletteColor(QSettings* ini, QPalette* palette, QPalette::ColorGroup group, const QString& role_name);
};
#endif // STYLEMANAGER_H
+1
View File
@@ -14,6 +14,7 @@
# 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(columnedgridlayout)
add_subdirectory(flowlayout)
add_subdirectory(footagecombobox)
add_subdirectory(menu)
@@ -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}
widget/columnedgridlayout/columnedgridlayout.h
widget/columnedgridlayout/columnedgridlayout.cpp
PARENT_SCOPE
)
@@ -0,0 +1,34 @@
#include "columnedgridlayout.h"
ColumnedGridLayout::ColumnedGridLayout(QWidget* parent,
int maximum_columns) :
QGridLayout (parent),
maximum_columns_(maximum_columns)
{
}
void ColumnedGridLayout::Add(QWidget *widget)
{
if (maximum_columns_ > 0) {
int row = count() / maximum_columns_;
int column = count() % maximum_columns_;
addWidget(widget, row, column);
} else {
addWidget(widget);
}
}
int ColumnedGridLayout::MaximumColumns() const
{
return maximum_columns_;
}
void ColumnedGridLayout::SetMaximumColumns(int maximum_columns)
{
maximum_columns_ = maximum_columns;
}
@@ -0,0 +1,27 @@
#ifndef COLUMNEDGRIDLAYOUT_H
#define COLUMNEDGRIDLAYOUT_H
#include <QGridLayout>
/**
* @brief The ColumnedGridLayout class
*
* A simple derivative of QGridLayout that provides a automatic row/column layout based on a specified maximum
* column count.
*/
class ColumnedGridLayout : public QGridLayout
{
Q_OBJECT
public:
ColumnedGridLayout(QWidget* parent = nullptr,
int maximum_columns = 0);
void Add(QWidget* widget);
int MaximumColumns() const;
void SetMaximumColumns(int maximum_columns);
private:
int maximum_columns_;
};
#endif // COLUMNEDGRIDLAYOUT_H
@@ -20,6 +20,8 @@
#include "playbackcontrols.h"
#include <QDebug>
#include <QEvent>
#include <QHBoxLayout>
#include "common/timecodefunctions.h"
@@ -63,28 +65,24 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
lower_middle_layout->addStretch();
// Go To Start Button
QPushButton* go_to_start_btn = new QPushButton();
go_to_start_btn->setIcon(olive::icon::GoToStart);
lower_middle_layout->addWidget(go_to_start_btn);
connect(go_to_start_btn, SIGNAL(clicked(bool)), this, SIGNAL(BeginClicked()));
go_to_start_btn_ = new QPushButton();
lower_middle_layout->addWidget(go_to_start_btn_);
connect(go_to_start_btn_, SIGNAL(clicked(bool)), this, SIGNAL(BeginClicked()));
// Prev Frame Button
QPushButton* prev_frame_btn = new QPushButton();
prev_frame_btn->setIcon(olive::icon::PrevFrame);
lower_middle_layout->addWidget(prev_frame_btn);
connect(prev_frame_btn, SIGNAL(clicked(bool)), this, SIGNAL(PrevFrameClicked()));
prev_frame_btn_ = new QPushButton();
lower_middle_layout->addWidget(prev_frame_btn_);
connect(prev_frame_btn_, SIGNAL(clicked(bool)), this, SIGNAL(PrevFrameClicked()));
// Play/Pause Button
playpause_stack_ = new QStackedWidget();
lower_middle_layout->addWidget(playpause_stack_);
play_btn_ = new QPushButton();
play_btn_->setIcon(olive::icon::Play);
playpause_stack_->addWidget(play_btn_);
connect(play_btn_, SIGNAL(clicked(bool)), this, SIGNAL(PlayClicked()));
pause_btn_ = new QPushButton();
pause_btn_->setIcon(olive::icon::Pause);
playpause_stack_->addWidget(pause_btn_);
connect(pause_btn_, SIGNAL(clicked(bool)), this, SIGNAL(PauseClicked()));
@@ -93,16 +91,14 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
playpause_stack_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Expanding);
// Next Frame Button
QPushButton* next_frame_btn = new QPushButton();
next_frame_btn->setIcon(olive::icon::NextFrame);
lower_middle_layout->addWidget(next_frame_btn);
connect(next_frame_btn, SIGNAL(clicked(bool)), this, SIGNAL(NextFrameClicked()));
next_frame_btn_ = new QPushButton();
lower_middle_layout->addWidget(next_frame_btn_);
connect(next_frame_btn_, SIGNAL(clicked(bool)), this, SIGNAL(NextFrameClicked()));
// Go To End Button
QPushButton* go_to_end_btn = new QPushButton();
go_to_end_btn->setIcon(olive::icon::GoToEnd);
lower_middle_layout->addWidget(go_to_end_btn);
connect(go_to_end_btn, SIGNAL(clicked(bool)), this, SIGNAL(EndClicked()));
go_to_end_btn_ = new QPushButton();
lower_middle_layout->addWidget(go_to_end_btn_);
connect(go_to_end_btn_, SIGNAL(clicked(bool)), this, SIGNAL(EndClicked()));
lower_middle_layout->addStretch();
@@ -119,6 +115,8 @@ PlaybackControls::PlaybackControls(QWidget *parent) :
lower_right_layout->addStretch();
end_tc_lbl_ = new QLabel("00:00:00;00");
lower_right_layout->addWidget(end_tc_lbl_);
UpdateIcons();
}
void PlaybackControls::SetTimecodeEnabled(bool enabled)
@@ -136,7 +134,9 @@ void PlaybackControls::SetTime(const int64_t &r)
{
Q_ASSERT(time_base_.denominator() != 0);
cur_tc_lbl_->setText(olive::timestamp_to_timecode(r, time_base_, kTimecodeDisplay));
cur_tc_lbl_->setText(olive::timestamp_to_timecode(r,
time_base_,
olive::CurrentTimecodeDisplay()));
}
void PlaybackControls::ShowPauseButton()
@@ -149,3 +149,22 @@ void PlaybackControls::ShowPlayButton()
{
playpause_stack_->setCurrentWidget(play_btn_);
}
void PlaybackControls::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
if (e->type() == QEvent::StyleChange) {
UpdateIcons();
}
}
void PlaybackControls::UpdateIcons()
{
go_to_start_btn_->setIcon(olive::icon::GoToStart);
prev_frame_btn_->setIcon(olive::icon::PrevFrame);
play_btn_->setIcon(olive::icon::Play);
pause_btn_->setIcon(olive::icon::Pause);
next_frame_btn_->setIcon(olive::icon::NextFrame);
go_to_end_btn_->setIcon(olive::icon::GoToEnd);
}
@@ -84,7 +84,12 @@ signals:
*/
void EndClicked();
protected:
virtual void changeEvent(QEvent *) override;
private:
void UpdateIcons();
QWidget* lower_left_container_;
QWidget* lower_right_container_;
@@ -93,8 +98,12 @@ private:
rational time_base_;
QPushButton* go_to_start_btn_;
QPushButton* prev_frame_btn_;
QPushButton* play_btn_;
QPushButton* pause_btn_;
QPushButton* next_frame_btn_;
QPushButton* go_to_end_btn_;
QStackedWidget* playpause_stack_;
@@ -36,7 +36,6 @@ ProjectExplorerNavigation::ProjectExplorerNavigation(QWidget *parent) :
// Create "directory up" button
dir_up_btn_ = new QPushButton(this);
dir_up_btn_->setEnabled(false);
dir_up_btn_->setIcon(olive::icon::DirUp);
dir_up_btn_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Preferred);
layout->addWidget(dir_up_btn_);
connect(dir_up_btn_, SIGNAL(clicked(bool)), this, SIGNAL(DirectoryUpClicked()));
@@ -49,14 +48,12 @@ ProjectExplorerNavigation::ProjectExplorerNavigation(QWidget *parent) :
// Create size slider
size_slider_ = new QSlider(this);
size_slider_->setOrientation(Qt::Horizontal);
size_slider_->setMinimum(olive::kProjectIconSizeMinimum);
size_slider_->setMaximum(olive::kProjectIconSizeMaximum);
size_slider_->setValue(olive::kProjectIconSizeDefault);
size_slider_->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Preferred);
layout->addWidget(size_slider_);
connect(size_slider_, SIGNAL(valueChanged(int)), this, SIGNAL(SizeChanged(int)));
Retranslate();
UpdateIcons();
}
void ProjectExplorerNavigation::set_text(const QString &s)
@@ -78,6 +75,8 @@ void ProjectExplorerNavigation::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
} else if (e->type() == QEvent::StyleChange) {
UpdateIcons();
}
QWidget::changeEvent(e);
}
@@ -86,3 +85,11 @@ void ProjectExplorerNavigation::Retranslate()
{
dir_up_btn_->setToolTip(tr("Go to parent folder"));
}
void ProjectExplorerNavigation::UpdateIcons()
{
dir_up_btn_->setIcon(olive::icon::DirUp);
size_slider_->setMinimum(olive::kProjectIconSizeMinimum);
size_slider_->setMaximum(olive::kProjectIconSizeMaximum);
size_slider_->setValue(olive::kProjectIconSizeDefault);
}
@@ -99,6 +99,8 @@ protected:
private:
void Retranslate();
void UpdateIcons();
QPushButton* dir_up_btn_;
QLabel* dir_lbl_;
+15 -8
View File
@@ -34,27 +34,22 @@ ProjectToolbar::ProjectToolbar(QWidget *parent) :
layout->setMargin(0);
new_button_ = new QPushButton();
new_button_->setIcon(olive::icon::New);
connect(new_button_, SIGNAL(clicked(bool)), this, SIGNAL(NewClicked()));
layout->addWidget(new_button_);
open_button_ = new QPushButton();
open_button_->setIcon(olive::icon::Open);
connect(open_button_, SIGNAL(clicked(bool)), this, SIGNAL(OpenClicked()));
layout->addWidget(open_button_);
save_button_ = new QPushButton();
save_button_->setIcon(olive::icon::Save);
connect(save_button_, SIGNAL(clicked(bool)), this, SIGNAL(SaveClicked()));
layout->addWidget(save_button_);
undo_button_ = new QPushButton();
undo_button_->setIcon(olive::icon::Undo);
connect(undo_button_, SIGNAL(clicked(bool)), this, SIGNAL(UndoClicked()));
layout->addWidget(undo_button_);
redo_button_ = new QPushButton();
redo_button_->setIcon(olive::icon::Redo);
connect(redo_button_, SIGNAL(clicked(bool)), this, SIGNAL(RedoClicked()));
layout->addWidget(redo_button_);
@@ -64,19 +59,16 @@ ProjectToolbar::ProjectToolbar(QWidget *parent) :
layout->addWidget(search_field_);
tree_button_ = new QPushButton();
tree_button_->setIcon(olive::icon::TreeView);
tree_button_->setCheckable(true);
connect(tree_button_, SIGNAL(clicked(bool)), this, SLOT(ViewButtonClicked()));
layout->addWidget(tree_button_);
list_button_ = new QPushButton();
list_button_->setIcon(olive::icon::ListView);
list_button_->setCheckable(true);
connect(list_button_, SIGNAL(clicked(bool)), this, SLOT(ViewButtonClicked()));
layout->addWidget(list_button_);
icon_button_ = new QPushButton();
icon_button_->setIcon(olive::icon::IconView);
icon_button_->setCheckable(true);
connect(icon_button_, SIGNAL(clicked(bool)), this, SLOT(ViewButtonClicked()));
layout->addWidget(icon_button_);
@@ -89,6 +81,7 @@ ProjectToolbar::ProjectToolbar(QWidget *parent) :
view_button_group->addButton(icon_button_);
Retranslate();
UpdateIcons();
}
void ProjectToolbar::SetView(olive::ProjectViewType type)
@@ -110,6 +103,8 @@ void ProjectToolbar::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
} else if (e->type() == QEvent::StyleChange) {
UpdateIcons();
}
QWidget::changeEvent(e);
}
@@ -129,6 +124,18 @@ void ProjectToolbar::Retranslate()
icon_button_->setToolTip(tr("Switch to Icon View"));
}
void ProjectToolbar::UpdateIcons()
{
new_button_->setIcon(olive::icon::New);
open_button_->setIcon(olive::icon::Open);
save_button_->setIcon(olive::icon::Save);
undo_button_->setIcon(olive::icon::Undo);
redo_button_->setIcon(olive::icon::Redo);
tree_button_->setIcon(olive::icon::TreeView);
list_button_->setIcon(olive::icon::ListView);
icon_button_->setIcon(olive::icon::IconView);
}
void ProjectToolbar::ViewButtonClicked()
{
// Determine which view button triggered this slot and emit a signal accordingly
@@ -61,6 +61,7 @@ signals:
private:
void Retranslate();
void UpdateIcons();
QPushButton* new_button_;
QPushButton* open_button_;
+1
View File
@@ -51,6 +51,7 @@ TimelineView::TimelineView(QWidget *parent) :
setAlignment(Qt::AlignLeft | Qt::AlignTop);
setDragMode(RubberBandDrag);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
setBackgroundRole(QPalette::Window);
connect(&scene_, SIGNAL(changed(const QList<QRectF>&)), this, SLOT(UpdateSceneRect()));
+2 -2
View File
@@ -83,7 +83,7 @@ void TimelineView::ImportTool::DragEnter(QDragEnterEvent *event)
if (stream->type() == Stream::kImage) {
// Stream is essentially length-less - use config's default image length
footage_duration = kDefaultImageLength;
footage_duration = Config::Current()["DefaultStillLength"].value<rational>();
} else {
// Use duration from file
footage_duration = rational(stream->timebase().numerator() * stream->duration(),
@@ -151,7 +151,7 @@ void TimelineView::ImportTool::DragMove(QDragMoveEvent *event)
int64_t earliest_timestamp = olive::time_to_timestamp(earliest_ghost, parent()->timebase_);
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase_,
kTimecodeDisplay);
olive::CurrentTimecodeDisplay());
QToolTip::showText(QCursor::pos(),
tooltip_text,
parent());
+1 -1
View File
@@ -279,7 +279,7 @@ void TimelineView::PointerTool::ProcessDrag(const QPoint &mouse_pos)
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase_);
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase_,
kTimecodeDisplay,
olive::CurrentTimecodeDisplay(),
true);
QToolTip::showText(QCursor::pos(),
tooltip_text,
+1 -1
View File
@@ -58,7 +58,7 @@ void TimelineView::SlipTool::ProcessDrag(const QPoint &mouse_pos)
int64_t earliest_timestamp = olive::time_to_timestamp(time_movement, parent()->timebase_);
QString tooltip_text = olive::timestamp_to_timecode(earliest_timestamp,
parent()->timebase_,
kTimecodeDisplay,
olive::CurrentTimecodeDisplay(),
true);
QToolTip::showText(QCursor::pos(),
tooltip_text,
+2 -2
View File
@@ -156,7 +156,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
if (text_visible_) {
QFontMetrics fm = p.fontMetrics();
double width_of_second = scale_;
int average_text_width = QFontMetricsWidth(&fm, olive::timestamp_to_timecode(0, timebase_, kTimecodeDisplay));
int average_text_width = QFontMetricsWidth(&fm, olive::timestamp_to_timecode(0, timebase_, olive::CurrentTimecodeDisplay()));
half_average_text_width = average_text_width/2;
while (width_of_second * text_skip < average_text_width) {
text_skip++;
@@ -202,7 +202,7 @@ void TimeRuler::paintEvent(QPaintEvent *)
// Try to draw text here
if (text_visible_ && sec%text_skip == 0) {
QString timecode_string = olive::timestamp_to_timecode(sec, timebase_, kTimecodeDisplay);
QString timecode_string = olive::timestamp_to_timecode(sec, timebase_, olive::CurrentTimecodeDisplay());
int text_x = i;
+37 -17
View File
@@ -34,24 +34,25 @@ Toolbar::Toolbar(QWidget *parent) :
layout_->setMargin(0);
// Create standard tool buttons
btn_pointer_tool_ = CreateToolButton(olive::icon::ToolPointer, olive::tool::kPointer);
btn_edit_tool_ = CreateToolButton(olive::icon::ToolEdit, olive::tool::kEdit);
btn_ripple_tool_ = CreateToolButton(olive::icon::ToolRipple, olive::tool::kRipple);
btn_rolling_tool_ = CreateToolButton(olive::icon::ToolRolling, olive::tool::kRolling);
btn_razor_tool_ = CreateToolButton(olive::icon::ToolRazor, olive::tool::kRazor);
btn_slip_tool_ = CreateToolButton(olive::icon::ToolSlip, olive::tool::kSlip);
btn_slide_tool_ = CreateToolButton(olive::icon::ToolSlide, olive::tool::kSlide);
btn_hand_tool_ = CreateToolButton(olive::icon::ToolHand, olive::tool::kHand);
btn_zoom_tool_ = CreateToolButton(olive::icon::ZoomIn, olive::tool::kZoom);
btn_record_ = CreateToolButton(olive::icon::Record, olive::tool::kRecord);
btn_transition_tool_ = CreateToolButton(olive::icon::ToolTransition, olive::tool::kTransition);
btn_add_ = CreateToolButton(olive::icon::Add, olive::tool::kAdd);
btn_pointer_tool_ = CreateToolButton(olive::tool::kPointer);
btn_edit_tool_ = CreateToolButton(olive::tool::kEdit);
btn_ripple_tool_ = CreateToolButton(olive::tool::kRipple);
btn_rolling_tool_ = CreateToolButton(olive::tool::kRolling);
btn_razor_tool_ = CreateToolButton(olive::tool::kRazor);
btn_slip_tool_ = CreateToolButton(olive::tool::kSlip);
btn_slide_tool_ = CreateToolButton(olive::tool::kSlide);
btn_hand_tool_ = CreateToolButton(olive::tool::kHand);
btn_zoom_tool_ = CreateToolButton(olive::tool::kZoom);
btn_record_ = CreateToolButton(olive::tool::kRecord);
btn_transition_tool_ = CreateToolButton(olive::tool::kTransition);
btn_add_ = CreateToolButton(olive::tool::kAdd);
// Create snapping button, which is not actually a tool, it's a toggle option
btn_snapping_toggle_ = CreateNonToolButton(olive::icon::Snapping);
btn_snapping_toggle_ = CreateNonToolButton();
connect(btn_snapping_toggle_, SIGNAL(clicked(bool)), this, SLOT(SnappingButtonClicked(bool)));
Retranslate();
UpdateIcons();
}
void Toolbar::SetTool(const olive::tool::Tool& tool)
@@ -74,6 +75,8 @@ void Toolbar::changeEvent(QEvent *e)
{
if (e->type() == QEvent::LanguageChange) {
Retranslate();
} else if (e->type() == QEvent::StyleChange) {
UpdateIcons();
}
QWidget::changeEvent(e);
}
@@ -95,10 +98,27 @@ void Toolbar::Retranslate()
btn_snapping_toggle_->setToolTip(tr("Toggle Snapping"));
}
ToolbarButton* Toolbar::CreateToolButton(const QIcon &icon, const olive::tool::Tool& tool)
void Toolbar::UpdateIcons()
{
btn_pointer_tool_->setIcon(olive::icon::ToolPointer);
btn_edit_tool_->setIcon(olive::icon::ToolEdit);
btn_ripple_tool_->setIcon(olive::icon::ToolRipple);
btn_rolling_tool_->setIcon(olive::icon::ToolRolling);
btn_razor_tool_->setIcon(olive::icon::ToolRazor);
btn_slip_tool_->setIcon(olive::icon::ToolSlip);
btn_slide_tool_->setIcon(olive::icon::ToolSlide);
btn_hand_tool_->setIcon(olive::icon::ToolHand);
btn_zoom_tool_->setIcon(olive::icon::ZoomIn);
btn_record_->setIcon(olive::icon::Record);
btn_transition_tool_->setIcon(olive::icon::ToolTransition);
btn_add_->setIcon(olive::icon::Add);
btn_snapping_toggle_->setIcon(olive::icon::Snapping);
}
ToolbarButton* Toolbar::CreateToolButton(const olive::tool::Tool& tool)
{
// Create a ToolbarButton object
ToolbarButton* b = new ToolbarButton(this, icon, tool);
ToolbarButton* b = new ToolbarButton(this, tool);
// Add it to the layout
layout_->addWidget(b);
@@ -112,10 +132,10 @@ ToolbarButton* Toolbar::CreateToolButton(const QIcon &icon, const olive::tool::T
return b;
}
ToolbarButton *Toolbar::CreateNonToolButton(const QIcon &icon)
ToolbarButton *Toolbar::CreateNonToolButton()
{
// Create a ToolbarButton object
ToolbarButton* b = new ToolbarButton(this, icon, olive::tool::kNone);
ToolbarButton* b = new ToolbarButton(this, olive::tool::kNone);
// Add it to the layout
layout_->addWidget(b);
+7 -2
View File
@@ -112,6 +112,11 @@ private:
*/
void Retranslate();
/**
* @brief Update icons after a style change
*/
void UpdateIcons();
/**
* @brief Internal convenience function for creating tool buttons quickly
*
@@ -125,7 +130,7 @@ private:
*
* The created ToolbarButton. The button parent is automatically set to `this`.
*/
ToolbarButton* CreateToolButton(const QIcon &icon, const olive::tool::Tool& tool);
ToolbarButton* CreateToolButton(const olive::tool::Tool& tool);
/**
* @brief Internal convenience function for creating buttons quickly
@@ -138,7 +143,7 @@ private:
*
* The created ToolbarButton. The button parent is automatically set to `this`.
*/
ToolbarButton* CreateNonToolButton(const QIcon &icon);
ToolbarButton* CreateNonToolButton();
/**
* @brief Internal layout used for buttons
+1 -2
View File
@@ -20,12 +20,11 @@
#include "toolbarbutton.h"
ToolbarButton::ToolbarButton(QWidget *parent, const QIcon &icon, const olive::tool::Tool &tool) :
ToolbarButton::ToolbarButton(QWidget *parent, const olive::tool::Tool &tool) :
QPushButton(parent),
tool_(tool)
{
setCheckable(true);
setIcon(icon);
}
const olive::tool::Tool &ToolbarButton::tool()
+1 -5
View File
@@ -38,15 +38,11 @@ public:
*
* QWidget parent. Almost always an instance of Toolbar.
*
* @param icon
*
* Icon to set this QWidget to.
*
* @param tool
*
* Tool object. Must be a member of enum olive::tool::Tool, including kNone if this button does not represent a tool.
*/
ToolbarButton(QWidget* parent, const QIcon& icon, const olive::tool::Tool& tool);
ToolbarButton(QWidget* parent, const olive::tool::Tool& tool);
/**
* @brief Retrieve tool ID that this button represents
+2 -2
View File
@@ -49,7 +49,7 @@ MainMenu::MainMenu(QMainWindow *parent) :
file_menu_->addSeparator();
file_export_item_ = file_menu_->AddItem("export", nullptr, nullptr, "Ctrl+M");
file_menu_->addSeparator();
file_exit_item_ = file_menu_->AddItem("exit", nullptr, nullptr);
file_exit_item_ = file_menu_->AddItem("exit", parent, SLOT(close()), "Ctrl+Q");
//
// EDIT MENU
@@ -289,7 +289,7 @@ MainMenu::MainMenu(QMainWindow *parent) :
tools_menu_->addSeparator();
tools_preferences_item_ = tools_menu_->AddItem("prefs", nullptr, nullptr, "Ctrl+,");
tools_preferences_item_ = tools_menu_->AddItem("prefs", &olive::core, SLOT(DialogPreferencesShow()), "Ctrl+,");
//
// HELP MENU