@ -25,8 +25,10 @@ MessageDelegate::MessageDelegate(QObject *parent)
struct VoicePlayState {
bool playing = false ;
bool paused = false ;
qint64 startMs = 0 ;
float durationSec = 0.0f ;
float pausedPosSec = 0.0f ;
} ;
static QMap < QString , VoicePlayState > s_voiceStates ;
static QTimer * s_voiceTimer = nullptr ;
@ -39,10 +41,13 @@ static void ensureVoiceTimer() {
bool anyPlaying = false ;
qint64 now = QDateTime : : currentMSecsSinceEpoch ( ) ;
for ( auto it = s_voiceStates . begin ( ) ; it ! = s_voiceStates . end ( ) ; ) {
if ( ! it - > playing & & ! it - > paused ) { + + it ; continue ; }
if ( it - > paused ) { + + it ; continue ; }
if ( ! it - > playing ) { + + it ; continue ; }
float elapsed = ( now - it - > startMs ) / 1000.0f ;
if ( elapsed > = it - > durationSec & & it - > durationSec > 0 ) {
it - > playing = false ;
it - > paused = false ;
SoundManager : : instance ( ) - > stopCurrentPcm ( ) ;
+ + it ;
} else {
@ -51,7 +56,6 @@ static void ensureVoiceTimer() {
}
}
if ( ! anyPlaying ) s_voiceTimer - > stop ( ) ;
// Trigger repaint through any visible view
if ( auto * w = QApplication : : activeWindow ( ) ) w - > update ( ) ;
} ) ;
}
@ -75,29 +79,57 @@ bool MessageDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
ensureVoiceTimer ( ) ;
VoicePlayState & st = s_voiceStates [ filePath ] ;
bool isOtherPlaying = false ;
for ( auto it = s_voiceStates . begin ( ) ; it ! = s_voiceStates . end ( ) ; + + it ) {
if ( it . key ( ) ! = filePath & & ( it - > playing | | it - > paused ) )
isOtherPlaying = true ;
}
if ( st . playing ) {
/* Playing → Pause */
qint64 now = QDateTime : : currentMSecsSinceEpoch ( ) ;
st . pausedPosSec = ( now - st . startMs ) / 1000.0f ;
st . playing = false ;
SoundManager : : instance ( ) - > stopCurrentPcm ( ) ;
model - > setData ( index , 0 , MsgVoicePlayStateRole ) ;
} else {
for ( auto it = s_voiceStates . begin ( ) ; it ! = s_voiceStates . end ( ) ; + + it )
it - > playing = false ;
SoundManager : : instance ( ) - > stopCurrentPcm ( ) ;
QString durStr = index . data ( MsgVoiceDurationRole ) . toString ( ) ;
durStr . remove ( ' s ' ) ;
float dur = durStr . toFloat ( ) ;
if ( dur < = 0 ) dur = 1.0f ;
st . paused = true ;
SoundManager : : instance ( ) - > pauseCurrentPcm ( ) ;
model - > setData ( index , 2 , MsgVoicePlayStateRole ) ;
return true ;
}
if ( st . paused ) {
/* Paused → Resume */
st . paused = false ;
st . playing = true ;
st . startMs = QDateTime : : currentMSecsSinceEpoch ( ) ;
st . durationSec = dur ;
VoicePlayer : : playOpusFile ( filePath ) ;
qint64 now = QDateTime : : currentMSecsSinceEpoch ( ) ;
st . startMs = now - ( qint64 ) ( st . pausedPosSec * 1000.0 ) ;
SoundManager : : instance ( ) - > resumeCurrentPcm ( ) ;
s_voiceTimer - > start ( ) ;
model - > setData ( index , 1 , MsgVoicePlayStateRole ) ;
return true ;
}
/* Stopped or different file → stop old, play new */
if ( isOtherPlaying ) {
for ( auto it = s_voiceStates . begin ( ) ; it ! = s_voiceStates . end ( ) ; + + it ) {
it - > playing = false ; it - > paused = false ;
}
SoundManager : : instance ( ) - > stopCurrentPcm ( ) ;
}
QString durStr = index . data ( MsgVoiceDurationRole ) . toString ( ) ;
durStr . remove ( ' s ' ) ;
float dur = durStr . toFloat ( ) ;
if ( dur < = 0 ) dur = 1.0f ;
st . playing = true ;
st . paused = false ;
st . pausedPosSec = 0 ;
st . startMs = QDateTime : : currentMSecsSinceEpoch ( ) ;
st . durationSec = dur ;
VoicePlayer : : playOpusFile ( filePath ) ;
s_voiceTimer - > start ( ) ;
model - > setData ( index , 1 , MsgVoicePlayStateRole ) ;
return true ;
}
@ -578,13 +610,14 @@ void MessageDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
}
bool isPlaying = st . playing ;
bool isPaused = st . paused ;
QRectF playR = L . voicePlayBtnRect ;
/* Play/Pause button */
painter - > setPen ( Qt : : NoPen ) ;
painter - > setBrush ( QColor ( 0x33 , 0x90 , 0xEC ) ) ;
if ( isPlaying ) {
if ( isPlaying | | isPaused ) {
/* Pause icon (two vertical bars) */
qreal bw = playR . width ( ) / 5.0 ;
qreal gap = playR . width ( ) / 8.0 ;
@ -617,10 +650,15 @@ void MessageDelegate::paint(QPainter *painter, const QStyleOptionViewItem &optio
int pbTop = L . voicePlayBtnRect . bottom ( ) + 6 ;
int pbHeight = 3 ;
if ( isPlaying & & st . durationSec > 0 ) {
qint64 now = QDateTime : : currentMSecsSinceEpoch ( ) ;
float elapsed = ( now - st . startMs ) / 1000.0f ;
if ( elapsed > st . durationSec ) elapsed = st . durationSec ;
if ( ( isPlaying | | isPaused ) & & st . durationSec > 0 ) {
float elapsed ;
if ( isPaused ) {
elapsed = st . pausedPosSec ;
} else {
qint64 now = QDateTime : : currentMSecsSinceEpoch ( ) ;
elapsed = ( now - st . startMs ) / 1000.0f ;
if ( elapsed > st . durationSec ) elapsed = st . durationSec ;
}
float frac = elapsed / st . durationSec ;
painter - > setPen ( Qt : : NoPen ) ;