mirror of
				https://github.com/JupiterBroadcasting/CasterSoundboard.git
				synced 2025-10-30 03:59:08 +00:00 
			
		
		
		
	More UI work in QML
This commit is contained in:
		
							parent
							
								
									b1149a1a82
								
							
						
					
					
						commit
						a4a15b15cf
					
				| @ -2,7 +2,16 @@ | ||||
| 
 | ||||
| CasterPlayerController::CasterPlayerController(QObject *parent) : QObject(parent) | ||||
| { | ||||
|     mItems.append({ false }); | ||||
|     // Add initial player
 | ||||
|     mItems.append({ | ||||
|                       false, // IsInPlayerMode
 | ||||
|                       false, // IsLooped
 | ||||
|                       1.0,   // Volume
 | ||||
|                       false, // IsPlayRegionEnabled
 | ||||
|                       0,     // PlayRegionBegin
 | ||||
|                       0,     // PlayRegionEnd
 | ||||
|                       0     // Trigger Style
 | ||||
|                   }); | ||||
| } | ||||
| 
 | ||||
| QVector<CasterPlayerItem> CasterPlayerController::items() const | ||||
| @ -23,10 +32,16 @@ bool CasterPlayerController::setItemAt(int index, const CasterPlayerItem &item) | ||||
| 
 | ||||
| void CasterPlayerController::appendItem() | ||||
| { | ||||
|     // Adds player
 | ||||
|     // Adds player with default settings
 | ||||
|     emit preItemAppend(); | ||||
|     CasterPlayerItem item; | ||||
|     item.isInPlayerMode = false; | ||||
|     item.isLooped = false; | ||||
|     item.volume = 1.0; | ||||
|     item.isPlayRegionEnabled = false; | ||||
|     item.playRegionBegin = 0; | ||||
|     item.playRegionEnd = 0; | ||||
|     item.triggerStyle = 0; | ||||
|     mItems.append(item); | ||||
|     emit postItemAppend(); | ||||
| } | ||||
|  | ||||
| @ -7,6 +7,12 @@ | ||||
| 
 | ||||
| struct CasterPlayerItem { | ||||
|     bool isInPlayerMode; | ||||
|     bool isLooped; | ||||
|     double volume; | ||||
|     bool isPlayRegionEnabled; | ||||
|     int playRegionBegin; | ||||
|     int playRegionEnd; | ||||
|     int triggerStyle; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -27,6 +27,18 @@ QVariant CasterPlayerModel::data(const QModelIndex &index, int role) const | ||||
|     switch (role) { | ||||
|     case IsInPlayerModeRole: | ||||
|         return QVariant(item.isInPlayerMode); | ||||
|     case IsLoopedRole: | ||||
|         return QVariant(item.isLooped); | ||||
|     case VolumeRole: | ||||
|         return QVariant(item.volume); | ||||
|     case IsPlayingRegionEnabledRole: | ||||
|         return QVariant(item.isPlayRegionEnabled); | ||||
|     case PlayRegionBeginRole: | ||||
|         return QVariant(item.playRegionBegin); | ||||
|     case PlayRegionEndRole: | ||||
|         return QVariant(item.playRegionEnd); | ||||
|     case TriggerStyleRole: | ||||
|         return QVariant(item.triggerStyle); | ||||
|     } | ||||
| 
 | ||||
|     return QVariant(); | ||||
| @ -42,6 +54,23 @@ bool CasterPlayerModel::setData(const QModelIndex &index, const QVariant &value, | ||||
|     case IsInPlayerModeRole: | ||||
|         item.isInPlayerMode = value.toBool(); | ||||
|         break; | ||||
|     case IsLoopedRole: | ||||
|         item.isLooped = value.toBool(); | ||||
|         break; | ||||
|     case VolumeRole: | ||||
|         item.volume = value.toDouble(); | ||||
|         break; | ||||
|     case IsPlayingRegionEnabledRole: | ||||
|         item.isPlayRegionEnabled = value.toBool(); | ||||
|         break; | ||||
|     case PlayRegionBeginRole: | ||||
|         item.playRegionBegin = value.toInt(); | ||||
|         break; | ||||
|     case PlayRegionEndRole: | ||||
|         item.playRegionEnd = value.toInt(); | ||||
|         break; | ||||
|     case TriggerStyleRole: | ||||
|         item.triggerStyle = value.toInt(); | ||||
|     } | ||||
| 
 | ||||
|     if (mList->setItemAt(index.row(), item)) { | ||||
| @ -65,8 +94,15 @@ Qt::ItemFlags CasterPlayerModel::flags(const QModelIndex &index) const | ||||
| */ | ||||
| QHash<int, QByteArray> CasterPlayerModel::roleNames() const | ||||
| { | ||||
|     // Set QML property names
 | ||||
|     QHash<int, QByteArray> names; | ||||
|     names[IsInPlayerModeRole] = "isInPlayerMode"; | ||||
|     names[IsLoopedRole] = "isLooped"; | ||||
|     names[VolumeRole] = "volume"; | ||||
|     names[IsPlayingRegionEnabledRole] = "isPlayRegionEnabled"; | ||||
|     names[PlayRegionBeginRole] = "playRegionBegin"; | ||||
|     names[PlayRegionEndRole] = "playRegionEnd"; | ||||
|     names[TriggerStyleRole] = "triggerStyle"; | ||||
|     return names; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -13,9 +13,22 @@ class CasterPlayerModel : public QAbstractListModel | ||||
| public: | ||||
|     explicit CasterPlayerModel(QObject *parent = nullptr); | ||||
| 
 | ||||
|     enum { | ||||
|         IsInPlayerModeRole = Qt::UserRole | ||||
|     enum ModelRoles { | ||||
|         IsInPlayerModeRole = Qt::UserRole, | ||||
|         IsLoopedRole, | ||||
|         VolumeRole, | ||||
|         IsPlayingRegionEnabledRole, | ||||
|         PlayRegionBeginRole, | ||||
|         PlayRegionEndRole, | ||||
|         TriggerStyleRole | ||||
|     }; | ||||
|     Q_ENUM(ModelRoles) | ||||
|     enum TriggerStyle { | ||||
|         PlayPauseTriggerStyle = 0, | ||||
|         PlayStopTriggerStyle, | ||||
|         PlayAgainTriggerStyle | ||||
|     }; | ||||
|     Q_ENUM(TriggerStyle) | ||||
| 
 | ||||
|     // Basic functionality:
 | ||||
|     int rowCount(const QModelIndex &parent = QModelIndex()) const override; | ||||
|  | ||||
| @ -46,5 +46,8 @@ | ||||
|         <file>qml/img/player_outline.png</file> | ||||
|         <file>qml/views/components/caster_player_settings_drawer/Component.qml</file> | ||||
|         <file>qml/views/components/caster_player_settings_drawer/subcomponents/BootstrapButton.qml</file> | ||||
|         <file>qml/views/components/caster_player_settings_drawer/subcomponents/FlatSwitch.qml</file> | ||||
|         <file>qml/views/components/caster_player_settings_drawer/subcomponents/StateSelector.qml</file> | ||||
|         <file>qml/views/components/caster_player_settings_drawer/subcomponents/TimeRangeSelector.qml</file> | ||||
|     </qresource> | ||||
| </RCC> | ||||
|  | ||||
| @ -8,31 +8,34 @@ import MVC_CasterPlayer 1.0 | ||||
| import "../caster_player" as CasterPlayer | ||||
| 
 | ||||
| Flickable { | ||||
|     id: soundboardFlickable | ||||
|     property int defaultPlayerSize: 210 | ||||
|     id: root | ||||
|     //Component Properties & Events | ||||
|     anchors.fill: parent | ||||
|     anchors.margins: 8 | ||||
|     contentHeight: soundboardGrid.height | ||||
|     //contentWidth: soundboardGrid.width | ||||
|     clip: true | ||||
|     flickableDirection: Flickable.VerticalFlick | ||||
|     ScrollBar.vertical: ScrollBar { | ||||
|                 id: soundboardScrollbar | ||||
|                 width: 30 | ||||
|                 active: true | ||||
|                 onActiveChanged: { | ||||
|                                 if (!active) | ||||
|                                     active = true;//Keep scrollbar always visible | ||||
|                             } | ||||
|             } | ||||
|         id: soundboardScrollbar | ||||
|         width: 30 | ||||
|         active: true | ||||
|         onActiveChanged: { | ||||
|             if (!active) | ||||
|                 active = true;//Keep scrollbar always visible | ||||
|         } | ||||
|     } | ||||
|     onWidthChanged: soundboardGrid.columns = soundboardGrid.computeNeededColumns(root.defaultPlayerSize, root.width, soundboardGrid.spacing, soundboardScrollbar.width) | ||||
|     onDefaultPlayerSizeChanged: soundboardGrid.columns = soundboardGrid.computeNeededColumns(root.defaultPlayerSize, root.width, soundboardGrid.spacing, soundboardScrollbar.width) | ||||
| 
 | ||||
|     onWidthChanged: soundboardGrid.columns = soundboardGrid.computeNeededColumns(soundboardFlickable.defaultPlayerSize, soundboardFlickable.width, soundboardGrid.spacing, soundboardScrollbar.width) | ||||
|     //Player Properties | ||||
|     property int defaultPlayerSize: 210 | ||||
|     property alias soundboardPlayers: playerRepeater | ||||
| 
 | ||||
|     Grid { | ||||
|             id: soundboardGrid | ||||
|             //Properties & Functions | ||||
|             spacing: 8 | ||||
|             columns: soundboardGrid.computeNeededColumns(soundboardFlickable.defaultPlayerSize, parent.width, soundboardGrid.spacing, soundboardScrollbar.width) | ||||
| 
 | ||||
|             columns: soundboardGrid.computeNeededColumns(root.defaultPlayerSize, parent.width, soundboardGrid.spacing, soundboardScrollbar.width) | ||||
|             function computeNeededColumns(playerWidth, containerWidth, gridSpacing, scrollbarWidth){ | ||||
|                 var neededColumnsWithoutSpacing = Math.floor(containerWidth / playerWidth); | ||||
|                 var adjustedGridWidth = containerWidth - ((neededColumnsWithoutSpacing - 1) * gridSpacing) - (gridSpacing + scrollbarWidth); | ||||
| @ -41,11 +44,25 @@ Flickable { | ||||
|                 return neededColumns; | ||||
|             } | ||||
| 
 | ||||
|             //Generate Players | ||||
|             Repeater { | ||||
|                 id: playerRepeater | ||||
|                 model: CasterPlayerModel { list: casterPlayerController } | ||||
|                 delegate: CasterPlayer.Component { | ||||
|                     size: soundboardFlickable.defaultPlayerSize | ||||
|                     size: root.defaultPlayerSize | ||||
|                     isInPlayerMode: model.isInPlayerMode | ||||
|                     isLooped: model.isLooped | ||||
|                     onIsLoopedChanged: model.isLooped = isLooped | ||||
|                     volume: model.volume | ||||
|                     onVolumeChanged: model.volume = volume | ||||
|                     isPlayRegionEnabled: model.isPlayRegionEnabled | ||||
|                     onIsPlayRegionEnabledChanged: model.isPlayRegionEnabled = isPlayRegionEnabled | ||||
|                     playRegionBegin: model.playRegionBegin | ||||
|                     onPlayRegionBeginChanged: model.playRegionBegin = playRegionBegin | ||||
|                     playRegionEnd: model.playRegionEnd | ||||
|                     onPlayRegionEndChanged: model.playRegionEnd = playRegionEnd | ||||
|                     triggerStyle: model.triggerStyle | ||||
|                     onTriggerStyleChanged: model.triggerStyle = triggerStyle | ||||
|                 } | ||||
|             } | ||||
|     } | ||||
|  | ||||
| @ -4,18 +4,39 @@ import QtQuick.Controls 2.4 | ||||
| import QtQuick.Layouts 1.11 | ||||
| import QtMultimedia 5.9 | ||||
| 
 | ||||
| import MVC_CasterPlayer 1.0 | ||||
| 
 | ||||
| import "./subcomponents" as Subcomponent | ||||
| 
 | ||||
| Rectangle { | ||||
|     id: root | ||||
|     //Component properties | ||||
|     property int size: 210 | ||||
|     width: root.size; height: root.size | ||||
|     color: "transparent" | ||||
|     property bool shouldKeepPlayingLoop: false | ||||
|     property int duration: player.duration | ||||
| 
 | ||||
|     //Player properties, functions & events | ||||
|     property bool isInPlayerMode: true | ||||
|     property bool isLooped: false | ||||
|     property double volume: 1.0 | ||||
|     property bool isPlayRegionEnabled: false | ||||
|     property int playRegionBegin: 0 | ||||
|     property int playRegionEnd: 0 | ||||
|     onPlayRegionEndChanged: progressBar.playRegionEnd = root.playRegionEnd | ||||
|     property int triggerStyle: 0 | ||||
| 
 | ||||
|     property alias trackTile: trackTitle.trackTitleString | ||||
|     property alias trackVolume: volumeBar.value | ||||
|     property alias isLooped: progressBar.isLooped | ||||
| 
 | ||||
|     onIsLoopedChanged: { | ||||
|         if(root.isLooped == false) | ||||
|             root.shouldKeepPlayingLoop = false; | ||||
|         else if (root.isLooped == true && player.playbackState == MediaPlayer.PlayingState){ | ||||
|             root.shouldKeepPlayingLoop = true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     function baseName(url) | ||||
|     { | ||||
| @ -23,6 +44,8 @@ Rectangle { | ||||
|         return filename; | ||||
|     } | ||||
| 
 | ||||
|     //Player Subcomponents | ||||
| 
 | ||||
|     MediaPlayer { | ||||
|         id: player | ||||
|         volume: volumeBar.value | ||||
| @ -30,14 +53,27 @@ Rectangle { | ||||
|         onPlaybackStateChanged: { | ||||
|             switch (playbackState) { | ||||
|             case MediaPlayer.StoppedState: | ||||
|                 playerStateOverlay.source = '/qml/icons/playState_stopped.png' | ||||
|                 // Enforce Looping | ||||
|                 if(root.shouldKeepPlayingLoop){ | ||||
|                     // Loop behavior | ||||
|                     player.play(); | ||||
|                 } else { | ||||
|                     // Normal behavior | ||||
|                     playerStateOverlay.source = '/qml/icons/playState_stopped.png' | ||||
|                     progressBar.state = "stopped"; | ||||
|                 } | ||||
|                 break; | ||||
|             case MediaPlayer.PausedState: | ||||
|                 playerStateOverlay.source = '/qml/icons/playState_paused.png' | ||||
|                 progressBar.state = "paused"; | ||||
|                 break; | ||||
|             case MediaPlayer.PlayingState: | ||||
|             default: | ||||
|                 playerStateOverlay.source = '/qml/icons/playState_playing.png' | ||||
|                 progressBar.state = "playing"; | ||||
|                 // Enforce Looping | ||||
|                 if(root.isLooped) | ||||
|                     root.shouldKeepPlayingLoop = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
| @ -54,10 +90,26 @@ Rectangle { | ||||
| 
 | ||||
|         onDurationChanged: { | ||||
|             progressBar.duration = player.duration; | ||||
|             root.playRegionBegin = 0; | ||||
|             root.playRegionEnd = player.duration; | ||||
|         } | ||||
| 
 | ||||
|         onPositionChanged: { | ||||
|             //Update ProgressBar | ||||
|             progressBar.elapsedTime = player.position; | ||||
|             //Enforce play region and looping | ||||
|             if(root.isPlayRegionEnabled) | ||||
|                 if(0 < root.playRegionEnd && root.playRegionEnd <= player.position){ | ||||
|                     if(root.isLooped) | ||||
|                         player.seek(root.playRegionBegin); | ||||
|                     else { | ||||
|                         player.stop(); | ||||
|                         player.seek(root.playRegionBegin); | ||||
|                     } | ||||
|                 } else if (player.position < root.playRegionBegin && 0 < root.playRegionBegin && root.playRegionBegin < root.playRegionEnd) { | ||||
|                     player.seek(root.playRegionBegin); | ||||
|                 } | ||||
| 
 | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| @ -121,14 +173,58 @@ Rectangle { | ||||
|             onClicked: { | ||||
|                 switch (player.playbackState) { | ||||
|                 case MediaPlayer.StoppedState: | ||||
|                     player.play(); | ||||
|                     switch(root.triggerStyle){ | ||||
|                     default: | ||||
|                     case CasterPlayerModel.PlayPauseTriggerStyle: | ||||
|                         player.play(); | ||||
|                         break; | ||||
|                     case CasterPlayerModel.PlayStopTriggerStyle: | ||||
|                         player.play(); | ||||
|                         break; | ||||
|                     case CasterPlayerModel.PlayAgainTriggerStyle: | ||||
|                         if(root.isPlayRegionEnabled) | ||||
|                             player.seek(root.playRegionBegin); | ||||
|                         else | ||||
|                             player.seek(0); | ||||
|                         player.play(); | ||||
|                         break; | ||||
|                     } | ||||
|                     break; | ||||
|                 case MediaPlayer.PausedState: | ||||
|                     player.play(); | ||||
|                     switch(root.triggerStyle){ | ||||
|                     default: | ||||
|                     case CasterPlayerModel.PlayPauseTriggerStyle: | ||||
|                         player.play(); | ||||
|                         break; | ||||
|                     case CasterPlayerModel.PlayStopTriggerStyle: | ||||
|                         player.play(); | ||||
|                         break; | ||||
|                     case CasterPlayerModel.PlayAgainTriggerStyle: | ||||
|                         if(root.isPlayRegionEnabled) | ||||
|                             player.seek(root.playRegionBegin); | ||||
|                         else | ||||
|                             player.seek(0); | ||||
|                         player.play(); | ||||
|                         break; | ||||
|                     } | ||||
|                     break; | ||||
|                 case MediaPlayer.PlayingState: | ||||
|                 default: | ||||
|                     player.pause(); | ||||
|                 case MediaPlayer.PlayingState: | ||||
|                     switch(root.triggerStyle){ | ||||
|                     default: | ||||
|                     case CasterPlayerModel.PlayPauseTriggerStyle: | ||||
|                         player.pause(); | ||||
|                         break; | ||||
|                     case CasterPlayerModel.PlayStopTriggerStyle: | ||||
|                         player.stop(); | ||||
|                         break; | ||||
|                     case CasterPlayerModel.PlayAgainTriggerStyle: | ||||
|                         if(root.isPlayRegionEnabled) | ||||
|                             player.seek(root.playRegionBegin); | ||||
|                         else | ||||
|                             player.seek(0); | ||||
|                         break; | ||||
|                     } | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
| @ -156,6 +252,10 @@ Rectangle { | ||||
|         id: progressBar | ||||
|         visible: root.isInPlayerMode | ||||
|         enabled: root.isInPlayerMode | ||||
|         isLooped: root.isLooped | ||||
|         isPlayRegionEnabled: root.isPlayRegionEnabled | ||||
|         playRegionBegin: root.playRegionBegin | ||||
|         playRegionEnd: root.playRegionEnd | ||||
|         x: 5 ; y: root.height - this.height - 12; | ||||
|         onMoved: { | ||||
|             player.seek(progressBar.value); | ||||
| @ -166,9 +266,11 @@ Rectangle { | ||||
|         id: volumeBar | ||||
|         visible: root.isInPlayerMode | ||||
|         enabled: root.isInPlayerMode | ||||
|         x: root.size - 45; y: 10; | ||||
|         x: root.size - this.width - 5; y: 10; | ||||
|         value: root.volume | ||||
|         onMoved: { | ||||
|             player.volume = volumeBar.value; | ||||
|             player.volume = volumeBar.value;//Change volume | ||||
|             root.volume = volumeBar.value;//Update model since we are changing volume internally | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -3,24 +3,126 @@ import QtGraphicalEffects 1.0 | ||||
| import QtQuick.Controls 2.4 | ||||
| 
 | ||||
| Slider { | ||||
|     id: control | ||||
|     id: root | ||||
| 
 | ||||
|     // Component properties | ||||
|     implicitWidth: 200 | ||||
|     implicitHeight: 25 | ||||
|     implicitHeight: 40 | ||||
|     from: 0 | ||||
|     to: 0 | ||||
|     stepSize: 1 | ||||
|     state: "stopped" | ||||
| 
 | ||||
|     // Volume bar properties, functions & events | ||||
|     property bool isLooped: false | ||||
|     property bool isPlayRegionEnabled: false | ||||
|     property int playRegionBegin: 0 | ||||
|     property int playRegionEnd: 0 | ||||
|     property int elapsedTime: 0 | ||||
|     property int duration: 0 | ||||
| 
 | ||||
|     states: [ | ||||
|         State { | ||||
|             name: "stopped" | ||||
|             PropertyChanges { target: sliderHandle; color: "#6AFF0000" } | ||||
|             PropertyChanges { target: repeatIcon; color: "#000000" } | ||||
|             PropertyChanges { target: foregroundBar; color: "red" } | ||||
|             PropertyChanges { | ||||
|                 target: trackTimeElapsed | ||||
|                 color: (sliderHandle.x >= sliderHandle.width + 8 ? "white" : "black") | ||||
|             } | ||||
|             PropertyChanges { | ||||
|                 target: trackTimeRemaining | ||||
|                 color: (sliderHandle.x + sliderHandle.width >= parent.width - this.width - 5 ? "white" : "black") | ||||
|             } | ||||
|         }, | ||||
|         State { | ||||
|             name: "paused" | ||||
|             PropertyChanges { target: sliderHandle; color: "#80FFFF00" } | ||||
|             PropertyChanges { target: repeatIcon; color: "#000000" } | ||||
|             PropertyChanges { target: foregroundBar; color: "yellow" } | ||||
|             PropertyChanges { target: trackTimeElapsed; color: "black" } | ||||
|             PropertyChanges { target: trackTimeRemaining; color: "black" } | ||||
|         }, | ||||
|         State { | ||||
|             name: "playing" | ||||
|             PropertyChanges { target: sliderHandle; color: "#6A00FF00" } | ||||
|             PropertyChanges { target: repeatIcon; color: "#000000" } | ||||
|             PropertyChanges { target: foregroundBar; color: "green" } | ||||
|             PropertyChanges { | ||||
|                 target: trackTimeElapsed | ||||
|                 color: (sliderHandle.x >= sliderHandle.width + 8 ? "white" : "black") | ||||
|             } | ||||
|             PropertyChanges { | ||||
|                 target: trackTimeRemaining | ||||
|                 color: (sliderHandle.x + sliderHandle.width >= parent.width - this.width - 5 ? "white" : "black") | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
| 
 | ||||
|     transitions: [ | ||||
|         Transition { | ||||
|             from: "stopped"; to: "playing" | ||||
|             ColorAnimation { target: sliderHandle; properties: "color" | ||||
|                 from: "#6AFF0000"; to: "#6A00FF00"; duration: 150 | ||||
|             } | ||||
|             ColorAnimation { target: foregroundBar; properties: "color" | ||||
|                 from: "red"; to: "green"; duration: 150 | ||||
|             } | ||||
|         }, | ||||
|         Transition { | ||||
|             from: "stopped"; to: "paused" | ||||
|             ColorAnimation { target: sliderHandle; properties: "color" | ||||
|                 from: "#6AFF0000"; to: "#80FFFF00"; duration: 150 | ||||
|             } | ||||
|             ColorAnimation { target: foregroundBar; properties: "color" | ||||
|                 from: "red"; to: "yellow"; duration: 150 | ||||
|             } | ||||
|         }, | ||||
|         Transition { | ||||
|             from: "playing"; to: "paused" | ||||
|             ColorAnimation { target: sliderHandle; properties: "color" | ||||
|                 from: "#6A00FF00"; to: "#80FFFF00"; duration: 150 | ||||
|             } | ||||
|             ColorAnimation { target: foregroundBar; properties: "color" | ||||
|                 from: "green"; to: "yellow"; duration: 150 | ||||
|             } | ||||
|         }, | ||||
|         Transition { | ||||
|             from: "playing"; to: "stopped" | ||||
|             ColorAnimation { target: sliderHandle; properties: "color" | ||||
|                 from: "#6A00FF00"; to: "#6AFF0000"; duration: 150 | ||||
|             } | ||||
|             ColorAnimation { target: foregroundBar; properties: "color" | ||||
|                 from: "green"; to: "red"; duration: 150 | ||||
|             } | ||||
|         }, | ||||
|         Transition { | ||||
|             from: "paused"; to: "playing" | ||||
|             ColorAnimation { target: sliderHandle; properties: "color" | ||||
|                 from: "#80FFFF00"; to: "#6A00FF00"; duration: 150 | ||||
|             } | ||||
|             ColorAnimation { target: foregroundBar; properties: "color" | ||||
|                 from: "yellow"; to: "green"; duration: 150 | ||||
|             } | ||||
|         }, | ||||
|         Transition { | ||||
|             from: "paused"; to: "stopped" | ||||
|             ColorAnimation { target: sliderHandle; properties: "color" | ||||
|                 from: "#80FFFF00"; to: "#6AFF0000"; duration: 150 | ||||
|             } | ||||
|             ColorAnimation { target: foregroundBar; properties: "color" | ||||
|                 from: "yellow"; to: "red"; duration: 150 | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
| 
 | ||||
|     onElapsedTimeChanged: { | ||||
|         control.value = control.elapsedTime; | ||||
|         root.value = root.elapsedTime; | ||||
|     } | ||||
| 
 | ||||
|     onDurationChanged: { | ||||
|         control.to = control.duration; | ||||
|         root.to = root.duration; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| @ -49,56 +151,81 @@ Slider { | ||||
|         return "-" + ("00" + mins).slice(-2) + ':' + ("00" + secs).slice(-2); | ||||
|     } | ||||
| 
 | ||||
|     // Component UI | ||||
| 
 | ||||
|     handle: Rectangle { | ||||
|         id: sliderHandle | ||||
|         x: control.visualPosition * (control.width - width) | ||||
|         y: (control.height - height) / 2 | ||||
|         x: root.visualPosition * (root.width - width) | ||||
|         y: (root.height - height) / 2 | ||||
|         width: 45 | ||||
|         height: 40 | ||||
|         color: control.pressed ? "#f0f0f0" : "#f6f6f6" | ||||
|         height: root.height | ||||
|         border.color: "white" | ||||
|         border.width: 2 | ||||
|         opacity: 0.87 | ||||
|         //color: "#414345" | ||||
|         /* | ||||
|         gradient: Gradient { | ||||
|             GradientStop { position: 0.0; color: "#414345" } | ||||
|             GradientStop { position: 1.0; color: "#232526" } | ||||
|         } | ||||
|         }*/ | ||||
| 
 | ||||
|         Image { | ||||
|             id: loopStateImage | ||||
|             width: Math.floor(0.90 * control.width); height: Math.floor(0.90 * control.height) | ||||
|             width: Math.floor(0.6 * sliderHandle.width); height: Math.floor(0.6 * sliderHandle.height) | ||||
|             fillMode: Image.PreserveAspectFit | ||||
|             anchors.centerIn: parent | ||||
|             source: '/qml/icons/loop.png' | ||||
|             visible: control.isLooped | ||||
|             visible: root.isLooped | ||||
|         } | ||||
| 
 | ||||
|         ColorOverlay { | ||||
|                 anchors.fill: loopStateImage; source: loopStateImage | ||||
|                 color: "#ffffff" | ||||
|                 visible: control.isLooped | ||||
|             id: repeatIcon | ||||
|             anchors.fill: loopStateImage; source: loopStateImage | ||||
|             visible: root.isLooped | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     background: Rectangle { | ||||
|         y: (control.height - height) / 2 | ||||
|         height: 20 | ||||
|         border.color: "white" | ||||
|         border.width: 2 | ||||
|         gradient: Gradient { | ||||
|             GradientStop { position: 0.0; color: "#cfcfcf" } | ||||
|             GradientStop { position: 1.0; color: "#9e9e9e" } | ||||
|     background: Item { | ||||
|         id: background | ||||
|         y: (root.height - height) / 2 | ||||
|         width: root.width; height: 20 | ||||
| 
 | ||||
|         Rectangle { | ||||
|             id: playRegion | ||||
|             x: (root.playRegionBegin <= 0 || root.duration <= 0) ? 0 : root.width * root.playRegionBegin / root.duration | ||||
|             y: -20 | ||||
|             width: (root.playRegionEnd <= 0 || root.duration <= 0) ? 0 : root.width * (root.playRegionEnd - root.playRegionBegin) / root.duration | ||||
|             height: root.height + 20 | ||||
|             opacity: 0.8 | ||||
|             color: "blue" | ||||
|             visible: root.isPlayRegionEnabled | ||||
|         } | ||||
| 
 | ||||
|         Rectangle { | ||||
|             width: control.visualPosition * parent.width | ||||
|             height: parent.height | ||||
|                 id: backgroundBar | ||||
|                 width: root.width; height: 20 | ||||
|                 border.color: "white" | ||||
|                 border.width: 2 | ||||
|                 gradient: Gradient { | ||||
|                     GradientStop { position: 0.0; color: "#cfcfcf" } | ||||
|                     GradientStop { position: 1.0; color: "#9e9e9e" } | ||||
|                 } | ||||
|         } | ||||
| 
 | ||||
|         Rectangle { | ||||
|             id: foregroundBar | ||||
|             width: root.visualPosition * parent.width | ||||
|             height: 20 | ||||
|             border.color: "white" | ||||
|             border.width: 2 | ||||
|             gradient: Gradient { | ||||
|                 GradientStop { position: 0.0; color: "#414345" } | ||||
|                 GradientStop { position: 1.0; color: "#232526" } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Rectangle { | ||||
|             id: playRegionPosition | ||||
|             x: root.visualPosition * (root.width - width/2); y: -20 | ||||
|             width: 5; height: root.height + 20 | ||||
|             opacity: 0.9 | ||||
|             color: "yellow" | ||||
|             visible: root.isPlayRegionEnabled | ||||
|         } | ||||
| 
 | ||||
|         Text { | ||||
| @ -109,7 +236,7 @@ Slider { | ||||
|              font.family: "Helvetica" | ||||
|              font.bold: true | ||||
|              font.pointSize: 14 | ||||
|              text: timeElapsed(control.elapsedTime) | ||||
|              text: timeElapsed(root.elapsedTime) | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
| @ -121,7 +248,7 @@ Slider { | ||||
|              font.family: "Helvetica" | ||||
|              font.bold: true | ||||
|              font.pointSize: 14 | ||||
|              text: timeRemaining(control.elapsedTime, control.duration) | ||||
|              text: timeRemaining(root.elapsedTime, root.duration) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -2,16 +2,15 @@ import QtQuick 2.7 | ||||
| import QtQuick.Controls 2.4 | ||||
| 
 | ||||
| Slider { | ||||
|     id: control | ||||
|     id: root | ||||
|     orientation: Qt.Vertical | ||||
| 
 | ||||
|     implicitWidth: 25 | ||||
|     implicitWidth: 50 | ||||
|     implicitHeight: 145 | ||||
| 
 | ||||
|     handle: Rectangle { | ||||
|         x: (control.width - width) / 2 | ||||
|         y: control.visualPosition * (control.height - height) | ||||
|         width: 50 | ||||
|         y: root.visualPosition * (root.height - height) | ||||
|         width: root.width | ||||
|         height: 60 | ||||
|         border.color: "white" | ||||
|         border.width: 2 | ||||
| @ -34,14 +33,14 @@ Slider { | ||||
|             anchors.centerIn: parent | ||||
|             color: "white" | ||||
|             font.family: "Helvetica"; font.pointSize: 18; font.bold: true | ||||
|             text: Math.floor(control.value * 100) + "%" | ||||
|             text: Math.floor(root.value * 100) + "%" | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     background: Rectangle { | ||||
|         x: (control.width - width) / 2; y: 25 | ||||
|         x: (root.width - width) / 2; y: 25 | ||||
|         width: 20 | ||||
|         height: control.height - 50 | ||||
|         height: root.height - 50 | ||||
|         border.color: "white" | ||||
|         border.width: 2 | ||||
|         gradient: Gradient { | ||||
|  | ||||
| @ -4,21 +4,54 @@ import QtQuick.Controls 2.4 | ||||
| import QtQuick.Layouts 1.11 | ||||
| import QtMultimedia 5.9 | ||||
| 
 | ||||
| import MVC_CasterPlayer 1.0 | ||||
| 
 | ||||
| import "./subcomponents" as Subcomponent | ||||
| 
 | ||||
| Drawer { | ||||
|     id: root | ||||
|     //Component properties | ||||
|     edge: Qt.RightEdge | ||||
|     interactive: false | ||||
|     width: parent.width * 0.66; height: parent.height | ||||
|     background: Rectangle { anchors.fill: parent; color: "#00000000" } | ||||
| 
 | ||||
|     //Settings properties & functions | ||||
|     property int playerIndex: 0 | ||||
|     function openSettings(player_index){ | ||||
|         root.playerIndex = player_index | ||||
|         //Set active player | ||||
|         root.playerIndex = player_index; | ||||
|         //Update setting components | ||||
|         settingLoopSwitch.checked = soundboard1.soundboardPlayers.itemAt(playerIndex).isLooped; | ||||
|         settingPlayRegionEnabledSwitch.checked = soundboard1.soundboardPlayers.itemAt(playerIndex).isPlayRegionEnabled; | ||||
|         settingPlayRegionRange.regionBegin = soundboard1.soundboardPlayers.itemAt(playerIndex).playRegionBegin; | ||||
|         settingPlayRegionRange.regionEnd = soundboard1.soundboardPlayers.itemAt(playerIndex).playRegionEnd; | ||||
|         settingPlayRegionRange.duration = soundboard1.soundboardPlayers.itemAt(playerIndex).duration; | ||||
|         //open settings drawer | ||||
|         root.open(); | ||||
|     } | ||||
|     signal settingChanged (var role, var settingValue) | ||||
|     onSettingChanged: { | ||||
|         switch (role) { | ||||
|         case CasterPlayerModel.IsLoopedRole: | ||||
|             soundboard1.soundboardPlayers.itemAt(playerIndex).isLooped = settingValue; | ||||
|             break; | ||||
|         case CasterPlayerModel.IsPlayingRegionEnabledRole: | ||||
|             soundboard1.soundboardPlayers.itemAt(playerIndex).isPlayRegionEnabled = settingValue; | ||||
|             break; | ||||
|         case CasterPlayerModel.TriggerStyleRole: | ||||
|             soundboard1.soundboardPlayers.itemAt(playerIndex).triggerStyle = settingValue; | ||||
|             break; | ||||
|         case CasterPlayerModel.PlayRegionBeginRole: | ||||
|             soundboard1.soundboardPlayers.itemAt(playerIndex).playRegionBegin = settingValue; | ||||
|             break; | ||||
|         case CasterPlayerModel.PlayRegionEndRole: | ||||
|             soundboard1.soundboardPlayers.itemAt(playerIndex).playRegionEnd = settingValue; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     // Settings subcomponents | ||||
|     Pane { | ||||
|         id: header | ||||
|         width: parent.width; height: 60 | ||||
| @ -42,6 +75,7 @@ Drawer { | ||||
|     } | ||||
| 
 | ||||
|     Rectangle { | ||||
|         id: settingsArea | ||||
|         anchors.top: header.bottom | ||||
|         width: parent.width; height: parent.height | ||||
|         color: "#DF333333" | ||||
| @ -55,15 +89,15 @@ Drawer { | ||||
| 
 | ||||
|             Column { | ||||
|                 id: columnView | ||||
|                 anchors.fill: parent | ||||
|                 width: root.width; | ||||
|                 spacing: 8 | ||||
| 
 | ||||
|                 Item { | ||||
|                 Item {//Action: Remove Player | ||||
|                     width: parent.width; height: 50 | ||||
| 
 | ||||
|                     Subcomponent.BootstrapButton { | ||||
|                         anchors.centerIn: parent | ||||
|                         text: 'Delete Player'; type: 'danger' | ||||
|                         text: 'Remove Player'; type: 'danger' | ||||
|                         onClicked: { | ||||
|                             casterPlayerController.removeItemAt(root.playerIndex); | ||||
|                             root.close(); | ||||
| @ -71,6 +105,77 @@ Drawer { | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 Item {//Setting: isLooped | ||||
|                     width: parent.width; height:100 | ||||
| 
 | ||||
|                     Subcomponent.FlatSwitch { | ||||
|                         id: settingLoopSwitch | ||||
|                         anchors.centerIn: parent | ||||
|                         questionText: "Loop sound?" | ||||
|                         checkedText: "YES" | ||||
|                         uncheckedText: "NO" | ||||
|                         onToggled: { | ||||
|                             root.settingChanged(CasterPlayerModel.IsLoopedRole, checked); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 Item {//Setting: isPlayRegionEnabled | ||||
|                     width: parent.width; height:100 | ||||
| 
 | ||||
|                     Subcomponent.FlatSwitch { | ||||
|                         id: settingPlayRegionEnabledSwitch | ||||
|                         anchors.centerIn: parent | ||||
|                         questionText: "Play region:" | ||||
|                         onToggled: { | ||||
|                             root.settingChanged(CasterPlayerModel.IsPlayingRegionEnabledRole, checked); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 Item {//Setting: play region time range | ||||
|                     width: parent.width; height:100 | ||||
| 
 | ||||
|                     Subcomponent.TimeRangeSelector { | ||||
|                         id: settingPlayRegionRange | ||||
|                         anchors.centerIn: parent | ||||
| 
 | ||||
|                         onRegionBeginChanged: { | ||||
|                             root.settingChanged(CasterPlayerModel.PlayRegionBeginRole, regionBegin); | ||||
|                         } | ||||
| 
 | ||||
|                         onRegionEndChanged: { | ||||
|                             root.settingChanged(CasterPlayerModel.PlayRegionEndRole, regionEnd); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 Item {//Setting: Trigger Style | ||||
|                     width: parent.width; height: 100 | ||||
| 
 | ||||
|                     Subcomponent.StateSelector { | ||||
|                         id: settingTriggerStyle | ||||
|                         anchors.centerIn: parent | ||||
| 
 | ||||
|                         label: "Test label" | ||||
|                         list: ListModel { | ||||
|                             ListElement { | ||||
|                                 name: "Play/Pause" | ||||
|                             } | ||||
|                             ListElement { | ||||
|                                 name: "Play/Stop" | ||||
|                             } | ||||
|                             ListElement { | ||||
|                                 name: "Play Again" | ||||
|                             } | ||||
|                         } | ||||
| 
 | ||||
|                         onSelectedIndexChanged: { | ||||
|                             root.settingChanged(CasterPlayerModel.TriggerStyleRole, selectedIndex); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|             } | ||||
|  | ||||
| @ -0,0 +1,135 @@ | ||||
| import QtQuick 2.7 | ||||
| import QtGraphicalEffects 1.0 | ||||
| import QtQuick.Controls 2.4 | ||||
| import QtQuick.Layouts 1.11 | ||||
| 
 | ||||
| Item { | ||||
|     id: root | ||||
|     // Component properties | ||||
|     width: parent.width; height: parent.height | ||||
|     state: "unchecked" | ||||
| 
 | ||||
|     // Switch Properties & events | ||||
|     property bool checked: false | ||||
|     property string questionText: "State:" | ||||
|     property alias questionTextFont: question.font | ||||
|     property string checkedText: "ON" | ||||
|     property string uncheckedText: "OFF" | ||||
|     signal toggled | ||||
|     onToggled: { | ||||
|         switch(root.checked){ | ||||
|         case false: | ||||
|             root.checked = true; | ||||
|             break; | ||||
|         case true: | ||||
|             root.checked = false; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     onCheckedChanged: { | ||||
|         switch(root.checked){ | ||||
|         case false: | ||||
|             root.state = "unchecked"; | ||||
|             break; | ||||
|         case true: | ||||
|             root.state = "checked"; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     states: [ | ||||
|         State { | ||||
|             name: "unchecked" | ||||
|             PropertyChanges { target: background; color: "#434343" } | ||||
|         }, | ||||
|         State { | ||||
|             name: "checked" | ||||
|             PropertyChanges { target: background; color: "#764ba2" } | ||||
|         } | ||||
|     ] | ||||
| 
 | ||||
|     transitions: [ | ||||
|         Transition { | ||||
|             from: "unchecked"; to: "checked" | ||||
|             NumberAnimation { target: handle; properties: "x"; from: 0; to: switchContainer.width - handle.width; duration: 70 } | ||||
|             ColorAnimation { | ||||
|                 target: background | ||||
|                 properties: "color" | ||||
|                 from: "#434343" | ||||
|                 to: "#764ba2" | ||||
|                 duration: 150 | ||||
|             } | ||||
|         }, | ||||
|         Transition { | ||||
|             from: "checked"; to: "unchecked" | ||||
|             NumberAnimation { target: handle; properties: "x"; from: switchContainer.width - handle.width; to: 0; duration: 70 } | ||||
|             ColorAnimation { | ||||
|                 target: background | ||||
|                 properties: "color" | ||||
|                 from: "#764ba2" | ||||
|                 to: "#434343" | ||||
|                 duration: 150 | ||||
|             } | ||||
|         } | ||||
|     ] | ||||
| 
 | ||||
|     Column { | ||||
|         id: gridContainer | ||||
|         width: root.width | ||||
|         height: root.height | ||||
|         spacing: 8 | ||||
| 
 | ||||
|         Item { | ||||
|             id: questionContainer | ||||
|             x: (parent.width - this.width)/2 | ||||
|             width: question.width; height: 0.5 * parent.height | ||||
| 
 | ||||
|             Text { | ||||
|                 id: question | ||||
|                 y: (questionContainer.height - this.height)/2 | ||||
|                 color: "white" | ||||
|                 font.bold: true | ||||
|                 font.pointSize: 24 | ||||
|                 text: root.questionText | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Item { | ||||
|             id: switchContainer | ||||
|             x: (parent.width - this.width)/2 | ||||
|             width: 120; height: 0.5 * parent.height | ||||
| 
 | ||||
|             Rectangle { | ||||
|                 id: background | ||||
|                 width: parent.width; height: parent.height | ||||
|                 radius: parent.height | ||||
|                 border.color: "white" | ||||
|                 border.width: 2 | ||||
|             } | ||||
| 
 | ||||
|             Text { | ||||
|                 x: root.checked ? (switchContainer.width - handle.width - this.width) : handle.width; y: (switchContainer.height - this.height)/2 | ||||
|                 color: "white" | ||||
|                 font.bold: true | ||||
|                 font.pointSize: 24 | ||||
|                 text: root.checked ? qsTr(root.checkedText) : qsTr(root.uncheckedText) | ||||
|             } | ||||
| 
 | ||||
|             Rectangle { | ||||
|                 id: handle | ||||
|                 width: parent.height; height: parent.height | ||||
|                 radius: parent.height | ||||
|                 border.color: "white" | ||||
|                 border.width: 2 | ||||
|                 color: "#667eea" | ||||
|             } | ||||
| 
 | ||||
|             MouseArea { | ||||
|                 width: parent.width; height: parent.height | ||||
|                 onClicked: root.toggled() | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,83 @@ | ||||
| import QtQuick 2.7 | ||||
| import QtGraphicalEffects 1.0 | ||||
| import QtQuick.Controls 2.4 | ||||
| import QtQuick.Layouts 1.11 | ||||
| 
 | ||||
| Item { | ||||
|     id: selector | ||||
| 
 | ||||
|     property alias list: view.model | ||||
|     property alias selectedIndex: view.currentIndex | ||||
|     property alias label: labelText.text | ||||
|     property bool expanded | ||||
| 
 | ||||
|     width: parent.width; height: parent.height | ||||
| 
 | ||||
|     Rectangle { | ||||
|         anchors { left: parent.left; right: parent.right; bottom: parent.bottom; } | ||||
| 
 | ||||
|         height: labelText.implicitHeight + 4 + (expanded ? 20 * view.count : 20) | ||||
|         Behavior on height { NumberAnimation { duration: 300 } } | ||||
| 
 | ||||
|         radius: 2 | ||||
|         border.width: 1 | ||||
|         border.color: "yellow" | ||||
|         color: "yellow" | ||||
| 
 | ||||
|         MouseArea { | ||||
|             anchors.fill: parent | ||||
| 
 | ||||
|             onClicked: selector.expanded = !selector.expanded | ||||
| 
 | ||||
|             Text { | ||||
|                 id: labelText | ||||
|                 anchors { left: parent.left; top: parent.top; margins: 2 } | ||||
|             } | ||||
| 
 | ||||
|             Rectangle { | ||||
|                 anchors { | ||||
|                     left: parent.left; top: labelText.bottom; | ||||
|                     right: parent.right; bottom: parent.bottom; | ||||
|                     margins: 2 | ||||
|                     leftMargin: 10 | ||||
|                 } | ||||
| 
 | ||||
|                 radius: 2 | ||||
|                 color: "white" | ||||
| 
 | ||||
|                 ListView { | ||||
|                     id: view | ||||
| 
 | ||||
|                     anchors.fill: parent | ||||
| 
 | ||||
|                     clip: true | ||||
| 
 | ||||
|                     delegate: Text { | ||||
|                         anchors { left: parent.left; right: parent.right } | ||||
|                         height: 20 | ||||
| 
 | ||||
|                         verticalAlignment: Text.AlignVCenter | ||||
| 
 | ||||
|                         text: modelData | ||||
| 
 | ||||
|                         MouseArea { | ||||
|                             anchors.fill: parent | ||||
| 
 | ||||
|                             onClicked: { | ||||
|                                 view.currentIndex = index | ||||
|                                 selector.expanded = !selector.expanded | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     highlight: Rectangle { | ||||
|                         anchors { left: parent.left; right: parent.right } | ||||
|                         height: 20 | ||||
|                         radius: 2 | ||||
| 
 | ||||
|                         color: "yellow" | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,152 @@ | ||||
| import QtQuick 2.7 | ||||
| import QtGraphicalEffects 1.0 | ||||
| import QtQuick.Controls 2.4 | ||||
| import QtQuick.Layouts 1.11 | ||||
| 
 | ||||
| import "./" as Subcomponent | ||||
| 
 | ||||
| Item { | ||||
|     id: root | ||||
|     // Component properties | ||||
|     width: parent.width; height: parent.height | ||||
| 
 | ||||
|     // Properties, functions & events | ||||
|     property int regionBegin: 0 | ||||
|     onRegionBeginChanged: beginInput.text = root.msToProperTime(root.regionBegin) | ||||
|     property int regionEnd: 0 | ||||
|     onRegionEndChanged: endInput.text = root.msToProperTime(root.regionEnd) | ||||
|     property int duration: 0 | ||||
|     property string labelText: "Set play region range:" | ||||
| 
 | ||||
|     function msToProperTime(msTime){ | ||||
|         var secs = (msTime / 1000 - (msTime % 1000) / 1000) % 60; | ||||
|         var mins = ((msTime / 1000 - (msTime % 1000) / 1000) - secs) / 60; | ||||
|         return ("00" + mins).slice(-2) + ':' + ("00" + secs).slice(-2); | ||||
|     } | ||||
| 
 | ||||
|     function properTimeToMs(properTime){ | ||||
|         var ms = 0; | ||||
|         var time = properTime.split(':'); | ||||
|         if(time.length === 2){ | ||||
|             ms = parseInt(time[0], 10) * 60 * 1000 + parseInt(time[1], 10) * 1000; | ||||
|         } | ||||
|         return ms; | ||||
|     } | ||||
| 
 | ||||
|     // Component UI | ||||
| 
 | ||||
|     Column { | ||||
|         id: columnContainer | ||||
|         width: root.width | ||||
|         height: root.height | ||||
|         spacing: 8 | ||||
| 
 | ||||
|         Item { | ||||
|             id: labelContainer | ||||
|             x: (parent.width - this.width)/2 | ||||
|             width: label.width; height: 0.33 * parent.height | ||||
| 
 | ||||
|             Text { | ||||
|                 id: label | ||||
|                 y: (labelContainer.height - this.height)/2 | ||||
|                 color: "white" | ||||
|                 font.bold: true | ||||
|                 font.pointSize: 24 | ||||
|                 text: root.labelText | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Item { | ||||
|             id: rangeContainer | ||||
|             width: parent.width; height: 0.33 * parent.height | ||||
| 
 | ||||
|             Row { | ||||
|                 anchors.centerIn: parent | ||||
| 
 | ||||
|                 Text { | ||||
|                     id: beginLabel | ||||
|                     color: "white" | ||||
|                     font.bold: true | ||||
|                     font.pointSize: 24 | ||||
|                     text: "BEGIN:" | ||||
|                 } | ||||
| 
 | ||||
|                 Item { | ||||
|                     width: 80; height: parent.height | ||||
|                     clip: true | ||||
| 
 | ||||
|                     Rectangle { | ||||
|                         width: parent.width; height: parent.height | ||||
|                         color: "white" | ||||
|                     } | ||||
| 
 | ||||
|                     TextInput { | ||||
|                         id: beginInput | ||||
|                         width: parent.width; height: parent.height | ||||
|                         font.bold: true | ||||
|                         font.pointSize: 20 | ||||
|                         verticalAlignment: Text.AlignVCenter | ||||
|                         horizontalAlignment: Text.AlignHCenter | ||||
|                         text: root.msToProperTime(root.regionBegin) | ||||
|                     } | ||||
|                 } | ||||
| 
 | ||||
|                 Text { | ||||
|                     id: endLabel | ||||
|                     color: "white" | ||||
|                     font.bold: true | ||||
|                     font.pointSize: 24 | ||||
|                     text: "END:" | ||||
|                 } | ||||
| 
 | ||||
|                 Item { | ||||
|                     width: 80; height: parent.height | ||||
|                     clip: true | ||||
| 
 | ||||
|                     Rectangle { | ||||
|                         width: parent.width; height: parent.height | ||||
|                         color: "white" | ||||
|                     } | ||||
| 
 | ||||
|                     TextInput { | ||||
|                         id: endInput | ||||
|                         width: parent.width; height: parent.height | ||||
|                         font.bold: true | ||||
|                         font.pointSize: 20 | ||||
|                         verticalAlignment: Text.AlignVCenter | ||||
|                         horizontalAlignment: Text.AlignHCenter | ||||
|                         text: root.msToProperTime(root.regionEnd) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         Item { | ||||
|             width: parent.width; height: 0.33 * parent.height | ||||
|             Subcomponent.BootstrapButton { | ||||
|                 id: setRangeButton | ||||
|                 width: 100; height: parent.height | ||||
|                 anchors.centerIn: parent | ||||
|                 text: 'Set Range'; type: 'info' | ||||
|                 onClicked: { | ||||
|                     var beginTemp = root.properTimeToMs(beginInput.text); | ||||
|                     var endTemp = root.properTimeToMs(endInput.text); | ||||
|                     if(0 <= beginTemp && beginTemp < root.duration && beginTemp < endTemp){ | ||||
|                         if(0 < endTemp && beginTemp < endTemp && endTemp <= root.duration){ | ||||
|                             root.regionBegin = beginTemp; | ||||
|                             root.regionEnd = endTemp; | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     // Update Inputs | ||||
|                     beginInput.text = root.msToProperTime(root.regionBegin); | ||||
|                     endInput.text = root.msToProperTime(root.regionEnd); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @ -4,6 +4,8 @@ import QtGraphicalEffects 1.0 | ||||
| import QtQuick.Controls 2.4 | ||||
| import QtQuick.Layouts 1.11 | ||||
| 
 | ||||
| import MVC_CasterPlayer 1.0 | ||||
| 
 | ||||
| import "./components/caster_board" as CasterBoard | ||||
| import "./components/caster_player_settings_drawer" as CasterPlayerSettingsDrawer | ||||
| 
 | ||||
| @ -22,9 +24,7 @@ ApplicationWindow { | ||||
|     height: 600 | ||||
|     color: "#4D4D4D" | ||||
| 
 | ||||
|     CasterPlayerSettingsDrawer.Component { | ||||
|         id: casterPlayerSettingsDrawer | ||||
|     } | ||||
|     CasterPlayerSettingsDrawer.Component { id: casterPlayerSettingsDrawer } | ||||
| 
 | ||||
|     Rectangle { | ||||
|         id: mainSideNav | ||||
| @ -234,7 +234,7 @@ ApplicationWindow { | ||||
|                     currentIndex: mainSoundboardsContainer_tabBar.currentIndex | ||||
|                     Item { | ||||
|                         id: tab1 | ||||
|                         CasterBoard.Component {} | ||||
|                         CasterBoard.Component {id: soundboard1 } | ||||
|                     } | ||||
|                     Item { | ||||
|                         id: tab2 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user