From b4dd976e907fd42c86dfc4c5bce4be023aebf06b Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Fri, 15 Jan 2021 18:44:34 +1100 Subject: [PATCH] revised UI color system when showing nodes Olive now has a set of colors that categories can be "assigned" to. The timeline also shares the same colors as the NodeView. Colors can be configured per node (aka per clip). --- app/config/config.cpp | 23 +++--- .../tabs/preferencesappearancetab.cpp | 40 +++------- .../tabs/preferencesappearancetab.h | 15 +--- app/node/node.cpp | 45 +++++++++++- app/node/node.h | 28 +++++++ app/panel/timeline/timeline.cpp | 5 ++ app/panel/timeline/timeline.h | 2 + app/ui/CMakeLists.txt | 2 + app/widget/CMakeLists.txt | 1 + app/widget/colorlabelmenu/CMakeLists.txt | 26 +++++++ app/widget/colorlabelmenu/colorlabelmenu.cpp | 73 +++++++++++++++++++ app/widget/colorlabelmenu/colorlabelmenu.h | 52 +++++++++++++ .../colorlabelmenu/colorlabelmenuitem.cpp | 58 +++++++++++++++ .../colorlabelmenu/colorlabelmenuitem.h | 48 ++++++++++++ app/widget/colorwheel/colorswatchwidget.cpp | 8 +- app/widget/menu/CMakeLists.txt | 4 +- app/widget/menu/menushared.cpp | 19 +++++ app/widget/menu/menushared.h | 8 ++ app/widget/panel/panel.h | 2 + app/widget/timelinewidget/timelinewidget.cpp | 13 ++++ app/widget/timelinewidget/timelinewidget.h | 2 + .../timelinewidget/view/timelineview.cpp | 41 ++++++++--- 22 files changed, 443 insertions(+), 72 deletions(-) create mode 100644 app/widget/colorlabelmenu/CMakeLists.txt create mode 100644 app/widget/colorlabelmenu/colorlabelmenu.cpp create mode 100644 app/widget/colorlabelmenu/colorlabelmenu.h create mode 100644 app/widget/colorlabelmenu/colorlabelmenuitem.cpp create mode 100644 app/widget/colorlabelmenu/colorlabelmenuitem.h diff --git a/app/config/config.cpp b/app/config/config.cpp index 45f219c90..c1309a7c0 100644 --- a/app/config/config.cpp +++ b/app/config/config.cpp @@ -90,20 +90,21 @@ void Config::SetDefaults() SetEntryInternal(QStringLiteral("DropWithoutSequenceBehavior"), NodeValue::kInt, ImportTool::kDWSAsk); SetEntryInternal(QStringLiteral("Loop"), NodeValue::kBoolean, false); SetEntryInternal(QStringLiteral("SplitClipsCopyNodes"), NodeValue::kBoolean, true); + SetEntryInternal(QStringLiteral("UseGradients"), NodeValue::kBoolean, true); SetEntryInternal(QStringLiteral("AutoCacheDelay"), NodeValue::kInt, 1000); - SetEntryInternal(QStringLiteral("NodeCatColor0"), NodeValue::kColor, QVariant::fromValue(Color(0.75, 0.75, 0.75))); - SetEntryInternal(QStringLiteral("NodeCatColor1"), NodeValue::kColor, QVariant::fromValue(Color(0.25, 0.25, 0.25))); - SetEntryInternal(QStringLiteral("NodeCatColor2"), NodeValue::kColor, QVariant::fromValue(Color(0.75, 0.75, 0.25))); - SetEntryInternal(QStringLiteral("NodeCatColor3"), NodeValue::kColor, QVariant::fromValue(Color(0.75, 0.25, 0.75))); - SetEntryInternal(QStringLiteral("NodeCatColor4"), NodeValue::kColor, QVariant::fromValue(Color(0.25, 0.75, 0.75))); - SetEntryInternal(QStringLiteral("NodeCatColor5"), NodeValue::kColor, QVariant::fromValue(Color(0.50, 0.50, 0.50))); - SetEntryInternal(QStringLiteral("NodeCatColor6"), NodeValue::kColor, QVariant::fromValue(Color(0.25, 0.75, 0.25))); - SetEntryInternal(QStringLiteral("NodeCatColor7"), NodeValue::kColor, QVariant::fromValue(Color(0.25, 0.25, 0.75))); - SetEntryInternal(QStringLiteral("NodeCatColor8"), NodeValue::kColor, QVariant::fromValue(Color(0.75, 0.25, 0.25))); - SetEntryInternal(QStringLiteral("NodeCatColor9"), NodeValue::kColor, QVariant::fromValue(Color(0.55, 0.55, 0.75))); - SetEntryInternal(QStringLiteral("NodeCatColor10"), NodeValue::kColor, QVariant::fromValue(Color(0.75, 0.55, 0.25))); + SetEntryInternal(QStringLiteral("CatColor0"), NodeValue::kInt, 0); + SetEntryInternal(QStringLiteral("CatColor1"), NodeValue::kInt, 1); + SetEntryInternal(QStringLiteral("CatColor2"), NodeValue::kInt, 2); + SetEntryInternal(QStringLiteral("CatColor3"), NodeValue::kInt, 3); + SetEntryInternal(QStringLiteral("CatColor4"), NodeValue::kInt, 4); + SetEntryInternal(QStringLiteral("CatColor5"), NodeValue::kInt, 5); + SetEntryInternal(QStringLiteral("CatColor6"), NodeValue::kInt, 6); + SetEntryInternal(QStringLiteral("CatColor7"), NodeValue::kInt, 7); + SetEntryInternal(QStringLiteral("CatColor8"), NodeValue::kInt, 8); + SetEntryInternal(QStringLiteral("CatColor9"), NodeValue::kInt, 9); + SetEntryInternal(QStringLiteral("CatColor10"), NodeValue::kInt, 10); SetEntryInternal(QStringLiteral("AudioOutput"), NodeValue::kText, QString()); SetEntryInternal(QStringLiteral("AudioInput"), NodeValue::kText, QString()); diff --git a/app/dialog/preferences/tabs/preferencesappearancetab.cpp b/app/dialog/preferences/tabs/preferencesappearancetab.cpp index 1ad9a6113..2b3ee7cb6 100644 --- a/app/dialog/preferences/tabs/preferencesappearancetab.cpp +++ b/app/dialog/preferences/tabs/preferencesappearancetab.cpp @@ -28,6 +28,8 @@ #include "node/node.h" #include "widget/colorbutton/colorbutton.h" +#include "widget/menu/menushared.h" +#include "ui/colorcoding.h" namespace olive { @@ -64,7 +66,7 @@ PreferencesAppearanceTab::PreferencesAppearanceTab() { QGroupBox* color_group = new QGroupBox(); - color_group->setTitle(tr("Node Color Scheme")); + color_group->setTitle(tr("Default Node Colors")); QGridLayout* color_layout = new QGridLayout(color_group); @@ -72,15 +74,10 @@ PreferencesAppearanceTab::PreferencesAppearanceTab() QString cat_name = Node::GetCategoryName(static_cast(i)); color_layout->addWidget(new QLabel(cat_name), i, 0); - Color c = Config::Current()[QStringLiteral("NodeCatColor%1").arg(i)].value(); - colors_.append(c.toQColor()); - - QPushButton* color_btn = new QPushButton(); - connect(color_btn, &QPushButton::clicked, this, &PreferencesAppearanceTab::ColorButtonClicked); - color_layout->addWidget(color_btn, i, 1); - color_btns_.append(color_btn); - - UpdateButtonColor(i); + ColorCodingComboBox* ccc = new ColorCodingComboBox(); + ccc->SetColor(Config::Current()[QStringLiteral("CatColor%1").arg(i)].toInt()); + color_layout->addWidget(ccc, i, 1); + color_btns_.append(ccc); } appearance_layout->addWidget(color_group, row, 0, 1, 2); @@ -98,27 +95,8 @@ void PreferencesAppearanceTab::Accept() Config::Current()["Style"] = style_path; } - for (int i=0;isetStyleSheet(QStringLiteral("background: %1;") - .arg(colors_.at(index).name())); -} - -void PreferencesAppearanceTab::ColorButtonClicked() -{ - int index = color_btns_.indexOf(static_cast(sender())); - - QColor new_color = QColorDialog::getColor(colors_.at(index), this); - - if (new_color.isValid()) { - colors_.replace(index, new_color); - - UpdateButtonColor(index); + for (int i=0; iGetSelectedColor(); } } diff --git a/app/dialog/preferences/tabs/preferencesappearancetab.h b/app/dialog/preferences/tabs/preferencesappearancetab.h index 6e3e82751..135673621 100644 --- a/app/dialog/preferences/tabs/preferencesappearancetab.h +++ b/app/dialog/preferences/tabs/preferencesappearancetab.h @@ -27,6 +27,7 @@ #include "preferencestab.h" #include "ui/style/style.h" +#include "widget/colorlabelmenu/colorcodingcombobox.h" namespace olive { @@ -39,24 +40,12 @@ public: 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(); - - void UpdateButtonColor(int index); - /** * @brief UI widget for selecting the current UI style */ QComboBox* style_combobox_; - QList colors_; - - QList color_btns_; - -private slots: - void ColorButtonClicked(); + QVector color_btns_; }; diff --git a/app/node/node.cpp b/app/node/node.cpp index 9a112f7c9..f712efe71 100644 --- a/app/node/node.cpp +++ b/app/node/node.cpp @@ -27,15 +27,18 @@ #include "common/timecodefunctions.h" #include "common/xmlutils.h" +#include "config/config.h" #include "project/project.h" #include "project/item/footage/footage.h" #include "project/item/footage/videostream.h" +#include "ui/colorcoding.h" #include "widget/nodeview/nodeviewundo.h" namespace olive { Node::Node() : - can_be_deleted_(true) + can_be_deleted_(true), + override_color_(-1) { } @@ -99,6 +102,8 @@ void Node::Load(QXmlStreamReader *reader, XMLNodeData& xml_node_data, const QAto SetPosition(p); } else if (reader->name() == QStringLiteral("label")) { SetLabel(reader->readElementText()); + } else if (reader->name() == QStringLiteral("color")) { + override_color_ = reader->readElementText().toInt(); } else if (reader->name() == QStringLiteral("custom")) { LoadInternal(reader, xml_node_data); } else { @@ -117,6 +122,7 @@ void Node::Save(QXmlStreamWriter *writer) const writer->writeEndElement(); // pos writer->writeTextElement(QStringLiteral("label"), GetLabel()); + writer->writeTextElement(QStringLiteral("color"), QString::number(override_color_)); foreach (NodeInput* input, inputs_) { writer->writeStartElement(QStringLiteral("input")); @@ -146,6 +152,43 @@ void Node::Retranslate() { } +Color Node::color() const +{ + int c; + + if (override_color_ >= 0) { + c = override_color_; + } else { + c = Config::Current()[QStringLiteral("CatColor%1").arg(this->Category().first())].toInt(); + } + + return ColorCoding::GetColor(c); +} + +QLinearGradient Node::gradient_color(qreal top, qreal bottom) const +{ + QLinearGradient grad; + + grad.setStart(0, top); + grad.setFinalStop(0, bottom); + + QColor c = color().toQColor(); + + grad.setColorAt(0.0, c.lighter()); + grad.setColorAt(1.0, c); + + return grad; +} + +QBrush Node::brush(qreal top, qreal bottom) const +{ + if (Config::Current()[QStringLiteral("UseGradients")].toBool()) { + return gradient_color(top, bottom); + } else { + return color().toQColor(); + } +} + void Node::RemoveNodesAndExclusiveDependencies(Node *node, QUndoCommand *command) { // Remove main node diff --git a/app/node/node.h b/app/node/node.h index abaad408d..de3fe922d 100644 --- a/app/node/node.h +++ b/app/node/node.h @@ -154,6 +154,29 @@ public: */ virtual void Retranslate(); + /** + * @brief Retrieve the color of this node + */ + Color color() const; + + /** + * @brief Same as color() but return a pretty gradient version + */ + QLinearGradient gradient_color(qreal top, qreal bottom) const; + + /** + * @brief Uses config and returns either color() for flat shading or gradient for gradient + */ + QBrush brush(qreal top, qreal bottom) const; + + /** + * @brief Sets the override color. Set to -1 for no override color. + */ + void SetOverrideColor(int index) + { + override_color_ = index; + } + /** * @brief Return a list of NodeParams */ @@ -485,6 +508,11 @@ private: */ QString label_; + /** + * @brief -1 if the color should be based on the category, >=0 if the user has set a custom color + */ + int override_color_; + }; template diff --git a/app/panel/timeline/timeline.cpp b/app/panel/timeline/timeline.cpp index 82ddffe63..f2681140b 100644 --- a/app/panel/timeline/timeline.cpp +++ b/app/panel/timeline/timeline.cpp @@ -165,6 +165,11 @@ void TimelinePanel::ToggleSelectedEnabled() static_cast(GetTimeBasedWidget())->ToggleSelectedEnabled(); } +void TimelinePanel::SetColorLabel(int index) +{ + static_cast(GetTimeBasedWidget())->SetColorLabel(index); +} + void TimelinePanel::InsertFootageAtPlayhead(const QVector &footage) { static_cast(GetTimeBasedWidget())->InsertFootageAtPlayhead(footage); diff --git a/app/panel/timeline/timeline.h b/app/panel/timeline/timeline.h index 5e80b222b..e3076ed35 100644 --- a/app/panel/timeline/timeline.h +++ b/app/panel/timeline/timeline.h @@ -83,6 +83,8 @@ public: virtual void ToggleSelectedEnabled() override; + virtual void SetColorLabel(int index) override; + void InsertFootageAtPlayhead(const QVector &footage); void OverwriteFootageAtPlayhead(const QVector &footage); diff --git a/app/ui/CMakeLists.txt b/app/ui/CMakeLists.txt index 793f616e7..dc29635a4 100644 --- a/app/ui/CMakeLists.txt +++ b/app/ui/CMakeLists.txt @@ -26,5 +26,7 @@ set(OLIVE_RESOURCES set(OLIVE_SOURCES ${OLIVE_SOURCES} + ui/colorcoding.cpp + ui/colorcoding.h PARENT_SCOPE ) diff --git a/app/widget/CMakeLists.txt b/app/widget/CMakeLists.txt index 15a58c87f..eee700c68 100644 --- a/app/widget/CMakeLists.txt +++ b/app/widget/CMakeLists.txt @@ -18,6 +18,7 @@ add_subdirectory(audiomonitor) add_subdirectory(clickablelabel) add_subdirectory(collapsebutton) add_subdirectory(colorbutton) +add_subdirectory(colorlabelmenu) add_subdirectory(colorwheel) add_subdirectory(columnedgridlayout) add_subdirectory(curvewidget) diff --git a/app/widget/colorlabelmenu/CMakeLists.txt b/app/widget/colorlabelmenu/CMakeLists.txt new file mode 100644 index 000000000..c4defa387 --- /dev/null +++ b/app/widget/colorlabelmenu/CMakeLists.txt @@ -0,0 +1,26 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2020 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 . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + widget/colorlabelmenu/colorcodingcombobox.cpp + widget/colorlabelmenu/colorcodingcombobox.h + widget/colorlabelmenu/colorlabelmenu.cpp + widget/colorlabelmenu/colorlabelmenu.h + widget/colorlabelmenu/colorlabelmenuitem.cpp + widget/colorlabelmenu/colorlabelmenuitem.h + PARENT_SCOPE +) diff --git a/app/widget/colorlabelmenu/colorlabelmenu.cpp b/app/widget/colorlabelmenu/colorlabelmenu.cpp new file mode 100644 index 000000000..37d8f7c13 --- /dev/null +++ b/app/widget/colorlabelmenu/colorlabelmenu.cpp @@ -0,0 +1,73 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2020 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 . + +***/ + +#include "colorlabelmenu.h" + +#include +#include + +#include "ui/colorcoding.h" + +namespace olive { + +ColorLabelMenu::ColorLabelMenu(QWidget *parent) : + Menu(parent) +{ + for (int i=0; iSetColor(ColorCoding::standard_colors().at(i)); + color_items_.append(item); + + QWidgetAction* a = new QWidgetAction(this); + Menu::ConformItem(a, QStringLiteral("colorlabel%1").arg(i), this, &ColorLabelMenu::ActionTriggered); + a->setData(i); + a->setDefaultWidget(item); + + this->addAction(a); + } + + Retranslate(); +} + +void ColorLabelMenu::changeEvent(QEvent *event) +{ + if (event->type() == QEvent::LanguageChange) { + Retranslate(); + } + + Menu::changeEvent(event); +} + +void ColorLabelMenu::Retranslate() +{ + this->setTitle(tr("Color")); + + for (int i=0; iSetText(ColorCoding::GetColorName(i)); + } +} + +void ColorLabelMenu::ActionTriggered() +{ + QAction* a = static_cast(sender()); + emit ColorSelected(a->data().toInt()); +} + +} diff --git a/app/widget/colorlabelmenu/colorlabelmenu.h b/app/widget/colorlabelmenu/colorlabelmenu.h new file mode 100644 index 000000000..602445218 --- /dev/null +++ b/app/widget/colorlabelmenu/colorlabelmenu.h @@ -0,0 +1,52 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2020 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 . + +***/ + +#ifndef COLORLABELMENU_H +#define COLORLABELMENU_H + +#include "colorlabelmenuitem.h" +#include "widget/menu/menu.h" + +namespace olive { + +class ColorLabelMenu : public Menu +{ + Q_OBJECT +public: + ColorLabelMenu(QWidget* parent = nullptr); + + virtual void changeEvent(QEvent* event) override; + +signals: + void ColorSelected(int i); + +private: + void Retranslate(); + + QVector color_items_; + +private slots: + void ActionTriggered(); + +}; + +} + +#endif // COLORLABELMENU_H diff --git a/app/widget/colorlabelmenu/colorlabelmenuitem.cpp b/app/widget/colorlabelmenu/colorlabelmenuitem.cpp new file mode 100644 index 000000000..fdd466a32 --- /dev/null +++ b/app/widget/colorlabelmenu/colorlabelmenuitem.cpp @@ -0,0 +1,58 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2020 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 . + +***/ + +#include "colorlabelmenuitem.h" + +#include + +#include "ui/style/style.h" + +namespace olive { + +ColorLabelMenuItem::ColorLabelMenuItem(QWidget* parent) : + QWidget(parent) +{ + int text_height = fontMetrics().height(); + int padding = text_height/4; + + QHBoxLayout* layout = new QHBoxLayout(this); + layout->setMargin(padding); + layout->setSpacing(padding); + + box_ = new ColorPreviewBox(); + box_->setFixedSize(text_height, text_height); + layout->addWidget(box_); + + label_ = new QLabel(); + StyleManager::UseOSNativeStyling(label_); + layout->addWidget(label_); +} + +void ColorLabelMenuItem::SetText(const QString &text) +{ + label_->setText(text); +} + +void ColorLabelMenuItem::SetColor(const Color &color) +{ + box_->SetColor(color); +} + +} diff --git a/app/widget/colorlabelmenu/colorlabelmenuitem.h b/app/widget/colorlabelmenu/colorlabelmenuitem.h new file mode 100644 index 000000000..ba91af382 --- /dev/null +++ b/app/widget/colorlabelmenu/colorlabelmenuitem.h @@ -0,0 +1,48 @@ +/*** + + Olive - Non-Linear Video Editor + Copyright (C) 2020 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 . + +***/ + +#ifndef COLORLABELMENUITEM_H +#define COLORLABELMENUITEM_H + +#include +#include + +#include "widget/colorwheel/colorpreviewbox.h" + +namespace olive { + +class ColorLabelMenuItem : public QWidget +{ +public: + ColorLabelMenuItem(QWidget* parent = nullptr); + + void SetText(const QString& text); + + void SetColor(const Color& color); + +private: + ColorPreviewBox* box_; + QLabel* label_; + +}; + +} + +#endif // COLORLABELMENUITEM_H diff --git a/app/widget/colorwheel/colorswatchwidget.cpp b/app/widget/colorwheel/colorswatchwidget.cpp index d0d030b38..a8ec538ef 100644 --- a/app/widget/colorwheel/colorswatchwidget.cpp +++ b/app/widget/colorwheel/colorswatchwidget.cpp @@ -22,6 +22,8 @@ #include +#include "ui/colorcoding.h" + namespace olive { ColorSwatchWidget::ColorSwatchWidget(QWidget *parent) : @@ -75,11 +77,7 @@ void ColorSwatchWidget::SelectedColorChangedEvent(const Color &, bool) Qt::GlobalColor ColorSwatchWidget::GetUISelectorColor() const { - if (GetSelectedColor().GetRoughLuminance() > 0.66) { - return Qt::black; - } else { - return Qt::white; - } + return ColorCoding::GetUISelectorColor(GetSelectedColor()); } Color ColorSwatchWidget::GetManagedColor(const Color &input) const diff --git a/app/widget/menu/CMakeLists.txt b/app/widget/menu/CMakeLists.txt index c1281270b..f4957d470 100644 --- a/app/widget/menu/CMakeLists.txt +++ b/app/widget/menu/CMakeLists.txt @@ -16,9 +16,9 @@ set(OLIVE_SOURCES ${OLIVE_SOURCES} - widget/menu/menu.h widget/menu/menu.cpp - widget/menu/menushared.h + widget/menu/menu.h widget/menu/menushared.cpp + widget/menu/menushared.h PARENT_SCOPE ) diff --git a/app/widget/menu/menushared.cpp b/app/widget/menu/menushared.cpp index 9701ec9a6..1589d000d 100644 --- a/app/widget/menu/menushared.cpp +++ b/app/widget/menu/menushared.cpp @@ -86,9 +86,18 @@ MenuShared::MenuShared() view_timecode_view_milliseconds_item_->setCheckable(true); frame_view_mode_group_->addAction(view_timecode_view_milliseconds_item_); + // Color coding menu items + color_coding_menu_ = new ColorLabelMenu(); + connect(color_coding_menu_, &ColorLabelMenu::ColorSelected, this, &MenuShared::ColorLabelTriggered); + Retranslate(); } +MenuShared::~MenuShared() +{ + delete color_coding_menu_; +} + void MenuShared::CreateInstance() { instance_ = new MenuShared(); @@ -137,6 +146,11 @@ void MenuShared::AddItemsForInOutMenu(Menu *m) m->addAction(inout_clear_inout_item_); } +void MenuShared::AddColorCodingMenu(Menu *m) +{ + m->addMenu(color_coding_menu_); +} + void MenuShared::AddItemsForClipEditMenu(Menu *m) { m->addAction(clip_add_default_transition_item_); @@ -271,6 +285,11 @@ void MenuShared::TimecodeDisplayTriggered() Core::instance()->SetTimecodeDisplay(display); } +void MenuShared::ColorLabelTriggered(int color_index) +{ + PanelManager::instance()->CurrentlyFocused()->SetColorLabel(color_index); +} + void MenuShared::Retranslate() { // "New" menu shared items diff --git a/app/widget/menu/menushared.h b/app/widget/menu/menushared.h index 60d0b6989..ae0707833 100644 --- a/app/widget/menu/menushared.h +++ b/app/widget/menu/menushared.h @@ -21,6 +21,7 @@ #ifndef MENUSHARED_H #define MENUSHARED_H +#include "widget/colorlabelmenu/colorlabelmenu.h" #include "widget/menu/menu.h" namespace olive { @@ -32,6 +33,7 @@ class MenuShared : public QObject { Q_OBJECT public: MenuShared(); + virtual ~MenuShared() override; static void CreateInstance(); static void DestroyInstance(); @@ -41,6 +43,7 @@ public: void AddItemsForNewMenu(Menu* m); void AddItemsForEditMenu(Menu* m, bool for_clips); void AddItemsForInOutMenu(Menu* m); + void AddColorCodingMenu(Menu* m); void AddItemsForClipEditMenu(Menu* m); void AddItemsForTimeRulerMenu(Menu* m); @@ -85,6 +88,9 @@ private: QAction* view_timecode_view_frames_item_; QAction* view_timecode_view_milliseconds_item_; + // Color coding menu items + ColorLabelMenu* color_coding_menu_; + static MenuShared* instance_; private slots: @@ -130,6 +136,8 @@ private slots: */ void TimecodeDisplayTriggered(); + void ColorLabelTriggered(int color_index); + }; } diff --git a/app/widget/panel/panel.h b/app/widget/panel/panel.h index 939baa2af..4ab26c87a 100644 --- a/app/widget/panel/panel.h +++ b/app/widget/panel/panel.h @@ -168,6 +168,8 @@ public: virtual void Duplicate(){} + virtual void SetColorLabel(int){} + signals: void CloseRequested(); diff --git a/app/widget/timelinewidget/timelinewidget.cpp b/app/widget/timelinewidget/timelinewidget.cpp index b6ff735f3..cca67d7ba 100644 --- a/app/widget/timelinewidget/timelinewidget.cpp +++ b/app/widget/timelinewidget/timelinewidget.cpp @@ -700,6 +700,15 @@ void TimelineWidget::ToggleSelectedEnabled() Core::instance()->undo_stack()->pushIfHasChildren(command); } +void TimelineWidget::SetColorLabel(int index) +{ + foreach (Block* b, selected_blocks_) { + b->SetOverrideColor(index); + } + + UpdateViewports(); +} + void TimelineWidget::InsertGapsAt(const rational &earliest_point, const rational &insert_length, QUndoCommand *command) { for (int i=0;iAddColorCodingMenu(&menu); + + menu.addSeparator(); + QAction* properties_action = menu.addAction(tr("Properties")); connect(properties_action, &QAction::triggered, this, [this](){ QVector block_items = GetSelectedBlocks(); diff --git a/app/widget/timelinewidget/timelinewidget.h b/app/widget/timelinewidget/timelinewidget.h index 449c071c5..6d5b19960 100644 --- a/app/widget/timelinewidget/timelinewidget.h +++ b/app/widget/timelinewidget/timelinewidget.h @@ -89,6 +89,8 @@ public: void ToggleSelectedEnabled(); + void SetColorLabel(int index); + const QVector& GetSelectedBlocks() const { return selected_blocks_; diff --git a/app/widget/timelinewidget/view/timelineview.cpp b/app/widget/timelinewidget/view/timelineview.cpp index ecf821ad8..9fcb3ef5b 100644 --- a/app/widget/timelinewidget/view/timelineview.cpp +++ b/app/widget/timelinewidget/view/timelineview.cpp @@ -32,6 +32,7 @@ #include "common/timecodefunctions.h" #include "node/input/media/media.h" #include "project/item/footage/footage.h" +#include "ui/colorcoding.h" namespace olive { @@ -386,8 +387,11 @@ TimelineViewMouseEvent TimelineView::CreateMouseEvent(const QPoint& pos, Qt::Mou void TimelineView::DrawBlocks(QPainter *painter, bool foreground) { - rational start_time = SceneToTime(0); - rational end_time = SceneToTime(viewport()->width()); + qreal left_bound = horizontalScrollBar()->value(); + qreal right_bound = viewport()->width() + horizontalScrollBar()->value(); + + rational start_time = SceneToTime(left_bound); + rational end_time = SceneToTime(right_bound); foreach (Track* track, connected_track_list_->GetTracks()) { // Get first visible block in this track @@ -396,22 +400,41 @@ void TimelineView::DrawBlocks(QPainter *painter, bool foreground) while (block) { if (block->type() == Block::kClip) { - qreal block_left = qMax(0.0, TimeToScene(block->in())); - qreal block_right = qMin(qreal(viewport()->width()), TimeToScene(block->out())); + qreal block_left = qMax(left_bound, TimeToScene(block->in())); + qreal block_right = qMin(right_bound, TimeToScene(block->out())) - 1; + qreal block_top = GetTrackY(track->Index()); + qreal block_height = GetTrackHeight(track->Index()); QRectF r(block_left, - GetTrackY(track->Index()), + block_top, block_right - block_left, - GetTrackHeight(track->Index())); + block_height); + + QColor shadow_color = block->color().toQColor().darker(); if (foreground) { - painter->setPen(Qt::white); painter->setBrush(Qt::NoBrush); + + painter->setPen(block->is_enabled() ? ColorCoding::GetUISelectorColor(block->color()) : Qt::lightGray); painter->drawText(r, block->GetLabel()); + + qreal line_bottom = block_top+block_height-1; + + painter->setPen(Qt::white); + painter->drawLine(block_left, block_top, block_right, block_top); + painter->drawLine(block_left, block_top, block_left, line_bottom); + + painter->setPen(shadow_color); + painter->drawLine(block_left, line_bottom, block_right, line_bottom); + painter->drawLine(block_right, line_bottom, block_right, block_top); } else { painter->setPen(Qt::NoPen); - painter->setBrush(QColor(128, 128, 192)); + painter->setBrush(block->is_enabled() ? block->brush(block_top, block_top + block_height) : Qt::gray); painter->drawRect(r); + + // Draw waveform + painter->setPen(shadow_color); + AudioVisualWaveform::DrawWaveform(painter, r.toRect(), this->GetScale(), track->waveform(), SceneToTime(block_left)); } } @@ -493,7 +516,7 @@ void TimelineView::ConnectTrackList(TrackList *list) void TimelineView::SetBeamCursor(const TimelineCoordinate &coord) { bool update_required = coord.GetTrack().type() == connected_track_list_->type() - || cursor_coord_.GetTrack().type() == connected_track_list_->type(); + || cursor_coord_.GetTrack().type() == connected_track_list_->type(); show_beam_cursor_ = true; cursor_coord_ = coord;