mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-22 01:44:49 -05:00
When horizontally large widgets (e.g. the Window condition) were part of the currently selected macro moving the splitter would result in it either fully hiding the macro list or the macro edit area. Now the list and edit area can be resized smoothly.
818 lines
21 KiB
C++
818 lines
21 KiB
C++
#include "advanced-scene-switcher.hpp"
|
|
#include "action-queue.hpp"
|
|
#include "macro-action-edit.hpp"
|
|
#include "macro-condition-edit.hpp"
|
|
#include "macro-export-import-dialog.hpp"
|
|
#include "macro-settings.hpp"
|
|
#include "macro-search.hpp"
|
|
#include "macro-signals.hpp"
|
|
#include "macro-tree.hpp"
|
|
#include "macro.hpp"
|
|
#include "math-helpers.hpp"
|
|
#include "name-dialog.hpp"
|
|
#include "path-helpers.hpp"
|
|
#include "splitter-helpers.hpp"
|
|
#include "switcher-data.hpp"
|
|
#include "ui-helpers.hpp"
|
|
#include "utility.hpp"
|
|
#include "version.h"
|
|
|
|
#include <obs-frontend-api.h>
|
|
#include <QColor>
|
|
#include <QMenu>
|
|
|
|
namespace advss {
|
|
|
|
static QObject *addPulse = nullptr;
|
|
static QTimer onChangeHighlightTimer;
|
|
static std::chrono::high_resolution_clock::time_point
|
|
lastOnChangeHighlightCheckTime{};
|
|
|
|
static void disableAddButtonHighlight()
|
|
{
|
|
if (addPulse) {
|
|
addPulse->deleteLater();
|
|
addPulse = nullptr;
|
|
}
|
|
}
|
|
|
|
static bool macroNameExists(const std::string &name)
|
|
{
|
|
return !!GetMacroByName(name.c_str());
|
|
}
|
|
|
|
static bool newMacroNameIsValid(const std::string &name)
|
|
{
|
|
if (!macroNameExists(name)) {
|
|
return true;
|
|
}
|
|
|
|
auto macro = GetMacroByName(name.c_str());
|
|
if (!macro) {
|
|
return false;
|
|
}
|
|
|
|
QString fmt = obs_module_text(
|
|
macro->IsGroup() ? "AdvSceneSwitcher.macroTab.groupNameExists"
|
|
: "AdvSceneSwitcher.macroTab.macroNameExists");
|
|
|
|
DisplayMessage(fmt.arg(QString::fromStdString(name)));
|
|
return false;
|
|
}
|
|
|
|
bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
|
|
std::string &name, std::string format)
|
|
{
|
|
QString fmt;
|
|
int i = 1;
|
|
if (format.empty()) {
|
|
fmt = QString(obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.defaultname"));
|
|
} else {
|
|
fmt = QString::fromStdString(format);
|
|
i = 2;
|
|
}
|
|
|
|
QString placeHolderText = fmt.arg(i);
|
|
while ((macroNameExists(placeHolderText.toUtf8().constData()))) {
|
|
placeHolderText = fmt.arg(++i);
|
|
}
|
|
|
|
bool accepted = NameDialog::AskForName(
|
|
this, obs_module_text("AdvSceneSwitcher.macroTab.add"),
|
|
obs_module_text("AdvSceneSwitcher.macroTab.name"), name,
|
|
placeHolderText);
|
|
|
|
if (!accepted) {
|
|
return false;
|
|
}
|
|
|
|
if (name.empty()) {
|
|
return false;
|
|
}
|
|
|
|
if (!newMacroNameIsValid(name)) {
|
|
return false;
|
|
}
|
|
|
|
res = std::make_shared<Macro>(name, GetGlobalMacroSettings());
|
|
return true;
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroAdd_clicked()
|
|
{
|
|
// Hotkey to add new macro will also use this function.
|
|
// Since we don't want the hotkey to have an effect if the macro tab is
|
|
// not focused we need to check this here.
|
|
if (!MacroTabIsInFocus()) {
|
|
return;
|
|
}
|
|
|
|
std::string name;
|
|
std::shared_ptr<Macro> newMacro;
|
|
if (!AddNewMacro(newMacro, name)) {
|
|
return;
|
|
}
|
|
|
|
disableAddButtonHighlight();
|
|
|
|
auto selectedMacro = GetSelectedMacro();
|
|
if (!selectedMacro) {
|
|
ui->macros->Add(newMacro);
|
|
MacroSignalManager::Instance()->Add(
|
|
QString::fromStdString(name));
|
|
return;
|
|
}
|
|
|
|
if (selectedMacro->IsGroup()) {
|
|
ui->macros->ExpandGroup(selectedMacro);
|
|
Macro::PrepareMoveToGroup(selectedMacro, newMacro);
|
|
ui->macros->AddToGroup(newMacro, selectedMacro);
|
|
MacroSignalManager::Instance()->Add(
|
|
QString::fromStdString(name));
|
|
return;
|
|
}
|
|
|
|
auto selectedMacroGroup = selectedMacro->Parent();
|
|
if (!selectedMacroGroup) {
|
|
ui->macros->Add(newMacro, selectedMacro);
|
|
MacroSignalManager::Instance()->Add(
|
|
QString::fromStdString(name));
|
|
return;
|
|
}
|
|
|
|
Macro::PrepareMoveToGroup(selectedMacroGroup, newMacro);
|
|
ui->macros->Add(newMacro, selectedMacro);
|
|
MacroSignalManager::Instance()->Add(QString::fromStdString(name));
|
|
}
|
|
|
|
static void addGroupSubitems(std::vector<std::shared_ptr<Macro>> ¯os,
|
|
const std::shared_ptr<Macro> &group)
|
|
{
|
|
auto subitems = GetGroupMacroEntries(group.get());
|
|
|
|
// Remove subitems which were already selected to avoid duplicates
|
|
for (const auto &subitem : subitems) {
|
|
auto it = std::find(macros.begin(), macros.end(), subitem);
|
|
if (it == macros.end()) {
|
|
continue;
|
|
}
|
|
macros.erase(it);
|
|
}
|
|
|
|
// Add group subitems
|
|
auto it = std::find(macros.begin(), macros.end(), group);
|
|
if (it == macros.end()) {
|
|
return;
|
|
}
|
|
it = std::next(it);
|
|
macros.insert(it, subitems.begin(), subitems.end());
|
|
}
|
|
|
|
void AdvSceneSwitcher::RemoveMacro(std::shared_ptr<Macro> ¯o)
|
|
{
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
auto name = QString::fromStdString(macro->Name());
|
|
if (macro->IsGroup() && macro->GroupSize() > 0) {
|
|
QString deleteWarning = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.removeGroupPopup.text");
|
|
if (!DisplayMessage(deleteWarning.arg(name), true)) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (macro->IsGroup()) {
|
|
std::vector<std::shared_ptr<Macro>> macros = {macro};
|
|
addGroupSubitems(macros, macro);
|
|
for (auto macro : macros) {
|
|
ui->macroEdit->ClearSegmentWidgetCacheFor(macro.get());
|
|
}
|
|
} else {
|
|
ui->macroEdit->ClearSegmentWidgetCacheFor(macro.get());
|
|
}
|
|
|
|
// Don't cache widgets for about to be deleted macros
|
|
MacroSegmentList::SetCachingEnabled(false);
|
|
ui->macros->Remove(macro);
|
|
MacroSegmentList::SetCachingEnabled(true);
|
|
|
|
MacroSignalManager::Instance()->Remove(name);
|
|
}
|
|
|
|
void AdvSceneSwitcher::RemoveSelectedMacros()
|
|
{
|
|
auto macros = GetSelectedMacros();
|
|
if (macros.empty()) {
|
|
return;
|
|
}
|
|
|
|
int macroCount = macros.size();
|
|
if (macroCount == 1) {
|
|
QString deleteWarning = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.removeSingleMacroPopup.text");
|
|
auto ¯o = macros.at(0);
|
|
deleteWarning = deleteWarning.arg(
|
|
QString::fromStdString(macro->Name()));
|
|
|
|
if ((!macro->IsGroup() || macro->GroupSize() == 0) &&
|
|
!DisplayMessage(deleteWarning, true)) {
|
|
return;
|
|
}
|
|
|
|
RemoveMacro(macro);
|
|
return;
|
|
}
|
|
|
|
QString deleteWarning = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.removeMultipleMacrosPopup.text");
|
|
if (!DisplayMessage(deleteWarning.arg(macroCount), true)) {
|
|
return;
|
|
}
|
|
|
|
for (auto ¯o : macros) {
|
|
RemoveMacro(macro);
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::RenameMacro(std::shared_ptr<Macro> ¯o,
|
|
const QString &name)
|
|
{
|
|
auto oldName = QString::fromStdString(macro->Name());
|
|
{
|
|
auto lock = LockContext();
|
|
macro->SetName(name.toStdString());
|
|
}
|
|
|
|
MacroSignalManager::Instance()->Rename(oldName, name);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroRemove_clicked()
|
|
{
|
|
RemoveSelectedMacros();
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroUp_clicked() const
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
ui->macros->Up(macro);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroDown_clicked() const
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
ui->macros->Down(macro);
|
|
}
|
|
|
|
void AdvSceneSwitcher::RenameSelectedMacro()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
std::string oldName = macro->Name();
|
|
std::string name;
|
|
if (!NameDialog::AskForName(
|
|
this, obs_module_text("AdvSceneSwitcher.windowTitle"),
|
|
obs_module_text("AdvSceneSwitcher.item.newName"), name,
|
|
QString::fromStdString(oldName))) {
|
|
return;
|
|
}
|
|
|
|
if (name.empty() || name == oldName || !newMacroNameIsValid(name)) {
|
|
return;
|
|
}
|
|
|
|
RenameMacro(macro, QString::fromStdString(name));
|
|
|
|
const QSignalBlocker b(ui->macroName);
|
|
ui->macroName->setText(QString::fromStdString(name));
|
|
}
|
|
|
|
void AdvSceneSwitcher::ExportMacros() const
|
|
{
|
|
auto selectedMacros = GetSelectedMacros();
|
|
auto macros = selectedMacros;
|
|
for (const auto ¯o : selectedMacros) {
|
|
if (macro->IsGroup() && macro->GroupSize() > 0) {
|
|
addGroupSubitems(macros, macro);
|
|
}
|
|
}
|
|
|
|
OBSDataAutoRelease data = obs_data_create();
|
|
OBSDataArrayAutoRelease macroArray = obs_data_array_create();
|
|
for (const auto ¯o : macros) {
|
|
OBSDataAutoRelease obj = obs_data_create();
|
|
macro->Save(obj);
|
|
obs_data_array_push_back(macroArray, obj);
|
|
}
|
|
obs_data_set_array(data, "macros", macroArray);
|
|
SaveVariables(data);
|
|
SaveActionQueues(data);
|
|
obs_data_set_string(data, "version", g_GIT_TAG);
|
|
auto json = obs_data_get_json(data);
|
|
QString exportString(json);
|
|
|
|
MacroExportImportDialog::ExportMacros(exportString);
|
|
}
|
|
|
|
bool AdvSceneSwitcher::ResolveMacroImportNameConflict(
|
|
std::shared_ptr<Macro> ¯o)
|
|
{
|
|
QString errorMesg = obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.import.nameConflict");
|
|
errorMesg = errorMesg.arg(QString::fromStdString(macro->Name()),
|
|
QString::fromStdString(macro->Name()));
|
|
bool continueResolve = DisplayMessage(errorMesg, true);
|
|
if (!continueResolve) {
|
|
return false;
|
|
}
|
|
|
|
QString format = QString::fromStdString(macro->Name()) + " %1";
|
|
int i = 2;
|
|
|
|
QString placeHolderText = format.arg(i);
|
|
while ((macroNameExists(placeHolderText.toUtf8().constData()))) {
|
|
placeHolderText = format.arg(++i);
|
|
}
|
|
|
|
std::string newName;
|
|
bool accepted = NameDialog::AskForName(
|
|
this,
|
|
obs_module_text(macro->IsGroup()
|
|
? "AdvSceneSwitcher.macroTab.addGroup"
|
|
: "AdvSceneSwitcher.macroTab.add"),
|
|
obs_module_text("AdvSceneSwitcher.macroTab.name"), newName,
|
|
placeHolderText);
|
|
|
|
if (!accepted) {
|
|
return false;
|
|
}
|
|
|
|
if (newName.empty()) {
|
|
return false;
|
|
}
|
|
|
|
if (!newMacroNameIsValid(newName)) {
|
|
return ResolveMacroImportNameConflict(macro);
|
|
}
|
|
|
|
macro->SetName(newName);
|
|
return true;
|
|
}
|
|
|
|
void AdvSceneSwitcher::ImportMacros()
|
|
{
|
|
QString json;
|
|
if (!MacroExportImportDialog::ImportMacros(json)) {
|
|
return;
|
|
}
|
|
OBSDataAutoRelease data =
|
|
obs_data_create_from_json(json.toStdString().c_str());
|
|
if (!data) {
|
|
DisplayMessage(obs_module_text(
|
|
"AdvSceneSwitcher.macroTab.import.invalid"));
|
|
ImportMacros();
|
|
return;
|
|
}
|
|
ImportVariables(data);
|
|
ImportQueues(data);
|
|
|
|
auto version = obs_data_get_string(data, "version");
|
|
if (strcmp(version, g_GIT_TAG) != 0) {
|
|
blog(LOG_WARNING,
|
|
"importing macros from non matching plugin version \"%s\"",
|
|
version);
|
|
}
|
|
|
|
OBSDataArrayAutoRelease array = obs_data_get_array(data, "macros");
|
|
size_t count = obs_data_array_count(array);
|
|
|
|
int groupSize = 0;
|
|
std::shared_ptr<Macro> group;
|
|
std::vector<std::shared_ptr<Macro>> importedMacros;
|
|
auto &tempMacros = GetTemporaryMacros();
|
|
|
|
auto lock = LockContext();
|
|
for (size_t i = 0; i < count; i++) {
|
|
tempMacros.clear();
|
|
|
|
OBSDataAutoRelease array_obj = obs_data_array_item(array, i);
|
|
auto macro = std::make_shared<Macro>();
|
|
tempMacros.emplace_back(macro);
|
|
macro->Load(array_obj);
|
|
RunAndClearPostLoadSteps();
|
|
|
|
if (macroNameExists(macro->Name()) &&
|
|
!ResolveMacroImportNameConflict(macro)) {
|
|
groupSize--;
|
|
continue;
|
|
}
|
|
|
|
importedMacros.emplace_back(macro);
|
|
GetTopLevelMacros().emplace_back(macro);
|
|
if (groupSize > 0 && !macro->IsGroup()) {
|
|
Macro::PrepareMoveToGroup(group, macro);
|
|
groupSize--;
|
|
}
|
|
|
|
if (macro->IsGroup()) {
|
|
group = macro;
|
|
groupSize = macro->GroupSize();
|
|
// We are not sure if all elements will be added so we
|
|
// have to reset the group size to zero and add elements
|
|
// to the group as they come up.
|
|
macro->ResetGroupSize();
|
|
}
|
|
}
|
|
|
|
for (const auto ¯o : importedMacros) {
|
|
macro->PostLoad();
|
|
}
|
|
RunAndClearPostLoadSteps();
|
|
tempMacros.clear();
|
|
|
|
ui->macros->Reset(GetTopLevelMacros(),
|
|
GetGlobalMacroSettings()._highlightExecuted);
|
|
disableAddButtonHighlight();
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroName_editingFinished()
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
QString newName = ui->macroName->text();
|
|
QString oldName = QString::fromStdString(macro->Name());
|
|
|
|
if (newName.isEmpty() || newName == oldName ||
|
|
!newMacroNameIsValid(newName.toStdString())) {
|
|
ui->macroName->setText(oldName);
|
|
return;
|
|
}
|
|
RenameMacro(macro, newName);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_runMacroInParallel_stateChanged(int value) const
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
auto lock = LockContext();
|
|
macro->SetRunInParallel(value);
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_actionTriggerMode_currentIndexChanged(int index) const
|
|
{
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
auto lock = LockContext();
|
|
const auto mode = static_cast<Macro::ActionTriggerMode>(
|
|
ui->actionTriggerMode->itemData(index).toInt());
|
|
macro->SetActionTriggerMode(mode);
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable) const
|
|
{
|
|
ui->macroName->setDisabled(disable);
|
|
ui->runMacro->setDisabled(disable);
|
|
ui->runMacroInParallel->setDisabled(disable);
|
|
ui->actionTriggerMode->setDisabled(disable);
|
|
ui->macroEdit->SetControlsDisabled(disable);
|
|
}
|
|
|
|
std::shared_ptr<Macro> AdvSceneSwitcher::GetSelectedMacro() const
|
|
{
|
|
return ui->macros->GetCurrentMacro();
|
|
}
|
|
|
|
std::vector<std::shared_ptr<Macro>> AdvSceneSwitcher::GetSelectedMacros() const
|
|
{
|
|
return ui->macros->GetCurrentMacros();
|
|
}
|
|
|
|
void AdvSceneSwitcher::MacroSelectionChanged()
|
|
{
|
|
if (loading) {
|
|
return;
|
|
}
|
|
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
SetMacroEditAreaDisabled(true);
|
|
ui->macroEdit->SetMacro(macro);
|
|
return;
|
|
}
|
|
|
|
{
|
|
const QSignalBlocker b1(ui->macroName);
|
|
const QSignalBlocker b2(ui->runMacroInParallel);
|
|
const QSignalBlocker b3(ui->actionTriggerMode);
|
|
ui->macroName->setText(macro->Name().c_str());
|
|
ui->runMacroInParallel->setChecked(macro->RunInParallel());
|
|
ui->actionTriggerMode->setCurrentIndex(
|
|
ui->actionTriggerMode->findData(static_cast<int>(
|
|
macro->GetActionTriggerMode())));
|
|
}
|
|
|
|
macro->ResetUIHelpers();
|
|
ui->macroEdit->SetMacro(macro);
|
|
SetMacroEditAreaDisabled(false);
|
|
|
|
if (macro->IsGroup()) {
|
|
SetMacroEditAreaDisabled(true);
|
|
ui->macroName->setEnabled(true);
|
|
return;
|
|
}
|
|
|
|
if (GetGlobalMacroSettings()._saveSettingsOnMacroChange) {
|
|
obs_frontend_save();
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::HighlightOnChange() const
|
|
{
|
|
if (!GetGlobalMacroSettings()._highlightActions &&
|
|
!GetGlobalMacroSettings()._highlightExecuted) {
|
|
return;
|
|
}
|
|
|
|
auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
if (macro->ActionTriggerModePreventedActionsSince(
|
|
lastOnChangeHighlightCheckTime)) {
|
|
HighlightWidget(ui->actionTriggerMode, Qt::yellow,
|
|
Qt::transparent, true);
|
|
}
|
|
|
|
lastOnChangeHighlightCheckTime =
|
|
std::chrono::high_resolution_clock::now();
|
|
}
|
|
|
|
void AdvSceneSwitcher::on_macroSettings_clicked()
|
|
{
|
|
GlobalMacroSettings prop = GetGlobalMacroSettings();
|
|
bool accepted = MacroSettingsDialog::AskForSettings(
|
|
this, prop, GetSelectedMacro().get());
|
|
if (!accepted) {
|
|
return;
|
|
}
|
|
|
|
GetGlobalMacroSettings() = prop;
|
|
MacroSignalManager::Instance()->HighlightChanged(
|
|
prop._highlightExecuted);
|
|
|
|
// Reset highlights to avoid all macro segments being highlighted, which
|
|
// would have been highlighted at least once since the moment the
|
|
// highlighting was disabled
|
|
if (prop._highlightConditions) {
|
|
ui->macroEdit->ResetConditionHighlights();
|
|
}
|
|
if (prop._highlightActions) {
|
|
ui->macroEdit->ResetActionHighlights();
|
|
}
|
|
|
|
SetCheckIntervalTooLowVisibility();
|
|
}
|
|
|
|
static bool shouldRestoreSplitter(const QList<int> &pos)
|
|
{
|
|
if (pos.size() == 0) {
|
|
return false;
|
|
}
|
|
|
|
for (int i = 0; i < pos.size(); ++i) {
|
|
if (pos[i] == 0) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static QToolBar *
|
|
setupToolBar(const std::initializer_list<std::initializer_list<QWidget *>>
|
|
&widgetGroups)
|
|
{
|
|
auto toolbar = new QToolBar();
|
|
toolbar->setIconSize({16, 16});
|
|
|
|
QAction *lastSeparator = nullptr;
|
|
|
|
for (const auto &widgetGroup : widgetGroups) {
|
|
for (const auto &widget : widgetGroup) {
|
|
if (!widget) {
|
|
continue;
|
|
}
|
|
toolbar->addWidget(widget);
|
|
}
|
|
lastSeparator = toolbar->addSeparator();
|
|
}
|
|
|
|
if (lastSeparator) {
|
|
toolbar->removeAction(lastSeparator);
|
|
}
|
|
|
|
// Prevent "extension" button from showing up
|
|
toolbar->setSizePolicy(QSizePolicy::MinimumExpanding,
|
|
QSizePolicy::Preferred);
|
|
return toolbar;
|
|
}
|
|
|
|
void AdvSceneSwitcher::SetupMacroTab()
|
|
{
|
|
ui->macros->installEventFilter(this);
|
|
|
|
auto ¯os = GetTopLevelMacros();
|
|
|
|
if (macros.size() == 0 && !switcher->disableHints) {
|
|
addPulse = HighlightWidget(ui->macroAdd, QColor(Qt::green));
|
|
}
|
|
|
|
auto macroControls = setupToolBar({{ui->macroAdd, ui->macroRemove},
|
|
{ui->macroUp, ui->macroDown}});
|
|
ui->macroControlLayout->addWidget(macroControls);
|
|
|
|
ui->macros->Reset(macros, GetGlobalMacroSettings()._highlightExecuted);
|
|
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
|
SLOT(MacroSelectionChanged()));
|
|
ui->runMacro->SetMacroTree(ui->macros);
|
|
|
|
ui->macros->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->macros, &QWidget::customContextMenuRequested, this,
|
|
&AdvSceneSwitcher::ShowMacroContextMenu);
|
|
|
|
SetMacroEditAreaDisabled(true);
|
|
ui->macroPriorityWarning->setVisible(
|
|
switcher->functionNamesByPriority[0] != macro_func);
|
|
|
|
lastOnChangeHighlightCheckTime =
|
|
std::chrono::high_resolution_clock::now();
|
|
onChangeHighlightTimer.setInterval(1500);
|
|
connect(&onChangeHighlightTimer, SIGNAL(timeout()), this,
|
|
SLOT(HighlightOnChange()));
|
|
onChangeHighlightTimer.start();
|
|
|
|
SetupMacroSearchWidgets(ui->macroSearchLayout, ui->macroSearchText,
|
|
ui->macroSearchClear, ui->macroSearchType,
|
|
ui->macroSearchRegex,
|
|
ui->macroSearchShowSettings,
|
|
[this]() { ui->macros->RefreshFilter(); });
|
|
|
|
static const std::vector<
|
|
std::pair<Macro::ActionTriggerMode, const char *>>
|
|
actionTriggerModes = {
|
|
{Macro::ActionTriggerMode::ALWAYS,
|
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.always"},
|
|
{Macro::ActionTriggerMode::MACRO_RESULT_CHANGED,
|
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.onOverallChange"},
|
|
{Macro::ActionTriggerMode::ANY_CONDITION_CHANGED,
|
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionChange"},
|
|
{Macro::ActionTriggerMode::ANY_CONDITION_TRIGGERED,
|
|
"AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionTriggered"},
|
|
};
|
|
|
|
for (const auto &[mode, name] : actionTriggerModes) {
|
|
ui->actionTriggerMode->addItem(obs_module_text(name),
|
|
static_cast<int>(mode));
|
|
}
|
|
|
|
ui->macroListBox->setSizePolicy(QSizePolicy::Ignored,
|
|
QSizePolicy::Preferred);
|
|
ui->macroListBox->setMinimumWidth(0);
|
|
ui->macroEditGroup->setSizePolicy(QSizePolicy::Ignored,
|
|
QSizePolicy::Preferred);
|
|
ui->macroEditGroup->setMinimumWidth(0);
|
|
|
|
if (shouldRestoreSplitter(
|
|
switcher->macroListMacroEditSplitterPosition)) {
|
|
ui->macroListMacroEditSplitter->setSizes(
|
|
switcher->macroListMacroEditSplitterPosition);
|
|
} else {
|
|
QTimer::singleShot(0, this, [this]() {
|
|
const auto totalWidth =
|
|
ui->macroListMacroEditSplitter->width();
|
|
ui->macroListMacroEditSplitter->setSizes(
|
|
{totalWidth / 5, totalWidth * 4 / 5});
|
|
});
|
|
}
|
|
}
|
|
|
|
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
|
{
|
|
QPoint globalPos = ui->macros->mapToGlobal(pos);
|
|
QMenu menu;
|
|
|
|
menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.contextMenuAdd"),
|
|
this, &AdvSceneSwitcher::on_macroAdd_clicked);
|
|
|
|
auto copy = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.copy"), this,
|
|
&AdvSceneSwitcher::CopyMacro);
|
|
copy->setEnabled(ui->macros->SingleItemSelected() &&
|
|
!ui->macros->GroupsSelected());
|
|
menu.addSeparator();
|
|
|
|
auto rename = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.rename"), this,
|
|
&AdvSceneSwitcher::RenameSelectedMacro);
|
|
rename->setEnabled(ui->macros->SingleItemSelected());
|
|
|
|
auto remove = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.remove"), this,
|
|
&AdvSceneSwitcher::on_macroRemove_clicked);
|
|
remove->setDisabled(ui->macros->SelectionEmpty());
|
|
menu.addSeparator();
|
|
|
|
auto group = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.group"), ui->macros,
|
|
&MacroTree::GroupSelectedItems);
|
|
group->setDisabled(ui->macros->GroupedItemsSelected() ||
|
|
ui->macros->GroupsSelected() ||
|
|
ui->macros->SelectionEmpty());
|
|
|
|
auto ungroup = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.ungroup"),
|
|
ui->macros, &MacroTree::UngroupSelectedGroups);
|
|
ungroup->setEnabled(ui->macros->GroupsSelected());
|
|
|
|
auto expandAll = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.expandAllGroups"),
|
|
ui->macros, &MacroTree::ExpandAll);
|
|
expandAll->setEnabled(ui->macros->GroupsExist());
|
|
|
|
auto collapseAll = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.collapseAllGroups"),
|
|
ui->macros, &MacroTree::CollapseAll);
|
|
collapseAll->setEnabled(ui->macros->GroupsExist());
|
|
menu.addSeparator();
|
|
|
|
auto exportAction = menu.addAction(
|
|
obs_module_text("AdvSceneSwitcher.macroTab.export"), this,
|
|
&AdvSceneSwitcher::ExportMacros);
|
|
exportAction->setDisabled(ui->macros->SelectionEmpty());
|
|
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.import"),
|
|
this, &AdvSceneSwitcher::ImportMacros);
|
|
|
|
menu.exec(globalPos);
|
|
}
|
|
|
|
void AdvSceneSwitcher::CopyMacro()
|
|
{
|
|
const auto macro = GetSelectedMacro();
|
|
if (!macro) {
|
|
return;
|
|
}
|
|
|
|
std::string format = macro->Name() + " %1";
|
|
std::string name;
|
|
std::shared_ptr<Macro> newMacro;
|
|
if (!AddNewMacro(newMacro, name, format)) {
|
|
return;
|
|
}
|
|
|
|
OBSDataAutoRelease data = obs_data_create();
|
|
macro->Save(data, true);
|
|
newMacro->Load(data);
|
|
newMacro->PostLoad();
|
|
newMacro->SetName(name);
|
|
RunAndClearPostLoadSteps();
|
|
Macro::PrepareMoveToGroup(macro->Parent(), newMacro);
|
|
|
|
ui->macros->Add(newMacro, macro);
|
|
disableAddButtonHighlight();
|
|
MacroSignalManager::Instance()->Add(QString::fromStdString(name));
|
|
}
|
|
|
|
bool MacroTabIsInFocus()
|
|
{
|
|
return AdvSceneSwitcher::window &&
|
|
AdvSceneSwitcher::window->MacroTabIsInFocus();
|
|
}
|
|
|
|
bool AdvSceneSwitcher::MacroTabIsInFocus()
|
|
{
|
|
return isActiveWindow() && isAncestorOf(focusWidget()) &&
|
|
(ui->tabWidget->currentWidget()->objectName() == "macroTab");
|
|
}
|
|
|
|
} // namespace advss
|