提交 bcd491a3 编写于 作者: C cg2121 提交者: jp9000

UI: Add copying/pasting of sources/filters

Closes jp9000/obs-studio#860
上级 1ef7a48e
......@@ -61,6 +61,14 @@ Deprecated="Deprecated"
ReplayBuffer="Replay Buffer"
Import="Import"
Export="Export"
Copy="Copy"
Paste="Paste"
PasteReference="Paste (Reference)"
PasteDuplicate="Paste (Duplicate)"
# copy filters
Copy.Filters="Copy Filters"
Paste.Filters="Paste Filters"
# updater
Updater.Title="New update available"
......
......@@ -892,6 +892,51 @@
<addaction name="actionScaleCanvas"/>
<addaction name="actionScaleOutput"/>
</widget>
<action name="actionCopySource">
<property name="text">
<string>Copy</string>
</property>
<property name="shortcut">
<string>Ctrl+C</string>
</property>
</action>
<action name="actionPasteRef">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>PasteReference</string>
</property>
<property name="iconText">
<string>PasteReference</string>
</property>
<property name="toolTip">
<string>PasteReference</string>
</property>
<property name="shortcut">
<string>Ctrl+V</string>
</property>
</action>
<action name="actionCopyFilters">
<property name="text">
<string>Copy.Filters</string>
</property>
</action>
<action name="actionPasteFilters">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Paste.Filters</string>
</property>
</action>
<addaction name="actionCopySource"/>
<addaction name="actionPasteRef"/>
<addaction name="actionPasteDup"/>
<addaction name="separator"/>
<addaction name="actionCopyFilters"/>
<addaction name="actionPasteFilters"/>
<addaction name="separator"/>
<addaction name="transformMenu"/>
<addaction name="orderMenu"/>
<addaction name="scalingMenu"/>
......@@ -1409,6 +1454,11 @@
<string>Basic.MainMenu.Edit.Scale.Output</string>
</property>
</action>
<action name="actionPasteDup">
<property name="text">
<string>PasteDuplicate</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
......
......@@ -225,6 +225,8 @@ void OBSBasic::RefreshSceneCollections()
OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
main->OpenSavedProjectors();
main->ui->actionPasteRef->setEnabled(false);
main->ui->actionPasteDup->setEnabled(false);
}
void OBSBasic::on_actionNewSceneCollection_triggered()
......
......@@ -3347,6 +3347,19 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview)
if (addSourceMenu)
popup.addMenu(addSourceMenu);
ui->actionCopyFilters->setEnabled(false);
popup.addSeparator();
popup.addAction(ui->actionCopySource);
popup.addAction(ui->actionPasteRef);
popup.addAction(ui->actionPasteDup);
popup.addSeparator();
popup.addSeparator();
popup.addAction(ui->actionCopyFilters);
popup.addAction(ui->actionPasteFilters);
popup.addSeparator();
if (item) {
if (addSourceMenu)
popup.addSeparator();
......@@ -3393,6 +3406,8 @@ void OBSBasic::CreateSourcePopupMenu(QListWidgetItem *item, bool preview)
SLOT(OpenFilters()));
popup.addAction(QTStr("Properties"), this,
SLOT(on_actionSourceProperties_triggered()));
ui->actionCopyFilters->setEnabled(true);
}
popup.exec(QCursor::pos());
......@@ -5270,3 +5285,60 @@ bool OBSBasic::sysTrayMinimizeToTray()
return config_get_bool(GetGlobalConfig(),
"BasicWindow", "SysTrayMinimizeToTray");
}
void OBSBasic::on_actionCopySource_triggered()
{
on_actionCopyTransform_triggered();
OBSSceneItem item = GetCurrentSceneItem();
if (!item)
return;
OBSSource source = obs_sceneitem_get_source(item);
copyString = obs_source_get_name(source);
copyVisible = obs_sceneitem_visible(item);
ui->actionPasteRef->setEnabled(true);
ui->actionPasteDup->setEnabled(true);
}
void OBSBasic::on_actionPasteRef_triggered()
{
OBSBasicSourceSelect::SourcePaste(copyString, copyVisible, false);
on_actionPasteTransform_triggered();
}
void OBSBasic::on_actionPasteDup_triggered()
{
OBSBasicSourceSelect::SourcePaste(copyString, copyVisible, true);
on_actionPasteTransform_triggered();
}
void OBSBasic::on_actionCopyFilters_triggered()
{
OBSSceneItem item = GetCurrentSceneItem();
if (!item)
return;
OBSSource source = obs_sceneitem_get_source(item);
copyFiltersString = obs_source_get_name(source);
ui->actionPasteFilters->setEnabled(true);
}
void OBSBasic::on_actionPasteFilters_triggered()
{
OBSSource source = obs_get_source_by_name(copyFiltersString);
OBSSceneItem sceneItem = GetCurrentSceneItem();
OBSSource dstSource = obs_sceneitem_get_source(sceneItem);
if (source == dstSource)
return;
obs_source_copy_filters(dstSource, source);
}
......@@ -119,6 +119,10 @@ private:
bool projectChanged = false;
bool previewEnabled = true;
const char *copyString;
const char *copyFiltersString;
bool copyVisible = true;
QPointer<QThread> updateCheckThread;
QPointer<QThread> logUploadThread;
......@@ -413,6 +417,13 @@ private slots:
void ToggleShowHide();
void on_actionCopySource_triggered();
void on_actionPasteRef_triggered();
void on_actionPasteDup_triggered();
void on_actionCopyFilters_triggered();
void on_actionPasteFilters_triggered();
private:
/* OBS Callbacks */
static void SceneReordered(void *data, calldata_t *params);
......
......@@ -93,7 +93,28 @@ static void AddSource(void *_data, obs_scene_t *scene)
obs_sceneitem_set_visible(sceneitem, data->visible);
}
static void AddExisting(const char *name, const bool visible)
static char *get_new_source_name(const char *name)
{
struct dstr new_name = {0};
int inc = 0;
dstr_copy(&new_name, name);
for (;;) {
obs_source_t *existing_source = obs_get_source_by_name(
new_name.array);
if (!existing_source)
break;
obs_source_release(existing_source);
dstr_printf(&new_name, "%s %d", name, ++inc + 1);
}
return new_name.array;
}
static void AddExisting(const char *name, bool visible, bool duplicate)
{
OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
OBSScene scene = main->GetCurrentScene();
......@@ -102,6 +123,17 @@ static void AddExisting(const char *name, const bool visible)
obs_source_t *source = obs_get_source_by_name(name);
if (source) {
if (duplicate) {
obs_source_t *from = source;
char *new_name = get_new_source_name(name);
source = obs_source_duplicate(from, new_name, false);
bfree(new_name);
obs_source_release(from);
if (!source)
return;
}
AddSourceData data;
data.source = source;
data.visible = visible;
......@@ -155,7 +187,7 @@ void OBSBasicSourceSelect::on_buttonBox_accepted()
if (!item)
return;
AddExisting(QT_TO_UTF8(item->text()), visible);
AddExisting(QT_TO_UTF8(item->text()), visible, false);
} else {
if (ui->sourceName->text().isEmpty()) {
QMessageBox::information(this,
......@@ -243,3 +275,8 @@ OBSBasicSourceSelect::OBSBasicSourceSelect(OBSBasic *parent, const char *id_)
obs_enum_sources(EnumSources, this);
}
}
void OBSBasicSourceSelect::SourcePaste(const char *name, bool visible, bool dup)
{
AddExisting(name, visible, dup);
}
......@@ -47,4 +47,6 @@ public:
OBSBasicSourceSelect(OBSBasic *parent, const char *id);
OBSSource newSource;
static void SourcePaste(const char *name, bool visible, bool duplicate);
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册