UI: Add list item widget w/ visibility checkbox
This is used to allow the user to temporarily disable sources/filters. For each item in the list box, it displays a visibility checkbox (with eye icon) that the user can click to disable/re-enable sources or filters. I did not end up using the Qt::ItemIsUserCheckable flag with the list items for a few reasons: - We could not style the checkbox indicator without qss screwing up other parts of the list widget style on certain operating systems - We could not get the icon to properly invert on active selection like the text does on mac/linux, which made it look strange - Clicking the checkbox too fast would cause it to signal a double-click on the icon, opening the properties for a source in the source list
This commit is contained in:
parent
2e053c849b
commit
642aa7454f
@ -109,6 +109,7 @@ set(obs_SOURCES
|
||||
adv-audio-control.cpp
|
||||
visibility-checkbox.cpp
|
||||
vertical-scroll-area.cpp
|
||||
visibility-item-widget.cpp
|
||||
source-list-widget.cpp
|
||||
crash-report.cpp
|
||||
qt-wrappers.cpp)
|
||||
@ -139,6 +140,7 @@ set(obs_HEADERS
|
||||
adv-audio-control.hpp
|
||||
visibility-checkbox.hpp
|
||||
vertical-scroll-area.hpp
|
||||
visibility-item-widget.hpp
|
||||
source-list-widget.hpp
|
||||
qt-display.hpp
|
||||
crash-report.hpp
|
||||
|
258
obs/visibility-item-widget.cpp
Normal file
258
obs/visibility-item-widget.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
#include "visibility-item-widget.hpp"
|
||||
#include "visibility-checkbox.hpp"
|
||||
#include "qt-wrappers.hpp"
|
||||
#include "obs-app.hpp"
|
||||
#include <QListWidget>
|
||||
#include <QLineEdit>
|
||||
#include <QHBoxLayout>
|
||||
#include <QMessageBox>
|
||||
#include <QLabel>
|
||||
|
||||
VisibilityItemWidget::VisibilityItemWidget(obs_source_t *source_)
|
||||
: source (source_),
|
||||
enabledSignal (obs_source_get_signal_handler(source), "enable",
|
||||
OBSSourceEnabled, this),
|
||||
renamedSignal (obs_source_get_signal_handler(source), "rename",
|
||||
OBSSourceRenamed, this)
|
||||
{
|
||||
const char *name = obs_source_get_name(source);
|
||||
bool enabled = obs_source_enabled(source);
|
||||
|
||||
vis = new VisibilityCheckBox();
|
||||
vis->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
/* Fix for non-apple systems where the spacing would be too big */
|
||||
#ifndef __APPLE__
|
||||
vis->setMaximumSize(16, 16);
|
||||
#endif
|
||||
vis->setChecked(enabled);
|
||||
|
||||
label = new QLabel(QT_UTF8(name));
|
||||
label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
QHBoxLayout *itemLayout = new QHBoxLayout();
|
||||
itemLayout->addWidget(vis);
|
||||
itemLayout->addWidget(label);
|
||||
itemLayout->setContentsMargins(5, 2, 5, 2);
|
||||
|
||||
setLayout(itemLayout);
|
||||
setStyleSheet("background-color: rgba(255, 255, 255, 0);");
|
||||
|
||||
connect(vis, SIGNAL(clicked(bool)),
|
||||
this, SLOT(VisibilityClicked(bool)));
|
||||
}
|
||||
|
||||
VisibilityItemWidget::VisibilityItemWidget(obs_sceneitem_t *item_)
|
||||
: item (item_),
|
||||
source (obs_sceneitem_get_source(item)),
|
||||
renamedSignal (obs_source_get_signal_handler(source), "rename",
|
||||
OBSSourceRenamed, this)
|
||||
{
|
||||
const char *name = obs_source_get_name(source);
|
||||
bool enabled = obs_sceneitem_visible(item);
|
||||
obs_scene_t *scene = obs_sceneitem_get_scene(item);
|
||||
obs_source_t *sceneSource = obs_scene_get_source(scene);
|
||||
|
||||
vis = new VisibilityCheckBox();
|
||||
vis->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
|
||||
/* Fix for non-apple systems where the spacing would be too big */
|
||||
#ifndef __APPLE__
|
||||
vis->setMaximumSize(16, 16);
|
||||
#endif
|
||||
vis->setChecked(enabled);
|
||||
|
||||
label = new QLabel(QT_UTF8(name));
|
||||
label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
QHBoxLayout *itemLayout = new QHBoxLayout();
|
||||
itemLayout->addWidget(vis);
|
||||
itemLayout->addWidget(label);
|
||||
itemLayout->setContentsMargins(5, 2, 5, 2);
|
||||
|
||||
setLayout(itemLayout);
|
||||
setStyleSheet("background-color: rgba(255, 255, 255, 0);");
|
||||
|
||||
signal_handler_t *signal = obs_source_get_signal_handler(sceneSource);
|
||||
signal_handler_connect(signal, "remove", OBSSceneRemove, this);
|
||||
signal_handler_connect(signal, "item_remove", OBSSceneItemRemove,
|
||||
this);
|
||||
signal_handler_connect(signal, "item_visible", OBSSceneItemVisible,
|
||||
this);
|
||||
|
||||
connect(vis, SIGNAL(clicked(bool)),
|
||||
this, SLOT(VisibilityClicked(bool)));
|
||||
}
|
||||
|
||||
VisibilityItemWidget::~VisibilityItemWidget()
|
||||
{
|
||||
DisconnectItemSignals();
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::DisconnectItemSignals()
|
||||
{
|
||||
if (!item || sceneRemoved)
|
||||
return;
|
||||
|
||||
obs_scene_t *scene = obs_sceneitem_get_scene(item);
|
||||
obs_source_t *sceneSource = obs_scene_get_source(scene);
|
||||
signal_handler_t *signal = obs_source_get_signal_handler(sceneSource);
|
||||
|
||||
signal_handler_disconnect(signal, "remove", OBSSceneRemove, this);
|
||||
signal_handler_disconnect(signal, "item_remove", OBSSceneItemRemove,
|
||||
this);
|
||||
signal_handler_disconnect(signal, "item_visible", OBSSceneItemVisible,
|
||||
this);
|
||||
|
||||
sceneRemoved = true;
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::OBSSceneRemove(void *param, calldata_t *data)
|
||||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget*>(param);
|
||||
|
||||
window->DisconnectItemSignals();
|
||||
|
||||
UNUSED_PARAMETER(data);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::OBSSceneItemRemove(void *param, calldata_t *data)
|
||||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget*>(param);
|
||||
obs_sceneitem_t *item = (obs_sceneitem_t*)calldata_ptr(data, "item");
|
||||
|
||||
if (item == window->item)
|
||||
window->DisconnectItemSignals();
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::OBSSceneItemVisible(void *param, calldata_t *data)
|
||||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget*>(param);
|
||||
obs_sceneitem_t *curItem = (obs_sceneitem_t*)calldata_ptr(data, "item");
|
||||
bool enabled = calldata_bool(data, "visible");
|
||||
|
||||
if (window->item == curItem)
|
||||
QMetaObject::invokeMethod(window, "SourceEnabled",
|
||||
Q_ARG(bool, enabled));
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::OBSSourceEnabled(void *param, calldata_t *data)
|
||||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget*>(param);
|
||||
bool enabled = calldata_bool(data, "enabled");
|
||||
|
||||
QMetaObject::invokeMethod(window, "SourceEnabled",
|
||||
Q_ARG(bool, enabled));
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::OBSSourceRenamed(void *param, calldata_t *data)
|
||||
{
|
||||
VisibilityItemWidget *window =
|
||||
reinterpret_cast<VisibilityItemWidget*>(param);
|
||||
const char *name = calldata_string(data, "new_name");
|
||||
|
||||
QMetaObject::invokeMethod(window, "SourceRenamed",
|
||||
Q_ARG(QString, QT_UTF8(name)));
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::VisibilityClicked(bool visible)
|
||||
{
|
||||
if (item)
|
||||
obs_sceneitem_set_visible(item, visible);
|
||||
else
|
||||
obs_source_set_enabled(source, visible);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SourceEnabled(bool enabled)
|
||||
{
|
||||
if (vis->isChecked() != enabled)
|
||||
vis->setChecked(enabled);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SourceRenamed(QString name)
|
||||
{
|
||||
if (label && name != label->text())
|
||||
label->setText(name);
|
||||
}
|
||||
|
||||
void VisibilityItemWidget::SetColor(const QColor &color,
|
||||
bool active_, bool selected_)
|
||||
{
|
||||
/* Do not update unless the state has actually changed */
|
||||
if (active_ == active && selected_ == selected)
|
||||
return;
|
||||
|
||||
QPalette pal = vis->palette();
|
||||
pal.setColor(QPalette::WindowText, color);
|
||||
vis->setPalette(pal);
|
||||
|
||||
label->setStyleSheet(QString("color: %1;").arg(color.name()));
|
||||
|
||||
active = active_;
|
||||
selected = selected_;
|
||||
}
|
||||
|
||||
VisibilityItemDelegate::VisibilityItemDelegate(QObject *parent)
|
||||
: QStyledItemDelegate(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void VisibilityItemDelegate::paint(QPainter *painter,
|
||||
const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const
|
||||
{
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
QObject *parentObj = parent();
|
||||
QListWidget *list = qobject_cast<QListWidget*>(parentObj);
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
QListWidgetItem *item = list->item(index.row());
|
||||
VisibilityItemWidget *widget =
|
||||
qobject_cast<VisibilityItemWidget*>(list->itemWidget(item));
|
||||
if (!widget)
|
||||
return;
|
||||
|
||||
bool selected = option.state.testFlag(QStyle::State_Selected);
|
||||
bool active = option.state.testFlag(QStyle::State_Active);
|
||||
|
||||
QPalette palette = list->palette();
|
||||
QPalette::ColorGroup group = active ?
|
||||
QPalette::Active : QPalette::Inactive;
|
||||
|
||||
#ifdef _WIN32
|
||||
QPalette::ColorRole highlightRole = QPalette::WindowText;
|
||||
#else
|
||||
QPalette::ColorRole highlightRole = QPalette::HighlightedText;
|
||||
#endif
|
||||
|
||||
QPalette::ColorRole role;
|
||||
|
||||
if (selected && active)
|
||||
role = highlightRole;
|
||||
else
|
||||
role = QPalette::WindowText;
|
||||
|
||||
widget->SetColor(palette.color(group, role), active, selected);
|
||||
}
|
||||
|
||||
void SetupVisibilityItem(QListWidget *list, QListWidgetItem *item,
|
||||
obs_source_t *source)
|
||||
{
|
||||
VisibilityItemWidget *baseWidget = new VisibilityItemWidget(source);
|
||||
|
||||
item->setSizeHint(baseWidget->sizeHint());
|
||||
list->setItemWidget(item, baseWidget);
|
||||
}
|
||||
|
||||
void SetupVisibilityItem(QListWidget *list, QListWidgetItem *item,
|
||||
obs_sceneitem_t *sceneItem)
|
||||
{
|
||||
VisibilityItemWidget *baseWidget = new VisibilityItemWidget(sceneItem);
|
||||
|
||||
item->setSizeHint(baseWidget->sizeHint());
|
||||
list->setItemWidget(item, baseWidget);
|
||||
}
|
65
obs/visibility-item-widget.hpp
Normal file
65
obs/visibility-item-widget.hpp
Normal file
@ -0,0 +1,65 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <obs.hpp>
|
||||
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class QListWidget;
|
||||
class QListWidgetItem;
|
||||
class VisibilityCheckBox;
|
||||
|
||||
class VisibilityItemWidget : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OBSSceneItem item;
|
||||
OBSSource source;
|
||||
QLabel *label = nullptr;
|
||||
VisibilityCheckBox *vis = nullptr;
|
||||
QString oldName;
|
||||
|
||||
OBSSignal sceneRemoveSignal;
|
||||
OBSSignal enabledSignal;
|
||||
OBSSignal renamedSignal;
|
||||
bool sceneRemoved = false;
|
||||
|
||||
bool active = false;
|
||||
bool selected = false;
|
||||
|
||||
static void OBSSceneRemove(void *param, calldata_t *data);
|
||||
static void OBSSceneItemRemove(void *param, calldata_t *data);
|
||||
static void OBSSceneItemVisible(void *param, calldata_t *data);
|
||||
static void OBSSourceEnabled(void *param, calldata_t *data);
|
||||
static void OBSSourceRenamed(void *param, calldata_t *data);
|
||||
|
||||
void DisconnectItemSignals();
|
||||
|
||||
private slots:
|
||||
void VisibilityClicked(bool visible);
|
||||
void SourceEnabled(bool enabled);
|
||||
void SourceRenamed(QString name);
|
||||
|
||||
public:
|
||||
VisibilityItemWidget(obs_source_t *source);
|
||||
VisibilityItemWidget(obs_sceneitem_t *item);
|
||||
~VisibilityItemWidget();
|
||||
|
||||
void SetColor(const QColor &color, bool active, bool selected);
|
||||
};
|
||||
|
||||
class VisibilityItemDelegate : public QStyledItemDelegate {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VisibilityItemDelegate(QObject *parent = nullptr);
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||
const QModelIndex &index) const override;
|
||||
};
|
||||
|
||||
void SetupVisibilityItem(QListWidget *list, QListWidgetItem *item,
|
||||
obs_source_t *source);
|
||||
void SetupVisibilityItem(QListWidget *list, QListWidgetItem *item,
|
||||
obs_sceneitem_t *sceneItem);
|
Loading…
x
Reference in New Issue
Block a user