UI: Add user interface for filters
This commit is contained in:
parent
ff363bc77b
commit
ceba24c7e9
@ -90,6 +90,7 @@ set(obs_SOURCES
|
||||
${obs_PLATFORM_SOURCES}
|
||||
obs-app.cpp
|
||||
window-basic-main.cpp
|
||||
window-basic-filters.cpp
|
||||
window-basic-settings.cpp
|
||||
window-basic-interaction.cpp
|
||||
window-basic-properties.cpp
|
||||
@ -120,6 +121,7 @@ set(obs_HEADERS
|
||||
platform.hpp
|
||||
window-main.hpp
|
||||
window-basic-main.hpp
|
||||
window-basic-filters.hpp
|
||||
window-basic-settings.hpp
|
||||
window-basic-interaction.hpp
|
||||
window-basic-properties.hpp
|
||||
@ -154,6 +156,7 @@ set(obs_UI
|
||||
forms/OBSLogReply.ui
|
||||
forms/OBSBasic.ui
|
||||
forms/OBSBasicTransform.ui
|
||||
forms/OBSBasicFilters.ui
|
||||
forms/OBSBasicSettings.ui
|
||||
forms/OBSBasicSourceSelect.ui
|
||||
forms/OBSBasicInteraction.ui
|
||||
|
@ -17,6 +17,7 @@ No="No"
|
||||
Add="Add"
|
||||
Remove="Remove"
|
||||
Rename="Rename"
|
||||
Filters="Filters"
|
||||
Properties="Properties"
|
||||
MoveUp="Move Up"
|
||||
MoveDown="Move Down"
|
||||
@ -127,6 +128,15 @@ Basic.InteractionWindow="Interacting with '%1'"
|
||||
Basic.StatusBar.Reconnecting="Disconnected, reconnecting (attempt %1)"
|
||||
Basic.StatusBar.ReconnectSuccessful="Reconnection successful"
|
||||
|
||||
# filters window
|
||||
Basic.Filters="Filters"
|
||||
Basic.Filters.AsyncFilters="Audio/Video Filters"
|
||||
Basic.Filters.AudioFilters="Audio Filters"
|
||||
Basic.Filters.EffectFilters="Effect Filters"
|
||||
Basic.Filters.Title="Filters for '%1'"
|
||||
Basic.Filters.AddFilter.Title="Filter name"
|
||||
Basic.Filters.AddFilter.Text="Please specify the name of the filter"
|
||||
|
||||
# transform window
|
||||
Basic.TransformWindow="Scene Item Transform"
|
||||
Basic.TransformWindow.Position="Position"
|
||||
|
466
obs/forms/OBSBasicFilters.ui
Normal file
466
obs/forms/OBSBasicFilters.ui
Normal file
@ -0,0 +1,466 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>OBSBasicFilters</class>
|
||||
<widget class="QDialog" name="OBSBasicFilters">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>861</width>
|
||||
<height>726</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Basic.Filters</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMinimumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QWidget" name="asyncWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="asyncLabel">
|
||||
<property name="text">
|
||||
<string>Basic.Filters.AsyncFilters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="FocusList" name="asyncFilters">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignLeft">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addAsyncFilter">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/add.png</normaloff>:/res/images/add.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>addIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeAsyncFilter">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/list_remove.png</normaloff>:/res/images/list_remove.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>removeIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveAsyncFilterUp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/up.png</normaloff>:/res/images/up.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>upArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveAsyncFilterDown">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/down.png</normaloff>:/res/images/down.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>downArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="separatorLine">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="effectWidget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Basic.Filters.EffectFilters</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="FocusList" name="effectFilters">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::CustomContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item alignment="Qt::AlignLeft">
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addEffectFilter">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/add.png</normaloff>:/res/images/add.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>addIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="removeEffectFilter">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/list_remove.png</normaloff>:/res/images/list_remove.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>removeIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveEffectFilterUp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/up.png</normaloff>:/res/images/up.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>upArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="moveEffectFilterDown">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>22</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="obs.qrc">
|
||||
<normaloff>:/res/images/down.png</normaloff>:/res/images/down.png</iconset>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string>downArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="rightContainerLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="rightLayout">
|
||||
<item>
|
||||
<widget class="OBSQTDisplay" name="preview" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="close">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
<property name="autoDefault">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>OBSQTDisplay</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>qt-display.hpp</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>FocusList</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>focus-list.hpp</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="obs.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>close</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>OBSBasicFilters</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>811</x>
|
||||
<y>701</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>722</x>
|
||||
<y>727</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
708
obs/window-basic-filters.cpp
Normal file
708
obs/window-basic-filters.cpp
Normal file
@ -0,0 +1,708 @@
|
||||
/******************************************************************************
|
||||
Copyright (C) 2015 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
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 2 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 "window-namedialog.hpp"
|
||||
#include "window-basic-filters.hpp"
|
||||
#include "display-helpers.hpp"
|
||||
#include "qt-wrappers.hpp"
|
||||
#include "visibility-item-widget.hpp"
|
||||
#include "obs-app.hpp"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QCloseEvent>
|
||||
#include <string>
|
||||
#include <QMenu>
|
||||
#include <QVariant>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Q_DECLARE_METATYPE(OBSSource);
|
||||
|
||||
OBSBasicFilters::OBSBasicFilters(QWidget *parent, OBSSource source_)
|
||||
: QDialog (parent),
|
||||
ui (new Ui::OBSBasicFilters),
|
||||
source (source_),
|
||||
addSignal (obs_source_get_signal_handler(source),
|
||||
"filter_add",
|
||||
OBSBasicFilters::OBSSourceFilterAdded,
|
||||
this),
|
||||
removeSignal (obs_source_get_signal_handler(source),
|
||||
"filter_remove",
|
||||
OBSBasicFilters::OBSSourceFilterRemoved,
|
||||
this),
|
||||
reorderSignal (obs_source_get_signal_handler(source),
|
||||
"reorder_filters",
|
||||
OBSBasicFilters::OBSSourceReordered,
|
||||
this),
|
||||
removeSourceSignal (obs_source_get_signal_handler(source),
|
||||
"remove",
|
||||
OBSBasicFilters::SourceRemoved, this),
|
||||
renameSourceSignal (obs_source_get_signal_handler(source),
|
||||
"rename",
|
||||
OBSBasicFilters::SourceRenamed, this)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
UpdateFilters();
|
||||
|
||||
ui->asyncFilters->setItemDelegate(
|
||||
new VisibilityItemDelegate(ui->asyncFilters));
|
||||
ui->effectFilters->setItemDelegate(
|
||||
new VisibilityItemDelegate(ui->effectFilters));
|
||||
|
||||
const char *name = obs_source_get_name(source);
|
||||
setWindowTitle(QTStr("Basic.Filters.Title").arg(QT_UTF8(name)));
|
||||
|
||||
connect(ui->preview, SIGNAL(DisplayResized()),
|
||||
this, SLOT(OnPreviewResized()));
|
||||
|
||||
connect(ui->asyncFilters->itemDelegate(),
|
||||
SIGNAL(closeEditor(QWidget*,
|
||||
QAbstractItemDelegate::EndEditHint)),
|
||||
this,
|
||||
SLOT(AsyncFilterNameEdited(QWidget*,
|
||||
QAbstractItemDelegate::EndEditHint)));
|
||||
|
||||
connect(ui->effectFilters->itemDelegate(),
|
||||
SIGNAL(closeEditor(QWidget*,
|
||||
QAbstractItemDelegate::EndEditHint)),
|
||||
this,
|
||||
SLOT(EffectFilterNameEdited(QWidget*,
|
||||
QAbstractItemDelegate::EndEditHint)));
|
||||
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
bool audio = (flags & OBS_SOURCE_AUDIO) != 0;
|
||||
bool audioOnly = (flags & OBS_SOURCE_VIDEO) == 0;
|
||||
bool async = (flags & OBS_SOURCE_ASYNC) != 0;
|
||||
|
||||
if (!async && !audio) {
|
||||
ui->asyncWidget->setVisible(false);
|
||||
ui->separatorLine->setVisible(false);
|
||||
}
|
||||
if (audioOnly) {
|
||||
ui->effectWidget->setVisible(false);
|
||||
ui->separatorLine->setVisible(false);
|
||||
}
|
||||
|
||||
if (audioOnly || (audio && !async))
|
||||
ui->asyncLabel->setText(QTStr("Basic.Filters.AudioFilters"));
|
||||
}
|
||||
|
||||
OBSBasicFilters::~OBSBasicFilters()
|
||||
{
|
||||
ui->asyncFilters->clear();
|
||||
ui->effectFilters->clear();
|
||||
QApplication::sendPostedEvents(this);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::Init()
|
||||
{
|
||||
gs_init_data init_data = {};
|
||||
|
||||
show();
|
||||
|
||||
QSize previewSize = GetPixelSize(ui->preview);
|
||||
init_data.cx = uint32_t(previewSize.width());
|
||||
init_data.cy = uint32_t(previewSize.height());
|
||||
init_data.format = GS_RGBA;
|
||||
QTToGSWindow(ui->preview->winId(), init_data.window);
|
||||
|
||||
display = obs_display_create(&init_data);
|
||||
|
||||
if (display)
|
||||
obs_display_add_draw_callback(display,
|
||||
OBSBasicFilters::DrawPreview, this);
|
||||
}
|
||||
|
||||
inline OBSSource OBSBasicFilters::GetFilter(int row, bool async)
|
||||
{
|
||||
if (row == -1)
|
||||
return OBSSource();
|
||||
|
||||
QListWidget *list = async ? ui->asyncFilters : ui->effectFilters;
|
||||
QListWidgetItem *item = list->item(row);
|
||||
if (!item)
|
||||
return OBSSource();
|
||||
|
||||
QVariant v = item->data(Qt::UserRole);
|
||||
return v.value<OBSSource>();
|
||||
}
|
||||
|
||||
void OBSBasicFilters::UpdatePropertiesView(int row, bool async)
|
||||
{
|
||||
delete view;
|
||||
view = nullptr;
|
||||
|
||||
OBSSource filter = GetFilter(row, async);
|
||||
if (!filter)
|
||||
return;
|
||||
|
||||
obs_data_t *settings = obs_source_get_settings(filter);
|
||||
|
||||
view = new OBSPropertiesView(settings, filter,
|
||||
(PropertiesReloadCallback)obs_source_properties,
|
||||
(PropertiesUpdateCallback)obs_source_update);
|
||||
|
||||
obs_data_release(settings);
|
||||
|
||||
view->setMaximumHeight(250);
|
||||
view->setMinimumHeight(150);
|
||||
ui->rightLayout->addWidget(view);
|
||||
view->show();
|
||||
}
|
||||
|
||||
void OBSBasicFilters::AddFilter(OBSSource filter)
|
||||
{
|
||||
uint32_t flags = obs_source_get_output_flags(filter);
|
||||
bool async = (flags & OBS_SOURCE_ASYNC) != 0;
|
||||
QListWidget *list = async ? ui->asyncFilters : ui->effectFilters;
|
||||
|
||||
QListWidgetItem *item = new QListWidgetItem();
|
||||
Qt::ItemFlags itemFlags = item->flags();
|
||||
|
||||
item->setFlags(itemFlags | Qt::ItemIsEditable);
|
||||
item->setData(Qt::UserRole, QVariant::fromValue(filter));
|
||||
|
||||
list->addItem(item);
|
||||
list->setCurrentItem(item);
|
||||
SetupVisibilityItem(list, item, filter);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::RemoveFilter(OBSSource filter)
|
||||
{
|
||||
uint32_t flags = obs_source_get_output_flags(filter);
|
||||
bool async = (flags & OBS_SOURCE_ASYNC) != 0;
|
||||
QListWidget *list = async ? ui->asyncFilters : ui->effectFilters;
|
||||
|
||||
for (int i = 0; i < list->count(); i++) {
|
||||
QListWidgetItem *item = list->item(i);
|
||||
QVariant v = item->data(Qt::UserRole);
|
||||
OBSSource curFilter = v.value<OBSSource>();
|
||||
|
||||
if (filter == curFilter) {
|
||||
delete item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FilterOrderInfo {
|
||||
int asyncIdx = 0;
|
||||
int effectIdx = 0;
|
||||
OBSBasicFilters *window;
|
||||
|
||||
inline FilterOrderInfo(OBSBasicFilters *window_) : window(window_) {}
|
||||
};
|
||||
|
||||
void OBSBasicFilters::ReorderFilter(QListWidget *list,
|
||||
obs_source_t *filter, size_t idx)
|
||||
{
|
||||
int count = list->count();
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
QListWidgetItem *listItem = list->item(i);
|
||||
QVariant v = listItem->data(Qt::UserRole);
|
||||
OBSSource filterItem = v.value<OBSSource>();
|
||||
|
||||
if (filterItem == filter) {
|
||||
if ((int)idx != i) {
|
||||
bool sel = (list->currentRow() == i);
|
||||
|
||||
listItem = list->takeItem(i);
|
||||
if (listItem) {
|
||||
list->insertItem((int)idx, listItem);
|
||||
SetupVisibilityItem(list,
|
||||
listItem, filterItem);
|
||||
|
||||
if (sel)
|
||||
list->setCurrentRow((int)idx);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::ReorderFilters()
|
||||
{
|
||||
FilterOrderInfo info(this);
|
||||
|
||||
obs_source_enum_filters(source,
|
||||
[] (obs_source_t*, obs_source_t *filter, void *p)
|
||||
{
|
||||
FilterOrderInfo *info =
|
||||
reinterpret_cast<FilterOrderInfo*>(p);
|
||||
uint32_t flags;
|
||||
bool async;
|
||||
|
||||
flags = obs_source_get_output_flags(filter);
|
||||
async = (flags & OBS_SOURCE_ASYNC) != 0;
|
||||
|
||||
if (async) {
|
||||
info->window->ReorderFilter(
|
||||
info->window->ui->asyncFilters,
|
||||
filter, info->asyncIdx++);
|
||||
} else {
|
||||
info->window->ReorderFilter(
|
||||
info->window->ui->effectFilters,
|
||||
filter, info->effectIdx++);
|
||||
}
|
||||
}, &info);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::UpdateFilters()
|
||||
{
|
||||
if (!source)
|
||||
return;
|
||||
|
||||
ui->effectFilters->clear();
|
||||
ui->asyncFilters->clear();
|
||||
|
||||
obs_source_enum_filters(source,
|
||||
[] (obs_source_t*, obs_source_t *filter, void *p)
|
||||
{
|
||||
OBSBasicFilters *window =
|
||||
reinterpret_cast<OBSBasicFilters*>(p);
|
||||
|
||||
window->AddFilter(filter);
|
||||
}, this);
|
||||
}
|
||||
|
||||
static bool filter_compatible(bool async, uint32_t sourceFlags,
|
||||
uint32_t filterFlags)
|
||||
{
|
||||
bool filterVideo = (filterFlags & OBS_SOURCE_VIDEO) != 0;
|
||||
bool filterAsync = (filterFlags & OBS_SOURCE_ASYNC) != 0;
|
||||
bool filterAudio = (filterFlags & OBS_SOURCE_AUDIO) != 0;
|
||||
bool audio = (sourceFlags & OBS_SOURCE_AUDIO) != 0;
|
||||
bool audioOnly = (sourceFlags & OBS_SOURCE_VIDEO) == 0;
|
||||
bool asyncSource = (sourceFlags & OBS_SOURCE_ASYNC) != 0;
|
||||
|
||||
if (async && ((audioOnly && filterVideo) || (!audio && !asyncSource)))
|
||||
return false;
|
||||
|
||||
return (async && (filterAudio || filterAsync)) ||
|
||||
(!async && !filterAudio && !filterAsync);
|
||||
}
|
||||
|
||||
QMenu *OBSBasicFilters::CreateAddFilterPopupMenu(bool async)
|
||||
{
|
||||
uint32_t sourceFlags = obs_source_get_output_flags(source);
|
||||
const char *type;
|
||||
bool foundValues = false;
|
||||
size_t idx = 0;
|
||||
|
||||
QMenu *popup = new QMenu(QTStr("Add"), this);
|
||||
while (obs_enum_filter_types(idx++, &type)) {
|
||||
const char *name = obs_source_get_display_name(
|
||||
OBS_SOURCE_TYPE_FILTER, type);
|
||||
uint32_t filterFlags = obs_get_source_output_flags(
|
||||
OBS_SOURCE_TYPE_FILTER, type);
|
||||
|
||||
if (!filter_compatible(async, sourceFlags, filterFlags))
|
||||
continue;
|
||||
|
||||
QAction *popupItem = new QAction(QT_UTF8(name), this);
|
||||
popupItem->setData(QT_UTF8(type));
|
||||
connect(popupItem, SIGNAL(triggered(bool)),
|
||||
this, SLOT(AddFilterFromAction()));
|
||||
popup->addAction(popupItem);
|
||||
|
||||
foundValues = true;
|
||||
}
|
||||
|
||||
if (!foundValues) {
|
||||
delete popup;
|
||||
popup = nullptr;
|
||||
}
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
void OBSBasicFilters::AddNewFilter(const char *id)
|
||||
{
|
||||
if (id && *id) {
|
||||
obs_source_t *existing_filter;
|
||||
string name = obs_source_get_display_name(
|
||||
OBS_SOURCE_TYPE_FILTER, id);
|
||||
|
||||
bool success = NameDialog::AskForName(this,
|
||||
QTStr("Basic.Filters.AddFilter.Title"),
|
||||
QTStr("Basic.FIlters.AddFilter.Text"), name,
|
||||
QT_UTF8(name.c_str()));
|
||||
if (!success)
|
||||
return;
|
||||
|
||||
if (name.empty()) {
|
||||
QMessageBox::information(this,
|
||||
QTStr("NoNameEntered.Title"),
|
||||
QTStr("NoNameEntered.Text"));
|
||||
AddNewFilter(id);
|
||||
return;
|
||||
}
|
||||
|
||||
existing_filter = obs_source_get_filter_by_name(source,
|
||||
name.c_str());
|
||||
if (existing_filter) {
|
||||
QMessageBox::information(this,
|
||||
QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
obs_source_release(existing_filter);
|
||||
AddNewFilter(id);
|
||||
return;
|
||||
}
|
||||
|
||||
obs_source_t *filter = obs_source_create(OBS_SOURCE_TYPE_FILTER,
|
||||
id, name.c_str(), nullptr);
|
||||
if (filter) {
|
||||
obs_source_filter_add(source, filter);
|
||||
obs_source_release(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::AddFilterFromAction()
|
||||
{
|
||||
QAction *action = qobject_cast<QAction*>(sender());
|
||||
if (!action)
|
||||
return;
|
||||
|
||||
AddNewFilter(QT_TO_UTF8(action->data().toString()));
|
||||
}
|
||||
|
||||
void OBSBasicFilters::OnPreviewResized()
|
||||
{
|
||||
if (resizeTimer)
|
||||
killTimer(resizeTimer);
|
||||
resizeTimer = startTimer(100);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QDialog::closeEvent(event);
|
||||
if (!event->isAccepted())
|
||||
return;
|
||||
|
||||
// remove draw callback and release display in case our drawable
|
||||
// surfaces go away before the destructor gets called
|
||||
obs_display_remove_draw_callback(display,
|
||||
OBSBasicFilters::DrawPreview, this);
|
||||
display = nullptr;
|
||||
}
|
||||
|
||||
void OBSBasicFilters::timerEvent(QTimerEvent *event)
|
||||
{
|
||||
if (event->timerId() == resizeTimer) {
|
||||
killTimer(resizeTimer);
|
||||
resizeTimer = 0;
|
||||
|
||||
QSize size = GetPixelSize(ui->preview);
|
||||
obs_display_resize(display, size.width(), size.height());
|
||||
}
|
||||
}
|
||||
|
||||
/* OBS Signals */
|
||||
|
||||
void OBSBasicFilters::OBSSourceFilterAdded(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicFilters *window = reinterpret_cast<OBSBasicFilters*>(param);
|
||||
obs_source_t *filter = (obs_source_t*)calldata_ptr(data, "filter");
|
||||
|
||||
QMetaObject::invokeMethod(window, "AddFilter",
|
||||
Q_ARG(OBSSource, OBSSource(filter)));
|
||||
}
|
||||
|
||||
void OBSBasicFilters::OBSSourceFilterRemoved(void *param, calldata_t *data)
|
||||
{
|
||||
OBSBasicFilters *window = reinterpret_cast<OBSBasicFilters*>(param);
|
||||
obs_source_t *filter = (obs_source_t*)calldata_ptr(data, "filter");
|
||||
|
||||
QMetaObject::invokeMethod(window, "RemoveFilter",
|
||||
Q_ARG(OBSSource, OBSSource(filter)));
|
||||
}
|
||||
|
||||
void OBSBasicFilters::OBSSourceReordered(void *param, calldata_t *data)
|
||||
{
|
||||
QMetaObject::invokeMethod(reinterpret_cast<OBSBasicFilters*>(param),
|
||||
"ReorderFilters");
|
||||
|
||||
UNUSED_PARAMETER(data);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::SourceRemoved(void *data, calldata_t *params)
|
||||
{
|
||||
UNUSED_PARAMETER(params);
|
||||
|
||||
QMetaObject::invokeMethod(static_cast<OBSBasicFilters*>(data),
|
||||
"close");
|
||||
}
|
||||
|
||||
void OBSBasicFilters::SourceRenamed(void *data, calldata_t *params)
|
||||
{
|
||||
const char *name = calldata_string(params, "new_name");
|
||||
QString title = QTStr("Basic.Filters.Title").arg(QT_UTF8(name));
|
||||
|
||||
QMetaObject::invokeMethod(static_cast<OBSBasicFilters*>(data),
|
||||
"setWindowTitle", Q_ARG(QString, title));
|
||||
}
|
||||
|
||||
void OBSBasicFilters::DrawPreview(void *data, uint32_t cx, uint32_t cy)
|
||||
{
|
||||
OBSBasicFilters *window = static_cast<OBSBasicFilters*>(data);
|
||||
|
||||
if (!window->source)
|
||||
return;
|
||||
|
||||
uint32_t sourceCX = max(obs_source_get_width(window->source), 1u);
|
||||
uint32_t sourceCY = max(obs_source_get_height(window->source), 1u);
|
||||
|
||||
int x, y;
|
||||
int newCX, newCY;
|
||||
float scale;
|
||||
|
||||
GetScaleAndCenterPos(sourceCX, sourceCY, cx, cy, x, y, scale);
|
||||
|
||||
newCX = int(scale * float(sourceCX));
|
||||
newCY = int(scale * float(sourceCY));
|
||||
|
||||
gs_viewport_push();
|
||||
gs_projection_push();
|
||||
gs_ortho(0.0f, float(sourceCX), 0.0f, float(sourceCY), -100.0f, 100.0f);
|
||||
gs_set_viewport(x, y, newCX, newCY);
|
||||
|
||||
obs_source_video_render(window->source);
|
||||
|
||||
gs_projection_pop();
|
||||
gs_viewport_pop();
|
||||
}
|
||||
|
||||
/* Qt Slots */
|
||||
|
||||
static bool QueryRemove(QWidget *parent, obs_source_t *source)
|
||||
{
|
||||
const char *name = obs_source_get_name(source);
|
||||
|
||||
QString text = QTStr("ConfirmRemove.Text");
|
||||
text.replace("$1", QT_UTF8(name));
|
||||
|
||||
QMessageBox remove_source(parent);
|
||||
remove_source.setText(text);
|
||||
QAbstractButton *Yes = remove_source.addButton(QTStr("Yes"),
|
||||
QMessageBox::YesRole);
|
||||
remove_source.addButton(QTStr("No"), QMessageBox::NoRole);
|
||||
remove_source.setIcon(QMessageBox::Question);
|
||||
remove_source.setWindowTitle(QTStr("ConfirmRemove.Title"));
|
||||
remove_source.exec();
|
||||
|
||||
return Yes == remove_source.clickedButton();
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_addAsyncFilter_clicked()
|
||||
{
|
||||
QPointer<QMenu> popup = CreateAddFilterPopupMenu(true);
|
||||
if (popup)
|
||||
popup->exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_removeAsyncFilter_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->asyncFilters->currentRow(), true);
|
||||
if (filter) {
|
||||
if (QueryRemove(this, filter))
|
||||
obs_source_filter_remove(source, filter);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_moveAsyncFilterUp_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->asyncFilters->currentRow(), true);
|
||||
if (filter)
|
||||
obs_source_filter_set_order(source, filter, OBS_ORDER_MOVE_UP);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_moveAsyncFilterDown_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->asyncFilters->currentRow(), true);
|
||||
if (filter)
|
||||
obs_source_filter_set_order(source, filter,
|
||||
OBS_ORDER_MOVE_DOWN);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_asyncFilters_GotFocus()
|
||||
{
|
||||
UpdatePropertiesView(ui->asyncFilters->currentRow(), true);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_asyncFilters_currentRowChanged(int row)
|
||||
{
|
||||
UpdatePropertiesView(row, true);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_addEffectFilter_clicked()
|
||||
{
|
||||
QPointer<QMenu> popup = CreateAddFilterPopupMenu(false);
|
||||
if (popup)
|
||||
popup->exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_removeEffectFilter_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->effectFilters->currentRow(), false);
|
||||
if (filter) {
|
||||
if (QueryRemove(this, filter))
|
||||
obs_source_filter_remove(source, filter);
|
||||
}
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_moveEffectFilterUp_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->effectFilters->currentRow(), false);
|
||||
if (filter)
|
||||
obs_source_filter_set_order(source, filter, OBS_ORDER_MOVE_UP);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_moveEffectFilterDown_clicked()
|
||||
{
|
||||
OBSSource filter = GetFilter(ui->effectFilters->currentRow(), false);
|
||||
if (filter)
|
||||
obs_source_filter_set_order(source, filter,
|
||||
OBS_ORDER_MOVE_DOWN);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_effectFilters_GotFocus()
|
||||
{
|
||||
UpdatePropertiesView(ui->effectFilters->currentRow(), false);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_effectFilters_currentRowChanged(int row)
|
||||
{
|
||||
UpdatePropertiesView(row, false);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::CustomContextMenu(const QPoint &pos, bool async)
|
||||
{
|
||||
QListWidget *list = async ? ui->asyncFilters : ui->effectFilters;
|
||||
QListWidgetItem *item = list->itemAt(pos);
|
||||
|
||||
QMenu popup(window());
|
||||
|
||||
QPointer<QMenu> addMenu = CreateAddFilterPopupMenu(async);
|
||||
if (addMenu)
|
||||
popup.addMenu(addMenu);
|
||||
|
||||
if (item) {
|
||||
const char *renameSlot = async ?
|
||||
SLOT(RenameAsyncFilter()) : SLOT(RenameEffectFilter());
|
||||
const char *removeSlot = async ?
|
||||
SLOT(on_removeAsyncFilter_clicked()) :
|
||||
SLOT(on_removeEffectFilter_clicked());
|
||||
|
||||
popup.addSeparator();
|
||||
popup.addAction(QTStr("Rename"), this, renameSlot);
|
||||
popup.addAction(QTStr("Remove"), this, removeSlot);
|
||||
}
|
||||
|
||||
popup.exec(QCursor::pos());
|
||||
}
|
||||
|
||||
void OBSBasicFilters::EditItem(QListWidgetItem *item, bool async)
|
||||
{
|
||||
Qt::ItemFlags flags = item->flags();
|
||||
OBSSource filter = item->data(Qt::UserRole).value<OBSSource>();
|
||||
const char *name = obs_source_get_name(filter);
|
||||
QListWidget *list = async ? ui->asyncFilters : ui->effectFilters;
|
||||
|
||||
item->setText(QT_UTF8(name));
|
||||
item->setFlags(flags | Qt::ItemIsEditable);
|
||||
list->removeItemWidget(item);
|
||||
list->editItem(item);
|
||||
item->setFlags(flags);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_asyncFilters_customContextMenuRequested(
|
||||
const QPoint &pos)
|
||||
{
|
||||
CustomContextMenu(pos, true);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::on_effectFilters_customContextMenuRequested(
|
||||
const QPoint &pos)
|
||||
{
|
||||
CustomContextMenu(pos, false);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::RenameAsyncFilter()
|
||||
{
|
||||
EditItem(ui->asyncFilters->currentItem(), true);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::RenameEffectFilter()
|
||||
{
|
||||
EditItem(ui->effectFilters->currentItem(), false);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::FilterNameEdited(QWidget *editor, QListWidget *list)
|
||||
{
|
||||
QListWidgetItem *listItem = list->currentItem();
|
||||
OBSSource filter = listItem->data(Qt::UserRole).value<OBSSource>();
|
||||
QLineEdit *edit = qobject_cast<QLineEdit*>(editor);
|
||||
string name = QT_TO_UTF8(edit->text().trimmed());
|
||||
|
||||
const char *prevName = obs_source_get_name(filter);
|
||||
bool sameName = (name == prevName);
|
||||
obs_source_t *foundFilter = nullptr;
|
||||
|
||||
if (!sameName)
|
||||
foundFilter = obs_source_get_filter_by_name(source,
|
||||
name.c_str());
|
||||
|
||||
if (foundFilter || name.empty() || sameName) {
|
||||
listItem->setText(QT_UTF8(prevName));
|
||||
|
||||
if (foundFilter) {
|
||||
QMessageBox::information(window(),
|
||||
QTStr("NameExists.Title"),
|
||||
QTStr("NameExists.Text"));
|
||||
obs_source_release(foundFilter);
|
||||
|
||||
} else if (name.empty()) {
|
||||
QMessageBox::information(window(),
|
||||
QTStr("NoNameEntered.Title"),
|
||||
QTStr("NoNameEntered.Text"));
|
||||
}
|
||||
} else {
|
||||
listItem->setText(QT_UTF8(name.c_str()));
|
||||
obs_source_set_name(filter, name.c_str());
|
||||
}
|
||||
|
||||
listItem->setText(QString());
|
||||
SetupVisibilityItem(list, listItem, filter);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::AsyncFilterNameEdited(QWidget *editor,
|
||||
QAbstractItemDelegate::EndEditHint endHint)
|
||||
{
|
||||
FilterNameEdited(editor, ui->asyncFilters);
|
||||
UNUSED_PARAMETER(endHint);
|
||||
}
|
||||
|
||||
void OBSBasicFilters::EffectFilterNameEdited(QWidget *editor,
|
||||
QAbstractItemDelegate::EndEditHint endHint)
|
||||
{
|
||||
FilterNameEdited(editor, ui->effectFilters);
|
||||
UNUSED_PARAMETER(endHint);
|
||||
}
|
114
obs/window-basic-filters.hpp
Normal file
114
obs/window-basic-filters.hpp
Normal file
@ -0,0 +1,114 @@
|
||||
/******************************************************************************
|
||||
Copyright (C) 2015 by Hugh Bailey <obs.jim@gmail.com>
|
||||
|
||||
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 2 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/>.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QDialogButtonBox>
|
||||
#include <memory>
|
||||
#include <obs.hpp>
|
||||
|
||||
#include "properties-view.hpp"
|
||||
|
||||
class OBSBasic;
|
||||
class QMenu;
|
||||
|
||||
#include "ui_OBSBasicFilters.h"
|
||||
|
||||
class OBSBasicFilters : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
OBSBasic *main;
|
||||
|
||||
std::unique_ptr<Ui::OBSBasicFilters> ui;
|
||||
int resizeTimer = 0;
|
||||
OBSSource source;
|
||||
OBSPropertiesView *view = nullptr;
|
||||
|
||||
OBSDisplay display;
|
||||
OBSSignal addSignal;
|
||||
OBSSignal removeSignal;
|
||||
OBSSignal reorderSignal;
|
||||
|
||||
OBSSignal removeSourceSignal;
|
||||
OBSSignal renameSourceSignal;
|
||||
|
||||
inline OBSSource GetFilter(int row, bool async);
|
||||
|
||||
void UpdateFilters();
|
||||
void UpdatePropertiesView(int row, bool async);
|
||||
|
||||
static void OBSSourceFilterAdded(void *param, calldata_t *data);
|
||||
static void OBSSourceFilterRemoved(void *param, calldata_t *data);
|
||||
static void OBSSourceReordered(void *param, calldata_t *data);
|
||||
static void SourceRemoved(void *param, calldata_t *data);
|
||||
static void SourceRenamed(void *param, calldata_t *data);
|
||||
static void DrawPreview(void *data, uint32_t cx, uint32_t cy);
|
||||
|
||||
QMenu *CreateAddFilterPopupMenu(bool async);
|
||||
|
||||
void AddNewFilter(const char *id);
|
||||
void ReorderFilter(QListWidget *list, obs_source_t *filter, size_t idx);
|
||||
|
||||
void CustomContextMenu(const QPoint &pos, bool async);
|
||||
void EditItem(QListWidgetItem *item, bool async);
|
||||
|
||||
void FilterNameEdited(QWidget *editor, QListWidget *list);
|
||||
|
||||
private slots:
|
||||
void AddFilter(OBSSource filter);
|
||||
void RemoveFilter(OBSSource filter);
|
||||
void ReorderFilters();
|
||||
void RenameAsyncFilter();
|
||||
void RenameEffectFilter();
|
||||
|
||||
void AddFilterFromAction();
|
||||
|
||||
void OnPreviewResized();
|
||||
|
||||
void on_addAsyncFilter_clicked();
|
||||
void on_removeAsyncFilter_clicked();
|
||||
void on_moveAsyncFilterUp_clicked();
|
||||
void on_moveAsyncFilterDown_clicked();
|
||||
void on_asyncFilters_currentRowChanged(int row);
|
||||
void on_asyncFilters_customContextMenuRequested(const QPoint &pos);
|
||||
void on_asyncFilters_GotFocus();
|
||||
|
||||
void on_addEffectFilter_clicked();
|
||||
void on_removeEffectFilter_clicked();
|
||||
void on_moveEffectFilterUp_clicked();
|
||||
void on_moveEffectFilterDown_clicked();
|
||||
void on_effectFilters_currentRowChanged(int row);
|
||||
void on_effectFilters_customContextMenuRequested(const QPoint &pos);
|
||||
void on_effectFilters_GotFocus();
|
||||
|
||||
void AsyncFilterNameEdited(QWidget *editor,
|
||||
QAbstractItemDelegate::EndEditHint endHint);
|
||||
void EffectFilterNameEdited(QWidget *editor,
|
||||
QAbstractItemDelegate::EndEditHint endHint);
|
||||
|
||||
public:
|
||||
OBSBasicFilters(QWidget *parent, OBSSource source_);
|
||||
~OBSBasicFilters();
|
||||
|
||||
void Init();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
virtual void timerEvent(QTimerEvent *event) override;
|
||||
};
|
@ -677,6 +677,9 @@ OBSBasic::~OBSBasic()
|
||||
if (properties)
|
||||
delete properties;
|
||||
|
||||
if (filters)
|
||||
delete filters;
|
||||
|
||||
if (transformWindow)
|
||||
delete transformWindow;
|
||||
|
||||
@ -794,6 +797,16 @@ void OBSBasic::CreatePropertiesWindow(obs_source_t *source)
|
||||
properties->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
}
|
||||
|
||||
void OBSBasic::CreateFiltersWindow(obs_source_t *source)
|
||||
{
|
||||
if (filters)
|
||||
filters->close();
|
||||
|
||||
filters = new OBSBasicFilters(this, source);
|
||||
filters->Init();
|
||||
filters->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
}
|
||||
|
||||
/* Qt callbacks for invokeMethod */
|
||||
|
||||
void OBSBasic::AddScene(OBSSource source)
|
||||
@ -1957,6 +1970,8 @@ void OBSBasic::on_sources_customContextMenuRequested(const QPoint &pos)
|
||||
action->setEnabled(obs_source_get_output_flags(source) &
|
||||
OBS_SOURCE_INTERACTION);
|
||||
|
||||
popup.addAction(QTStr("Filters"), this,
|
||||
SLOT(OpenFilters()));
|
||||
popup.addAction(QTStr("Properties"), this,
|
||||
SLOT(on_actionSourceProperties_triggered()));
|
||||
}
|
||||
@ -2305,6 +2320,14 @@ void OBSBasic::SceneItemNameEdited(QWidget *editor,
|
||||
UNUSED_PARAMETER(endHint);
|
||||
}
|
||||
|
||||
void OBSBasic::OpenFilters()
|
||||
{
|
||||
OBSSceneItem item = GetCurrentSceneItem();
|
||||
OBSSource source = obs_sceneitem_get_source(item);
|
||||
|
||||
CreateFiltersWindow(source);
|
||||
}
|
||||
|
||||
void OBSBasic::StreamingStart()
|
||||
{
|
||||
ui->streamButton->setText(QTStr("Basic.Main.StopStreaming"));
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "window-basic-properties.hpp"
|
||||
#include "window-basic-transform.hpp"
|
||||
#include "window-basic-adv-audio.hpp"
|
||||
#include "window-basic-filters.hpp"
|
||||
|
||||
#include <util/platform.h>
|
||||
#include <util/util.hpp>
|
||||
@ -67,6 +68,7 @@ private:
|
||||
QPointer<OBSBasicProperties> properties;
|
||||
QPointer<OBSBasicTransform> transformWindow;
|
||||
QPointer<OBSBasicAdvAudio> advAudioWindow;
|
||||
QPointer<OBSBasicFilters> filters;
|
||||
|
||||
QNetworkAccessManager networkManager;
|
||||
|
||||
@ -133,6 +135,7 @@ private:
|
||||
|
||||
void CreateInteractionWindow(obs_source_t *source);
|
||||
void CreatePropertiesWindow(obs_source_t *source);
|
||||
void CreateFiltersWindow(obs_source_t *source);
|
||||
|
||||
public slots:
|
||||
void StreamingStart();
|
||||
@ -297,6 +300,8 @@ private slots:
|
||||
void SceneItemNameEdited(QWidget *editor,
|
||||
QAbstractItemDelegate::EndEditHint endHint);
|
||||
|
||||
void OpenFilters();
|
||||
|
||||
public:
|
||||
explicit OBSBasic(QWidget *parent = 0);
|
||||
virtual ~OBSBasic();
|
||||
|
Loading…
x
Reference in New Issue
Block a user