diff --git a/UI/data/locale/en-US.ini b/UI/data/locale/en-US.ini
index b837b3703..1074ba5a3 100644
--- a/UI/data/locale/en-US.ini
+++ b/UI/data/locale/en-US.ini
@@ -903,6 +903,7 @@ FinalScene.Text="There needs to be at least one scene."
NoSources.Title="No Sources"
NoSources.Text="It looks like you haven't added any video sources yet, so you will only be outputting a blank screen. Are you sure you want to do this?"
NoSources.Text.AddSource="You can add sources by clicking the + icon under the Sources box in the main window at any time."
+NoSources.Label="You don't have any sources.\nClick the + button below,\nor right click here to add one."
# Scene item color selection
ChangeBG="Set Color"
diff --git a/UI/data/themes/Dark/no_sources.svg b/UI/data/themes/Dark/no_sources.svg
new file mode 100644
index 000000000..1710db96b
--- /dev/null
+++ b/UI/data/themes/Dark/no_sources.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/UI/forms/images/no_sources.svg b/UI/forms/images/no_sources.svg
new file mode 100644
index 000000000..84b87c5eb
--- /dev/null
+++ b/UI/forms/images/no_sources.svg
@@ -0,0 +1,18 @@
+
+
+
diff --git a/UI/forms/obs.qrc b/UI/forms/obs.qrc
index 6e41d3c8f..8d7b9f3be 100644
--- a/UI/forms/obs.qrc
+++ b/UI/forms/obs.qrc
@@ -3,6 +3,7 @@
images/mute.png
images/unmute.png
images/refresh.png
+ images/no_sources.svg
images/configuration21_16.png
images/configuration21_16_2x.png
images/invisible_mask.png
diff --git a/UI/source-tree.cpp b/UI/source-tree.cpp
index 983b64b2c..95e774fb7 100644
--- a/UI/source-tree.cpp
+++ b/UI/source-tree.cpp
@@ -5,6 +5,7 @@
#include "visibility-checkbox.hpp"
#include "locked-checkbox.hpp"
#include "expand-checkbox.hpp"
+#include "platform.hpp"
#include
#include
@@ -915,6 +916,10 @@ SourceTree::SourceTree(QWidget *parent_) : QListView(parent_)
"*[bgColor=\"8\"]{background-color:rgba(255,255,255,33%);}"));
setMouseTracking(true);
+
+ UpdateNoSourcesMessage();
+ connect(App(), &OBSApp::StyleChanged,
+ this, &SourceTree::UpdateNoSourcesMessage);
}
void SourceTree::ResetWidgets()
@@ -1429,3 +1434,56 @@ void SourceTree::AddGroup()
{
GetStm()->AddGroup();
}
+
+void SourceTree::UpdateNoSourcesMessage()
+{
+ std::string darkPath;
+ GetDataFilePath("themes/Dark/no_sources.svg", darkPath);
+
+ QColor color = palette().text().color();
+ bool lightTheme = (color.redF() < 0.5);
+ QString file = lightTheme
+ ? ":res/images/no_sources.svg"
+ : darkPath.c_str();
+ iconNoSources.load(file);
+
+ QTextOption opt(Qt::AlignHCenter);
+ opt.setWrapMode(QTextOption::WordWrap);
+ textNoSources.setTextOption(opt);
+ textNoSources.setText(QTStr("NoSources.Label").replace("\n", "
"));
+
+ textPrepared = false;
+}
+
+void SourceTree::paintEvent(QPaintEvent *event)
+{
+ SourceTreeModel *stm = GetStm();
+ if (stm && !stm->items.count()) {
+ QPainter p(viewport());
+
+ if (!textPrepared) {
+ textNoSources.prepare(QTransform(), p.font());
+ textPrepared = true;
+ }
+
+ QRectF iconRect = iconNoSources.viewBoxF();
+
+ QSizeF iconSize = iconRect.size();
+ QSizeF textSize = textNoSources.size();
+ QSizeF thisSize = size();
+
+ qreal totalHeight = textSize.height() + iconSize.height();
+
+ qreal x = thisSize.width() / 2.0 - textSize.width() / 2.0;
+ qreal y = thisSize.height() / 2.0 - totalHeight / 2.0;
+ p.drawStaticText(x, y, textNoSources);
+
+ x = thisSize.width() / 2.0 - iconSize.width() / 2.0;
+ y += textSize.height();
+ iconRect.moveTo(x, y);
+
+ iconNoSources.render(&p, iconRect);
+ } else {
+ QListView::paintEvent(event);
+ }
+}
diff --git a/UI/source-tree.hpp b/UI/source-tree.hpp
index 551993b21..46577d20d 100644
--- a/UI/source-tree.hpp
+++ b/UI/source-tree.hpp
@@ -5,6 +5,8 @@
#include
#include
#include
+#include
+#include
#include
class QLabel;
@@ -133,6 +135,12 @@ class SourceTree : public QListView {
friend class SourceTreeModel;
friend class SourceTreeItem;
+ bool textPrepared = false;
+ QStaticText textNoSources;
+ QSvgRenderer iconNoSources;
+
+ void UpdateNoSourcesMessage();
+
void ResetWidgets();
void UpdateWidget(const QModelIndex &idx, obs_sceneitem_t *item);
void UpdateWidgets(bool force = false);
@@ -177,6 +185,7 @@ protected:
virtual void dropEvent(QDropEvent *event) override;
virtual void mouseMoveEvent(QMouseEvent *event) override;
virtual void leaveEvent(QEvent *event) override;
+ virtual void paintEvent(QPaintEvent *event) override;
virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) override;
};