Merge pull request #1338 from VodBox/scene-item-colors

UI: Add Color Coding to Source Tree Widget
master
Jim 2018-08-01 17:42:29 -07:00 committed by GitHub
commit 324071f5a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 567 additions and 1 deletions

View File

@ -236,6 +236,7 @@ set(obs_UI
forms/AutoConfigVideoPage.ui
forms/AutoConfigStreamPage.ui
forms/AutoConfigTestPage.ui
forms/ColorSelect.ui
forms/OBSLicenseAgreement.ui
forms/OBSLogReply.ui
forms/OBSBasic.ui

View File

@ -850,3 +850,7 @@ FinalScene.Text="There needs to be at least one scene."
NoSources.Title="No Sources"
NoSources.Text="It looks like you haven't added any video sources yet, so you will only be outputting a blank screen. Are you sure you want to do this?"
NoSources.Text.AddSource="You can add sources by clicking the + icon under the Sources box in the main window at any time."
# Scene item color selection
ChangeBG="Set Color"
CustomColor="Custom Color"

265
UI/forms/ColorSelect.ui Normal file
View File

@ -0,0 +1,265 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ColorSelect</class>
<widget class="QWidget" name="ColorSelect">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>98</width>
<height>61</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
border: 1px solid black;
}</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QPushButton" name="preset1">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string/>
</property>
<property name="preset" stdset="0">
<string>1</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="preset2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="preset" stdset="0">
<string>2</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QPushButton" name="preset3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="preset" stdset="0">
<string>3</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="preset4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="preset" stdset="0">
<string>4</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="preset5">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="preset" stdset="0">
<string>5</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="preset6">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="preset" stdset="0">
<string>6</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="preset7">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="preset" stdset="0">
<string>7</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="preset8">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="preset8" stdset="0">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources>
<include location="obs.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -39,6 +39,23 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
obs_source_t *source = obs_sceneitem_get_source(sceneitem);
const char *name = obs_source_get_name(source);
obs_data_t *privData = obs_sceneitem_get_private_settings(sceneitem);
int preset = obs_data_get_int(privData, "color-preset");
if (preset == 1) {
const char *color = obs_data_get_string(privData, "color");
std::string col = "background: ";
col += color;
setStyleSheet(col.c_str());
} else if (preset > 1) {
setStyleSheet("");
setProperty("bgColor", preset - 1);
} else {
setStyleSheet("background: none");
}
obs_data_release(privData);
vis = new VisibilityCheckBox();
vis->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
vis->setMaximumSize(16, 16);
@ -88,6 +105,16 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_)
connect(lock, &QAbstractButton::clicked, setItemLocked);
}
void SourceTreeItem::paintEvent(QPaintEvent *event)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
QWidget::paintEvent(event);
}
void SourceTreeItem::DisconnectSignals()
{
sceneRemoveSignal.Disconnect();
@ -836,6 +863,15 @@ SourceTree::SourceTree(QWidget *parent_) : QListView(parent_)
{
SourceTreeModel *stm_ = new SourceTreeModel(this);
setModel(stm_);
setStyleSheet(QString(
"*[bgColor=\"1\"]{background-color:rgba(255,68,68,33%);}" \
"*[bgColor=\"2\"]{background-color:rgba(255,255,68,33%);}" \
"*[bgColor=\"3\"]{background-color:rgba(68,255,68,33%);}" \
"*[bgColor=\"4\"]{background-color:rgba(68,255,255,33%);}" \
"*[bgColor=\"5\"]{background-color:rgba(68,68,255,33%);}" \
"*[bgColor=\"6\"]{background-color:rgba(255,68,255,33%);}" \
"*[bgColor=\"7\"]{background-color:rgba(68,68,68,33%);}" \
"*[bgColor=\"8\"]{background-color:rgba(255,255,255,33%);}"));
}
void SourceTree::ResetWidgets()

View File

@ -67,6 +67,8 @@ private:
OBSSignal renameSignal;
OBSSignal removeSignal;
virtual void paintEvent(QPaintEvent* event) override;
private slots:
void EnterEditMode();
void ExitEditMode(bool save);
@ -134,13 +136,13 @@ class SourceTree : public QListView {
return reinterpret_cast<SourceTreeModel *>(model());
}
public:
inline SourceTreeItem *GetItemWidget(int idx)
{
QWidget *widget = indexWidget(GetStm()->createIndex(idx, 0));
return reinterpret_cast<SourceTreeItem *>(widget);
}
public:
explicit SourceTree(QWidget *parent = nullptr);
inline bool IgnoreReorder() const {return ignoreReorder;}

View File

@ -27,6 +27,9 @@
#include <QDesktopWidget>
#include <QRect>
#include <QScreen>
#include <QColorDialog>
#include <QWidgetAction>
#include <QSizePolicy>
#include <util/dstr.h>
#include <util/util.hpp>
@ -61,6 +64,7 @@
#endif
#include "ui_OBSBasic.h"
#include "ui_ColorSelect.h"
#include <fstream>
#include <sstream>
@ -3959,6 +3963,63 @@ QMenu *OBSBasic::AddScaleFilteringMenu(obs_sceneitem_t *item)
return menu;
}
QMenu *OBSBasic::AddBackgroundColorMenu(obs_sceneitem_t *item)
{
QMenu *menu = new QMenu(QTStr("ChangeBG"));
QAction *action;
menu->setStyleSheet(QString(
"*[bgColor=\"1\"]{background-color:rgba(255,68,68,33%);}" \
"*[bgColor=\"2\"]{background-color:rgba(255,255,68,33%);}" \
"*[bgColor=\"3\"]{background-color:rgba(68,255,68,33%);}" \
"*[bgColor=\"4\"]{background-color:rgba(68,255,255,33%);}" \
"*[bgColor=\"5\"]{background-color:rgba(68,68,255,33%);}" \
"*[bgColor=\"6\"]{background-color:rgba(255,68,255,33%);}" \
"*[bgColor=\"7\"]{background-color:rgba(68,68,68,33%);}" \
"*[bgColor=\"8\"]{background-color:rgba(255,255,255,33%);}"));
obs_data_t *privData = obs_sceneitem_get_private_settings(item);
obs_data_release(privData);
obs_data_set_default_int(privData, "color-preset", 0);
int preset = obs_data_get_int(privData, "color-preset");
action = menu->addAction(QTStr("Clear"), this,
+ SLOT(ColorChange()));
action->setCheckable(true);
action->setProperty("bgColor", 0);
action->setChecked(preset == 0);
action = menu->addAction(QTStr("CustomColor"), this,
+ SLOT(ColorChange()));
action->setCheckable(true);
action->setProperty("bgColor", 1);
action->setChecked(preset == 1);
menu->addSeparator();
QWidgetAction *widgetAction = new QWidgetAction(menu);
ColorSelect *select = new ColorSelect(menu);
widgetAction->setDefaultWidget(select);
for (int i = 1; i < 9; i++) {
stringstream button;
button << "preset" << i;
QPushButton *colorButton = select->findChild<QPushButton *>(
button.str().c_str());
if (preset == i + 1)
colorButton->setStyleSheet("border: 2px solid black");
colorButton->setProperty("bgColor", i);
select->connect(colorButton, SIGNAL(released()), this,
SLOT(ColorChange()));
}
menu->addAction(widgetAction);
return menu;
}
void OBSBasic::CreateSourcePopupMenu(int idx, bool preview)
{
QMenu popup(this);
@ -4035,6 +4096,7 @@ void OBSBasic::CreateSourcePopupMenu(int idx, bool preview)
OBS_SOURCE_AUDIO;
QAction *action;
popup.addMenu(AddBackgroundColorMenu(sceneItem));
popup.addAction(QTStr("Rename"), this,
SLOT(EditSceneItemName()));
popup.addAction(QTStr("Remove"), this,
@ -6327,6 +6389,180 @@ void OBSBasic::on_actionPasteFilters_triggered()
obs_source_copy_filters(dstSource, source);
}
static void ConfirmColor(SourceTree *sources, const QColor &color,
QModelIndexList selectedItems)
{
for (int x = 0; x < selectedItems.count(); x++) {
SourceTreeItem *treeItem = sources
->GetItemWidget(selectedItems[x].row());
treeItem->setStyleSheet("background: "
+ color.name(QColor::HexArgb));
treeItem->style()->unpolish(treeItem);
treeItem->style()->polish(treeItem);
OBSSceneItem sceneItem = sources->Get(
selectedItems[x].row());
obs_data_t *privData =
obs_sceneitem_get_private_settings(sceneItem);
obs_data_set_int(privData, "color-preset", 1);
obs_data_set_string(privData, "color",
QT_TO_UTF8(color.name(
QColor::HexArgb)));
obs_data_release(privData);
}
}
void OBSBasic::ColorChange()
{
QModelIndexList selectedItems =
ui->sources->selectionModel()->selectedIndexes();
QAction *action = qobject_cast<QAction*>(sender());
QPushButton *colorButton = qobject_cast<QPushButton*>(sender());
if (selectedItems.count() == 0)
return;
if (colorButton) {
int preset = colorButton->property("bgColor").value<int>();
for (int x = 0; x < selectedItems.count(); x++) {
SourceTreeItem *treeItem = ui->sources
->GetItemWidget(selectedItems[x].row());
treeItem->setStyleSheet("");
treeItem->setProperty("bgColor", preset);
treeItem->style()->unpolish(treeItem);
treeItem->style()->polish(treeItem);
OBSSceneItem sceneItem = ui->sources->Get(
selectedItems[x].row());
obs_data_t *privData =
obs_sceneitem_get_private_settings(sceneItem);
obs_data_set_int(privData, "color-preset", preset + 1);
obs_data_set_string(privData, "color", "");
obs_data_release(privData);
}
for (int i = 1; i < 9; i++) {
stringstream button;
button << "preset" << i;
QPushButton *cButton = colorButton->parentWidget()
->findChild<QPushButton *>(button.str().c_str());
cButton->setStyleSheet("border: 1px solid black");
}
colorButton->setStyleSheet("border: 2px solid black");
} else if (action) {
int preset = action->property("bgColor").value<int>();
if (preset == 1) {
OBSSceneItem curSceneItem = GetCurrentSceneItem();
SourceTreeItem *curTreeItem =
GetItemWidgetFromSceneItem(curSceneItem);
obs_data_t *curPrivData =
obs_sceneitem_get_private_settings(curSceneItem);
int oldPreset = obs_data_get_int(
curPrivData, "color-preset");
const QString oldSheet = curTreeItem->styleSheet();
auto liveChangeColor = [=](const QColor &color) {
if (color.isValid()) {
curTreeItem->setStyleSheet(
"background: "
+ color.name(QColor::HexArgb));
}
};
auto changedColor = [=](const QColor &color) {
if (color.isValid()) {
ConfirmColor(ui->sources, color,
selectedItems);
}
};
auto rejected = [=]() {
if (oldPreset == 1) {
curTreeItem->setStyleSheet(oldSheet);
curTreeItem->setProperty("bgColor", 0);
} else if (oldPreset == 0) {
curTreeItem->setStyleSheet(
"background: none");
curTreeItem->setProperty("bgColor", 0);
} else {
curTreeItem->setStyleSheet("");
curTreeItem->setProperty("bgColor",
oldPreset - 1);
}
curTreeItem->style()->unpolish(curTreeItem);
curTreeItem->style()->polish(curTreeItem);
};
QColorDialog::ColorDialogOptions options =
QColorDialog::ShowAlphaChannel;
const char *oldColor = obs_data_get_string(curPrivData,
"color");
const char *customColor = *oldColor != 0 ? oldColor
: "#55FF0000";
#ifdef __APPLE__
options |= QColorDialog::DontUseNativeDialog;
#endif
QColorDialog *colorDialog = new QColorDialog(this);
colorDialog->setOptions(options);
colorDialog->setCurrentColor(
QColor(customColor));
connect(colorDialog, &QColorDialog::currentColorChanged,
liveChangeColor);
connect(colorDialog, &QColorDialog::colorSelected,
changedColor);
connect(colorDialog, &QColorDialog::rejected,
rejected);
colorDialog->open();
obs_data_release(curPrivData);
} else {
for (int x = 0; x < selectedItems.count(); x++) {
SourceTreeItem *treeItem = ui->sources
->GetItemWidget(selectedItems[x].row());
treeItem->setStyleSheet("background: none");
treeItem->setProperty("bgColor", preset);
treeItem->style()->unpolish(treeItem);
treeItem->style()->polish(treeItem);
OBSSceneItem sceneItem = ui->sources->Get(
selectedItems[x].row());
obs_data_t *privData =
obs_sceneitem_get_private_settings(
sceneItem);
obs_data_set_int(privData, "color-preset",
preset);
obs_data_set_string(privData, "color", "");
obs_data_release(privData);
}
}
}
}
SourceTreeItem *OBSBasic::GetItemWidgetFromSceneItem(
obs_sceneitem_t *sceneItem)
{
int i = 0;
SourceTreeItem *treeItem = ui->sources->GetItemWidget(i);
OBSSceneItem item = ui->sources->Get(i);
int64_t id = obs_sceneitem_get_id(sceneItem);
while (treeItem && obs_sceneitem_get_id(item) != id) {
i++;
treeItem = ui->sources->GetItemWidget(i);
item = ui->sources->Get(i);
}
if(treeItem)
return treeItem;
return nullptr;
}
void OBSBasic::on_autoConfigure_triggered()
{
AutoConfig test(this);
@ -6348,3 +6584,10 @@ void OBSBasic::on_stats_triggered()
statsDlg->show();
stats = statsDlg;
}
ColorSelect::ColorSelect(QWidget *parent)
: QWidget(parent),
ui(new Ui::ColorSelect)
{
ui->setupUi(this);
}

View File

@ -46,6 +46,7 @@ class QNetworkReply;
class OBSBasicStats;
#include "ui_OBSBasic.h"
#include "ui_ColorSelect.h"
#define DESKTOP_AUDIO_1 Str("DesktopAudioDevice1")
#define DESKTOP_AUDIO_2 Str("DesktopAudioDevice2")
@ -473,6 +474,10 @@ private slots:
void on_actionCopyFilters_triggered();
void on_actionPasteFilters_triggered();
void ColorChange();
SourceTreeItem *GetItemWidgetFromSceneItem(obs_sceneitem_t *sceneItem);
private:
/* OBS Callbacks */
static void SceneReordered(void *data, calldata_t *params);
@ -563,6 +568,7 @@ public:
QMenu *AddDeinterlacingMenu(obs_source_t *source);
QMenu *AddScaleFilteringMenu(obs_sceneitem_t *item);
QMenu *AddBackgroundColorMenu(obs_sceneitem_t *item);
void CreateSourcePopupMenu(int idx, bool preview);
void UpdateTitleBar();
@ -745,3 +751,12 @@ public:
private:
std::unique_ptr<Ui::OBSBasic> ui;
};
class ColorSelect : public QWidget {
public:
explicit ColorSelect(QWidget *parent = 0);
private:
std::unique_ptr<Ui::ColorSelect> ui;
};