Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • videolan/vlc
  • chouquette/vlc
  • bakiewicz.marek122/vlc
  • devnexen/vlc
  • rohanrajpal/vlc
  • blurrrb/vlc
  • gsoc/gsoc2019/darkapex/vlc
  • b1ue/vlc
  • fkuehne/vlc
  • magsoft/vlc
  • chub/vlc
  • cramiro9/vlc
  • robUx4/vlc
  • rom1v/vlc
  • akshayaky/vlc
  • tmk907/vlc
  • akymaster/vlc
  • govind.sharma/vlc
  • psilokos/vlc
  • xjbeta/vlc
  • jahan/vlc
  • 1480c1/vlc
  • amanchande/vlc
  • aaqib/vlc
  • rist/vlc
  • apol/vlc
  • mindfreeze/vlc
  • alexandre-janniaux/vlc
  • sandsmark/vlc
  • jagannatharjun/vlc
  • gsoc/gsoc2020/matiaslgonzalez/vlc
  • gsoc/gsoc2020/jagannatharjun/vlc
  • mstorsjo/vlc
  • gsoc/gsoc2020/vedenta/vlc
  • gsoc/gsoc2020/arnav-ishaan/vlc
  • gsoc/gsoc2020/andreduong/vlc
  • fuzun/vlc
  • gsoc/gsoc2020/vatsin/vlc
  • gsoc/gsoc2020/sagid/vlc
  • yaron/vlc
  • Phoenix/vlc
  • Garf/vlc
  • ePiratWorkarounds/vlc
  • tguillem/vlc
  • jnqnfe/vlc
  • mdc/vlc
  • Vedaa/vlc
  • rasa/vlc
  • quink/vlc
  • yealo/vlc
  • aleksey_ak/vlc
  • ePirat/vlc
  • ilya.yanok/vlc
  • asenat/vlc
  • m/vlc
  • bunjee/vlc
  • BLumia/vlc
  • sagudev/vlc
  • hamedmonji30/vlc
  • nullgemm/vlc
  • DivyamAhuja/vlc
  • thesamesam/vlc
  • dag7/vlc
  • snehil101/vlc
  • haasn/vlc
  • jbk/vlc
  • ValZapod/vlc
  • mfkl/vlc
  • WangChuan/vlc
  • core1024/vlc
  • GhostVaibhav/vlc
  • dfuhrmann/vlc
  • davide.prade/vlc
  • tmatth/vlc
  • Courmisch/vlc
  • zouya/vlc
  • hpi/vlc
  • EwoutH/vlc
  • aleung27/vlc
  • hengwu0/vlc
  • saladin/vlc
  • ashuio/vlc
  • richselwood/vlc
  • verma16Ayush/vlc
  • chemicalflash/vlc
  • PoignardAzur/vlc
  • huangjieNT/vlc
  • Blake-Haydon/vlc
  • AnuthaDev/vlc
  • gsoc/gsoc2021/mpd/vlc
  • nicolas_lequec/vlc
  • sambassaly/vlc
  • thresh/vlc
  • bonniegong/vlc
  • myaashish/vlc
  • stavros.vagionitis/vlc
  • ileoo/vlc
  • louis-santucci/vlc
  • cchristiansen/vlc
  • sabyasachi07/vlc
  • AbduAmeen/vlc
  • ashishb0410/vlc
  • urbanhusky/vlc
  • davidepietrasanta/vlc
  • riksleutelstad/vlc
  • jeremyVignelles/vlc
  • komh/vlc
  • iamjithinjohn/vlc
  • JohannesKauffmann/vlc2
  • kunglao/vlc
  • natzberg/vlc
  • jill/vlc
  • cwendling/vlc
  • adufou/vlc
  • ErwanAirone/vlc
  • HasinduDilshan10/vlc
  • vagrantc/vlc
  • rafiv/macos-bigsur-icon
  • Aymeriic/vlc
  • saranshg20/vlc
  • metzlove24/vlc
  • linkfanel/vlc
  • Ds886/vlc
  • metehan-arslan/vlc
  • Skantes/vlc
  • kgsandundananjaya96/vlc
  • mitchcapper/vlc
  • advaitgupta/vlc
  • StefanBruens/vlc
  • ratajs/vlc
  • T.M.F.B.3761/vlc
  • m222059/vlc
  • casemerrick/vlc
  • joshuaword2alt/vlc
  • sjwaddy/vlc
  • dima/vlc
  • Ybalrid/vlc
  • umxprime/vlc
  • eschmidt/vlc
  • vannieuwenhuysenmichelle/vlc
  • badcf00d/vlc
  • wesinator/vlc
  • louis/vlc
  • xqq/vlc
  • EmperorYP7/vlc
  • NicoLiam/vlc
  • loveleen/vlc
  • rofferom/vlc
  • rbultje/vlc
  • TheUnamed/vlc
  • pratiksharma341/vlc
  • Saurab17/vlc
  • purist.coder/vlc
  • Shuicheng/vlc
  • mdrrubel292/vlc
  • silverbleu00/vlc
  • metif12/vlc
  • asher-m/vlc
  • jeffk/vlc
  • Brandonbr1/vlc
  • beautyyuyanli/vlc
  • rego21/vlc
  • muyangren907/vlc
  • collectionbylawrencejason/vlc
  • evelez/vlc
  • GSMgeeth/vlc
  • Oneric/vlc
  • TJ5/vlc
  • XuanTung95/vlc
  • darrenjenny21/vlc
  • Trenly/vlc
  • RockyTDR/vlc
  • mjakubowski/vlc
  • caprica/vlc
  • ForteFrankie/vlc
  • seannamiller19/vlc
  • junlon2006/vlc
  • kiwiren6666/vlc
  • iuseiphonexs/vlc
  • fenngtun/vlc
  • Rajdutt999/vlc
  • typx/vlc
  • leon.vitanos/vlc
  • robertogarci0938/vlc
  • gsoc/gsoc2022/luc65r/vlc-mpd
  • skeller/vlc
  • MCJack123/vlc
  • luc65r/vlc-mpd
  • popov895/vlc
  • claucambra/vlc
  • brad/vlc
  • matthewmurua88/vlc
  • Tomas8874/vlc
  • philenotfound/vlc
  • makita-do3/vlc
  • LZXCorp/vlc
  • mar0x/vlc
  • senojetkennedy0102/vlc
  • shaneb243/vlc
  • ahmadbader/vlc
  • rajduttcse26/vlc-audio-filters
  • Juniorzito8415/vlc
  • achernyakov/vlc
  • lucasjetgroup/vlc
  • pupdoggy666/vlc
  • gmde9363/vlc
  • alexnwayne/vlc
  • bahareebrahimi781/vlc
  • hamad633666/vlc
  • umghof3112/vlc
  • joe0199771874/vlc
  • Octocats66666666/vlc
  • jjm_223/vlc
  • btech10110.19/vlc
  • sunnykfc028/vlc-audio-filters
  • loic/vlc
  • nguyenminhducmx1/vlc
  • JanekKrueger/vlc
  • bstubbington2/vlc
  • rcombs/vlc
  • Ordissimo/vlc
  • king7532/vlc
  • noobsauce101/vlc
  • schong0525/vlc
  • myQwil/vlc
  • apisbg91/vlc
  • geeboy0101017/vlc
  • kim.faughey/vlc
  • nurupo/vlc
  • yyusea/vlc
  • 0711235879.khco/vlc
  • ialo/vlc
  • iloveyeye2/vlc
  • gdtdftdqtd/vlc
  • leandroconsiglio/vlc
  • AndyHTML2012/vlc
  • ncz/vlc
  • lucenticus/vlc
  • knr1931/vlc
  • kjoonlee/vlc
  • chandrakant100/vlc-qt
  • johge42/vlc
  • polter/vlc
  • hexchain/vlc
  • Tushwrld/vlc
  • mztea928/vlc
  • jbelloncastro/vlc
  • alvinhochun/vlc
  • ghostpiratecrow/vlc
  • ujjwaltwitx/vlc
  • alexsonarin06/vlc
  • adrianbon76/vlc
  • altsod/vlc
  • damien.lucas44/vlc
  • dmytrivtaisa/vlc
  • utk202/vlc
  • aaxhrj/vlc
  • thomas.hermes/vlc
  • structurenewworldorder/vlc
  • slomo/vlc
  • wantlamy/vlc
  • musc.o3cminc/vlc
  • thebarshablog/vlc
  • kerrick/vlc
  • kratos142518/vlc
  • leogps/vlc
  • vacantron/vlc
  • luna_koly/vlc
  • Ratio2/vlc
  • anuoshemohammad/vlc
  • apsun/vlc
  • aaa1115910/vlc
  • alimotmoyo/vlc
  • Ambossmann/vlc
  • Sam-LearnsToCode/vlc
  • Chilledheart/vlc
  • Labnann/vlc
  • ktcoooot1/vlc
  • mohit-marathe/vlc
  • johnddx/vlc
  • manstabuk/vlc
  • Omar-ahmed314/vlc
  • vineethkm/vlc
  • 9Enemi86/vlc
  • radoslav.m.panteleev/vlc
  • ashishami2002/vlc
  • Corbax/vlc
  • firnasahmed/vlc
  • pelayarmalam4/vlc
  • c0ff330k/vlc
  • shikhindahikar/vlc
  • l342723951/vlc
  • christianschwandner/vlc
  • douniwan5788/vlc
  • 7damian7/vlc
  • ferdnyc/vlc
  • f.ales1/vlc
  • pandagby/vlc
  • BaaBaa/vlc
  • jewe37/vlc
  • w00drow/vlc
  • russelltg/vlc
  • ironicallygod/vlc
  • soumyaDghosh/vlc
  • linzihao1999/vlc
  • deyayush6/vlc
  • mibi88/vlc
  • newabdallah10/vlc
  • jhorbincolombia/vlc
  • rimvihaqueshupto/vlc
  • andrewkhon98/vlc
  • fab78/vlc
  • lapaz17/vlc
  • amanna13/vlc
  • mdakram28/vlc
  • 07jw1980/vlc
  • sohamgupta/vlc
  • Eson-Jia1/vlc
  • Sumou/vlc
  • vikram-kangotra/vlc
  • chalice191/vlc
  • olivercalder/vlc
  • aaasg4001/vlc
  • zipdox/vlc
  • kwizart/vlc
  • Dragon-S/vlc
  • jdemeule/vlc
  • gabriel_lt/vlc
  • locutusofborg/vlc
  • sammirata/vlc-librist
  • another/vlc
  • Benjamin_Loison/vlc
  • ahmedmoselhi/vlc
  • petergaal/vlc
  • huynhsontung/vlc
  • dariusmihut/vlc
  • tvermaashutosh/vlc
  • buti/vlc
  • Niram7777/vlc
  • rohan-here/vlc
  • balaji-sivasakthi/vlc
  • rlindner81/vlc
  • Kakadus/vlc
  • djain/vlc
  • ABBurmeister/vlc
  • craighuggins/vlc
  • orbea/vlc
  • maxos/vlc
  • aakarshmj/vlc
  • kblaschke/vlc
  • ankitm/vlc
  • advait-0/vlc
  • mohak2003/vlc
  • yselkowitz/vlc
  • AZM999/vlc-azm
  • andrey.turkin/vlc
  • Disha-Baghel/vlc
  • nowrep/vlc
  • Apeng/vlc
  • Choucroute_melba/vlc
  • autra/vlc
  • eclipseo/vlc
  • fhuber/vlc
  • olafhering/vlc
  • sdasda7777/vlc
  • 1div0/vlc
  • skosnits/vlc-extended-playlist-support
  • dnicolson/vlc
  • Timshel/vlc
  • octopols/vlc
  • MangalK/vlc
  • nima64/vlc
  • misawai/vlc
  • Alexander-Wilms/vlc
  • Maxime2/vlc-fork-for-visualizer
  • ww/vlc
  • jeske/vlc
  • sgross-emlix/vlc
  • morenonatural/vlc
  • freakingLovesVLC/vlc
  • borisgolovnev/vlc
  • mpromonet/vlc
  • diogo.simao-marques/vlc
  • masstock/vlc
  • pratikpatel8982/vlc
  • hugok79/vlc
  • longervision/vlc
  • abhiudaysurya/vlc
  • rishabhgarg/vlc
  • tumic/vlc
  • cart/vlc
  • shubham442/vlc
  • Aditya692005/vlc
  • sammirata/vlc4
  • syrykh/vlc
  • Vvorcun/macos-new-icon
  • AyaanshC/vlc
  • nasso/vlc
  • Quark/vlc
  • sebastinas/vlc
  • rhstone/vlc
  • talregev/vlc
  • Managor/vlc
403 results
Show changes
Commits on Source (10)
Showing
with 1225 additions and 175 deletions
......@@ -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 \
......
......@@ -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" );
......
......@@ -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)
{}
......
......@@ -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)
......
......@@ -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" },
......
No preview for this file type
<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
......@@ -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()
}
}
}
......@@ -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")
}
}
}
......
/*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* Authors: Benjamin Arnaud <bunjee@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
}
}
/*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* Authors: Benjamin Arnaud <bunjee@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
}
}
}
}
/*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* Authors: Benjamin Arnaud <bunjee@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
}
}
/*****************************************************************************
* Copyright (C) 2022 VLC authors and VideoLAN
*
* Authors: Benjamin Arnaud <bunjee@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
}
}
}
}
......@@ -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: {
......
......@@ -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
}
}
......@@ -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"
}
......@@ -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>
......
......@@ -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)
......
......@@ -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
......
......@@ -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
......