[vlc-commits] [Git][videolan/vlc][master] 10 commits: qt: Create QmlTrackMenu(s)
Felix Paul Kühne (@fkuehne)
gitlab at videolan.org
Sat May 14 10:47:17 UTC 2022
Felix Paul Kühne pushed to branch master at VideoLAN / VLC
Commits:
1191b4ba by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qt: Create QmlTrackMenu(s)
This patch contains the three QmlMenu(s) required for the Tracks panel:
QmlTrackMenu, QmlSubtitleMenu and QmlAudioMenu. The video tracks do not
require a dedicated menu for now.
- - - - -
29e4b3f9 by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml: Update playback speed Popup implementation
- - - - -
709290ed by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml: Create TracksPage
- - - - -
4bf7b4b6 by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml: Create TracksPageSpeed
- - - - -
9e4eaa74 by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml: Create TracksPageSubtitle
- - - - -
59a815b7 by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml: Create TracksPageAudio
- - - - -
49bba44e by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qt/VLCIcons: Add the 'expand' icon
- - - - -
21534c39 by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml/LanguageMenu: Revamp implementation
- - - - -
fb58afc9 by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml/SpinBox(s): Update the 'visualFocus' implementation
- - - - -
3203bfe1 by Benjamin Arnaud at 2022-05-14T10:33:17+00:00
qml: Rename LanguageMenu to TracksMenu
- - - - -
20 changed files:
- modules/gui/qt/Makefile.am
- modules/gui/qt/maininterface/mainui.cpp
- modules/gui/qt/menus/qml_menu_wrapper.cpp
- modules/gui/qt/menus/qml_menu_wrapper.hpp
- modules/gui/qt/pixmaps/VLCIcons.json
- modules/gui/qt/pixmaps/VLCIcons.ttf
- + modules/gui/qt/pixmaps/expand.svg
- modules/gui/qt/player/qml/PlaybackSpeed.qml
- modules/gui/qt/player/qml/LanguageMenu.qml â modules/gui/qt/player/qml/TracksMenu.qml
- + modules/gui/qt/player/qml/TracksPage.qml
- + modules/gui/qt/player/qml/TracksPageAudio.qml
- + modules/gui/qt/player/qml/TracksPageSpeed.qml
- + modules/gui/qt/player/qml/TracksPageSubtitle.qml
- modules/gui/qt/player/qml/controlbarcontrols/LangButton.qml
- modules/gui/qt/player/qml/controlbarcontrols/PlaybackSpeedButton.qml
- modules/gui/qt/style/VLCIcons.qml
- modules/gui/qt/vlc.qrc
- modules/gui/qt/widgets/qml/SpinBoxExt.qml
- modules/gui/qt/widgets/qml/TransparentSpinBox.qml
- po/POTFILES.in
Changes:
=====================================
modules/gui/qt/Makefile.am
=====================================
@@ -806,7 +806,6 @@ libqt_plugin_la_QML = \
gui/qt/player/qml/qmldir \
gui/qt/player/qml/ControlBar.qml \
gui/qt/player/qml/ControlbarControls.qml \
- gui/qt/player/qml/LanguageMenu.qml \
gui/qt/player/qml/PlaybackSpeed.qml \
gui/qt/player/qml/MiniPlayer.qml \
gui/qt/player/qml/PIPPlayer.qml \
@@ -819,6 +818,11 @@ libqt_plugin_la_QML = \
gui/qt/player/qml/SliderBar.qml \
gui/qt/player/qml/TopBar.qml \
gui/qt/player/qml/TrackInfo.qml \
+ gui/qt/player/qml/TracksMenu.qml \
+ gui/qt/player/qml/TracksPage.qml \
+ gui/qt/player/qml/TracksPageAudio.qml \
+ gui/qt/player/qml/TracksPageSpeed.qml \
+ gui/qt/player/qml/TracksPageSubtitle.qml \
gui/qt/player/qml/ControlLayout.qml \
gui/qt/player/qml/controlbarcontrols/HighResolutionTimeWidget.qml \
gui/qt/player/qml/controlbarcontrols/ArtworkInfoWidget.qml \
=====================================
modules/gui/qt/maininterface/mainui.cpp
=====================================
@@ -267,6 +267,8 @@ void MainUI::registerQMLTypes()
qmlRegisterType<QmlMenuBar>( uri, versionMajor, versionMinor, "QmlMenuBar" );
qmlRegisterType<QmlBookmarkMenu>( uri, versionMajor, versionMinor, "QmlBookmarkMenu" );
qmlRegisterType<QmlRendererMenu>( uri, versionMajor, versionMinor, "QmlRendererMenu" );
+ qmlRegisterType<QmlSubtitleMenu>( uri, versionMajor, versionMinor, "QmlSubtitleMenu" );
+ qmlRegisterType<QmlAudioMenu>( uri, versionMajor, versionMinor, "QmlAudioMenu" );
qmlRegisterType<NetworkMediaContextMenu>( uri, versionMajor, versionMinor, "NetworkMediaContextMenu" );
qmlRegisterType<NetworkDeviceContextMenu>( uri, versionMajor, versionMinor, "NetworkDeviceContextMenu" );
qmlRegisterType<PlaylistContextMenu>( uri, versionMajor, versionMinor, "PlaylistContextMenu" );
=====================================
modules/gui/qt/menus/qml_menu_wrapper.cpp
=====================================
@@ -516,6 +516,79 @@ bool QmlMenuPositioner::eventFilter(QObject * object, QEvent * event)
m_positioner.popup(m_menu.get(), position, above);
}
+// Tracks
+
+// QmlTrackMenu
+
+/* explicit */ QmlTrackMenu::QmlTrackMenu(QObject * parent) : QObject(parent) {}
+
+// Interface
+
+/* Q_INVOKABLE */ void QmlTrackMenu::popup(const QPoint & position)
+{
+ m_menu = std::make_unique<QMenu>();
+
+ beforePopup(m_menu.get());
+
+ m_menu->popup(position);
+}
+
+// QmlSubtitleMenu
+
+/* explicit */ QmlSubtitleMenu::QmlSubtitleMenu(QObject * parent) : QmlTrackMenu(parent) {}
+
+// Protected QmlTrackMenu implementation
+
+void QmlSubtitleMenu::beforePopup(QMenu * menu) /* override */
+{
+ menu->addAction(qtr("Open file"), this, [this]()
+ {
+ emit triggered(Open);
+ });
+
+ menu->addAction(QIcon(":/sync.svg"), qtr("Synchronize"), this, [this]()
+ {
+ emit triggered(Synchronize);
+ });
+
+ menu->addAction(QIcon(":/download.svg"), qtr("Search online"), this, [this]()
+ {
+ emit triggered(Download);
+ });
+
+ menu->addSeparator();
+
+ QAction * action = menu->addAction(qtr("Select multiple"), this, [this]()
+ {
+ TrackListModel * tracks = this->m_player->getSubtitleTracks();
+
+ tracks->setMultiSelect(!(tracks->getMultiSelect()));
+ });
+
+ action->setCheckable(true);
+
+ action->setChecked(m_player->getSubtitleTracks()->getMultiSelect());
+}
+
+// QmlAudioMenu
+
+/* explicit */ QmlAudioMenu::QmlAudioMenu(QObject * parent) : QmlTrackMenu(parent) {}
+
+// Protected QmlTrackMenu implementation
+
+void QmlAudioMenu::beforePopup(QMenu * menu) /* override */
+{
+ menu->addAction(qtr("Open file"), this, [this]()
+ {
+ emit triggered(Open);
+ });
+
+ menu->addAction(QIcon(":/sync.svg"), qtr("Synchronize"), this, [this]()
+ {
+ emit triggered(Synchronize);
+ });
+}
+
BaseMedialibMenu::BaseMedialibMenu(QObject* parent)
: QObject(parent)
{}
=====================================
modules/gui/qt/menus/qml_menu_wrapper.hpp
=====================================
@@ -237,6 +237,62 @@ private:
std::unique_ptr<RendererMenu> m_menu;
};
+// Tracks
+
+class QmlTrackMenu : public QObject
+{
+ Q_OBJECT
+
+public: // Enums
+ enum Action
+ {
+ Open,
+ Synchronize,
+ Download
+ };
+
+ Q_ENUM(Action)
+
+public:
+ QmlTrackMenu(QObject * parent = nullptr);
+
+public: // Interface
+ Q_INVOKABLE void popup(const QPoint & position);
+
+protected: // Abstract functions
+ virtual void beforePopup(QMenu * menu) = 0;
+
+signals:
+ void triggered(Action action);
+
+private:
+ std::unique_ptr<QMenu> m_menu;
+};
+
+class QmlSubtitleMenu : public QmlTrackMenu
+{
+ Q_OBJECT
+
+ SIMPLE_MENU_PROPERTY(PlayerController *, player, nullptr)
+
+public:
+ QmlSubtitleMenu(QObject * parent = nullptr);
+
+protected: // QmlTrackMenu implementation
+ void beforePopup(QMenu * menu) override;
+};
+
+class QmlAudioMenu : public QmlTrackMenu
+{
+ Q_OBJECT
+
+public:
+ QmlAudioMenu(QObject * parent = nullptr);
+
+protected: // QmlTrackMenu implementation
+ void beforePopup(QMenu * menu) override;
+};
+
class BaseMedialibMenu : public QObject
{
Q_OBJECT
@@ -423,7 +479,6 @@ private:
std::unique_ptr<QMenu> m_menu;
};
-
class PlaylistContextMenu : public QObject {
Q_OBJECT
SIMPLE_MENU_PROPERTY(vlc::playlist::PlaylistListModel*, model, nullptr)
=====================================
modules/gui/qt/pixmaps/VLCIcons.json
=====================================
@@ -153,6 +153,7 @@
{"key":"play_outline", "path": "./play_outline.svg"},
{"key":"enqueue", "path": "./enqueue.svg"},
{"key":"back", "path": "./back.svg"},
+ {"key":"expand", "path": "./expand.svg"},
{"key":"history", "path": "./history.svg"},
{"key": "window_close", "path": "./topbar/window_close.svg" },
{"key": "window_maximize", "path": "./topbar/window_maximize.svg" },
=====================================
modules/gui/qt/pixmaps/VLCIcons.ttf
=====================================
Binary files a/modules/gui/qt/pixmaps/VLCIcons.ttf and b/modules/gui/qt/pixmaps/VLCIcons.ttf differ
=====================================
modules/gui/qt/pixmaps/expand.svg
=====================================
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48"><path d="m10 15.5-2 1.7 16 15.3 16-15.3-2-1.7-14 13.3z"/></svg>
\ No newline at end of file
=====================================
modules/gui/qt/player/qml/PlaybackSpeed.qml
=====================================
@@ -26,168 +26,151 @@ import org.videolan.vlc 0.1
import "qrc:///style/"
import "qrc:///widgets/" as Widgets
-Popup {
+// FIXME: We should refactor this item with a list of presets.
+ColumnLayout {
id: root
property VLCColors colors: VLCStyle.nightColors
- height: implicitHeight
- width: implicitWidth
- padding: VLCStyle.margin_small
+ Widgets.ListLabel {
+ text: I18n.qtr("Playback Speed")
+ color: root.colors.text
+ font.pixelSize: VLCStyle.fontSize_large
- // Popup.CloseOnPressOutside doesn't work with non-model Popup on Qt < 5.15
- closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
- modal: true
- Overlay.modal: Rectangle {
- color: "transparent"
- }
+ Layout.fillWidth: true
+ Layout.bottomMargin: VLCStyle.margin_xsmall
- background: Rectangle {
- color: colors.bg
- opacity: .85
+ Layout.alignment: Qt.AlignTop
}
- contentItem: ColumnLayout {
- spacing: VLCStyle.margin_xsmall
-
- Widgets.ListLabel {
- text: I18n.qtr("Playback Speed")
- color: root.colors.text
- font.pixelSize: VLCStyle.fontSize_large
-
- Layout.fillWidth: true
- Layout.bottomMargin: VLCStyle.margin_xsmall
- }
-
- Slider {
- id: speedSlider
-
- // '_inhibitPlayerUpdate' is used to guard against double update
- // initialize with true so that we don't update the Player till
- // we initialize `value` property
- property bool _inhibitPlayerUpdate: true
-
- from: 0.25
- to: 4
- clip: true
- implicitHeight: VLCStyle.heightBar_small
-
- Navigation.parentItem: root.Navigation.parentItem
- Navigation.downItem: resetButton
- Keys.priority: Keys.AfterItem
- Keys.onPressed: Navigation.defaultKeyAction(event)
-
- background: Rectangle {
- x: speedSlider.leftPadding
- y: speedSlider.topPadding + speedSlider.availableHeight / 2 - height / 2
- implicitWidth: 200
- implicitHeight: 4
- width: speedSlider.availableWidth
- height: implicitHeight
+ Slider {
+ id: speedSlider
+
+ // '_inhibitPlayerUpdate' is used to guard against double update
+ // initialize with true so that we don't update the Player till
+ // we initialize `value` property
+ property bool _inhibitPlayerUpdate: true
+
+ from: 0.25
+ to: 4
+ clip: true
+ implicitHeight: VLCStyle.heightBar_small
+
+ Navigation.parentItem: root
+ Navigation.downItem: resetButton
+ Keys.priority: Keys.AfterItem
+ Keys.onPressed: Navigation.defaultKeyAction(event)
+
+ background: Rectangle {
+ x: speedSlider.leftPadding
+ y: speedSlider.topPadding + speedSlider.availableHeight / 2 - height / 2
+ implicitWidth: 200
+ implicitHeight: 4
+ width: speedSlider.availableWidth
+ height: implicitHeight
+ radius: 2
+ color: root.colors.bgAlt
+
+ Rectangle {
+ width: speedSlider.visualPosition * parent.width
+ height: parent.height
radius: 2
- color: root.colors.bgAlt
-
- Rectangle {
- width: speedSlider.visualPosition * parent.width
- height: parent.height
- radius: 2
- color: (speedSlider.visualFocus || speedSlider.pressed)
- ? root.colors.accent
- : root.colors.text
- }
+ color: (speedSlider.visualFocus || speedSlider.pressed)
+ ? root.colors.accent
+ : root.colors.text
}
+ }
- handle: Rectangle {
- x: speedSlider.leftPadding + speedSlider.visualPosition * (speedSlider.availableWidth - width)
- y: speedSlider.topPadding + speedSlider.availableHeight / 2 - height / 2
- width: speedSlider.implicitHeight
- height: speedSlider.implicitHeight
- radius: speedSlider.implicitHeight
- color: (speedSlider.visualFocus || speedSlider.pressed) ? root.colors.accent : root.colors.text
- }
+ handle: Rectangle {
+ x: speedSlider.leftPadding + speedSlider.visualPosition * (speedSlider.availableWidth - width)
+ y: speedSlider.topPadding + speedSlider.availableHeight / 2 - height / 2
+ width: speedSlider.implicitHeight
+ height: speedSlider.implicitHeight
+ radius: speedSlider.implicitHeight
+ color: (speedSlider.visualFocus || speedSlider.pressed) ? root.colors.accent : root.colors.text
+ }
- onValueChanged: {
- if (_inhibitPlayerUpdate)
- return
- Player.rate = value
- }
+ onValueChanged: {
+ if (_inhibitPlayerUpdate)
+ return
+ Player.rate = value
+ }
- function _updateFromPlayer() {
- _inhibitPlayerUpdate = true
- value = Player.rate
- _inhibitPlayerUpdate = false
- }
+ function _updateFromPlayer() {
+ _inhibitPlayerUpdate = true
+ value = Player.rate
+ _inhibitPlayerUpdate = false
+ }
- Connections {
- target: Player
- onRateChanged: speedSlider._updateFromPlayer()
- }
+ Connections {
+ target: Player
+ onRateChanged: speedSlider._updateFromPlayer()
+ }
- Layout.fillWidth: true
+ Layout.fillWidth: true
- Component.onCompleted: speedSlider._updateFromPlayer()
- }
+ Component.onCompleted: speedSlider._updateFromPlayer()
+ }
- RowLayout {
- id: buttonLayout
+ RowLayout {
+ id: buttonLayout
- spacing: 0
+ spacing: 0
- Navigation.parentItem: root.Navigation.parentItem
- Navigation.upItem: speedSlider
+ Navigation.parentItem: root
+ Navigation.upItem: speedSlider
- Widgets.IconControlButton {
- id: slowerButton
+ Widgets.IconControlButton {
+ id: slowerButton
- iconText: VLCIcons.slower
- colors: root.colors
+ iconText: VLCIcons.slower
+ colors: root.colors
- Navigation.parentItem: buttonLayout
- Navigation.rightItem: resetButton
+ Navigation.parentItem: buttonLayout
+ Navigation.rightItem: resetButton
- onClicked: speedSlider.decrease()
- }
+ onClicked: speedSlider.decrease()
+ }
- Item {
- Layout.fillWidth: true
- }
+ Item {
+ Layout.fillWidth: true
+ }
- Widgets.IconControlButton {
- id: resetButton
+ Widgets.IconControlButton {
+ id: resetButton
- colors: root.colors
+ colors: root.colors
- Navigation.parentItem: buttonLayout
- Navigation.leftItem: slowerButton
- Navigation.rightItem: fasterButton
+ Navigation.parentItem: buttonLayout
+ Navigation.leftItem: slowerButton
+ Navigation.rightItem: fasterButton
- onClicked: speedSlider.value = 1.0
+ onClicked: speedSlider.value = 1.0
- focus: true
+ focus: true
- T.Label {
- anchors.centerIn: parent
- font.pixelSize: VLCStyle.fontSize_normal
- text: I18n.qtr("1x")
- color: resetButton.background.foregroundColor // IconToolButton.background is a AnimatedBackground
- }
+ T.Label {
+ anchors.centerIn: parent
+ font.pixelSize: VLCStyle.fontSize_normal
+ text: I18n.qtr("1x")
+ color: resetButton.background.foregroundColor // IconToolButton.background is a AnimatedBackground
}
+ }
- Item {
- Layout.fillWidth: true
- }
+ Item {
+ Layout.fillWidth: true
+ }
- Widgets.IconControlButton {
- id: fasterButton
+ Widgets.IconControlButton {
+ id: fasterButton
- iconText: VLCIcons.faster
- colors: root.colors
+ iconText: VLCIcons.faster
+ colors: root.colors
- Navigation.parentItem: buttonLayout
- Navigation.leftItem: resetButton
+ Navigation.parentItem: buttonLayout
+ Navigation.leftItem: resetButton
- onClicked: speedSlider.increase()
- }
+ onClicked: speedSlider.increase()
}
}
}
=====================================
modules/gui/qt/player/qml/LanguageMenu.qml â modules/gui/qt/player/qml/TracksMenu.qml
=====================================
@@ -28,8 +28,11 @@ import "qrc:///style/"
import "qrc:///widgets/" as Widgets
import "qrc:///util/" as Util
+// FIXME: Keyboard navigation needs to be fixed for this Popup.
T.Popup {
- id: control
+ id: root
+
+ // Settings
height: VLCStyle.dp(296, VLCStyle.scale)
width: rootPlayer.width
@@ -37,16 +40,33 @@ T.Popup {
// Popup.CloseOnPressOutside doesn't work with non-model Popup on Qt < 5.15
closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
modal: true
- T.Overlay.modal: Rectangle {
- color: "transparent"
+
+ // Animations
+
+ Behavior on width {
+ SmoothedAnimation {
+ duration: VLCStyle.ms64
+ easing.type: Easing.InOutSine
+ }
+ }
+
+ // Children
+
+ T.Overlay.modal: null
+
+ background: Rectangle {
+ opacity: 0.8
+ color: "#212121"
}
contentItem: StackView {
id: view
- initialItem: frontPage
- clip: true
focus: true
+ clip: true
+
+ initialItem: frontPage
+
onCurrentItemChanged: currentItem.forceActiveFocus()
@@ -84,103 +104,81 @@ T.Popup {
}
}
- background: Rectangle {
- color: "#212121"
- opacity: .8
- }
-
- function _updateWidth(isFirstPage) {
- if (isFirstPage)
- control.width = Qt.binding(function () {
- return rootPlayer.width
- })
- else
- control.width = Qt.binding(function () {
- return Math.min(VLCStyle.dp(624, VLCStyle.scale),
- rootPlayer.width)
- })
- }
-
- Behavior on width {
- SmoothedAnimation {
- duration: VLCStyle.ms64
- easing.type: Easing.InOutSine
- }
- }
-
Component {
id: frontPage
RowLayout {
- id: frontPageRoot
+ id: frontRoot
+
+ property var currentItem: StackView.view.currentItem
spacing: 0
+
focus: true
- onActiveFocusChanged: if (activeFocus) btnsCol.forceActiveFocus()
+
+ onActiveFocusChanged: if (activeFocus) column.forceActiveFocus()
+
+ Connections {
+ target: frontRoot.StackView.view
+
+ onCurrentItemChanged: {
+ if (currentItem instanceof TracksPage)
+ root.width = Qt.binding(function () {
+ return Math.min(currentItem.preferredWidth, rootPlayer.width)
+ })
+ else
+ root.width = Qt.binding(function () { return rootPlayer.width })
+ }
+ }
+
+ Connections {
+ target: (currentItem && currentItem instanceof TracksPage) ? currentItem : null
+
+ onBackRequested: frontRoot.StackView.view.pop()
+ }
Widgets.NavigableCol {
- id: btnsCol
+ id: column
focus: true
+
Layout.preferredWidth: VLCStyle.dp(72, VLCStyle.scale)
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
Layout.topMargin: VLCStyle.margin_large
- Navigation.rightItem: tracksListRow
+
+ Navigation.rightItem: row
model: [{
- "icon": VLCIcons.download,
- "tooltip": I18n.qtr("Download Subtitles"),
- "component": undefined
- }, {
- "icon": VLCIcons.time,
- "tooltip": I18n.qtr("Delay"),
- "component": delayPage
- }, {
- "icon": VLCIcons.sync,
- "tooltip": I18n.qtr("Sync"),
- "component": syncPage
- }, {
- "icon": VLCIcons.multiselect,
- "tooltip": I18n.qtr("Select Multiple Subtitles"),
- "component": undefined
- }]
+ "tooltip": I18n.qtr("Playback Speed"),
+ "source": "qrc:///player/TracksPageSpeed.qml"
+ }]
delegate: Widgets.IconTrackButton {
- iconText: modelData.icon
+ size: (index === 0) ? VLCStyle.dp(24, VLCStyle.scale)
+ : VLCStyle.dp(40, VLCStyle.scale)
- size: VLCStyle.dp(40, VLCStyle.scale)
- x: (btnsCol.width - width) / 2
- highlighted: index === 3
- && Player.subtitleTracks.multiSelect
+ x: (column.width - width) / 2
+
+ iconText: (index === 0) ? I18n.qtr("%1x").arg(+Player.rate.toFixed(2))
+ : modelData.icon
T.ToolTip.visible: (hovered || activeFocus)
T.ToolTip.text: modelData.tooltip
T.ToolTip.delay: 1000
- Navigation.parentItem: btnsCol
-
- onClicked: {
- if (index === 0) {
- Player.openVLsub()
- } else if (index === 3) {
- Player.subtitleTracks.multiSelect = !Player.subtitleTracks.multiSelect
- focus = false
- } else {
- control._updateWidth(false)
- frontPageRoot.StackView.view.push(
- modelData.component)
- }
- }
+ Navigation.parentItem: column
+
+ onClicked: frontRoot.StackView.view.push(modelData.source)
}
}
Widgets.NavigableRow {
- id: tracksListRow
+ id: row
Layout.fillHeight: true
Layout.fillWidth: true
- Navigation.leftItem: btnsCol
+ Navigation.leftItem: column
model: [{
"title": I18n.qtr("Subtitle"),
@@ -198,8 +196,9 @@ T.Popup {
property var tracksModel: modelData.tracksModel
- width: tracksListRow.width / 3
- height: tracksListRow.height
+ width: row.width / 3
+ height: row.height
+
focus: true
onActiveFocusChanged: if (activeFocus) tracksList.forceActiveFocus(focusReason)
@@ -224,44 +223,52 @@ T.Popup {
width: tracksListContainer.width
height: implicitHeight
- focus: true
+
+ padding: VLCStyle.margin_xsmall
topPadding: VLCStyle.margin_large
leftPadding: VLCStyle.margin_xxlarge + separator.width
- padding: VLCStyle.margin_xsmall
+
+ focus: true
+
clip: true
Widgets.SubtitleLabel {
id: titleText
+ width: parent.width - button.width - parent.leftPadding
+ - parent.rightPadding
+
text: modelData.title
color: "white"
- width: parent.width - addBtn.width
- - parent.leftPadding - parent.rightPadding
}
Widgets.IconTrackButton {
- id: addBtn
+ id: button
- iconText: VLCIcons.add
size: VLCStyle.icon_normal
+
focus: true
+
+ iconText: (index === 2) ? VLCIcons.add
+ : VLCIcons.expand
+
+ Navigation.parentItem: tracksListContainer
+ Navigation.downItem: tracksList
+
onClicked: {
switch (index) {
case 0:
- DialogsProvider.loadSubtitlesFile()
+ menuSubtitle.popup(mapToGlobal(0, height))
break
case 1:
- DialogsProvider.loadAudioFile()
+ menuAudio.popup(mapToGlobal(0, height))
break
case 2:
DialogsProvider.loadVideoFile()
break
}
}
-
- Navigation.parentItem: tracksListContainer
- Navigation.downItem: tracksList
}
}
@@ -276,7 +283,7 @@ T.Popup {
clip: true
Navigation.parentItem: tracksListContainer
- Navigation.upItem: addBtn
+ Navigation.upItem: button
Keys.priority: Keys.AfterItem
Keys.onPressed: Navigation.defaultKeyAction(event)
@@ -308,373 +315,33 @@ T.Popup {
}
}
- Component {
- id: delayPage
+ QmlSubtitleMenu {
+ id: menuSubtitle
- RowLayout {
- id: delayPageRoot
-
- spacing: 0
- focus: true
- onActiveFocusChanged: if (activeFocus) backBtn.forceActiveFocus()
+ player: Player
- Item {
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- Layout.preferredWidth: VLCStyle.dp(72, VLCStyle.scale)
- Layout.topMargin: VLCStyle.margin_large
- Layout.fillHeight: true
-
- Widgets.IconTrackButton {
- id: backBtn
-
- anchors.horizontalCenter: parent.horizontalCenter
- size: VLCStyle.dp(36, VLCStyle.scale)
- iconText: VLCIcons.back
-
- onClicked: {
- control._updateWidth(true)
- delayPageRoot.StackView.view.pop()
- }
- Navigation.rightItem: audioDelaySpin
- }
+ onTriggered: {
+ if (action === QmlSubtitleMenu.Open) {
+ DialogsProvider.loadSubtitlesFile()
}
-
- Rectangle {
- Layout.preferredWidth: VLCStyle.margin_xxxsmall
- Layout.fillHeight: true
- color: "white"
- opacity: .1
+ else if (action === QmlSubtitleMenu.Synchronize) {
+ contentItem.currentItem.StackView.view.push("qrc:///player/TracksPageSubtitle.qml")
}
-
- ColumnLayout {
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- Layout.leftMargin: VLCStyle.margin_xxlarge
- Layout.rightMargin: VLCStyle.margin_xxlarge
- Layout.topMargin: VLCStyle.margin_large
- spacing: VLCStyle.margin_xxsmall
-
- Navigation.leftItem: backBtn
-
- Widgets.SubtitleLabel {
- Layout.fillWidth: true
- text: I18n.qtr("Audio track synchronization")
- color: "white"
- }
- RowLayout {
- Layout.fillWidth: true
- spacing: VLCStyle.margin_xsmall
-
- Widgets.MenuCaption {
- text: I18n.qtr("Audio track delay")
- color: "white"
-
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter
- }
-
- Widgets.TransparentSpinBox {
- id: audioDelaySpin
-
- property bool inhibitUpdate: true
-
- textFromValue: function (value, locale) {
- return I18n.qtr("%1 ms").arg(
- Number(value).toLocaleString(locale,
- 'f', 0))
- }
- valueFromText: function (text, locale) {
- return Number.fromLocaleString(
- locale, text.substring(0,
- text.length - 3))
- }
- stepSize: 50
- from: -10000
-
- Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
-
- onValueChanged: {
- if (inhibitUpdate)
- return
- Player.audioDelayMS = value
- }
-
- Component.onCompleted: {
- value = Player.audioDelayMS
- inhibitUpdate = false
- }
-
- Connections {
- target: Player
- onAudioDelayChanged: {
- inhibitUpdate = true
- value = Player.audioDelayMS
- inhibitUpdate = false
- }
- }
-
- Navigation.rightItem: audioDelaySpinReset
- }
-
- Widgets.ActionButtonOverlay {
- id: audioDelaySpinReset
-
- text: I18n.qtr("Reset")
-
- onClicked: audioDelaySpin.value = 0
- Navigation.leftItem: audioDelaySpin
- Navigation.rightItem: primarySubSpin
- Navigation.downItem: primarySubSpinReset
- }
- }
-
- Widgets.SubtitleLabel {
- Layout.fillWidth: true
- Layout.topMargin: VLCStyle.margin_large
- text: I18n.qtr("Subtitle synchronization")
- color: "white"
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: VLCStyle.margin_xsmall
-
- Widgets.MenuCaption {
- text: I18n.qtr("Primary subtitle delay")
- color: "white"
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter
- }
-
- Widgets.TransparentSpinBox {
- id: primarySubSpin
-
- property bool inhibitUpdate: true
-
- textFromValue: audioDelaySpin.textFromValue
- valueFromText: audioDelaySpin.valueFromText
- stepSize: 50
- from: -10000
-
- Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
-
- onValueChanged: {
- if (inhibitUpdate)
- return
- Player.subtitleDelayMS = value
- }
-
- Component.onCompleted: {
- value = Player.subtitleDelayMS
- inhibitUpdate = false
- }
-
- Connections {
- target: Player
- onSubtitleDelayChanged: {
- inhibitUpdate = true
- value = Player.subtitleDelayMS
- inhibitUpdate = false
- }
- }
-
- Navigation.rightItem: primarySubSpinReset
- }
-
- Widgets.ActionButtonOverlay {
- id: primarySubSpinReset
-
- text: I18n.qtr("Reset")
- focus: true
- onClicked: primarySubSpin.value = 0
- Navigation.leftItem: primarySubSpin
- Navigation.rightItem: secondarySubSpin
- Navigation.upItem: audioDelaySpinReset
- Navigation.downItem: secondarySubSpinReset
- }
- }
-
- RowLayout {
- Layout.fillWidth: true
- spacing: VLCStyle.margin_xsmall
-
- Widgets.MenuCaption {
- text: I18n.qtr("Secondary subtitle delay")
- color: "white"
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter
- }
-
- Widgets.TransparentSpinBox {
- id: secondarySubSpin
-
- property bool inhibitUpdate: true
-
- textFromValue: primarySubSpin.textFromValue
- valueFromText: primarySubSpin.valueFromText
- stepSize: 50
- from: -10000
-
- Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
-
- onValueChanged: {
- if (inhibitUpdate)
- return
- Player.secondarySubtitleDelayMS = value
- }
-
- Component.onCompleted: {
- value = Player.secondarySubtitleDelayMS
- inhibitUpdate = false
- }
-
- Connections {
- target: Player
- onSecondarySubtitleDelayChanged: {
- inhibitUpdate = true
- value = Player.secondarySubtitleDelayMS
- inhibitUpdate = false
- }
- }
-
- Navigation.rightItem: secondarySubSpinReset
- }
-
- Widgets.ActionButtonOverlay {
- id: secondarySubSpinReset
-
- text: I18n.qtr("Reset")
- onClicked: secondarySubSpin.value = 0
- Navigation.leftItem: secondarySubSpin
- Navigation.upItem: primarySubSpinReset
- }
- }
+ else if (action === QmlSubtitleMenu.Download) {
+ Player.openVLsub()
}
}
}
- Component {
- id: syncPage
-
- RowLayout {
- id: syncPageRoot
-
- spacing: 0
- focus: true
- onActiveFocusChanged: if (activeFocus) backBtn.forceActiveFocus()
-
- Item {
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- Layout.preferredWidth: VLCStyle.dp(72, VLCStyle.scale)
- Layout.topMargin: VLCStyle.margin_large
- Layout.fillHeight: true
-
- Widgets.IconTrackButton {
- id: backBtn
+ QmlAudioMenu {
+ id: menuAudio
- anchors.horizontalCenter: parent.horizontalCenter
- size: VLCStyle.dp(36, VLCStyle.scale)
- iconText: VLCIcons.back
-
- onClicked: {
- control._updateWidth(true)
- syncPageRoot.StackView.view.pop()
- }
- Navigation.rightItem: subSpeedSpin
- }
+ onTriggered: {
+ if (action === QmlSubtitleMenu.Open) {
+ DialogsProvider.loadAudioFile()
}
-
- Rectangle {
- Layout.preferredWidth: VLCStyle.margin_xxxsmall
- Layout.fillHeight: true
- color: "white"
- opacity: .1
- }
-
- ColumnLayout {
- id: subtitleSyncLayout
-
- Layout.fillWidth: true
- Layout.fillHeight: true
- Layout.alignment: Qt.AlignLeft | Qt.AlignTop
- Layout.leftMargin: VLCStyle.margin_xxlarge
- Layout.rightMargin: VLCStyle.margin_xxlarge
- Layout.topMargin: VLCStyle.margin_large
- spacing: VLCStyle.margin_xsmall
-
- Navigation.leftItem: backBtn
-
- Widgets.SubtitleLabel {
- Layout.fillWidth: true
- text: I18n.qtr("Subtitles")
- color: "white"
- }
- RowLayout {
- width: parent.width
- spacing: VLCStyle.margin_xsmall
-
- Widgets.MenuCaption {
- text: I18n.qtr("Subtitle Speed")
- color: "white"
- Layout.fillWidth: true
- Layout.alignment: Qt.AlignHCenter
- }
-
- Widgets.TransparentSpinBox {
- id: subSpeedSpin
-
- property bool inhibitUpdate: true
-
- stepSize: 1
- textFromValue: function (value, locale) {
- return I18n.qtr("%1 fps").arg(
- Number(value / 10).toLocaleString(
- locale, 'f', 3))
- }
- valueFromText: function (text, locale) {
- return Number.fromLocaleString(
- locale,
- text.substring(0, text.length - 4)) * 10
- }
-
- Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
-
- onValueChanged: {
- if (inhibitUpdate)
- return
- Player.subtitleFPS = value / 10
- }
-
- Component.onCompleted: {
- value = Player.subtitleFPS * 10
- inhibitUpdate = false
- }
-
- Connections {
- target: Player
- onSecondarySubtitleDelayChanged: {
- inhibitUpdate = true
- value = Player.subtitleFPS / 10
- inhibitUpdate = false
- }
- }
-
- Navigation.parentItem: subtitleSyncLayout
- Navigation.rightItem: subSpeedSpinReset
- }
-
- Widgets.ActionButtonOverlay {
- id: subSpeedSpinReset
-
- text: I18n.qtr("Reset")
- onClicked: subSpeedSpin.value = 10
-
-
- Navigation.parentItem: subtitleSyncLayout
- Navigation.leftItem: subSpeedSpin
- }
- }
+ else if (action === QmlSubtitleMenu.Synchronize) {
+ contentItem.currentItem.StackView.view.push("qrc:///player/TracksPageAudio.qml")
}
}
}
=====================================
modules/gui/qt/player/qml/TracksPage.qml
=====================================
@@ -0,0 +1,93 @@
+/*****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Benjamin Arnaud <bunjee at omega.gg>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+import QtQuick 2.11
+import QtQuick.Layouts 1.11
+
+import org.videolan.vlc 0.1
+
+import "qrc:///style/"
+import "qrc:///widgets/" as Widgets
+
+RowLayout {
+ id: root
+
+ // Properties
+
+ default property alias content: content.data
+
+ property int preferredWidth: VLCStyle.dp(512, VLCStyle.scale)
+
+ // Settings
+
+ spacing: 0
+
+ focus: true
+
+ Navigation.leftItem: button
+
+ // Signals
+
+ signal backRequested
+
+ // Children
+
+ Item {
+ Layout.preferredWidth: VLCStyle.dp(72, VLCStyle.scale)
+ Layout.fillHeight: true
+
+ Layout.topMargin: VLCStyle.margin_large
+
+ Layout.alignment: Qt.AlignLeft | Qt.AlignTop
+
+ Widgets.IconTrackButton {
+ id: button
+
+ anchors.horizontalCenter: parent.horizontalCenter
+
+ size: VLCStyle.dp(36, VLCStyle.scale)
+
+ iconText: VLCIcons.back
+
+ Navigation.parentItem: root
+ Navigation.rightItem: content
+
+ onClicked: root.backRequested()
+ }
+ }
+
+ Rectangle {
+ Layout.preferredWidth: VLCStyle.margin_xxxsmall
+ Layout.fillHeight: true
+
+ opacity: 0.1
+
+ color: "white"
+ }
+
+ FocusScope {
+ id: content
+
+ Layout.fillWidth: true
+ Layout.fillHeight: true
+
+ Layout.margins: VLCStyle.margin_large
+ }
+}
=====================================
modules/gui/qt/player/qml/TracksPageAudio.qml
=====================================
@@ -0,0 +1,127 @@
+/*****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Benjamin Arnaud <bunjee at omega.gg>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+import QtQuick 2.11
+import QtQuick.Layouts 1.11
+
+import org.videolan.vlc 0.1
+
+import "qrc:///style/"
+import "qrc:///widgets/" as Widgets
+
+TracksPage {
+ id: root
+
+ // Functions
+
+ function textFromValue(value, locale) {
+ return I18n.qtr("%1 ms").arg(Number(value).toLocaleString(locale, 'f', 0))
+ }
+
+ function valueFromText(text, locale) {
+ return Number.fromLocaleString(locale, text.substring(0, text.length - 3))
+ }
+
+ // Children
+
+ ColumnLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ spacing: VLCStyle.margin_xxsmall
+
+ Widgets.SubtitleLabel {
+ Layout.fillWidth: true
+
+ text: I18n.qtr("Audio track synchronization")
+
+ color: "white"
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ Layout.topMargin: VLCStyle.margin_large
+
+ spacing: VLCStyle.margin_xsmall
+
+ Widgets.MenuCaption {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+
+ text: I18n.qtr("Audio track delay")
+
+ color: "white"
+ }
+
+ Widgets.TransparentSpinBox {
+ id: spinBox
+
+ property bool update: false
+
+ Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
+
+ stepSize: 50
+ from: -10000
+
+ textFromValue: root.textFromValue
+ valueFromText: root.valueFromText
+
+ Navigation.parentItem: root
+ Navigation.rightItem: reset
+
+ Component.onCompleted: {
+ value = Player.audioDelayMS
+
+ update = true
+ }
+
+ onValueChanged: {
+ if (update === false)
+ return
+
+ Player.audioDelayMS = value
+ }
+
+ Connections {
+ target: Player
+
+ onAudioDelayChanged: {
+ spinBox.update = false
+
+ spinBox.value = Player.audioDelayMS
+
+ spinBox.update = true
+ }
+ }
+ }
+
+ Widgets.ActionButtonOverlay {
+ id: reset
+
+ text: I18n.qtr("Reset")
+
+ onClicked: spinBox.value = 0
+
+ Navigation.parentItem: root
+ Navigation.leftItem: spinBox
+ }
+ }
+ }
+}
=====================================
modules/gui/qt/player/qml/TracksPageSpeed.qml
=====================================
@@ -0,0 +1,35 @@
+/*****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Benjamin Arnaud <bunjee at omega.gg>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+import QtQuick 2.11
+
+import org.videolan.vlc 0.1
+
+TracksPage {
+ id: root
+
+ // Children
+
+ PlaybackSpeed {
+ anchors.fill: parent
+
+ Navigation.parentItem: root
+ }
+}
=====================================
modules/gui/qt/player/qml/TracksPageSubtitle.qml
=====================================
@@ -0,0 +1,276 @@
+/*****************************************************************************
+ * Copyright (C) 2022 VLC authors and VideoLAN
+ *
+ * Authors: Benjamin Arnaud <bunjee at omega.gg>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * ( at your option ) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+import QtQuick 2.11
+import QtQuick.Layouts 1.11
+
+import org.videolan.vlc 0.1
+
+import "qrc:///style/"
+import "qrc:///widgets/" as Widgets
+
+TracksPage {
+ id: root
+
+ // Functions
+
+ function textFromValueA(value, locale) {
+ return I18n.qtr("%1 ms").arg(Number(value).toLocaleString(locale, 'f', 0))
+ }
+
+ function valueFromTextA(text, locale) {
+ return Number.fromLocaleString(locale, text.substring(0, text.length - 3))
+ }
+
+ function textFromValueB(value, locale) {
+ return I18n.qtr("%1 fps").arg(Number(value / 10).toLocaleString(locale, 'f', 3))
+ }
+
+ function valueFromTextB(text, locale) {
+ return Number.fromLocaleString(locale, text.substring(0, text.length - 4)) * 10
+ }
+
+ // Children
+
+ ColumnLayout {
+ anchors.left: parent.left
+ anchors.right: parent.right
+
+ spacing: VLCStyle.margin_xxsmall
+
+ Widgets.SubtitleLabel {
+ Layout.fillWidth: true
+
+ text: I18n.qtr("Subtitle synchronization")
+
+ color: "white"
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+ Layout.topMargin: VLCStyle.margin_large
+
+ spacing: VLCStyle.margin_xsmall
+
+ Widgets.MenuCaption {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+
+ text: I18n.qtr("Primary subtitle delay")
+
+ color: "white"
+ }
+
+ Widgets.TransparentSpinBox {
+ id: spinBoxA
+
+ property bool update: false
+
+ Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
+
+ stepSize: 50
+ from: -10000
+
+ textFromValue: root.textFromValueA
+ valueFromText: root.valueFromTextA
+
+ Navigation.parentItem: root
+ Navigation.rightItem: resetA
+
+ Component.onCompleted: {
+ value = Player.subtitleDelayMS
+
+ update = true
+ }
+
+ onValueChanged: {
+ if (update === false)
+ return
+
+ Player.subtitleDelayMS = value
+ }
+
+ Connections {
+ target: Player
+
+ onSubtitleDelayChanged: {
+ spinBoxA.update = false
+
+ spinBoxA.value = Player.subtitleDelayMS
+
+ spinBoxA.update = true
+ }
+ }
+ }
+
+ Widgets.ActionButtonOverlay {
+ id: resetA
+
+ focus: true
+
+ text: I18n.qtr("Reset")
+
+ Navigation.parentItem: root
+ Navigation.leftItem: spinBoxA
+ Navigation.downItem: resetB
+
+ onClicked: spinBoxA.value = 0
+ }
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ spacing: VLCStyle.margin_xsmall
+
+ Widgets.MenuCaption {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+
+ text: I18n.qtr("Secondary subtitle delay")
+
+ color: "white"
+ }
+
+ Widgets.TransparentSpinBox {
+ id: spinBoxB
+
+ property bool update: false
+
+ Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
+
+ stepSize: 50
+ from: -10000
+
+ textFromValue: root.textFromValueA
+ valueFromText: root.valueFromTextA
+
+ Navigation.parentItem: root
+ Navigation.rightItem: resetB
+
+ Component.onCompleted: {
+ value = Player.secondarySubtitleDelayMS
+
+ update = true
+ }
+
+ onValueChanged: {
+ if (update === false)
+ return
+
+ Player.secondarySubtitleDelayMS = value
+ }
+
+ Connections {
+ target: Player
+
+ onSecondarySubtitleDelayChanged: {
+ spinBoxB.update = false
+
+ spinBoxB.value = Player.secondarySubtitleDelayMS
+
+ spinBoxB.update = true
+ }
+ }
+ }
+
+ Widgets.ActionButtonOverlay {
+ id: resetB
+
+ text: I18n.qtr("Reset")
+
+ Navigation.parentItem: root
+ Navigation.leftItem: spinBoxB
+ Navigation.upItem: resetA
+ Navigation.downItem: resetC
+
+ onClicked: spinBoxB.value = 0
+ }
+ }
+
+ RowLayout {
+ Layout.fillWidth: true
+
+ spacing: VLCStyle.margin_xsmall
+
+ Widgets.MenuCaption {
+ Layout.fillWidth: true
+ Layout.alignment: Qt.AlignHCenter
+
+ text: I18n.qtr("Subtitle Speed")
+
+ color: "white"
+ }
+
+ Widgets.TransparentSpinBox {
+ id: spinBoxC
+
+ property bool update: false
+
+ Layout.preferredWidth: VLCStyle.dp(128, VLCStyle.scale)
+
+ stepSize: 1
+
+ textFromValue: root.textFromValueB
+ valueFromText: root.valueFromTextB
+
+ Navigation.parentItem: root
+ Navigation.rightItem: resetC
+
+ Component.onCompleted: {
+ value = Player.subtitleFPS * 10
+
+ update = true
+ }
+
+ onValueChanged: {
+ if (update === false)
+ return
+
+ Player.subtitleFPS = value / 10
+ }
+
+ Connections {
+ target: Player
+
+ onSecondarySubtitleDelayChanged: {
+ spinBoxC.update = false
+
+ value = Player.subtitleFPS / 10
+
+ spinBoxC.update = true
+ }
+ }
+ }
+
+ Widgets.ActionButtonOverlay {
+ id: resetC
+
+ text: I18n.qtr("Reset")
+
+ onClicked: spinBoxC.value = 10
+
+ Navigation.parentItem: root
+ Navigation.leftItem: spinBoxC
+ Navigation.upItem: resetB
+ }
+ }
+ }
+}
=====================================
modules/gui/qt/player/qml/controlbarcontrols/LangButton.qml
=====================================
@@ -29,18 +29,18 @@ Widgets.IconControlButton {
size: VLCStyle.icon_medium
iconText: VLCIcons.audiosub
- enabled: langMenuLoader.status === Loader.Ready
- onClicked: langMenuLoader.item.open()
+ enabled: menuLoader.status === Loader.Ready
+ onClicked: menuLoader.item.open()
text: I18n.qtr("Languages and tracks")
Loader {
- id: langMenuLoader
+ id: menuLoader
active: (typeof rootPlayer !== 'undefined') && (rootPlayer !== null)
- sourceComponent: Player.LanguageMenu {
- id: langMenu
+ sourceComponent: Player.TracksMenu {
+ id: menu
parent: rootPlayer
focus: true
@@ -51,7 +51,7 @@ Widgets.IconControlButton {
onOpened: {
playerControlLayout.requestLockUnlockAutoHide(true, playerControlLayout)
if (!!rootPlayer)
- rootPlayer.menu = langMenu
+ rootPlayer.menu = menu
}
onClosed: {
=====================================
modules/gui/qt/player/qml/controlbarcontrols/PlaybackSpeedButton.qml
=====================================
@@ -15,7 +15,9 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
+
import QtQuick 2.11
+import QtQuick.Controls 2.4
import QtQuick.Templates 2.4 as T
import org.videolan.vlc 0.1
@@ -26,66 +28,104 @@ import "qrc:///player/" as P
import "qrc:///util/Helpers.js" as Helpers
Widgets.IconControlButton {
- id: playbackSpeedButton
+ id: root
readonly property bool _isCurrentViewPlayer: !paintOnly && (History.current.name === "player")
size: VLCStyle.icon_medium
+
text: I18n.qtr("Playback Speed")
- color: playbackSpeedPopup.visible ? colors.accent : colors.playerControlBarFg
- onClicked: playbackSpeedPopup.open()
+ color: (popup.visible) ? colors.accent : colors.playerControlBarFg
+
+ onClicked: popup.open()
+
+ Popup {
+ id: popup
+
+ parent: root.paintOnly
+ ? root // button is not part of main display (ToolbarEditorDialog)
+ : root._isCurrentViewPlayer ? rootPlayer : g_root
+
+ width: implicitWidth
+ height: implicitHeight
- P.PlaybackSpeed {
- id: playbackSpeedPopup
+ padding: VLCStyle.margin_small
z: 1
- colors: playbackSpeedButton.colors
+
focus: true
- parent: playbackSpeedButton.paintOnly
- ? playbackSpeedButton // button is not part of main display (ToolbarEditorDialog)
- : playbackSpeedButton._isCurrentViewPlayer ? rootPlayer : g_root
- Navigation.parentItem: playbackSpeedButton
+ // Popup.CloseOnPressOutside doesn't work with non-model Popup on Qt < 5.15
+ closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
+
+ modal: true
onOpened: {
// update popup coordinates
//
- // mapFromItem is affected by various properties of source and target objects
- // which can't be represented in a binding expression so a initial setting in
- // object definition (x: clamp(...)) doesn't work, so we set x and y on initial open
+ // mapFromItem is affected by various properties of source and target objects which
+ // can't be represented in a binding expression so a initial setting in object
+ // definition (x: clamp(...)) doesn't work, so we set x and y on initial open
x = Qt.binding(function () {
- // coords are mapped through playbackSpeedButton.parent so that binding is generated based on playbackSpeedButton.x
- var mappedParentCoordinates = parent.mapFromItem(playbackSpeedButton.parent, playbackSpeedButton.x, 0)
- return Helpers.clamp(mappedParentCoordinates.x - ((width - playbackSpeedButton.width) / 2),
- VLCStyle.margin_xxsmall + VLCStyle.applicationHorizontalMargin,
- parent.width - VLCStyle.applicationHorizontalMargin - VLCStyle.margin_xxsmall - width)
+ // coords are mapped through root.parent so that binding is
+ // generated based on root.x
+ var position = parent.mapFromItem(root.parent, root.x, 0)
+
+ var minimum = VLCStyle.margin_xxsmall + VLCStyle.applicationHorizontalMargin
+
+ var maximum = parent.width - VLCStyle.applicationHorizontalMargin
+ - VLCStyle.margin_xxsmall - width
+
+ return Helpers.clamp(position.x - ((width - root.width) / 2), minimum, maximum)
})
y = Qt.binding(function () {
- // coords are mapped through playbackSpeedButton.parent so that binding is generated based on playbackSpeedButton.y
- var mappedParentCoordinates = parent.mapFromItem(playbackSpeedButton.parent, 0, playbackSpeedButton.y)
- return mappedParentCoordinates.y - playbackSpeedPopup.height - VLCStyle.margin_xxsmall
+ // coords are mapped through root.parent so that binding is
+ // generated based on root.y
+ var position = parent.mapFromItem(root.parent, 0, root.y)
+
+ return position.y - popup.height - VLCStyle.margin_xxsmall
})
// player related --
playerControlLayout.requestLockUnlockAutoHide(true, playerControlLayout)
- if (playbackSpeedButton._isCurrentViewPlayer)
- rootPlayer.menu = playbackSpeedPopup
+
+ if (root._isCurrentViewPlayer)
+ rootPlayer.menu = popup
}
onClosed: {
playerControlLayout.requestLockUnlockAutoHide(false, playerControlLayout)
- playbackSpeedButton.forceActiveFocus()
- if (playbackSpeedButton._isCurrentViewPlayer)
+
+ root.forceActiveFocus()
+
+ if (root._isCurrentViewPlayer)
rootPlayer.menu = undefined
}
+
+ Overlay.modal: null
+
+ background: Rectangle {
+ color: colors.bg
+ opacity: .85
+ }
+
+ contentItem: P.PlaybackSpeed {
+ colors: root.colors
+
+ Navigation.parentItem: root
+ }
}
T.Label {
anchors.centerIn: parent
font.pixelSize: VLCStyle.fontSize_normal
- text: !playbackSpeedButton.paintOnly ? I18n.qtr("%1x").arg(+Player.rate.toFixed(2)) : I18n.qtr("1x")
- color: playbackSpeedButton.background.foregroundColor // IconToolButton.background is a AnimatedBackground
+
+ text: !root.paintOnly ? I18n.qtr("%1x").arg(+Player.rate.toFixed(2))
+ : I18n.qtr("1x")
+
+ // IconToolButton.background is a AnimatedBackground
+ color: root.background.foregroundColor
}
}
=====================================
modules/gui/qt/style/VLCIcons.qml
=====================================
@@ -166,16 +166,17 @@ QtObject {
readonly property string play_outline : "\ue092"
readonly property string enqueue : "\ue093"
readonly property string back : "\ue094"
- readonly property string history : "\ue095"
- readonly property string window_close : "\ue096"
- readonly property string window_maximize : "\ue097"
- readonly property string window_minimize : "\ue098"
- readonly property string window_restore : "\ue099"
- readonly property string home : "\ue09a"
- readonly property string download : "\ue09b"
- readonly property string multiselect : "\ue09c"
- readonly property string sync : "\ue09d"
- readonly property string check : "\ue09e"
- readonly property string visualization : "\ue09f"
+ readonly property string expand : "\ue095"
+ readonly property string history : "\ue096"
+ readonly property string window_close : "\ue097"
+ readonly property string window_maximize : "\ue098"
+ readonly property string window_minimize : "\ue099"
+ readonly property string window_restore : "\ue09a"
+ readonly property string home : "\ue09b"
+ readonly property string download : "\ue09c"
+ readonly property string multiselect : "\ue09d"
+ readonly property string sync : "\ue09e"
+ readonly property string check : "\ue09f"
+ readonly property string visualization : "\ue0a0"
}
=====================================
modules/gui/qt/vlc.qrc
=====================================
@@ -104,6 +104,7 @@
<file alias="file_black.svg">pixmaps/types/file_black.svg</file>
</qresource>
<qresource prefix="/">
+ <file alias="download.svg">pixmaps/download.svg</file>
<file alias="update.svg">pixmaps/update.svg</file>
<file alias="noart.png">pixmaps/noart.png</file>
<file alias="noart64.png">pixmaps/noart-64.png</file>
@@ -123,6 +124,7 @@
<file alias="noart_videoCover.svg">pixmaps/noart_videoCover.svg</file>
<file alias="play_button.svg">pixmaps/play_button.svg</file>
<file alias="back.svg">pixmaps/back.svg</file>
+ <file alias="sync.svg">pixmaps/sync.svg</file>
<file alias="theme_dark.svg">pixmaps/theme_dark.svg</file>
<file alias="theme_daynight.svg">pixmaps/theme_daynight.svg</file>
<file alias="theme_light.svg">pixmaps/theme_light.svg</file>
@@ -343,7 +345,12 @@
<file alias="ControlBar.qml">player/qml/ControlBar.qml</file>
<file alias="ResumeDialog.qml">player/qml/ResumeDialog.qml</file>
<file alias="SliderBar.qml">player/qml/SliderBar.qml</file>
+ <file alias="TracksMenu.qml">player/qml/TracksMenu.qml</file>
<file alias="TrackInfo.qml">player/qml/TrackInfo.qml</file>
+ <file alias="TracksPage.qml">player/qml/TracksPage.qml</file>
+ <file alias="TracksPageSpeed.qml">player/qml/TracksPageSpeed.qml</file>
+ <file alias="TracksPageAudio.qml">player/qml/TracksPageAudio.qml</file>
+ <file alias="TracksPageSubtitle.qml">player/qml/TracksPageSubtitle.qml</file>
<file alias="ControlbarControls.qml">player/qml/ControlbarControls.qml</file>
<file alias="MiniPlayer.qml">player/qml/MiniPlayer.qml</file>
<file alias="TopBar.qml">player/qml/TopBar.qml</file>
@@ -351,7 +358,6 @@
<file alias="PlayerControlLayout.qml">player/qml/PlayerControlLayout.qml</file>
<file alias="PlayerMenu.qml">player/qml/PlayerMenu.qml</file>
<file alias="PlayerMenuItem.qml">player/qml/PlayerMenuItem.qml</file>
- <file alias="LanguageMenu.qml">player/qml/LanguageMenu.qml</file>
<file alias="ControlLayout.qml">player/qml/ControlLayout.qml</file>
<file alias="PlaybackSpeed.qml">player/qml/PlaybackSpeed.qml</file>
<file alias="PlayerPlaylistVisibilityFSM.qml">player/qml/PlayerPlaylistVisibilityFSM.qml</file>
=====================================
modules/gui/qt/widgets/qml/SpinBoxExt.qml
=====================================
@@ -52,7 +52,7 @@ SpinBox{
contentItem: TextInput {
// NOTE: This is required for InterfaceWindowHandler::applyKeyEvent.
- property bool visualFocus: control.visualFocus
+ property bool visualFocus: control.activeFocus
text: control.textFromValue(control.value, control.locale)
=====================================
modules/gui/qt/widgets/qml/TransparentSpinBox.qml
=====================================
@@ -45,6 +45,9 @@ T.SpinBox {
Keys.onPressed: Navigation.defaultKeyAction(event)
contentItem: TextInput {
+ // NOTE: This is required for InterfaceWindowHandler::applyKeyEvent.
+ property bool visualFocus: control.activeFocus
+
z: 2
text: control.textFromValue(control.value, control.locale)
color: control.color
=====================================
po/POTFILES.in
=====================================
@@ -869,10 +869,12 @@ modules/gui/qt/network/qml/NetworkHomeDisplay.qml
modules/gui/qt/network/qml/NetworkListItem.qml
modules/gui/qt/network/qml/ServicesHomeDisplay.qml
modules/gui/qt/player/qml/ControlbarControls.qml
-modules/gui/qt/player/qml/LanguageMenu.qml
modules/gui/qt/player/qml/Player.qml
modules/gui/qt/player/qml/ResumeDialog.qml
modules/gui/qt/player/qml/TopBar.qml
+modules/gui/qt/player/qml/TracksMenu.qml
+modules/gui/qt/player/qml/TracksPageAudio.qml
+modules/gui/qt/player/qml/TracksPageSubtitle.qml
modules/gui/qt/player/qml/controlbarcontrols/TeletextWidget.qml
modules/gui/qt/player/qml/controlbarcontrols/VolumeWidget.qml
modules/gui/qt/player/qml/controlbarcontrols/ArtworkInfoWidget.qml
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/db6b36b6b1d85932c4f919ff43dbac363f20a57c...3203bfe1a626388b725fb68a274e92f78891d82c
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/db6b36b6b1d85932c4f919ff43dbac363f20a57c...3203bfe1a626388b725fb68a274e92f78891d82c
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance
More information about the vlc-commits
mailing list