context-bar-controls.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. #include "window-basic-main.hpp"
  2. #include "context-bar-controls.hpp"
  3. #include "qt-wrappers.hpp"
  4. #include "obs-app.hpp"
  5. #include <QStandardItemModel>
  6. #include <QColorDialog>
  7. #include <QFontDialog>
  8. #include "ui_browser-source-toolbar.h"
  9. #include "ui_device-select-toolbar.h"
  10. #include "ui_game-capture-toolbar.h"
  11. #include "ui_image-source-toolbar.h"
  12. #include "ui_color-source-toolbar.h"
  13. #include "ui_text-source-toolbar.h"
  14. #ifdef _WIN32
  15. #define get_os_module(win, mac, linux) obs_get_module(win)
  16. #define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, win)
  17. #elif __APPLE__
  18. #define get_os_module(win, mac, linux) obs_get_module(mac)
  19. #define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, mac)
  20. #else
  21. #define get_os_module(win, mac, linux) obs_get_module(linux)
  22. #define get_os_text(mod, win, mac, linux) obs_module_get_locale_text(mod, linux)
  23. #endif
  24. /* ========================================================================= */
  25. SourceToolbar::SourceToolbar(QWidget *parent, OBSSource source)
  26. : QWidget(parent),
  27. weakSource(OBSGetWeakRef(source)),
  28. props(obs_source_properties(source), obs_properties_destroy)
  29. {
  30. }
  31. void SourceToolbar::SaveOldProperties(obs_source_t *source)
  32. {
  33. oldData = obs_data_create();
  34. OBSDataAutoRelease oldSettings = obs_source_get_settings(source);
  35. obs_data_apply(oldData, oldSettings);
  36. obs_data_set_string(oldData, "undo_suuid", obs_source_get_uuid(source));
  37. }
  38. void SourceToolbar::SetUndoProperties(obs_source_t *source, bool repeatable)
  39. {
  40. if (!oldData) {
  41. blog(LOG_ERROR, "%s: somehow oldData was null.", __FUNCTION__);
  42. return;
  43. }
  44. OBSBasic *main = reinterpret_cast<OBSBasic *>(App()->GetMainWindow());
  45. OBSSource currentSceneSource = main->GetCurrentSceneSource();
  46. if (!currentSceneSource)
  47. return;
  48. std::string scene_uuid = obs_source_get_uuid(currentSceneSource);
  49. auto undo_redo = [scene_uuid = std::move(scene_uuid),
  50. main](const std::string &data) {
  51. OBSDataAutoRelease settings =
  52. obs_data_create_from_json(data.c_str());
  53. OBSSourceAutoRelease source = obs_get_source_by_uuid(
  54. obs_data_get_string(settings, "undo_suuid"));
  55. obs_source_reset_settings(source, settings);
  56. OBSSourceAutoRelease scene_source =
  57. obs_get_source_by_uuid(scene_uuid.c_str());
  58. main->SetCurrentScene(scene_source.Get(), true);
  59. main->UpdateContextBar();
  60. };
  61. OBSDataAutoRelease new_settings = obs_data_create();
  62. OBSDataAutoRelease curr_settings = obs_source_get_settings(source);
  63. obs_data_apply(new_settings, curr_settings);
  64. obs_data_set_string(new_settings, "undo_suuid",
  65. obs_source_get_uuid(source));
  66. std::string undo_data(obs_data_get_json(oldData));
  67. std::string redo_data(obs_data_get_json(new_settings));
  68. if (undo_data.compare(redo_data) != 0)
  69. main->undo_s.add_action(
  70. QTStr("Undo.Properties")
  71. .arg(obs_source_get_name(source)),
  72. undo_redo, undo_redo, undo_data, redo_data, repeatable);
  73. oldData = nullptr;
  74. }
  75. /* ========================================================================= */
  76. BrowserToolbar::BrowserToolbar(QWidget *parent, OBSSource source)
  77. : SourceToolbar(parent, source),
  78. ui(new Ui_BrowserSourceToolbar)
  79. {
  80. ui->setupUi(this);
  81. }
  82. BrowserToolbar::~BrowserToolbar() {}
  83. void BrowserToolbar::on_refresh_clicked()
  84. {
  85. OBSSource source = GetSource();
  86. if (!source) {
  87. return;
  88. }
  89. obs_property_t *p = obs_properties_get(props.get(), "refreshnocache");
  90. obs_property_button_clicked(p, source.Get());
  91. }
  92. /* ========================================================================= */
  93. ComboSelectToolbar::ComboSelectToolbar(QWidget *parent, OBSSource source)
  94. : SourceToolbar(parent, source),
  95. ui(new Ui_DeviceSelectToolbar)
  96. {
  97. ui->setupUi(this);
  98. }
  99. ComboSelectToolbar::~ComboSelectToolbar() {}
  100. static int FillPropertyCombo(QComboBox *c, obs_property_t *p,
  101. const std::string &cur_id, bool is_int = false)
  102. {
  103. size_t count = obs_property_list_item_count(p);
  104. int cur_idx = -1;
  105. for (size_t i = 0; i < count; i++) {
  106. const char *name = obs_property_list_item_name(p, i);
  107. std::string id;
  108. if (is_int) {
  109. id = std::to_string(obs_property_list_item_int(p, i));
  110. } else {
  111. const char *val = obs_property_list_item_string(p, i);
  112. id = val ? val : "";
  113. }
  114. if (cur_id == id)
  115. cur_idx = (int)i;
  116. c->addItem(name, id.c_str());
  117. }
  118. return cur_idx;
  119. }
  120. void UpdateSourceComboToolbarProperties(QComboBox *combo, OBSSource source,
  121. obs_properties_t *props,
  122. const char *prop_name, bool is_int)
  123. {
  124. std::string cur_id;
  125. OBSDataAutoRelease settings = obs_source_get_settings(source);
  126. if (is_int) {
  127. cur_id = std::to_string(obs_data_get_int(settings, prop_name));
  128. } else {
  129. cur_id = obs_data_get_string(settings, prop_name);
  130. }
  131. combo->blockSignals(true);
  132. obs_property_t *p = obs_properties_get(props, prop_name);
  133. int cur_idx = FillPropertyCombo(combo, p, cur_id, is_int);
  134. if (cur_idx == -1 || obs_property_list_item_disabled(p, cur_idx)) {
  135. if (cur_idx == -1) {
  136. combo->insertItem(
  137. 0,
  138. QTStr("Basic.Settings.Audio.UnknownAudioDevice"));
  139. cur_idx = 0;
  140. }
  141. SetComboItemEnabled(combo, cur_idx, false);
  142. }
  143. combo->setCurrentIndex(cur_idx);
  144. combo->blockSignals(false);
  145. }
  146. void ComboSelectToolbar::Init()
  147. {
  148. OBSSource source = GetSource();
  149. if (!source) {
  150. return;
  151. }
  152. UpdateSourceComboToolbarProperties(ui->device, source, props.get(),
  153. prop_name, is_int);
  154. }
  155. void UpdateSourceComboToolbarValue(QComboBox *combo, OBSSource source, int idx,
  156. const char *prop_name, bool is_int)
  157. {
  158. QString id = combo->itemData(idx).toString();
  159. OBSDataAutoRelease settings = obs_data_create();
  160. if (is_int) {
  161. obs_data_set_int(settings, prop_name, id.toInt());
  162. } else {
  163. obs_data_set_string(settings, prop_name, QT_TO_UTF8(id));
  164. }
  165. obs_source_update(source, settings);
  166. }
  167. void ComboSelectToolbar::on_device_currentIndexChanged(int idx)
  168. {
  169. OBSSource source = GetSource();
  170. if (idx == -1 || !source) {
  171. return;
  172. }
  173. SaveOldProperties(source);
  174. UpdateSourceComboToolbarValue(ui->device, source, idx, prop_name,
  175. is_int);
  176. SetUndoProperties(source);
  177. }
  178. AudioCaptureToolbar::AudioCaptureToolbar(QWidget *parent, OBSSource source)
  179. : ComboSelectToolbar(parent, source)
  180. {
  181. }
  182. void AudioCaptureToolbar::Init()
  183. {
  184. delete ui->activateButton;
  185. ui->activateButton = nullptr;
  186. obs_module_t *mod =
  187. get_os_module("win-wasapi", "mac-capture", "linux-pulseaudio");
  188. if (!mod)
  189. return;
  190. const char *device_str =
  191. get_os_text(mod, "Device", "CoreAudio.Device", "Device");
  192. ui->deviceLabel->setText(device_str);
  193. prop_name = "device_id";
  194. ComboSelectToolbar::Init();
  195. }
  196. WindowCaptureToolbar::WindowCaptureToolbar(QWidget *parent, OBSSource source)
  197. : ComboSelectToolbar(parent, source)
  198. {
  199. }
  200. void WindowCaptureToolbar::Init()
  201. {
  202. delete ui->activateButton;
  203. ui->activateButton = nullptr;
  204. obs_module_t *mod =
  205. get_os_module("win-capture", "mac-capture", "linux-capture");
  206. if (!mod)
  207. return;
  208. const char *device_str = get_os_text(mod, "WindowCapture.Window",
  209. "WindowUtils.Window", "Window");
  210. ui->deviceLabel->setText(device_str);
  211. #if !defined(_WIN32) && !defined(__APPLE__) //linux
  212. prop_name = "capture_window";
  213. #else
  214. prop_name = "window";
  215. #endif
  216. #ifdef __APPLE__
  217. is_int = true;
  218. #endif
  219. ComboSelectToolbar::Init();
  220. }
  221. ApplicationAudioCaptureToolbar::ApplicationAudioCaptureToolbar(QWidget *parent,
  222. OBSSource source)
  223. : ComboSelectToolbar(parent, source)
  224. {
  225. }
  226. void ApplicationAudioCaptureToolbar::Init()
  227. {
  228. delete ui->activateButton;
  229. ui->activateButton = nullptr;
  230. obs_module_t *mod = obs_get_module("win-wasapi");
  231. const char *device_str = obs_module_get_locale_text(mod, "Window");
  232. ui->deviceLabel->setText(device_str);
  233. prop_name = "window";
  234. ComboSelectToolbar::Init();
  235. }
  236. DisplayCaptureToolbar::DisplayCaptureToolbar(QWidget *parent, OBSSource source)
  237. : ComboSelectToolbar(parent, source)
  238. {
  239. }
  240. void DisplayCaptureToolbar::Init()
  241. {
  242. delete ui->activateButton;
  243. ui->activateButton = nullptr;
  244. obs_module_t *mod =
  245. get_os_module("win-capture", "mac-capture", "linux-capture");
  246. if (!mod)
  247. return;
  248. const char *device_str =
  249. get_os_text(mod, "Monitor", "DisplayCapture.Display", "Screen");
  250. ui->deviceLabel->setText(device_str);
  251. #ifdef _WIN32
  252. prop_name = "monitor_id";
  253. #elif __APPLE__
  254. prop_name = "display_uuid";
  255. #else
  256. is_int = true;
  257. prop_name = "screen";
  258. #endif
  259. ComboSelectToolbar::Init();
  260. }
  261. /* ========================================================================= */
  262. DeviceCaptureToolbar::DeviceCaptureToolbar(QWidget *parent, OBSSource source)
  263. : QWidget(parent),
  264. weakSource(OBSGetWeakRef(source)),
  265. ui(new Ui_DeviceSelectToolbar)
  266. {
  267. ui->setupUi(this);
  268. delete ui->deviceLabel;
  269. delete ui->device;
  270. ui->deviceLabel = nullptr;
  271. ui->device = nullptr;
  272. OBSDataAutoRelease settings = obs_source_get_settings(source);
  273. active = obs_data_get_bool(settings, "active");
  274. obs_module_t *mod = obs_get_module("win-dshow");
  275. if (!mod)
  276. return;
  277. activateText = obs_module_get_locale_text(mod, "Activate");
  278. deactivateText = obs_module_get_locale_text(mod, "Deactivate");
  279. ui->activateButton->setText(active ? deactivateText : activateText);
  280. }
  281. DeviceCaptureToolbar::~DeviceCaptureToolbar() {}
  282. void DeviceCaptureToolbar::on_activateButton_clicked()
  283. {
  284. OBSSource source = OBSGetStrongRef(weakSource);
  285. if (!source) {
  286. return;
  287. }
  288. OBSDataAutoRelease settings = obs_source_get_settings(source);
  289. bool now_active = obs_data_get_bool(settings, "active");
  290. bool desyncedSetting = now_active != active;
  291. active = !active;
  292. const char *text = active ? deactivateText : activateText;
  293. ui->activateButton->setText(text);
  294. if (desyncedSetting) {
  295. return;
  296. }
  297. calldata_t cd = {};
  298. calldata_set_bool(&cd, "active", active);
  299. proc_handler_t *ph = obs_source_get_proc_handler(source);
  300. proc_handler_call(ph, "activate", &cd);
  301. calldata_free(&cd);
  302. }
  303. /* ========================================================================= */
  304. GameCaptureToolbar::GameCaptureToolbar(QWidget *parent, OBSSource source)
  305. : SourceToolbar(parent, source),
  306. ui(new Ui_GameCaptureToolbar)
  307. {
  308. obs_property_t *p;
  309. int cur_idx;
  310. ui->setupUi(this);
  311. obs_module_t *mod = obs_get_module("win-capture");
  312. if (!mod)
  313. return;
  314. ui->modeLabel->setText(obs_module_get_locale_text(mod, "Mode"));
  315. ui->windowLabel->setText(
  316. obs_module_get_locale_text(mod, "WindowCapture.Window"));
  317. OBSDataAutoRelease settings = obs_source_get_settings(source);
  318. std::string cur_mode = obs_data_get_string(settings, "capture_mode");
  319. std::string cur_window = obs_data_get_string(settings, "window");
  320. ui->mode->blockSignals(true);
  321. p = obs_properties_get(props.get(), "capture_mode");
  322. cur_idx = FillPropertyCombo(ui->mode, p, cur_mode);
  323. ui->mode->setCurrentIndex(cur_idx);
  324. ui->mode->blockSignals(false);
  325. ui->window->blockSignals(true);
  326. p = obs_properties_get(props.get(), "window");
  327. cur_idx = FillPropertyCombo(ui->window, p, cur_window);
  328. ui->window->setCurrentIndex(cur_idx);
  329. ui->window->blockSignals(false);
  330. if (cur_idx != -1 && obs_property_list_item_disabled(p, cur_idx)) {
  331. SetComboItemEnabled(ui->window, cur_idx, false);
  332. }
  333. UpdateWindowVisibility();
  334. }
  335. GameCaptureToolbar::~GameCaptureToolbar() {}
  336. void GameCaptureToolbar::UpdateWindowVisibility()
  337. {
  338. QString mode = ui->mode->currentData().toString();
  339. bool is_window = (mode == "window");
  340. ui->windowLabel->setVisible(is_window);
  341. ui->window->setVisible(is_window);
  342. }
  343. void GameCaptureToolbar::on_mode_currentIndexChanged(int idx)
  344. {
  345. OBSSource source = GetSource();
  346. if (idx == -1 || !source) {
  347. return;
  348. }
  349. QString id = ui->mode->itemData(idx).toString();
  350. SaveOldProperties(source);
  351. OBSDataAutoRelease settings = obs_data_create();
  352. obs_data_set_string(settings, "capture_mode", QT_TO_UTF8(id));
  353. obs_source_update(source, settings);
  354. SetUndoProperties(source);
  355. UpdateWindowVisibility();
  356. }
  357. void GameCaptureToolbar::on_window_currentIndexChanged(int idx)
  358. {
  359. OBSSource source = GetSource();
  360. if (idx == -1 || !source) {
  361. return;
  362. }
  363. QString id = ui->window->itemData(idx).toString();
  364. SaveOldProperties(source);
  365. OBSDataAutoRelease settings = obs_data_create();
  366. obs_data_set_string(settings, "window", QT_TO_UTF8(id));
  367. obs_source_update(source, settings);
  368. SetUndoProperties(source);
  369. }
  370. /* ========================================================================= */
  371. ImageSourceToolbar::ImageSourceToolbar(QWidget *parent, OBSSource source)
  372. : SourceToolbar(parent, source),
  373. ui(new Ui_ImageSourceToolbar)
  374. {
  375. ui->setupUi(this);
  376. obs_module_t *mod = obs_get_module("image-source");
  377. ui->pathLabel->setText(obs_module_get_locale_text(mod, "File"));
  378. OBSDataAutoRelease settings = obs_source_get_settings(source);
  379. std::string file = obs_data_get_string(settings, "file");
  380. ui->path->setText(file.c_str());
  381. }
  382. ImageSourceToolbar::~ImageSourceToolbar() {}
  383. void ImageSourceToolbar::on_browse_clicked()
  384. {
  385. OBSSource source = GetSource();
  386. if (!source) {
  387. return;
  388. }
  389. obs_property_t *p = obs_properties_get(props.get(), "file");
  390. const char *desc = obs_property_description(p);
  391. const char *filter = obs_property_path_filter(p);
  392. const char *default_path = obs_property_path_default_path(p);
  393. QString startDir = ui->path->text();
  394. if (startDir.isEmpty())
  395. startDir = default_path;
  396. QString path = OpenFile(this, desc, startDir, filter);
  397. if (path.isEmpty()) {
  398. return;
  399. }
  400. ui->path->setText(path);
  401. SaveOldProperties(source);
  402. OBSDataAutoRelease settings = obs_data_create();
  403. obs_data_set_string(settings, "file", QT_TO_UTF8(path));
  404. obs_source_update(source, settings);
  405. SetUndoProperties(source);
  406. }
  407. /* ========================================================================= */
  408. static inline QColor color_from_int(long long val)
  409. {
  410. return QColor(val & 0xff, (val >> 8) & 0xff, (val >> 16) & 0xff,
  411. (val >> 24) & 0xff);
  412. }
  413. static inline long long color_to_int(QColor color)
  414. {
  415. auto shift = [&](unsigned val, int shift) {
  416. return ((val & 0xff) << shift);
  417. };
  418. return shift(color.red(), 0) | shift(color.green(), 8) |
  419. shift(color.blue(), 16) | shift(color.alpha(), 24);
  420. }
  421. ColorSourceToolbar::ColorSourceToolbar(QWidget *parent, OBSSource source)
  422. : SourceToolbar(parent, source),
  423. ui(new Ui_ColorSourceToolbar)
  424. {
  425. ui->setupUi(this);
  426. OBSDataAutoRelease settings = obs_source_get_settings(source);
  427. unsigned int val = (unsigned int)obs_data_get_int(settings, "color");
  428. color = color_from_int(val);
  429. UpdateColor();
  430. }
  431. ColorSourceToolbar::~ColorSourceToolbar() {}
  432. void ColorSourceToolbar::UpdateColor()
  433. {
  434. QPalette palette = QPalette(color);
  435. ui->color->setFrameStyle(QFrame::Sunken | QFrame::Panel);
  436. ui->color->setText(color.name(QColor::HexRgb));
  437. ui->color->setPalette(palette);
  438. ui->color->setStyleSheet(
  439. QString("background-color :%1; color: %2;")
  440. .arg(palette.color(QPalette::Window)
  441. .name(QColor::HexRgb))
  442. .arg(palette.color(QPalette::WindowText)
  443. .name(QColor::HexRgb)));
  444. ui->color->setAutoFillBackground(true);
  445. ui->color->setAlignment(Qt::AlignCenter);
  446. }
  447. void ColorSourceToolbar::on_choose_clicked()
  448. {
  449. OBSSource source = GetSource();
  450. if (!source) {
  451. return;
  452. }
  453. obs_property_t *p = obs_properties_get(props.get(), "color");
  454. const char *desc = obs_property_description(p);
  455. QColorDialog::ColorDialogOptions options;
  456. options |= QColorDialog::ShowAlphaChannel;
  457. #ifdef __linux__
  458. // TODO: Revisit hang on Ubuntu with native dialog
  459. options |= QColorDialog::DontUseNativeDialog;
  460. #endif
  461. QColor newColor = QColorDialog::getColor(color, this, desc, options);
  462. if (!newColor.isValid()) {
  463. return;
  464. }
  465. color = newColor;
  466. UpdateColor();
  467. SaveOldProperties(source);
  468. OBSDataAutoRelease settings = obs_data_create();
  469. obs_data_set_int(settings, "color", color_to_int(color));
  470. obs_source_update(source, settings);
  471. SetUndoProperties(source);
  472. }
  473. /* ========================================================================= */
  474. extern void MakeQFont(obs_data_t *font_obj, QFont &font, bool limit = false);
  475. TextSourceToolbar::TextSourceToolbar(QWidget *parent, OBSSource source)
  476. : SourceToolbar(parent, source),
  477. ui(new Ui_TextSourceToolbar)
  478. {
  479. ui->setupUi(this);
  480. OBSDataAutoRelease settings = obs_source_get_settings(source);
  481. const char *id = obs_source_get_unversioned_id(source);
  482. bool ft2 = strcmp(id, "text_ft2_source") == 0;
  483. bool read_from_file = obs_data_get_bool(
  484. settings, ft2 ? "from_file" : "read_from_file");
  485. OBSDataAutoRelease font_obj = obs_data_get_obj(settings, "font");
  486. MakeQFont(font_obj, font);
  487. // Use "color1" if it's a freetype source and "color" elsewise
  488. unsigned int val = (unsigned int)obs_data_get_int(
  489. settings,
  490. (strncmp(obs_source_get_id(source), "text_ft2_source", 15) == 0)
  491. ? "color1"
  492. : "color");
  493. color = color_from_int(val);
  494. const char *text = obs_data_get_string(settings, "text");
  495. bool single_line = !read_from_file &&
  496. (!text || (strchr(text, '\n') == nullptr));
  497. ui->emptySpace->setVisible(!single_line);
  498. ui->text->setVisible(single_line);
  499. if (single_line)
  500. ui->text->setText(text);
  501. }
  502. TextSourceToolbar::~TextSourceToolbar() {}
  503. void TextSourceToolbar::on_selectFont_clicked()
  504. {
  505. OBSSource source = GetSource();
  506. if (!source) {
  507. return;
  508. }
  509. QFontDialog::FontDialogOptions options;
  510. uint32_t flags;
  511. bool success;
  512. #ifndef _WIN32
  513. options = QFontDialog::DontUseNativeDialog;
  514. #endif
  515. font = QFontDialog::getFont(
  516. &success, font, this,
  517. QTStr("Basic.PropertiesWindow.SelectFont.WindowTitle"),
  518. options);
  519. if (!success) {
  520. return;
  521. }
  522. OBSDataAutoRelease font_obj = obs_data_create();
  523. obs_data_set_string(font_obj, "face", QT_TO_UTF8(font.family()));
  524. obs_data_set_string(font_obj, "style", QT_TO_UTF8(font.styleName()));
  525. obs_data_set_int(font_obj, "size", font.pointSize());
  526. flags = font.bold() ? OBS_FONT_BOLD : 0;
  527. flags |= font.italic() ? OBS_FONT_ITALIC : 0;
  528. flags |= font.underline() ? OBS_FONT_UNDERLINE : 0;
  529. flags |= font.strikeOut() ? OBS_FONT_STRIKEOUT : 0;
  530. obs_data_set_int(font_obj, "flags", flags);
  531. SaveOldProperties(source);
  532. OBSDataAutoRelease settings = obs_data_create();
  533. obs_data_set_obj(settings, "font", font_obj);
  534. obs_source_update(source, settings);
  535. SetUndoProperties(source);
  536. }
  537. void TextSourceToolbar::on_selectColor_clicked()
  538. {
  539. OBSSource source = GetSource();
  540. if (!source) {
  541. return;
  542. }
  543. bool freetype =
  544. strncmp(obs_source_get_id(source), "text_ft2_source", 15) == 0;
  545. obs_property_t *p =
  546. obs_properties_get(props.get(), freetype ? "color1" : "color");
  547. const char *desc = obs_property_description(p);
  548. QColorDialog::ColorDialogOptions options;
  549. options |= QColorDialog::ShowAlphaChannel;
  550. #ifdef __linux__
  551. // TODO: Revisit hang on Ubuntu with native dialog
  552. options |= QColorDialog::DontUseNativeDialog;
  553. #endif
  554. QColor newColor = QColorDialog::getColor(color, this, desc, options);
  555. if (!newColor.isValid()) {
  556. return;
  557. }
  558. color = newColor;
  559. SaveOldProperties(source);
  560. OBSDataAutoRelease settings = obs_data_create();
  561. if (freetype) {
  562. obs_data_set_int(settings, "color1", color_to_int(color));
  563. obs_data_set_int(settings, "color2", color_to_int(color));
  564. } else {
  565. obs_data_set_int(settings, "color", color_to_int(color));
  566. }
  567. obs_source_update(source, settings);
  568. SetUndoProperties(source);
  569. }
  570. void TextSourceToolbar::on_text_textChanged()
  571. {
  572. OBSSource source = GetSource();
  573. if (!source) {
  574. return;
  575. }
  576. std::string newText = QT_TO_UTF8(ui->text->text());
  577. OBSDataAutoRelease settings = obs_source_get_settings(source);
  578. if (newText == obs_data_get_string(settings, "text")) {
  579. return;
  580. }
  581. SaveOldProperties(source);
  582. obs_data_set_string(settings, "text", newText.c_str());
  583. obs_source_update(source, nullptr);
  584. SetUndoProperties(source, true);
  585. }