mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-21 17:34:57 -05:00
Add clipboard condition type
This commit is contained in:
parent
c72f9abc2b
commit
00fc313609
|
|
@ -623,6 +623,15 @@ AdvSceneSwitcher.condition.queue.type.stopped="Stopped"
|
|||
AdvSceneSwitcher.condition.queue.type.size="Size"
|
||||
AdvSceneSwitcher.condition.queue.entry.startStop="Queue{{queues}}is{{conditions}}"
|
||||
AdvSceneSwitcher.condition.queue.entry.size="Queue{{queues}}{{conditions}}is less than{{size}}"
|
||||
AdvSceneSwitcher.condition.clipboard="Clipboard"
|
||||
AdvSceneSwitcher.condition.clipboard.placeholder="Clipboard text"
|
||||
AdvSceneSwitcher.condition.clipboard.urlTooltip="Depending on the OS files might be represented as URLs also!"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.changed="Clipboard content changed"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.isText="Clipboard contains text"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.isImage="Clipboard contains an image"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.isURL="Clipboard contains an URL"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.matches="Clipboard content matches"
|
||||
AdvSceneSwitcher.condition.clipboard.condition.entry="{{conditions}}{{regex}}{{urlInfo}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.scene="Switch scene"
|
||||
|
|
@ -1639,6 +1648,9 @@ AdvSceneSwitcher.tempVar.streaming.keyframeInterval.description="Stream keyframe
|
|||
AdvSceneSwitcher.tempVar.streaming.durationSeconds="Stream duration"
|
||||
AdvSceneSwitcher.tempVar.streaming.durationSeconds.description="Seconds passed since the stream was started.\nThis value will be zero if the stream is stopped."
|
||||
|
||||
AdvSceneSwitcher.tempVar.clipboard.text="Clipboard text"
|
||||
AdvSceneSwitcher.tempVar.clipboard.text.description="The text contained in the clipboard.\nWill be empty if the clipboard does not contain text."
|
||||
|
||||
AdvSceneSwitcher.selectScene="--select scene--"
|
||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||
|
|
|
|||
|
|
@ -75,6 +75,8 @@ target_sources(
|
|||
macro-action-window.hpp
|
||||
macro-condition-audio.cpp
|
||||
macro-condition-audio.hpp
|
||||
macro-condition-clipboard.cpp
|
||||
macro-condition-clipboard.hpp
|
||||
macro-condition-cursor.cpp
|
||||
macro-condition-cursor.hpp
|
||||
macro-condition-date.cpp
|
||||
|
|
|
|||
312
plugins/base/macro-condition-clipboard.cpp
Normal file
312
plugins/base/macro-condition-clipboard.cpp
Normal file
|
|
@ -0,0 +1,312 @@
|
|||
#include "macro-condition-clipboard.hpp"
|
||||
#include "layout-helpers.hpp"
|
||||
#include "ui-helpers.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QMimeData>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroConditionClipboard::id = "clipboard";
|
||||
|
||||
bool MacroConditionClipboard::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionClipboard::id,
|
||||
{MacroConditionClipboard::Create, MacroConditionClipboardEdit::Create,
|
||||
"AdvSceneSwitcher.condition.clipboard"});
|
||||
|
||||
const static std::map<MacroConditionClipboard::Condition, std::string>
|
||||
conditionTypes = {
|
||||
{MacroConditionClipboard::Condition::CHANGED,
|
||||
"AdvSceneSwitcher.condition.clipboard.condition.changed"},
|
||||
{MacroConditionClipboard::Condition::IS_TEXT,
|
||||
"AdvSceneSwitcher.condition.clipboard.condition.isText"},
|
||||
{MacroConditionClipboard::Condition::IS_IMAGE,
|
||||
"AdvSceneSwitcher.condition.clipboard.condition.isImage"},
|
||||
{MacroConditionClipboard::Condition::IS_URL,
|
||||
"AdvSceneSwitcher.condition.clipboard.condition.isURL"},
|
||||
{MacroConditionClipboard::Condition::MATCHES,
|
||||
"AdvSceneSwitcher.condition.clipboard.condition.matches"},
|
||||
};
|
||||
|
||||
ClipboardMessageBuffer ClipboardListener::RegisterForClipboardChanges()
|
||||
{
|
||||
return Instance()->_dispatcher.RegisterClient();
|
||||
}
|
||||
|
||||
ClipboardListener *ClipboardListener::Instance()
|
||||
{
|
||||
static ClipboardListener instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
ClipboardListener::ClipboardListener() : QObject(nullptr)
|
||||
{
|
||||
if (!QApplication::clipboard()) {
|
||||
return;
|
||||
}
|
||||
QObject::connect(QApplication::clipboard(), &QClipboard::dataChanged,
|
||||
this, &ClipboardListener::ClipboardDataChanged);
|
||||
}
|
||||
|
||||
void ClipboardListener::ClipboardDataChanged()
|
||||
{
|
||||
auto text = QApplication::clipboard()->text();
|
||||
_dispatcher.DispatchMessage(text.toStdString());
|
||||
}
|
||||
|
||||
MacroConditionClipboard::MacroConditionClipboard(Macro *m) : MacroCondition(m)
|
||||
{
|
||||
_messageBuffer = ClipboardListener::RegisterForClipboardChanges();
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroCondition> MacroConditionClipboard::Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroConditionClipboard>(m);
|
||||
}
|
||||
|
||||
static bool clipboardContainsImage()
|
||||
{
|
||||
const QClipboard *clipboard = QApplication::clipboard();
|
||||
const QMimeData *mimeData = clipboard->mimeData();
|
||||
return mimeData->hasImage();
|
||||
}
|
||||
|
||||
static bool clipboardContainsText()
|
||||
{
|
||||
const QClipboard *clipboard = QApplication::clipboard();
|
||||
const QMimeData *mimeData = clipboard->mimeData();
|
||||
return mimeData->hasText();
|
||||
}
|
||||
|
||||
static bool clipboardContainsUrl()
|
||||
{
|
||||
const QClipboard *clipboard = QApplication::clipboard();
|
||||
const QMimeData *mimeData = clipboard->mimeData();
|
||||
return mimeData->hasUrls();
|
||||
}
|
||||
|
||||
static std::string getCurrentClipboardText()
|
||||
{
|
||||
auto clipboard = QApplication::clipboard();
|
||||
if (!clipboard) {
|
||||
return "";
|
||||
}
|
||||
return clipboard->text().toStdString();
|
||||
}
|
||||
|
||||
bool MacroConditionClipboard::CheckCondition()
|
||||
{
|
||||
switch (_condition) {
|
||||
case Condition::CHANGED:
|
||||
while (!_messageBuffer->Empty()) {
|
||||
auto message = _messageBuffer->ConsumeMessage();
|
||||
if (!message) {
|
||||
continue;
|
||||
}
|
||||
SetTempVarValue("text", *message);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case Condition::IS_TEXT:
|
||||
if (clipboardContainsText()) {
|
||||
SetTempVarValue("text", getCurrentClipboardText());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case Condition::IS_IMAGE:
|
||||
return clipboardContainsImage();
|
||||
case Condition::IS_URL:
|
||||
if (clipboardContainsUrl()) {
|
||||
SetTempVarValue("text", getCurrentClipboardText());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case Condition::MATCHES:
|
||||
if (_regex.Enabled()) {
|
||||
auto text = getCurrentClipboardText();
|
||||
if (_regex.Matches(text, _text)) {
|
||||
SetTempVarValue("text", text);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
auto text = getCurrentClipboardText();
|
||||
if (text == std::string(_text)) {
|
||||
SetTempVarValue("text", text);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacroConditionClipboard::SetCondition(Condition condition)
|
||||
{
|
||||
_condition = condition;
|
||||
_messageBuffer.reset();
|
||||
if (_condition == Condition::CHANGED) {
|
||||
_messageBuffer =
|
||||
ClipboardListener::RegisterForClipboardChanges();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionClipboard::SetupTempVars()
|
||||
{
|
||||
MacroCondition::SetupTempVars();
|
||||
|
||||
AddTempvar(
|
||||
"text",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.clipboard.text"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.clipboard.text.description"));
|
||||
}
|
||||
|
||||
bool MacroConditionClipboard::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
_text.Save(obj, "text");
|
||||
_regex.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionClipboard::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_text.Load(obj, "text");
|
||||
_regex.Load(obj);
|
||||
SetCondition(
|
||||
static_cast<Condition>(obs_data_get_int(obj, "condition")));
|
||||
return true;
|
||||
}
|
||||
|
||||
static void populateCompareModeselection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, name] : conditionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionClipboardEdit::MacroConditionClipboardEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionClipboard> entryData)
|
||||
: QWidget(parent),
|
||||
_conditions(new QComboBox(this)),
|
||||
_text(new VariableTextEdit(this)),
|
||||
_regex(new RegexConfigWidget(parent)),
|
||||
_urlInfo(new QLabel())
|
||||
{
|
||||
populateCompareModeselection(_conditions);
|
||||
|
||||
QString path = GetThemeTypeName() == "Light"
|
||||
? ":/res/images/help.svg"
|
||||
: ":/res/images/help_light.svg";
|
||||
QIcon icon(path);
|
||||
QPixmap pixmap = icon.pixmap(QSize(16, 16));
|
||||
_urlInfo->setPixmap(pixmap);
|
||||
_urlInfo->hide();
|
||||
_urlInfo->setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.clipboard.urlTooltip"));
|
||||
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_text, SIGNAL(textChanged()), this,
|
||||
SLOT(TextChanged()));
|
||||
QWidget::connect(_regex,
|
||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||
SLOT(RegexChanged(const RegexConfig &)));
|
||||
|
||||
auto layout = new QHBoxLayout();
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.condition.clipboard.condition.entry"),
|
||||
layout,
|
||||
{{"{{conditions}}", _conditions},
|
||||
{"{{regex}}", _regex},
|
||||
{"{{urlInfo}}", _urlInfo}});
|
||||
|
||||
auto mainLayout = new QVBoxLayout();
|
||||
mainLayout->addLayout(layout);
|
||||
mainLayout->addWidget(_text);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
QWidget *
|
||||
MacroConditionClipboardEdit::Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> action)
|
||||
{
|
||||
return new MacroConditionClipboardEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionClipboard>(action));
|
||||
}
|
||||
|
||||
void MacroConditionClipboardEdit::ConditionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->SetCondition(
|
||||
static_cast<MacroConditionClipboard::Condition>(value));
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionClipboardEdit::TextChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_text = _text->toPlainText().toStdString();
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionClipboardEdit::RegexChanged(const RegexConfig &conf)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_regex = conf;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionClipboardEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_conditions->setCurrentIndex(
|
||||
static_cast<int>(_entryData->GetCondition()));
|
||||
_text->setPlainText(_entryData->_text);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionClipboardEdit::SetWidgetVisibility()
|
||||
{
|
||||
const bool requiresTextInput =
|
||||
_entryData->GetCondition() ==
|
||||
MacroConditionClipboard::Condition::MATCHES;
|
||||
_regex->setVisible(requiresTextInput);
|
||||
_text->setVisible(requiresTextInput);
|
||||
_urlInfo->setVisible(_entryData->GetCondition() ==
|
||||
MacroConditionClipboard::Condition::IS_URL);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
92
plugins/base/macro-condition-clipboard.hpp
Normal file
92
plugins/base/macro-condition-clipboard.hpp
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
#pragma once
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "filter-combo-box.hpp"
|
||||
#include "message-buffer.hpp"
|
||||
#include "message-dispatcher.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
using ClipboardMessageBuffer = std::shared_ptr<MessageBuffer<std::string>>;
|
||||
using ClipboardMessageDispatcher = MessageDispatcher<std::string>;
|
||||
|
||||
class ClipboardListener : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
[[nodiscard]] static ClipboardMessageBuffer
|
||||
RegisterForClipboardChanges();
|
||||
|
||||
private slots:
|
||||
void ClipboardDataChanged();
|
||||
|
||||
private:
|
||||
ClipboardListener();
|
||||
static ClipboardListener *Instance();
|
||||
|
||||
ClipboardMessageDispatcher _dispatcher;
|
||||
};
|
||||
|
||||
class MacroConditionClipboard : public MacroCondition {
|
||||
public:
|
||||
MacroConditionClipboard(Macro *m);
|
||||
static std::shared_ptr<MacroCondition> Create(Macro *m);
|
||||
std::string GetId() const { return id; };
|
||||
bool CheckCondition();
|
||||
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
|
||||
enum class Condition {
|
||||
CHANGED,
|
||||
IS_TEXT,
|
||||
IS_IMAGE,
|
||||
IS_URL,
|
||||
MATCHES,
|
||||
};
|
||||
void SetCondition(Condition);
|
||||
Condition GetCondition() const { return _condition; }
|
||||
|
||||
StringVariable _text = obs_module_text(
|
||||
"AdvSceneSwitcher.condition.clipboard.placeholder");
|
||||
RegexConfig _regex;
|
||||
|
||||
private:
|
||||
void SetupTempVars();
|
||||
|
||||
Condition _condition = Condition::CHANGED;
|
||||
ClipboardMessageBuffer _messageBuffer;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionClipboardEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionClipboardEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionClipboard> entryData = nullptr);
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> action);
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int);
|
||||
void TextChanged();
|
||||
void RegexChanged(const RegexConfig &conf);
|
||||
|
||||
private:
|
||||
void UpdateEntryData();
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QComboBox *_conditions;
|
||||
VariableTextEdit *_text;
|
||||
RegexConfigWidget *_regex;
|
||||
QLabel *_urlInfo;
|
||||
|
||||
std::shared_ptr<MacroConditionClipboard> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
Loading…
Reference in New Issue
Block a user