UI: Redesign status bar

This redesigns the status bar to look more modern.

Co-authored-by: Warchamp7 <warchamp2003@hotmail.com>
Co-authored-by: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
This commit is contained in:
cg2121
2023-05-20 18:22:52 -05:00
committed by Lain
parent 9d611a064f
commit 1c84071830
29 changed files with 891 additions and 369 deletions

View File

@@ -116,6 +116,7 @@ target_sources(
forms/OBSRemux.ui
forms/OBSUpdate.ui
forms/OBSYoutubeActions.ui
forms/StatusBarWidget.ui
forms/source-toolbar/browser-source-toolbar.ui
forms/source-toolbar/color-source-toolbar.ui
forms/source-toolbar/device-select-toolbar.ui

View File

@@ -337,8 +337,20 @@ QScrollArea {
border-radius: 4px;
}
/* Qt enforces a padding inside its status bar, so we
* oversize it and use margin to crunch it back down
*/
OBSBasicStatusBar {
margin-top: 8px;
margin-top: 4px;
border-top: 1px solid #3c404b;
background: palette(dark);
}
StatusBarWidget > QFrame {
margin-top: 1px;
border: 0px solid #3c404b;
border-left-width: 1px;
padding: 0px 12px 2px;
}
/* Group Box */

View File

@@ -644,6 +644,22 @@ QStatusBar::item {
border: none;
}
/* Qt enforces a padding inside its status bar, so we
* oversize it and use margin to crunch it back down
*/
OBSBasicStatusBar {
margin-top: 4px;
border-top: 1px solid palette(dark);
background: palette(window);
}
StatusBarWidget > QFrame {
margin-top: 2px;
border: 0px solid palette(dark);
border-left-width: 1px;
padding: 0px 12px 4px;
}
/* Table View */
QTableView {

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(-2388.3 -3285.1)">
<path d="m2401.3 3286.1c-0.5547 0-1 0.4453-1 1v7.2695c0.1485 0.09 0.2891 0.1914 0.4141 0.3164l0.414 0.4141h0.3438l0.4141-0.4141c0.375-0.375 0.8828-0.5859 1.414-0.5859v-7c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v9c0 0.5547 0.4453 1 1 1h0.01c0-0.5156 0.1914-1.0273 0.5781-1.4141l0.4141-0.414v-0.3438l-0.4141-0.414c-0.7734-0.7735-0.7734-2.0547 0-2.8282 0.375-0.375 0.8829-0.5859 1.4141-0.5859v-4c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v6c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-6c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v3c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-3c0-0.5547-0.4453-1-1-1z" fill="#fff" fill-opacity=".2"/>
<path d="m2399.3 3295.1c-0.2656 0-0.5195 0.1055-0.707 0.293-0.3906 0.3906-0.3906 1.0234 0 1.414l1.293 1.293-1.293 1.293c-0.3906 0.3906-0.3906 1.0234 0 1.414 0.3906 0.3907 1.0234 0.3907 1.414 0l1.293-1.2929 1.293 1.2929c0.3906 0.3907 1.0234 0.3907 1.414 0 0.3907-0.3906 0.3907-1.0234 0-1.414l-1.2929-1.293 1.2929-1.293c0.3907-0.3906 0.3907-1.0234 0-1.414-0.1875-0.1875-0.4414-0.293-0.707-0.293s-0.5195 0.1055-0.707 0.293l-1.293 1.2929-1.293-1.2929c-0.1875-0.1875-0.4414-0.293-0.707-0.293z" fill="#b8131a"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m13 1c-0.55469 0-1 0.44531-1 1v12c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-12c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v9c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-9c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v6c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-6c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v3c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-3c0-0.55469-0.44531-1-1-1z" fill="#fff" fill-opacity=".2"/>
</svg>

After

Width:  |  Height:  |  Size: 634 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m15 8c0 3.8672-3.1328 7-7 7s-7-3.1328-7-7 3.1328-7 7-7 7 3.1328 7 7z" fill="#fff" fill-opacity=".2"/>
</svg>

After

Width:  |  Height:  |  Size: 260 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill="#fff" fill-opacity=".2">
<path d="m3 1h3c0.55078 0 1 0.44922 1 1v12c0 0.55078-0.44922 1-1 1h-3c-0.55078 0-1-0.44922-1-1v-12c0-0.55078 0.44922-1 1-1z"/>
<path d="m10 1h3c0.55078 0 1 0.44922 1 1v12c0 0.55078-0.44922 1-1 1h-3c-0.55078 0-1-0.44922-1-1v-12c0-0.55078 0.44922-1 1-1z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 448 B

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="matrix(1.8565 0 0 1.8565 .152 -547.29)">
<circle cx="1.0583" cy="295.94" r=".37705" fill="#fff" fill-opacity=".4" style="paint-order:normal"/>
<g fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round">
<path d="m0.6324 296.42a0.62244 0.62244 0 0 1-0.22234-0.47682 0.62244 0.62244 0 0 1 0.22234-0.47682" stroke-opacity=".22" stroke-width=".18852" style="paint-order:normal"/>
<path d="m1.4833 296.42a0.62244 0.62244 0 0 0 0.22234-0.47682 0.62244 0.62244 0 0 0-0.22234-0.47682" stroke-opacity=".22" stroke-width=".18852" style="paint-order:normal"/>
<path d="m0.39544 296.7a0.98443 0.98443 0 0 1-0.35165-0.75411 0.98443 0.98443 0 0 1 0.35165-0.75413" stroke-opacity=".08" stroke-width=".25133" style="paint-order:normal"/>
<path d="m1.7211 296.7a0.98443 0.98443 0 0 0 0.35165-0.75411 0.98443 0.98443 0 0 0-0.35165-0.75413" stroke-opacity=".08" stroke-width=".25133" style="paint-order:normal"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -337,8 +337,20 @@ QScrollArea {
border-radius: 4px;
}
/* Qt enforces a padding inside its status bar, so we
* oversize it and use margin to crunch it back down
*/
OBSBasicStatusBar {
margin-top: 8px;
margin-top: 4px;
border-top: 1px solid #3c404b;
background: palette(dark);
}
StatusBarWidget > QFrame {
margin-top: 1px;
border: 0px solid #3c404b;
border-left-width: 1px;
padding: 0px 12px 2px;
}
/* Group Box */

View File

@@ -337,8 +337,20 @@ QScrollArea {
border-radius: 4px;
}
/* Qt enforces a padding inside its status bar, so we
* oversize it and use margin to crunch it back down
*/
OBSBasicStatusBar {
margin-top: 8px;
margin-top: 4px;
border-top: 1px solid rgb(192,192,192);
background: palette(dark);
}
StatusBarWidget > QFrame {
margin-top: 1px;
border: 0px solid rgb(192,192,192);
border-left-width: 1px;
padding: 0px 12px 2px;
}
/* Group Box */

View File

@@ -339,8 +339,20 @@ QScrollArea {
border-radius: 4px;
}
/* Qt enforces a padding inside its status bar, so we
* oversize it and use margin to crunch it back down
*/
OBSBasicStatusBar {
margin-top: 8px;
margin-top: 4px;
border-top: 1px solid #3c404b;
background: palette(dark);
}
StatusBarWidget > QFrame {
margin-top: 1px;
border: 0px solid #3c404b;
border-left-width: 1px;
padding: 0px 12px 2px;
}
/* Group Box */

View File

@@ -402,3 +402,8 @@ QCalendarWidget #qt_calendar_nextmonth {
qproperty-icon: url(./Dark/right.svg);
icon-size: 16px, 16px;
}
/* Status Bar */
StatusBarWidget > QFrame {
padding: 0px 12px 8px;
}

View File

@@ -341,8 +341,20 @@ QScrollArea {
border-radius: 4px;
}
/* Qt enforces a padding inside its status bar, so we
* oversize it and use margin to crunch it back down
*/
OBSBasicStatusBar {
margin-top: 8px;
margin-top: 4px;
border-top: 1px solid #3c404b;
background: palette(dark);
}
StatusBarWidget > QFrame {
margin-top: 1px;
border: 0px solid #3c404b;
border-left-width: 1px;
padding: 0px 12px 2px;
}
/* Group Box */

418
UI/forms/StatusBarWidget.ui Normal file
View File

@@ -0,0 +1,418 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>StatusBarWidget</class>
<widget class="QWidget" name="StatusBarWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>714</width>
<height>34</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>34</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer_11">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>2</width>
<height>2</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QFrame" name="delayFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="delayInfo">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>DelayInfo</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="issuesFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="droppedFrames">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>DroppedFrames</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="networkFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="statusIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="obs.qrc">:/res/images/network-inactive.svg</pixmap>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="kbps">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>0 kbps</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="streamFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="streamIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="obs.qrc">:/res/images/streaming-inactive.svg</pixmap>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="streamTime">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>00:00:00</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="recordFrame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="recordIcon">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string/>
</property>
<property name="pixmap">
<pixmap resource="obs.qrc">:/res/images/recording-inactive.svg</pixmap>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="recordTime">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>00:00:00</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="cpuFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="cpuUsage">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>CPU: 0.0%</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="fpsFrame">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>0</number>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="fpsCurrent">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>0.00 / 0.00 FPS</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="obs.qrc"/>
</resources>
<connections/>
</ui>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill="#b8131a">
<path d="m1 10c-0.55469 0-1 0.44531-1 1v3c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-3c0-0.55469-0.44531-1-1-1z"/>
<path d="m13 1c-0.55469 0-1 0.44531-1 1v12c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-12c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v9c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-9c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v6c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-6c0-0.55469-0.44531-1-1-1z" fill-opacity=".30196"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 668 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g transform="translate(-2388.3 -3285.1)">
<path d="m2401.3 3286.1c-0.5547 0-1 0.4453-1 1v7.2695c0.1485 0.09 0.2891 0.1914 0.4141 0.3164l0.414 0.4141h0.3438l0.4141-0.4141c0.375-0.375 0.8828-0.5859 1.414-0.5859v-7c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v9c0 0.5547 0.4453 1 1 1h0.01c0-0.5156 0.1914-1.0273 0.5781-1.4141l0.4141-0.414v-0.3438l-0.4141-0.414c-0.7734-0.7735-0.7734-2.0547 0-2.8282 0.375-0.375 0.8829-0.5859 1.4141-0.5859v-4c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v6c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-6c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v3c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-3c0-0.5547-0.4453-1-1-1z" fill-opacity=".1"/>
<path d="m2399.3 3295.1c-0.2656 0-0.5195 0.1055-0.707 0.293-0.3906 0.3906-0.3906 1.0234 0 1.414l1.293 1.293-1.293 1.293c-0.3906 0.3906-0.3906 1.0234 0 1.414 0.3906 0.3907 1.0234 0.3907 1.414 0l1.293-1.2929 1.293 1.2929c0.3906 0.3907 1.0234 0.3907 1.414 0 0.3907-0.3906 0.3907-1.0234 0-1.414l-1.2929-1.293 1.2929-1.293c0.3907-0.3906 0.3907-1.0234 0-1.414-0.1875-0.1875-0.4414-0.293-0.707-0.293s-0.5195 0.1055-0.707 0.293l-1.293 1.2929-1.293-1.2929c-0.1875-0.1875-0.4414-0.293-0.707-0.293z" fill="#b8131a"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m13 1c-0.5547 0-1 0.4453-1 1v12c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-12c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v9c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-9c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v6c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-6c0-0.5547-0.4453-1-1-1zm-4 3c-0.5547 0-1 0.4453-1 1v3c0 0.5547 0.4453 1 1 1h1c0.5547 0 1-0.4453 1-1v-3c0-0.5547-0.4453-1-1-1z" fill="#2bc62f"/>
</svg>

After

Width:  |  Height:  |  Size: 587 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill="#49b37a">
<path d="m9 4c-0.55469 0-1 0.44531-1 1v9c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-9c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v6c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-6c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v3c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-3c0-0.55469-0.44531-1-1-1z"/>
<path d="m13 1c-0.55469 0-1 0.44531-1 1v12c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-12c0-0.55469-0.44531-1-1-1z" fill-opacity=".30196"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 667 B

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m13 1c-0.55469 0-1 0.44531-1 1v12c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-12c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v9c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-9c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v6c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-6c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v3c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-3c0-0.55469-0.44531-1-1-1z" fill-opacity=".15"/>
</svg>

After

Width:  |  Height:  |  Size: 623 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill="#e4ac3c">
<path d="m5 7c-0.55469 0-1 0.44531-1 1v6c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-6c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v3c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-3c0-0.55469-0.44531-1-1-1z"/>
<path d="m13 1c-0.55469 0-1 0.44531-1 1v12c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-12c0-0.55469-0.44531-1-1-1zm-4 3c-0.55469 0-1 0.44531-1 1v9c0 0.55469 0.44531 1 1 1h1c0.55469 0 1-0.44531 1-1v-9c0-0.55469-0.44531-1-1-1z" fill-opacity=".3"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 663 B

View File

@@ -1,37 +1,4 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 2.1166666 2.1166667"
height="8"
width="8">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-294.88332)"
id="layer1">
<circle
r="0.52916664"
cy="295.94165"
cx="1.0583333"
id="path4544"
style="fill:#c01c28;fill-opacity:1;stroke:none;stroke-width:0.06614584;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m15 8c0 3.8672-3.1328 7-7 7s-7-3.1328-7-7 3.1328-7 7-7 7 3.1328 7 7z" fill="#c31212"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 245 B

View File

@@ -1,14 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg8" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 8 8"
style="enable-background:new 0 0 8 8;" xml:space="preserve">
<style type="text/css">
.st0{fill:#9a9996;}
</style>
<g>
<path class="st0" d="M5.8,1.5L5,2.3C4.7,2.1,4.4,2,4,2C2.9,2,2,2.9,2,4c0,0.4,0.1,0.7,0.3,1L1.5,5.8l0.4,0.4l4.2-4.2L5.8,1.5z"/>
<path class="st0" d="M3,5.7C3.3,5.9,3.6,6,4,6c1.1,0,2-0.9,2-2c0-0.4-0.1-0.7-0.3-1L3,5.7z"/>
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<path d="m15 8c0 3.8672-3.1328 7-7 7s-7-3.1328-7-7 3.1328-7 7-7 7 3.1328 7 7z" fill-opacity=".1"/>
</svg>

Before

Width:  |  Height:  |  Size: 813 B

After

Width:  |  Height:  |  Size: 248 B

View File

@@ -1,45 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 5.2916665 5.2916668"
height="20"
width="20">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-291.70832)"
id="layer1">
<rect
y="293.03125"
x="1.3229166"
height="2.6458333"
width="1.0583333"
id="rect822"
style="fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<rect
y="293.03125"
x="2.9104166"
height="2.6458333"
width="1.0583333"
id="rect822-1"
style="fill:#9a9996;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill-opacity=".1">
<path d="m3 1h3c0.55078 0 1 0.44922 1 1v12c0 0.55078-0.44922 1-1 1h-3c-0.55078 0-1-0.44922-1-1v-12c0-0.55078 0.44922-1 1-1z"/>
<path d="m10 1h3c0.55078 0 1 0.44922 1 1v12c0 0.55078-0.44922 1-1 1h-3c-0.55078 0-1-0.44922-1-1v-12c0-0.55078 0.44922-1 1-1z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 436 B

View File

@@ -1,45 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 5.2916665 5.2916668"
height="20"
width="20">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-291.70832)"
id="layer1">
<rect
y="293.03125"
x="1.3229166"
height="2.6458333"
width="1.0583333"
id="rect822"
style="fill:#f5c211;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<rect
y="293.03125"
x="2.9104166"
height="2.6458333"
width="1.0583333"
id="rect822-1"
style="fill:#f5c211;fill-opacity:1;stroke:none;stroke-width:0.5020116;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" version="1.1" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg">
<g fill="#e5a50a">
<path d="m3 1h3c0.55078 0 1 0.44922 1 1v12c0 0.55078-0.44922 1-1 1h-3c-0.55078 0-1-0.44922-1-1v-12c0-0.55078 0.44922-1 1-1z"/>
<path d="m10 1h3c0.55078 0 1 0.44922 1 1v12c0 0.55078-0.44922 1-1 1h-3c-0.55078 0-1-0.44922-1-1v-12c0-0.55078 0.44922-1 1-1z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 433 B

View File

@@ -1,55 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
id="svg8"
version="1.1"
viewBox="0 0 2.1166666 2.1166667"
height="8"
width="8">
<defs
id="defs2" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-294.88332)"
id="layer1">
<circle
r="0.39687499"
cy="295.94165"
cx="1.0582843"
id="path4544-3"
style="fill:#1c71d8;fill-opacity:1;stroke:none;stroke-width:0.13229169;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
d="M 0.41577997,296.5497 A 0.79374999,0.79374999 0 0 1 0.13224262,295.94165 0.79374999,0.79374999 0 0 1 0.41577996,295.3336"
id="path4546-7"
style="fill:none;fill-opacity:1;stroke:#1c71d8;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
transform="scale(-1,1)"
d="m -1.7008867,296.5497 a 0.79374999,0.79374999 0 0 1 -0.2835374,-0.60805 0.79374999,0.79374999 0 0 1 0.2835374,-0.60805"
id="path4546-1-3"
style="fill:none;fill-opacity:1;stroke:#1c71d8;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
d="M 0.63239977,296.41847 A 0.62244385,0.62244385 0 0 1 0.4100551,295.94165 0.62244385,0.62244385 0 0 1 0.63239977,295.46483"
id="path4546-5-7"
style="fill:none;fill-opacity:1;stroke:#1c71d8;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<path
transform="scale(-1,1)"
d="m -1.484193,296.41847 a 0.62244391,0.62244391 0 0 1 -0.2223447,-0.47682 0.62244391,0.62244391 0 0 1 0.2223447,-0.47682"
id="path4546-5-4-2"
style="fill:none;fill-opacity:1;stroke:#1c71d8;stroke-width:0.15875001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" />
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="matrix(1.8565 0 0 1.8565 .152 -547.29)">
<circle cx="1.0583" cy="295.94" r=".37705" fill="#2f95ff" style="paint-order:normal"/>
<g fill="none" stroke="#2f95ff" stroke-linecap="round" stroke-linejoin="round">
<path d="m0.6324 296.42a0.62244 0.62244 0 0 1-0.22234-0.47682 0.62244 0.62244 0 0 1 0.22234-0.47682" stroke-opacity=".67" stroke-width=".18852" style="paint-order:normal"/>
<path d="m1.4833 296.42a0.62244 0.62244 0 0 0 0.22234-0.47682 0.62244 0.62244 0 0 0-0.22234-0.47682" stroke-opacity=".67" stroke-width=".18852" style="paint-order:normal"/>
<path d="m0.39544 296.7a0.98443 0.98443 0 0 1-0.35165-0.75411 0.98443 0.98443 0 0 1 0.35165-0.75413" stroke-opacity=".33" stroke-width=".25133" style="paint-order:normal"/>
<path d="m1.7211 296.7a0.98443 0.98443 0 0 0 0.35165-0.75411 0.98443 0.98443 0 0 0-0.35165-0.75413" stroke-opacity=".33" stroke-width=".25133" style="paint-order:normal"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -1,21 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1"
id="svg8" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 8 8"
style="enable-background:new 0 0 8 8;" xml:space="preserve">
<style type="text/css">
.st0{fill:#9a9996;}
</style>
<g>
<path class="st0" d="M6.5,0.8L4.6,2.6C4.4,2.6,4.2,2.5,4,2.5C3.2,2.5,2.5,3.2,2.5,4c0,0.2,0.1,0.4,0.1,0.6L2.2,5.1
C2,4.8,1.8,4.4,1.8,4c0-0.6,0.3-1.2,0.7-1.6c0.1-0.1,0.1-0.3,0-0.4C2.5,1.9,2.3,1.9,2.2,2C1.6,2.5,1.2,3.2,1.2,4
c0,0.6,0.2,1.1,0.5,1.5L1.5,5.8C1.1,5.3,0.8,4.7,0.8,4c0-0.8,0.4-1.6,1-2.1c0.1-0.1,0.1-0.3,0-0.4c-0.1-0.1-0.3-0.1-0.4,0
C0.6,2.1,0.2,3,0.2,4c0,0.8,0.3,1.6,0.9,2.2L0.8,6.5l0.4,0.4l5.7-5.7L6.5,0.8z"/>
<path class="st0" d="M5.4,3.4l-2,2C3.6,5.4,3.8,5.5,4,5.5c0.8,0,1.5-0.7,1.5-1.5C5.5,3.8,5.4,3.6,5.4,3.4z"/>
<path class="st0" d="M6.2,2.5L5.8,2.9C6,3.2,6.2,3.6,6.2,4c0,0.6-0.3,1.2-0.7,1.6C5.3,5.7,5.3,5.9,5.4,6c0.1,0.1,0.1,0.1,0.2,0.1
c0.1,0,0.1,0,0.2-0.1c0.6-0.5,0.9-1.2,0.9-2C6.8,3.4,6.6,2.9,6.2,2.5z"/>
<path class="st0" d="M6.9,1.8L6.5,2.2C6.9,2.7,7.2,3.3,7.2,4c0,0.8-0.4,1.6-1,2.1c-0.1,0.1-0.1,0.3,0,0.4c0.1,0.1,0.1,0.1,0.2,0.1
c0.1,0,0.1,0,0.2-0.1C7.4,5.9,7.8,5,7.8,4C7.8,3.2,7.5,2.4,6.9,1.8z"/>
</g>
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16" height="16" version="1.1" viewBox="0 0 4.2333 4.2333" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<metadata>
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="matrix(1.8565 0 0 1.8565 .152 -547.29)">
<circle cx="1.0583" cy="295.94" r=".37705" fill-opacity=".18" style="paint-order:normal"/>
<g fill="none" stroke-linecap="round" stroke-linejoin="round">
<path d="m0.6324 296.42a0.62244 0.62244 0 0 1-0.22234-0.47682 0.62244 0.62244 0 0 1 0.22234-0.47682" stroke="#000" stroke-opacity=".12" stroke-width=".18852" style="paint-order:normal"/>
<path d="m1.4833 296.42a0.62244 0.62244 0 0 0 0.22234-0.47682 0.62244 0.62244 0 0 0-0.22234-0.47682" stroke="#000" stroke-opacity=".12" stroke-width=".18852" style="paint-order:normal"/>
<path d="m0.39544 296.7a0.98443 0.98443 0 0 1-0.35165-0.75411 0.98443 0.98443 0 0 1 0.35165-0.75413" stroke="#060606" stroke-opacity=".07" stroke-width=".25133" style="paint-order:normal"/>
<path d="m1.7211 296.7a0.98443 0.98443 0 0 0 0.35165-0.75411 0.98443 0.98443 0 0 0-0.35165-0.75413" stroke="#060606" stroke-opacity=".07" stroke-width=".25133" style="paint-order:normal"/>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -64,6 +64,12 @@
<file>images/expand.svg</file>
<file>images/collapse.svg</file>
<file>images/entry-clear.svg</file>
<file>images/network-excellent.svg</file>
<file>images/network-good.svg</file>
<file>images/network-mediocre.svg</file>
<file>images/network-bad.svg</file>
<file>images/network-disconnected.svg</file>
<file>images/network-inactive.svg</file>
</qresource>
<qresource prefix="/settings">
<file>images/settings/output.svg</file>

View File

@@ -1,97 +1,66 @@
#include <QLabel>
#include <QHBoxLayout>
#include <QPainter>
#include <QPixmap>
#include "obs-app.hpp"
#include "window-basic-main.hpp"
#include "window-basic-status-bar.hpp"
#include "window-basic-main-outputs.hpp"
#include "qt-wrappers.hpp"
#include "platform.hpp"
#include "ui_StatusBarWidget.h"
static constexpr int bitrateUpdateSeconds = 2;
static constexpr int congestionUpdateSeconds = 4;
static constexpr float excellentThreshold = 0.0f;
static constexpr float goodThreshold = 0.3333f;
static constexpr float mediocreThreshold = 0.6667f;
static constexpr float badThreshold = 1.0f;
StatusBarWidget::StatusBarWidget(QWidget *parent)
: QWidget(parent),
ui(new Ui::StatusBarWidget)
{
ui->setupUi(this);
}
StatusBarWidget::~StatusBarWidget() {}
OBSBasicStatusBar::OBSBasicStatusBar(QWidget *parent)
: QStatusBar(parent),
delayInfo(new QLabel),
droppedFrames(new QLabel),
streamIcon(new QLabel),
streamTime(new QLabel),
recordTime(new QLabel),
recordIcon(new QLabel),
cpuUsage(new QLabel),
transparentPixmap(20, 20),
greenPixmap(20, 20),
grayPixmap(20, 20),
redPixmap(20, 20),
excellentPixmap(QIcon(":/res/images/network-excellent.svg")
.pixmap(QSize(16, 16))),
goodPixmap(
QIcon(":/res/images/network-good.svg").pixmap(QSize(16, 16))),
mediocrePixmap(QIcon(":/res/images/network-mediocre.svg")
.pixmap(QSize(16, 16))),
badPixmap(
QIcon(":/res/images/network-bad.svg").pixmap(QSize(16, 16))),
recordingActivePixmap(QIcon(":/res/images/recording-active.svg")
.pixmap(QSize(20, 20))),
.pixmap(QSize(16, 16))),
recordingPausePixmap(QIcon(":/res/images/recording-pause.svg")
.pixmap(QSize(20, 20))),
recordingPauseInactivePixmap(
QIcon(":/res/images/recording-pause-inactive.svg")
.pixmap(QSize(20, 20))),
recordingInactivePixmap(QIcon(":/res/images/recording-inactive.svg")
.pixmap(QSize(20, 20))),
.pixmap(QSize(16, 16))),
streamingActivePixmap(QIcon(":/res/images/streaming-active.svg")
.pixmap(QSize(20, 20))),
streamingInactivePixmap(QIcon(":/res/images/streaming-inactive.svg")
.pixmap(QSize(20, 20)))
.pixmap(QSize(16, 16)))
{
streamTime->setText(QString("LIVE: 00:00:00"));
recordTime->setText(QString("REC: 00:00:00"));
cpuUsage->setText(QString("CPU: 0.0%, 0.00 fps"));
statusWidget = new StatusBarWidget(this);
statusWidget->ui->delayInfo->setText("");
statusWidget->ui->droppedFrames->setText(
QTStr("DroppedFrames").arg("0", "0.0"));
statusWidget->ui->statusIcon->setPixmap(inactivePixmap);
statusWidget->ui->streamIcon->setPixmap(streamingInactivePixmap);
statusWidget->ui->streamTime->setDisabled(true);
statusWidget->ui->recordIcon->setPixmap(recordingInactivePixmap);
statusWidget->ui->recordTime->setDisabled(true);
statusWidget->ui->delayFrame->hide();
statusWidget->ui->issuesFrame->hide();
statusWidget->ui->kbps->hide();
streamIcon->setPixmap(streamingInactivePixmap);
recordIcon->setPixmap(recordingInactivePixmap);
addPermanentWidget(statusWidget);
setMinimumHeight(statusWidget->height());
QWidget *brWidget = new QWidget(this);
QHBoxLayout *brLayout = new QHBoxLayout(brWidget);
brLayout->setContentsMargins(0, 0, 0, 0);
statusSquare = new QLabel(brWidget);
brLayout->addWidget(statusSquare);
kbps = new QLabel(brWidget);
brLayout->addWidget(kbps);
brWidget->setLayout(brLayout);
delayInfo->setAlignment(Qt::AlignRight);
delayInfo->setAlignment(Qt::AlignVCenter);
droppedFrames->setAlignment(Qt::AlignRight);
droppedFrames->setAlignment(Qt::AlignVCenter);
streamIcon->setAlignment(Qt::AlignRight);
streamIcon->setAlignment(Qt::AlignVCenter);
streamTime->setAlignment(Qt::AlignRight);
streamTime->setAlignment(Qt::AlignVCenter);
recordIcon->setAlignment(Qt::AlignRight);
recordIcon->setAlignment(Qt::AlignVCenter);
recordTime->setAlignment(Qt::AlignRight);
recordTime->setAlignment(Qt::AlignVCenter);
cpuUsage->setAlignment(Qt::AlignRight);
cpuUsage->setAlignment(Qt::AlignVCenter);
kbps->setAlignment(Qt::AlignRight);
kbps->setAlignment(Qt::AlignVCenter);
delayInfo->setIndent(20);
droppedFrames->setIndent(20);
streamIcon->setIndent(20);
recordIcon->setIndent(20);
cpuUsage->setIndent(20);
kbps->setIndent(10);
addPermanentWidget(droppedFrames);
addPermanentWidget(streamIcon);
addPermanentWidget(streamTime);
addPermanentWidget(recordIcon);
addPermanentWidget(recordTime);
addPermanentWidget(cpuUsage);
addPermanentWidget(delayInfo);
addPermanentWidget(brWidget);
transparentPixmap.fill(QColor(0, 0, 0, 0));
greenPixmap.fill(QColor(0, 255, 0));
grayPixmap.fill(QColor(72, 72, 72));
redPixmap.fill(QColor(255, 0, 0));
statusSquare->setPixmap(transparentPixmap);
UpdateIcons();
connect(App(), &OBSApp::StyleChanged, this,
&OBSBasicStatusBar::UpdateIcons);
}
void OBSBasicStatusBar::Activate()
@@ -114,16 +83,21 @@ void OBSBasicStatusBar::Activate()
active = true;
if (streamOutput) {
statusSquare->setPixmap(grayPixmap);
statusWidget->ui->statusIcon->setPixmap(inactivePixmap);
}
}
if (streamOutput) {
streamIcon->setPixmap(streamingActivePixmap);
statusWidget->ui->streamIcon->setPixmap(streamingActivePixmap);
statusWidget->ui->streamTime->setDisabled(false);
statusWidget->ui->issuesFrame->show();
statusWidget->ui->kbps->show();
firstCongestionUpdate = true;
}
if (recordOutput) {
recordIcon->setPixmap(recordingActivePixmap);
statusWidget->ui->recordIcon->setPixmap(recordingActivePixmap);
statusWidget->ui->recordTime->setDisabled(false);
}
}
@@ -134,23 +108,35 @@ void OBSBasicStatusBar::Deactivate()
return;
if (!streamOutput) {
streamTime->setText(QString("LIVE: 00:00:00"));
streamIcon->setPixmap(streamingInactivePixmap);
statusWidget->ui->streamTime->setText(QString("00:00:00"));
statusWidget->ui->streamTime->setDisabled(true);
statusWidget->ui->streamIcon->setPixmap(
streamingInactivePixmap);
statusWidget->ui->statusIcon->setPixmap(inactivePixmap);
statusWidget->ui->delayFrame->hide();
statusWidget->ui->issuesFrame->hide();
statusWidget->ui->kbps->hide();
totalStreamSeconds = 0;
congestionArray.clear();
disconnected = false;
firstCongestionUpdate = false;
}
if (!recordOutput) {
recordTime->setText(QString("REC: 00:00:00"));
recordIcon->setPixmap(recordingInactivePixmap);
statusWidget->ui->recordTime->setText(QString("00:00:00"));
statusWidget->ui->recordTime->setDisabled(true);
statusWidget->ui->recordIcon->setPixmap(
recordingInactivePixmap);
totalRecordSeconds = 0;
}
if (main->outputHandler && !main->outputHandler->Active()) {
delete refreshTimer;
delayInfo->setText("");
droppedFrames->setText("");
kbps->setText("");
statusWidget->ui->delayInfo->setText("");
statusWidget->ui->droppedFrames->setText(
QTStr("DroppedFrames").arg("0", "0.0"));
statusWidget->ui->kbps->setText("0 kbps");
delaySecTotal = 0;
delaySecStarting = 0;
@@ -159,7 +145,7 @@ void OBSBasicStatusBar::Deactivate()
active = false;
overloadedNotify = true;
statusSquare->setPixmap(transparentPixmap);
statusWidget->ui->statusIcon->setPixmap(inactivePixmap);
}
}
@@ -184,19 +170,20 @@ void OBSBasicStatusBar::UpdateDelayMsg()
msg = QTStr("Basic.StatusBar.Delay");
msg = msg.arg(QString::number(delaySecTotal));
}
if (!statusWidget->ui->delayFrame->isVisible())
statusWidget->ui->delayFrame->show();
statusWidget->ui->delayInfo->setText(msg);
}
delayInfo->setText(msg);
}
#define BITRATE_UPDATE_SECONDS 2
void OBSBasicStatusBar::UpdateBandwidth()
{
if (!streamOutput)
return;
if (++bitrateUpdateSeconds < BITRATE_UPDATE_SECONDS)
if (++seconds < bitrateUpdateSeconds)
return;
uint64_t bytesSent = obs_output_get_total_bytes(streamOutput);
@@ -215,14 +202,18 @@ void OBSBasicStatusBar::UpdateBandwidth()
double kbitsPerSec = double(bitsBetween) / timePassed / 1000.0;
QString text;
text += QString("kb/s: ") + QString::number(kbitsPerSec, 'f', 0);
text += QString::number(kbitsPerSec, 'f', 0) + QString(" kbps");
kbps->setText(text);
kbps->setMinimumWidth(kbps->width());
statusWidget->ui->kbps->setText(text);
statusWidget->ui->kbps->setMinimumWidth(
statusWidget->ui->kbps->width());
if (!statusWidget->ui->kbps->isVisible())
statusWidget->ui->kbps->show();
lastBytesSent = bytesSent;
lastBytesSentTime = bytesSentTime;
bitrateUpdateSeconds = 0;
seconds = 0;
}
void OBSBasicStatusBar::UpdateCPUUsage()
@@ -233,11 +224,34 @@ void OBSBasicStatusBar::UpdateCPUUsage()
QString text;
text += QString("CPU: ") +
QString::number(main->GetCPUUsage(), 'f', 1) + QString("%, ") +
QString::number(obs_get_active_fps(), 'f', 2) + QString(" fps");
QString::number(main->GetCPUUsage(), 'f', 1) + QString("%");
cpuUsage->setText(text);
cpuUsage->setMinimumWidth(cpuUsage->width());
statusWidget->ui->cpuUsage->setText(text);
statusWidget->ui->cpuUsage->setMinimumWidth(
statusWidget->ui->cpuUsage->width());
UpdateCurrentFPS();
}
void OBSBasicStatusBar::UpdateCurrentFPS()
{
OBSBasic *main = qobject_cast<OBSBasic *>(parent());
if (!main)
return;
struct obs_video_info ovi;
obs_get_video_info(&ovi);
float targetFPS = (float)ovi.fps_num / (float)ovi.fps_den;
QString text;
text += QString::number(obs_get_active_fps(), 'f', 2);
text += QString(" / ");
text += QString::number(targetFPS, 'f', 2);
text += QString(" FPS");
statusWidget->ui->fpsCurrent->setText(text);
statusWidget->ui->fpsCurrent->setMinimumWidth(
statusWidget->ui->fpsCurrent->width());
}
void OBSBasicStatusBar::UpdateStreamTime()
@@ -249,16 +263,20 @@ void OBSBasicStatusBar::UpdateStreamTime()
int minutes = totalMinutes % 60;
int hours = totalMinutes / 60;
QString text = QString::asprintf("LIVE: %02d:%02d:%02d", hours, minutes,
seconds);
streamTime->setText(text);
streamTime->setMinimumWidth(streamTime->width());
QString text =
QString::asprintf("%02d:%02d:%02d", hours, minutes, seconds);
statusWidget->ui->streamTime->setText(text);
if (streamOutput && !statusWidget->ui->streamTime->isEnabled())
statusWidget->ui->streamTime->setDisabled(false);
if (reconnectTimeout > 0) {
QString msg = QTStr("Basic.StatusBar.Reconnecting")
.arg(QString::number(retries),
QString::number(reconnectTimeout));
showMessage(msg);
disconnected = true;
statusWidget->ui->statusIcon->setPixmap(disconnectedPixmap);
congestionArray.clear();
reconnectTimeout--;
} else if (retries > 0) {
@@ -289,14 +307,15 @@ void OBSBasicStatusBar::UpdateRecordTime()
int minutes = totalMinutes % 60;
int hours = totalMinutes / 60;
QString text = QString::asprintf("REC: %02d:%02d:%02d", hours,
QString text = QString::asprintf("%02d:%02d:%02d", hours,
minutes, seconds);
recordTime->setText(text);
recordTime->setMinimumWidth(recordTime->width());
statusWidget->ui->recordTime->setText(text);
if (recordOutput && !statusWidget->ui->recordTime->isEnabled())
statusWidget->ui->recordTime->setDisabled(false);
} else {
recordIcon->setPixmap(streamPauseIconToggle
? recordingPauseInactivePixmap
statusWidget->ui->recordIcon->setPixmap(
streamPauseIconToggle ? recordingPauseInactivePixmap
: recordingPausePixmap);
streamPauseIconToggle = !streamPauseIconToggle;
@@ -318,8 +337,10 @@ void OBSBasicStatusBar::UpdateDroppedFrames()
QString text = QTStr("DroppedFrames");
text = text.arg(QString::number(totalDropped),
QString::number(percent, 'f', 1));
droppedFrames->setText(text);
droppedFrames->setMinimumWidth(droppedFrames->width());
statusWidget->ui->droppedFrames->setText(text);
if (!statusWidget->ui->issuesFrame->isVisible())
statusWidget->ui->issuesFrame->show();
/* ----------------------------------- *
* calculate congestion color */
@@ -331,28 +352,37 @@ void OBSBasicStatusBar::UpdateDroppedFrames()
if (avgCongestion > 1.0f)
avgCongestion = 1.0f;
if (avgCongestion < EPSILON) {
statusSquare->setPixmap(greenPixmap);
} else if (fabsf(avgCongestion - 1.0f) < EPSILON) {
statusSquare->setPixmap(redPixmap);
lastCongestion = congestion;
if (disconnected)
return;
bool update = firstCongestionUpdate;
float congestionOverTime = avgCongestion;
if (congestionArray.size() >= congestionUpdateSeconds) {
congestionOverTime = accumulate(congestionArray.begin(),
congestionArray.end(), 0.0f) /
(float)congestionArray.size();
congestionArray.clear();
update = true;
} else {
QPixmap pixmap(20, 20);
float red = avgCongestion * 2.0f;
if (red > 1.0f)
red = 1.0f;
red *= 255.0;
float green = (1.0f - avgCongestion) * 2.0f;
if (green > 1.0f)
green = 1.0f;
green *= 255.0;
pixmap.fill(QColor(int(red), int(green), 0));
statusSquare->setPixmap(pixmap);
congestionArray.emplace_back(avgCongestion);
}
lastCongestion = congestion;
if (update) {
if (congestionOverTime <= excellentThreshold + EPSILON)
statusWidget->ui->statusIcon->setPixmap(
excellentPixmap);
else if (congestionOverTime <= goodThreshold)
statusWidget->ui->statusIcon->setPixmap(goodPixmap);
else if (congestionOverTime <= mediocreThreshold)
statusWidget->ui->statusIcon->setPixmap(mediocrePixmap);
else if (congestionOverTime <= badThreshold)
statusWidget->ui->statusIcon->setPixmap(badPixmap);
firstCongestionUpdate = false;
}
}
void OBSBasicStatusBar::OBSOutputReconnect(void *data, calldata_t *params)
@@ -395,7 +425,7 @@ void OBSBasicStatusBar::ReconnectClear()
{
retries = 0;
reconnectTimeout = 0;
bitrateUpdateSeconds = -1;
seconds = -1;
lastBytesSent = 0;
lastBytesSentTime = os_gettime_ns();
delaySecTotal = 0;
@@ -414,6 +444,8 @@ void OBSBasicStatusBar::ReconnectSuccess()
if (streamOutput) {
delaySecTotal = obs_output_get_active_delay(streamOutput);
UpdateDelayMsg();
disconnected = false;
firstCongestionUpdate = true;
}
}
@@ -518,11 +550,12 @@ void OBSBasicStatusBar::RecordingStopped()
void OBSBasicStatusBar::RecordingPaused()
{
QString text = recordTime->text() + QStringLiteral(" (PAUSED)");
recordTime->setText(text);
QString text = statusWidget->ui->recordTime->text() +
QStringLiteral(" (PAUSED)");
statusWidget->ui->recordTime->setText(text);
if (recordOutput) {
recordIcon->setPixmap(recordingPausePixmap);
statusWidget->ui->recordIcon->setPixmap(recordingPausePixmap);
streamPauseIconToggle = true;
}
}
@@ -530,6 +563,53 @@ void OBSBasicStatusBar::RecordingPaused()
void OBSBasicStatusBar::RecordingUnpaused()
{
if (recordOutput) {
recordIcon->setPixmap(recordingActivePixmap);
statusWidget->ui->recordIcon->setPixmap(recordingActivePixmap);
}
}
static QPixmap GetPixmap(const QString &filename)
{
bool darkTheme = obs_frontend_is_theme_dark();
QString path;
if (darkTheme) {
std::string darkPath;
QString themePath = QString("themes/Dark/") + filename;
GetDataFilePath(QT_TO_UTF8(themePath), darkPath);
path = QT_UTF8(darkPath.c_str());
} else {
path = QString(":/res/images/" + filename);
}
return QIcon(path).pixmap(QSize(16, 16));
}
void OBSBasicStatusBar::UpdateIcons()
{
disconnectedPixmap = GetPixmap("network-disconnected.svg");
inactivePixmap = GetPixmap("network-inactive.svg");
streamingInactivePixmap = GetPixmap("streaming-inactive.svg");
recordingInactivePixmap = GetPixmap("recording-inactive.svg");
recordingPauseInactivePixmap =
GetPixmap("recording-pause-inactive.svg");
bool streaming = obs_frontend_streaming_active();
if (!streaming) {
statusWidget->ui->streamIcon->setPixmap(
streamingInactivePixmap);
statusWidget->ui->statusIcon->setPixmap(inactivePixmap);
} else {
if (disconnected)
statusWidget->ui->statusIcon->setPixmap(
disconnectedPixmap);
}
bool recording = obs_frontend_recording_active();
if (!recording)
statusWidget->ui->recordIcon->setPixmap(
recordingInactivePixmap);
}

View File

@@ -3,30 +3,39 @@
#include <QStatusBar>
#include <QPointer>
#include <QTimer>
#include <util/platform.h>
#include <obs.h>
#include <memory>
class QLabel;
class Ui_StatusBarWidget;
class StatusBarWidget : public QWidget {
Q_OBJECT
friend class OBSBasicStatusBar;
private:
std::unique_ptr<Ui_StatusBarWidget> ui;
public:
StatusBarWidget(QWidget *parent = nullptr);
~StatusBarWidget();
};
class OBSBasicStatusBar : public QStatusBar {
Q_OBJECT
private:
QLabel *delayInfo;
QLabel *droppedFrames;
QLabel *streamIcon;
QLabel *streamTime;
QLabel *recordTime;
QLabel *recordIcon;
QLabel *cpuUsage;
QLabel *kbps;
QLabel *statusSquare;
StatusBarWidget *statusWidget = nullptr;
obs_output_t *streamOutput = nullptr;
obs_output_t *recordOutput = nullptr;
bool active = false;
bool overloadedNotify = true;
bool streamPauseIconToggle = false;
bool disconnected = false;
bool firstCongestionUpdate = false;
std::vector<float> congestionArray;
int retries = 0;
int totalStreamSeconds = 0;
@@ -42,14 +51,16 @@ private:
int startTotalFrameCount = 0;
int lastSkippedFrameCount = 0;
int bitrateUpdateSeconds = 0;
int seconds = 0;
uint64_t lastBytesSent = 0;
uint64_t lastBytesSentTime = 0;
QPixmap transparentPixmap;
QPixmap greenPixmap;
QPixmap grayPixmap;
QPixmap redPixmap;
QPixmap excellentPixmap;
QPixmap goodPixmap;
QPixmap mediocrePixmap;
QPixmap badPixmap;
QPixmap disconnectedPixmap;
QPixmap inactivePixmap;
QPixmap recordingActivePixmap;
QPixmap recordingPausePixmap;
@@ -81,6 +92,8 @@ private slots:
void ReconnectSuccess();
void UpdateStatusBar();
void UpdateCPUUsage();
void UpdateCurrentFPS();
void UpdateIcons();
public:
OBSBasicStatusBar(QWidget *parent);