Compare commits

...

8 Commits

Author SHA1 Message Date
WarmUpTill
2af0735a2f Expand date condition functionality
The date condition now supports the condition types "after", "before"
and specifying a time range.
2021-08-12 11:01:45 -07:00
WarmUpTill
556943c293 Fix writing current scene to file 2021-08-11 12:49:07 -07:00
WarmUpTill
e3004184c4 Format json strings of user input and source settings
Source settings and user specified settings might use different json
formatting and thus not match even though the json contents match.

It might not be possible to do the formatting for regex strings so
revert to the originally specified settings string if it cannot.
2021-08-09 11:39:48 -07:00
WarmUpTill
7b2c2e91db Rename function 2021-08-09 11:39:48 -07:00
WarmUpTill
06ea7bf1d9 Fix crash when deleting macro with wait action
Note that this might still not be completely race free but should
improve the situation a lot.
2021-08-09 11:39:20 -07:00
WarmUpTill
1474509cb9 Fix extended sequence abort when using non-instant transitions 2021-07-30 00:47:40 +02:00
WarmUpTill
87aa8d3b40 Remove code used for backwards compatibility 2021-07-29 15:16:29 -07:00
WarmUpTill
d3e8b76fa6 Do not apply MouseWheelWidgetAdjustmentGuard to QScrollBars
Without this change, it will be annoying to interact with expanded
QComboBoxes and there should be no danger of accidentally modifying
macro settings by interacting with QScrollBars
2021-07-29 15:16:19 -07:00
23 changed files with 173 additions and 111 deletions

View File

@@ -185,8 +185,12 @@ AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
AdvSceneSwitcher.condition.replay.entry="{{state}}"
AdvSceneSwitcher.condition.date="Date"
AdvSceneSwitcher.condition.date.entry.line1="{{dateTime}} {{ignoreDate}} Ignore date selection {{ignoreTime}} Ignore time selection"
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Repeat every {{duration}}"
AdvSceneSwitcher.condition.date.state.at="At"
AdvSceneSwitcher.condition.date.state.after="After"
AdvSceneSwitcher.condition.date.state.before="Before"
AdvSceneSwitcher.condition.date.state.between="Between"
AdvSceneSwitcher.condition.date.entry.line1="{{condition}} {{dateTime}} {{dateTime2}} {{ignoreDate}} Ignore date component {{ignoreTime}} Ignore time component"
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Reschedule {{duration}} later when matching"
; Macro Actions
AdvSceneSwitcher.action.switchScene="Switch scene"

View File

@@ -424,8 +424,9 @@ void SwitcherData::Stop()
{
if (th && th->isRunning()) {
stop = true;
transitionCv.notify_one();
cv.notify_one();
abortMacroWait = true;
macroWaitCv.notify_one();
th->wait();
delete th;
th = nullptr;

View File

@@ -4,6 +4,14 @@
#include <QCheckBox>
#include <QDateTimeEdit>
#include <QComboBox>
enum class DateCondition {
AT,
AFTER,
BEFORE,
BETWEEN,
};
class MacroConditionDate : public MacroCondition {
public:
@@ -18,10 +26,12 @@ public:
}
QDateTime _dateTime;
QDateTime _dateTime2;
bool _ignoreDate = false;
bool _ignoreTime = false;
bool _repeat = false;
Duration _duration;
DateCondition _condition = DateCondition::AT;
private:
static bool _registered;
@@ -45,7 +55,9 @@ public:
}
private slots:
void ConditionChanged(int cond);
void DateTimeChanged(const QDateTime &datetime);
void DateTime2Changed(const QDateTime &datetime);
void IgnoreDateChanged(int state);
void IgnoreTimeChanged(int state);
void RepeatChanged(int state);
@@ -55,7 +67,9 @@ signals:
void HeaderInfoChanged(const QString &);
protected:
QComboBox *_condition;
QDateTimeEdit *_dateTime;
QDateTimeEdit *_dateTime2;
QCheckBox *_ignoreDate;
QCheckBox *_ignoreTime;
QCheckBox *_repeat;
@@ -63,5 +77,6 @@ protected:
std::shared_ptr<MacroConditionDate> _entryData;
private:
void ShowSecondDateSelection(bool visible);
bool _loading = true;
};

View File

@@ -35,8 +35,7 @@ struct SceneSequenceSwitch : SceneSwitcherEntry {
bool reduce();
SceneSequenceSwitch *extend();
bool checkMatch(OBSWeakSource currentScene, int &linger,
SceneSequenceSwitch *root = nullptr);
bool checkMatch(int &linger, SceneSequenceSwitch *root = nullptr);
bool checkDurationMatchInterruptible();
void prepareUninterruptibleMatch(int &linger);
void advanceActiveSequence();

View File

@@ -67,7 +67,6 @@ struct SwitcherData {
std::mutex m;
bool transitionActive = false;
bool waitForTransition = false;
std::condition_variable transitionCv;
bool stop = false;
bool verbose = false;
bool disableHints = false;
@@ -92,6 +91,8 @@ struct SwitcherData {
std::chrono::high_resolution_clock::time_point lastMatchTime;
std::deque<Macro> macros;
std::condition_variable macroWaitCv;
std::atomic_bool abortMacroWait = {false};
bool macroSceneSwitched = false;
bool replayBufferSaved = false;

View File

@@ -30,8 +30,8 @@ bool compareSourceSettings(const OBSWeakSource &source,
std::vector<obs_scene_item *> getSceneItemsWithName(OBSScene scene,
std::string &name);
std::string getDataFilePath(const std::string &file);
QString fromatJsonString(std::string);
QString fromatJsonString(const char *);
QString formatJsonString(std::string);
QString formatJsonString(const char *);
/**
* Populate layout with labels and widgets based on provided text

View File

@@ -174,6 +174,8 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx)
std::lock_guard<std::mutex> lock(switcher->m);
macro->Actions().erase(macro->Actions().begin() + idx);
switcher->abortMacroWait = true;
switcher->macroWaitCv.notify_one();
macro->UpdateActionIndices();
// All entry pointers in existing edit widgets after the new entry will

View File

@@ -198,7 +198,7 @@ void MacroActionFilterEdit::GetSettingsClicked()
}
_settings->setPlainText(
fromatJsonString(getSourceSettings(_entryData->_filter)));
formatJsonString(getSourceSettings(_entryData->_filter)));
}
void MacroActionFilterEdit::SettingsChanged()

View File

@@ -201,7 +201,7 @@ void MacroActionSceneTransformEdit::UpdateEntryData()
GetWeakSourceName(_entryData->_source).c_str());
if (_entryData->_source) {
_settings->setPlainText(
fromatJsonString(_entryData->GetSettings()));
formatJsonString(_entryData->GetSettings()));
}
}
@@ -255,7 +255,7 @@ void MacroActionSceneTransformEdit::GetSettingsClicked()
auto data = obs_data_create();
save_transform_state(data, info, crop);
auto json = obs_data_get_json(data);
_settings->setPlainText(fromatJsonString(json));
_settings->setPlainText(formatJsonString(json));
obs_data_release(data);
}

View File

@@ -173,7 +173,7 @@ void MacroActionSourceEdit::GetSettingsClicked()
}
_settings->setPlainText(
fromatJsonString(getSourceSettings(_entryData->_source)));
formatJsonString(getSourceSettings(_entryData->_source)));
}
void MacroActionSourceEdit::SettingsChanged()

View File

@@ -38,10 +38,12 @@ bool MacroActionWait::PerformAction()
sleep_duration);
std::unique_lock<std::mutex> lock(switcher->m);
auto r = switcher->cv.wait_for(
switcher->abortMacroWait = false;
switcher->macroWaitCv.wait_for(
lock,
std::chrono::milliseconds((long long)(sleep_duration * 1000)));
return r == std::cv_status::timeout;
std::chrono::milliseconds((long long)(sleep_duration * 1000)),
[] { return switcher->abortMacroWait.load(); });
return !switcher->abortMacroWait;
}
bool MacroActionWait::Save(obs_data_t *obj)

View File

@@ -10,12 +10,6 @@ bool MacroConditionCursor::_registered = MacroConditionFactory::Register(
{MacroConditionCursor::Create, MacroConditionCursorEdit::Create,
"AdvSceneSwitcher.condition.cursor"});
// TODO: Remove in future version - just added for backwards compatibility
static const std::string idOld = "region";
static bool oldRegisterd = MacroConditionFactory::Register(
idOld, {MacroConditionCursor::Create, MacroConditionCursorEdit::Create,
"AdvSceneSwitcher.condition.cursor"});
static std::map<CursorCondition, std::string> cursorConditionTypes = {
{CursorCondition::REGION,
"AdvSceneSwitcher.condition.cursor.type.region"},

View File

@@ -10,21 +10,52 @@ bool MacroConditionDate::_registered = MacroConditionFactory::Register(
{MacroConditionDate::Create, MacroConditionDateEdit::Create,
"AdvSceneSwitcher.condition.date", false});
static std::map<DateCondition, std::string> dateConditionTypes = {
{DateCondition::AT, "AdvSceneSwitcher.condition.date.state.at"},
{DateCondition::AFTER, "AdvSceneSwitcher.condition.date.state.after"},
{DateCondition::BEFORE, "AdvSceneSwitcher.condition.date.state.before"},
{DateCondition::BETWEEN,
"AdvSceneSwitcher.condition.date.state.between"},
};
bool MacroConditionDate::CheckCondition()
{
bool match = false;
QDateTime cur = QDateTime::currentDateTime();
if (_ignoreDate) {
_dateTime.setDate(cur.date());
_dateTime2.setDate(cur.date());
}
if (_ignoreTime) {
_dateTime.setTime(cur.time());
_dateTime2.setTime(cur.time());
}
switch (_condition) {
case DateCondition::AT:
match = _dateTime >= cur &&
_dateTime <= cur.addMSecs(switcher->interval);
break;
case DateCondition::AFTER:
match = cur >= _dateTime;
break;
case DateCondition::BEFORE:
match = cur <= _dateTime;
break;
case DateCondition::BETWEEN:
if (_dateTime2 > _dateTime) {
match = cur >= _dateTime && cur <= _dateTime2;
} else {
match = cur >= _dateTime2 && cur <= _dateTime;
}
break;
default:
break;
}
match = _dateTime >= cur &&
_dateTime <= cur.addMSecs(switcher->interval);
if (match && _repeat) {
_dateTime = _dateTime.addSecs(_duration.seconds);
_dateTime2 = _dateTime2.addSecs(_duration.seconds);
}
return match;
@@ -33,8 +64,11 @@ bool MacroConditionDate::CheckCondition()
bool MacroConditionDate::Save(obs_data_t *obj)
{
MacroCondition::Save(obj);
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
obs_data_set_string(obj, "dateTime",
_dateTime.toString().toStdString().c_str());
obs_data_set_string(obj, "dateTime2",
_dateTime2.toString().toStdString().c_str());
obs_data_set_bool(obj, "ignoreDate", _ignoreDate);
obs_data_set_bool(obj, "ignoreTime", _ignoreTime);
obs_data_set_bool(obj, "repeat", _repeat);
@@ -46,8 +80,12 @@ bool MacroConditionDate::Save(obs_data_t *obj)
bool MacroConditionDate::Load(obs_data_t *obj)
{
MacroCondition::Load(obj);
_condition =
static_cast<DateCondition>(obs_data_get_int(obj, "condition"));
_dateTime = QDateTime::fromString(
QString::fromStdString(obs_data_get_string(obj, "dateTime")));
_dateTime2 = QDateTime::fromString(
QString::fromStdString(obs_data_get_string(obj, "dateTime2")));
_ignoreDate = obs_data_get_bool(obj, "ignoreDate");
_ignoreTime = obs_data_get_bool(obj, "ignoreTime");
_repeat = obs_data_get_bool(obj, "repeat");
@@ -60,20 +98,35 @@ std::string MacroConditionDate::GetShortDesc()
return _dateTime.toString().toStdString();
}
static inline void populateConditionSelection(QComboBox *list)
{
for (auto entry : dateConditionTypes) {
list->addItem(obs_module_text(entry.second.c_str()));
}
}
MacroConditionDateEdit::MacroConditionDateEdit(
QWidget *parent, std::shared_ptr<MacroConditionDate> entryData)
: QWidget(parent)
{
_condition = new QComboBox();
_dateTime = new QDateTimeEdit();
_dateTime->setCalendarPopup(true);
_dateTime->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
_dateTime2 = new QDateTimeEdit();
_dateTime2->setCalendarPopup(true);
_dateTime2->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
_ignoreDate = new QCheckBox();
_ignoreTime = new QCheckBox();
_repeat = new QCheckBox();
_duration = new DurationSelection();
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
SLOT(ConditionChanged(int)));
QWidget::connect(_dateTime, SIGNAL(dateTimeChanged(const QDateTime &)),
this, SLOT(DateTimeChanged(const QDateTime &)));
QWidget::connect(_dateTime2, SIGNAL(dateTimeChanged(const QDateTime &)),
this, SLOT(DateTime2Changed(const QDateTime &)));
QWidget::connect(_ignoreDate, SIGNAL(stateChanged(int)), this,
SLOT(IgnoreDateChanged(int)));
QWidget::connect(_ignoreTime, SIGNAL(stateChanged(int)), this,
@@ -85,9 +138,13 @@ MacroConditionDateEdit::MacroConditionDateEdit(
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
SLOT(DurationUnitChanged(DurationUnit)));
populateConditionSelection(_condition);
auto line1Layout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{condition}}", _condition},
{"{{dateTime}}", _dateTime},
{"{{dateTime2}}", _dateTime2},
{"{{ignoreDate}}", _ignoreDate},
{"{{ignoreTime}}", _ignoreTime},
{"{{repeat}}", _repeat},
@@ -111,6 +168,18 @@ MacroConditionDateEdit::MacroConditionDateEdit(
_loading = false;
}
void MacroConditionDateEdit::ConditionChanged(int cond)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_condition = static_cast<DateCondition>(cond);
ShowSecondDateSelection(_entryData->_condition ==
DateCondition::BETWEEN);
}
void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime)
{
if (_loading || !_entryData) {
@@ -124,6 +193,16 @@ void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime)
QString::fromStdString(_entryData->GetShortDesc()));
}
void MacroConditionDateEdit::DateTime2Changed(const QDateTime &datetime)
{
if (_loading || !_entryData) {
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
_entryData->_dateTime2 = datetime;
}
void MacroConditionDateEdit::IgnoreDateChanged(int state)
{
if (_loading || !_entryData) {
@@ -180,10 +259,21 @@ void MacroConditionDateEdit::UpdateEntryData()
if (!_entryData) {
return;
}
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
_dateTime->setDateTime(_entryData->_dateTime);
_dateTime2->setDateTime(_entryData->_dateTime2);
_ignoreDate->setChecked(_entryData->_ignoreDate);
_ignoreTime->setChecked(_entryData->_ignoreTime);
_repeat->setChecked(_entryData->_repeat);
_duration->SetDuration(_entryData->_duration);
_duration->setDisabled(!_entryData->_repeat);
ShowSecondDateSelection(_entryData->_condition ==
DateCondition::BETWEEN);
}
void MacroConditionDateEdit::ShowSecondDateSelection(bool visible)
{
_dateTime2->setVisible(visible);
adjustSize();
}

View File

@@ -192,7 +192,7 @@ void MacroConditionFilterEdit::GetSettingsClicked()
}
_settings->setPlainText(
fromatJsonString(getSourceSettings(_entryData->_filter)));
formatJsonString(getSourceSettings(_entryData->_filter)));
}
void MacroConditionFilterEdit::SettingsChanged()

View File

@@ -10,12 +10,6 @@ bool MacroConditionMacro::_registered = MacroConditionFactory::Register(
{MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
"AdvSceneSwitcher.condition.macro"});
// TODO: Remove in future version - just added for backward compatibility
static std::string idOld = "counter";
static bool oldRegisterd = MacroConditionFactory::Register(
idOld, {MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
"AdvSceneSwitcher.condition.macro"});
static std::map<MacroConditionMacroType, std::string> macroConditionTypes = {
{MacroConditionMacroType::COUNT,
"AdvSceneSwitcher.condition.macro.type.count"},

View File

@@ -171,7 +171,7 @@ void MacroConditionSourceEdit::GetSettingsClicked()
}
_settings->setPlainText(
fromatJsonString(getSourceSettings(_entryData->_source)));
formatJsonString(getSourceSettings(_entryData->_source)));
}
void MacroConditionSourceEdit::SettingsChanged()

View File

@@ -10,12 +10,6 @@ bool MacroConditionTimer::_registered = MacroConditionFactory::Register(
{MacroConditionTimer::Create, MacroConditionTimerEdit::Create,
"AdvSceneSwitcher.condition.timer", false});
// TODO: Remove in future version - just added for backward compatibility
static const std::string idOld = "interval";
static bool oldRegisterd = MacroConditionFactory::Register(
idOld, {MacroConditionTimer::Create, MacroConditionTimerEdit::Create,
"AdvSceneSwitcher.condition.timer", false});
bool MacroConditionTimer::CheckCondition()
{
if (_duration.DurationReached()) {

View File

@@ -5,6 +5,7 @@
#include <obs.hpp>
#include <QEvent>
#include <QLabel>
#include <QScrollBar>
bool MacroSegment::Save(obs_data_t *obj)
{
@@ -136,6 +137,11 @@ void MacroSegmentEdit::SetFocusPolicyOfWidgets()
QList<QWidget *> widgets = this->findChildren<QWidget *>();
for (auto w : widgets) {
w->setFocusPolicy(Qt::StrongFocus);
// Ignore QScrollBar as there is no danger of accidentally modifying anything
// and long expanded QComboBox would be difficult to interact with otherwise.
if (qobject_cast<QScrollBar *>(w)) {
continue;
}
w->installEventFilter(new MouseWheelWidgetAdjustmentGuard(w));
}
}

View File

@@ -80,6 +80,8 @@ void AdvSceneSwitcher::on_macroRemove_clicked()
QString name;
{
std::lock_guard<std::mutex> lock(switcher->m);
switcher->abortMacroWait = true;
switcher->macroWaitCv.notify_one();
int idx = ui->macros->currentRow();
QString::fromStdString(switcher->macros[idx].Name());
switcher->macros.erase(switcher->macros.begin() + idx);

View File

@@ -107,8 +107,8 @@ bool Macro::PerformAction()
{
bool ret = true;
for (auto &a : _actions) {
ret = ret && a->PerformAction();
a->LogAction();
ret = ret && a->PerformAction();
if (!ret) {
return false;
}
@@ -454,71 +454,8 @@ void SwitcherData::saveMacros(obs_data_t *obj)
obs_data_array_release(macroArray);
}
// Temporary helper functions to convert old settings format to new one
static std::unordered_map<int, std::string> actionIntToActionString = {
{2, "audio"}, {4, "recording"}, {5, "replay_buffer"}, {6, "run"},
{3, "streaming"}, {0, "scene_switch"}, {1, "wait"},
};
static void replaceActionIds(obs_data_t *obj)
{
obs_data_array_t *actions = obs_data_get_array(obj, "actions");
size_t count = obs_data_array_count(actions);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(actions, i);
auto oldId = obs_data_get_int(array_obj, "id");
obs_data_set_string(array_obj, "id",
actionIntToActionString[oldId].c_str());
obs_data_release(array_obj);
}
obs_data_array_release(actions);
}
static std::unordered_map<int, std::string> conditionIntToConditionString = {
{3, "audio"}, {4, "file"}, {10, "idle"}, {5, "media"},
{11, "plugin_state"}, {9, "process"}, {8, "recording"}, {2, "region"},
{0, "scene"}, {7, "streaming"}, {6, "video"}, {1, "window"},
};
static void replaceConditionIds(obs_data_t *obj)
{
obs_data_array_t *conditions = obs_data_get_array(obj, "conditions");
size_t count = obs_data_array_count(conditions);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(conditions, i);
auto oldId = obs_data_get_int(array_obj, "id");
obs_data_set_string(
array_obj, "id",
conditionIntToConditionString[oldId].c_str());
obs_data_release(array_obj);
}
obs_data_array_release(conditions);
}
static void convertOldMacroIdsToString(obs_data_t *obj)
{
obs_data_array_t *macroArray = obs_data_get_array(obj, "macros");
size_t count = obs_data_array_count(macroArray);
for (size_t i = 0; i < count; i++) {
obs_data_t *array_obj = obs_data_array_item(macroArray, i);
replaceActionIds(array_obj);
replaceConditionIds(array_obj);
obs_data_release(array_obj);
}
obs_data_array_release(macroArray);
}
void SwitcherData::loadMacros(obs_data_t *obj)
{
// TODO: Remove conversion helper in future version
std::string previousVersion = obs_data_get_string(obj, "version");
if (previousVersion == "2ce0b35921be892c987c7dbb5fc90db38f15f0a6") {
convertOldMacroIdsToString(obj);
}
macros.clear();
obs_data_array_t *macroArray = obs_data_get_array(obj, "macros");

View File

@@ -92,7 +92,11 @@ void SwitcherData::writeSceneInfoToFile()
QFile file(QString::fromStdString(fileIO.writePath));
if (file.open(QIODevice::WriteOnly)) {
const char *msg = GetWeakSourceName(currentScene).c_str();
// switcher->currentScene cannot be used here as scene might
// have changed already
obs_source_t *source = obs_frontend_get_current_scene();
auto msg = obs_source_get_name(source);
obs_source_release(source);
file.write(msg, qstrlen(msg));
file.close();
}

View File

@@ -203,7 +203,7 @@ bool SwitcherData::checkSceneSequence(OBSWeakSource &scene,
continue;
}
bool matched = s.checkMatch(currentScene, linger);
bool matched = s.checkMatch(linger);
if (!match && matched) {
match = matched;
@@ -395,8 +395,7 @@ SceneSequenceSwitch *SceneSequenceSwitch::extend()
return extendedSequence.get();
}
bool SceneSequenceSwitch::checkMatch(OBSWeakSource currentScene, int &linger,
SceneSequenceSwitch *root)
bool SceneSequenceSwitch::checkMatch(int &linger, SceneSequenceSwitch *root)
{
if (!initialized()) {
if (root) {
@@ -407,8 +406,18 @@ bool SceneSequenceSwitch::checkMatch(OBSWeakSource currentScene, int &linger,
bool match = false;
// We cannot rely on switcher->currentScene for this information.
// Depending on the transition length the frontend event for the scene
// change of the previous element in the sequence might not yet have
// been received, which would lead to the sequencence being aborted.
// Thus we have to use obs_frontend_get_current_scene() here.
auto sceneSource = obs_frontend_get_current_scene();
auto currentScene = obs_source_get_weak_source(sceneSource);
obs_weak_source_release(currentScene);
obs_source_release(sceneSource);
if (activeSequence) {
return activeSequence->checkMatch(currentScene, linger, this);
return activeSequence->checkMatch(linger, this);
}
if (startScene == currentScene) {

View File

@@ -283,14 +283,22 @@ bool compareSourceSettings(const OBSWeakSource &source,
{
bool ret = false;
std::string currentSettings = getSourceSettings(source);
// User input and source settings might be formatted differently
currentSettings = formatJsonString(currentSettings).toStdString();
std::string userSettings = formatJsonString(settings).toStdString();
if (userSettings.empty()) {
userSettings = settings;
}
if (useRegex) {
try {
std::regex expr(settings);
std::regex expr(userSettings);
ret = std::regex_match(currentSettings, expr);
} catch (const std::regex_error &) {
}
} else {
ret = currentSettings == settings;
ret = currentSettings == userSettings;
}
return ret;
}
@@ -304,12 +312,12 @@ std::string getDataFilePath(const std::string &file)
return "";
}
QString fromatJsonString(std::string s)
QString formatJsonString(std::string s)
{
return fromatJsonString(s.c_str());
return formatJsonString(s.c_str());
}
QString fromatJsonString(const char *json)
QString formatJsonString(const char *json)
{
QJsonDocument doc = QJsonDocument::fromJson(json);
return doc.toJson(QJsonDocument::Indented);