Compare commits

...

5 commits

Author SHA1 Message Date
xiaoyifang 1c842a06c2
Merge 15b918eb6a into bd13598cc2 2024-11-16 08:48:35 +02:00
shenleban tongying bd13598cc2
refactor: move internalpayerbackend out of config.cc to src/audio
Some checks are pending
SonarCloud / Build and analyze (push) Waiting to run
2024-11-15 20:31:36 -05:00
autofix-ci[bot] 15b918eb6a
[autofix.ci] apply automated fixes 2024-11-08 01:47:29 +00:00
xiaoyifang 27cbb7351b opt: add option about 2024-11-06 13:35:22 +08:00
xiaoyifang c787a08d2f opt: add option about 2024-11-06 12:07:23 +08:00
10 changed files with 180 additions and 143 deletions

View file

@ -67,7 +67,7 @@ jobs:
libzim \ libzim \
qt qt
wget ftp://ftp.sra.co.jp/pub/misc/eb/eb-4.4.3.tar.bz2 wget https://github.com/mistydemeo/eb/releases/download/v4.4.3/eb-4.4.3.tar.bz2
tar xvjf eb-4.4.3.tar.bz2 tar xvjf eb-4.4.3.tar.bz2
cd eb-4.4.3 && ./configure && make -j 8 && sudo make install && cd .. cd eb-4.4.3 && ./configure && make -j 8 && sudo make install && cd ..

View file

@ -3,34 +3,39 @@
#include <QScopedPointer> #include <QScopedPointer>
#include <QObject> #include <QObject>
#include <utility>
#include "audioplayerfactory.hh" #include "audioplayerfactory.hh"
#include "ffmpegaudioplayer.hh" #include "ffmpegaudioplayer.hh"
#include "multimediaaudioplayer.hh" #include "multimediaaudioplayer.hh"
#include "externalaudioplayer.hh" #include "externalaudioplayer.hh"
#include "gddebug.hh" #include "gddebug.hh"
AudioPlayerFactory::AudioPlayerFactory( Config::Preferences const & p ): AudioPlayerFactory::AudioPlayerFactory( bool useInternalPlayer,
useInternalPlayer( p.useInternalPlayer ), InternalPlayerBackend internalPlayerBackend,
internalPlayerBackend( p.internalPlayerBackend ), QString audioPlaybackProgram ):
audioPlaybackProgram( p.audioPlaybackProgram ) useInternalPlayer( useInternalPlayer ),
internalPlayerBackend( std::move( internalPlayerBackend ) ),
audioPlaybackProgram( std::move( audioPlaybackProgram ) )
{ {
reset(); reset();
} }
void AudioPlayerFactory::setPreferences( Config::Preferences const & p ) void AudioPlayerFactory::setPreferences( bool new_useInternalPlayer,
const InternalPlayerBackend & new_internalPlayerBackend,
const QString & new_audioPlaybackProgram )
{ {
if ( p.useInternalPlayer != useInternalPlayer ) { if ( useInternalPlayer != new_useInternalPlayer ) {
useInternalPlayer = p.useInternalPlayer; useInternalPlayer = new_useInternalPlayer;
internalPlayerBackend = p.internalPlayerBackend; internalPlayerBackend = new_internalPlayerBackend;
audioPlaybackProgram = p.audioPlaybackProgram; audioPlaybackProgram = new_audioPlaybackProgram;
reset(); reset();
} }
else if ( useInternalPlayer && p.internalPlayerBackend != internalPlayerBackend ) { else if ( useInternalPlayer && internalPlayerBackend != new_internalPlayerBackend ) {
internalPlayerBackend = p.internalPlayerBackend; internalPlayerBackend = new_internalPlayerBackend;
reset(); reset();
} }
else if ( !useInternalPlayer && p.audioPlaybackProgram != audioPlaybackProgram ) { else if ( !useInternalPlayer && new_audioPlaybackProgram != audioPlaybackProgram ) {
audioPlaybackProgram = p.audioPlaybackProgram; audioPlaybackProgram = new_audioPlaybackProgram;
ExternalAudioPlayer * const externalPlayer = qobject_cast< ExternalAudioPlayer * >( playerPtr.data() ); ExternalAudioPlayer * const externalPlayer = qobject_cast< ExternalAudioPlayer * >( playerPtr.data() );
if ( externalPlayer ) { if ( externalPlayer ) {
setAudioPlaybackProgram( *externalPlayer ); setAudioPlaybackProgram( *externalPlayer );
@ -50,7 +55,7 @@ void AudioPlayerFactory::reset()
// another object of the same type. // another object of the same type.
#ifdef MAKE_FFMPEG_PLAYER #ifdef MAKE_FFMPEG_PLAYER
Q_ASSERT( Config::InternalPlayerBackend::defaultBackend().isFfmpeg() Q_ASSERT( InternalPlayerBackend::defaultBackend().isFfmpeg()
&& "Adjust the code below after changing the default backend." ); && "Adjust the code below after changing the default backend." );
if ( !internalPlayerBackend.isQtmultimedia() ) { if ( !internalPlayerBackend.isQtmultimedia() ) {

View file

@ -4,7 +4,7 @@
#pragma once #pragma once
#include "audioplayerinterface.hh" #include "audioplayerinterface.hh"
#include "config.hh" #include "internalplayerbackend.hh"
class ExternalAudioPlayer; class ExternalAudioPlayer;
@ -13,8 +13,12 @@ class AudioPlayerFactory
Q_DISABLE_COPY( AudioPlayerFactory ) Q_DISABLE_COPY( AudioPlayerFactory )
public: public:
explicit AudioPlayerFactory( Config::Preferences const & ); explicit AudioPlayerFactory( bool useInternalPlayer,
void setPreferences( Config::Preferences const & ); InternalPlayerBackend internalPlayerBackend,
QString audioPlaybackProgram );
void setPreferences( bool new_useInternalPlayer,
const InternalPlayerBackend & new_internalPlayerBackend,
const QString & new_audioPlaybackProgram );
/// The returned reference to a smart pointer is valid as long as this object /// The returned reference to a smart pointer is valid as long as this object
/// exists. The pointer to the owned AudioPlayerInterface may change after the /// exists. The pointer to the owned AudioPlayerInterface may change after the
/// call to setPreferences(), but it is guaranteed to never be null. /// call to setPreferences(), but it is guaranteed to never be null.
@ -28,7 +32,7 @@ private:
void setAudioPlaybackProgram( ExternalAudioPlayer & externalPlayer ); void setAudioPlaybackProgram( ExternalAudioPlayer & externalPlayer );
bool useInternalPlayer; bool useInternalPlayer;
Config::InternalPlayerBackend internalPlayerBackend; InternalPlayerBackend internalPlayerBackend;
QString audioPlaybackProgram; QString audioPlaybackProgram;
AudioPlayerPtr playerPtr; AudioPlayerPtr playerPtr;
}; };

View file

@ -0,0 +1,51 @@
#include "internalplayerbackend.hh"
bool InternalPlayerBackend::anyAvailable()
{
#if defined( MAKE_FFMPEG_PLAYER ) || defined( MAKE_QTMULTIMEDIA_PLAYER )
return true;
#else
return false;
#endif
}
InternalPlayerBackend InternalPlayerBackend::defaultBackend()
{
#if defined( MAKE_FFMPEG_PLAYER )
return ffmpeg();
#elif defined( MAKE_QTMULTIMEDIA_PLAYER )
return qtmultimedia();
#else
return InternalPlayerBackend( QString() );
#endif
}
QStringList InternalPlayerBackend::nameList()
{
QStringList result;
#ifdef MAKE_FFMPEG_PLAYER
result.push_back( ffmpeg().uiName() );
#endif
#ifdef MAKE_QTMULTIMEDIA_PLAYER
result.push_back( qtmultimedia().uiName() );
#endif
return result;
}
bool InternalPlayerBackend::isFfmpeg() const
{
#ifdef MAKE_FFMPEG_PLAYER
return *this == ffmpeg();
#else
return false;
#endif
}
bool InternalPlayerBackend::isQtmultimedia() const
{
#ifdef MAKE_QTMULTIMEDIA_PLAYER
return *this == qtmultimedia();
#else
return false;
#endif
}

View file

@ -0,0 +1,61 @@
#pragma once
#include <QStringList>
/// Overly engineered dummy/helper/wrapper "backend", which is not, to manage backends.
class InternalPlayerBackend
{
public:
/// Returns true if at least one backend is available.
static bool anyAvailable();
/// Returns the default backend or null backend if none is available.
static InternalPlayerBackend defaultBackend();
/// Returns the name list of supported backends.
static QStringList nameList();
/// Returns true if built with FFmpeg player support and the name matches.
bool isFfmpeg() const;
/// Returns true if built with Qt Multimedia player support and the name matches.
bool isQtmultimedia() const;
QString const & uiName() const
{
return name;
}
void setUiName( QString const & name_ )
{
name = name_;
}
bool operator==( InternalPlayerBackend const & other ) const
{
return name == other.name;
}
bool operator!=( InternalPlayerBackend const & other ) const
{
return !operator==( other );
}
private:
#ifdef MAKE_FFMPEG_PLAYER
static InternalPlayerBackend ffmpeg()
{
return InternalPlayerBackend( "FFmpeg" );
}
#endif
#ifdef MAKE_QTMULTIMEDIA_PLAYER
static InternalPlayerBackend qtmultimedia()
{
return InternalPlayerBackend( "Qt Multimedia" );
}
#endif
explicit InternalPlayerBackend( QString const & name_ ):
name( name_ )
{
}
QString name;
};

View file

@ -119,57 +119,6 @@ QKeySequence HotKey::toKeySequence() const
; ;
} }
bool InternalPlayerBackend::anyAvailable()
{
#if defined( MAKE_FFMPEG_PLAYER ) || defined( MAKE_QTMULTIMEDIA_PLAYER )
return true;
#else
return false;
#endif
}
InternalPlayerBackend InternalPlayerBackend::defaultBackend()
{
#if defined( MAKE_FFMPEG_PLAYER )
return ffmpeg();
#elif defined( MAKE_QTMULTIMEDIA_PLAYER )
return qtmultimedia();
#else
return InternalPlayerBackend( QString() );
#endif
}
QStringList InternalPlayerBackend::nameList()
{
QStringList result;
#ifdef MAKE_FFMPEG_PLAYER
result.push_back( ffmpeg().uiName() );
#endif
#ifdef MAKE_QTMULTIMEDIA_PLAYER
result.push_back( qtmultimedia().uiName() );
#endif
return result;
}
bool InternalPlayerBackend::isFfmpeg() const
{
#ifdef MAKE_FFMPEG_PLAYER
return *this == ffmpeg();
#else
return false;
#endif
}
bool InternalPlayerBackend::isQtmultimedia() const
{
#ifdef MAKE_QTMULTIMEDIA_PLAYER
return *this == qtmultimedia();
#else
return false;
#endif
}
QString Preferences::sanitizeInputPhrase( QString const & inputWord ) const QString Preferences::sanitizeInputPhrase( QString const & inputWord ) const
{ {
QString result = inputWord; QString result = inputWord;
@ -201,6 +150,7 @@ Preferences::Preferences():
doubleClickTranslates( true ), doubleClickTranslates( true ),
selectWordBySingleClick( false ), selectWordBySingleClick( false ),
autoScrollToTargetArticle( true ), autoScrollToTargetArticle( true ),
targetArticleAtFirst( false ),
escKeyHidesMainWindow( false ), escKeyHidesMainWindow( false ),
alwaysOnTop( false ), alwaysOnTop( false ),
searchInDock( false ), searchInDock( false ),
@ -929,6 +879,11 @@ Class load()
( preferences.namedItem( "autoScrollToTargetArticle" ).toElement().text() == "1" ); ( preferences.namedItem( "autoScrollToTargetArticle" ).toElement().text() == "1" );
} }
if ( !preferences.namedItem( "targetArticleAtFirst" ).isNull() ) {
c.preferences.targetArticleAtFirst =
( preferences.namedItem( "targetArticleAtFirst" ).toElement().text() == "1" );
}
if ( !preferences.namedItem( "escKeyHidesMainWindow" ).isNull() ) { if ( !preferences.namedItem( "escKeyHidesMainWindow" ).isNull() ) {
c.preferences.escKeyHidesMainWindow = c.preferences.escKeyHidesMainWindow =
( preferences.namedItem( "escKeyHidesMainWindow" ).toElement().text() == "1" ); ( preferences.namedItem( "escKeyHidesMainWindow" ).toElement().text() == "1" );
@ -1866,6 +1821,10 @@ void save( Class const & c )
opt.appendChild( dd.createTextNode( c.preferences.autoScrollToTargetArticle ? "1" : "0" ) ); opt.appendChild( dd.createTextNode( c.preferences.autoScrollToTargetArticle ? "1" : "0" ) );
preferences.appendChild( opt ); preferences.appendChild( opt );
opt = dd.createElement( "targetArticleAtFirst" );
opt.appendChild( dd.createTextNode( c.preferences.targetArticleAtFirst ? "1" : "0" ) );
preferences.appendChild( opt );
opt = dd.createElement( "escKeyHidesMainWindow" ); opt = dd.createElement( "escKeyHidesMainWindow" );
opt.appendChild( dd.createTextNode( c.preferences.escKeyHidesMainWindow ? "1" : "0" ) ); opt.appendChild( dd.createTextNode( c.preferences.escKeyHidesMainWindow ? "1" : "0" ) );
preferences.appendChild( opt ); preferences.appendChild( opt );

View file

@ -3,19 +3,20 @@
#pragma once #pragma once
#include <QObject> #include "audio/internalplayerbackend.hh"
#include <QList>
#include <QString>
#include <QSize>
#include <QDateTime>
#include <QKeySequence>
#include <QSet>
#include <QMetaType>
#include "ex.hh" #include "ex.hh"
#include <QDateTime>
#include <QDomDocument> #include <QDomDocument>
#include <QKeySequence>
#include <QList>
#include <QLocale> #include <QLocale>
#include <optional> #include <QMetaType>
#include <QObject>
#include <QSet>
#include <QSize>
#include <QString>
#include <QThread> #include <QThread>
#include <optional>
/// Special group IDs /// Special group IDs
enum GroupId : unsigned { enum GroupId : unsigned {
@ -269,66 +270,6 @@ struct CustomFonts
} }
}; };
/// This class encapsulates supported backend preprocessor logic,
/// discourages duplicating backend names in code, which is error-prone.
class InternalPlayerBackend
{
public:
/// Returns true if at least one backend is available.
static bool anyAvailable();
/// Returns the default backend or null backend if none is available.
static InternalPlayerBackend defaultBackend();
/// Returns the name list of supported backends.
static QStringList nameList();
/// Returns true if built with FFmpeg player support and the name matches.
bool isFfmpeg() const;
/// Returns true if built with Qt Multimedia player support and the name matches.
bool isQtmultimedia() const;
QString const & uiName() const
{
return name;
}
void setUiName( QString const & name_ )
{
name = name_;
}
bool operator==( InternalPlayerBackend const & other ) const
{
return name == other.name;
}
bool operator!=( InternalPlayerBackend const & other ) const
{
return !operator==( other );
}
private:
#ifdef MAKE_FFMPEG_PLAYER
static InternalPlayerBackend ffmpeg()
{
return InternalPlayerBackend( "FFmpeg" );
}
#endif
#ifdef MAKE_QTMULTIMEDIA_PLAYER
static InternalPlayerBackend qtmultimedia()
{
return InternalPlayerBackend( "Qt Multimedia" );
}
#endif
explicit InternalPlayerBackend( QString const & name_ ):
name( name_ )
{
}
QString name;
};
/// Various user preferences /// Various user preferences
struct Preferences struct Preferences
{ {
@ -356,6 +297,7 @@ struct Preferences
bool doubleClickTranslates; bool doubleClickTranslates;
bool selectWordBySingleClick; bool selectWordBySingleClick;
bool autoScrollToTargetArticle; bool autoScrollToTargetArticle;
bool targetArticleAtFirst;
bool escKeyHidesMainWindow; bool escKeyHidesMainWindow;
bool alwaysOnTop; bool alwaysOnTop;

View file

@ -167,7 +167,8 @@ MainWindow::MainWindow( Config::Class & cfg_ ):
cfg.preferences.disallowContentFromOtherSites, cfg.preferences.disallowContentFromOtherSites,
cfg.preferences.hideGoldenDictHeader ), cfg.preferences.hideGoldenDictHeader ),
dictNetMgr( this ), dictNetMgr( this ),
audioPlayerFactory( cfg.preferences ), audioPlayerFactory(
cfg.preferences.useInternalPlayer, cfg.preferences.internalPlayerBackend, cfg.preferences.audioPlaybackProgram ),
wordFinder( this ), wordFinder( this ),
wordListSelChanged( false ), wordListSelChanged( false ),
wasMaximized( false ), wasMaximized( false ),
@ -2356,7 +2357,9 @@ void MainWindow::editPreferences()
#endif #endif
} }
audioPlayerFactory.setPreferences( cfg.preferences ); audioPlayerFactory.setPreferences( cfg.preferences.useInternalPlayer,
cfg.preferences.internalPlayerBackend,
cfg.preferences.audioPlaybackProgram );
trayIconUpdateOrInit(); trayIconUpdateOrInit();
applyProxySettings(); applyProxySettings();

View file

@ -185,6 +185,7 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
ui.doubleClickTranslates->setChecked( p.doubleClickTranslates ); ui.doubleClickTranslates->setChecked( p.doubleClickTranslates );
ui.selectBySingleClick->setChecked( p.selectWordBySingleClick ); ui.selectBySingleClick->setChecked( p.selectWordBySingleClick );
ui.autoScrollToTargetArticle->setChecked( p.autoScrollToTargetArticle ); ui.autoScrollToTargetArticle->setChecked( p.autoScrollToTargetArticle );
ui.targetArticleAtFirst->setChecked( p.targetArticleAtFirst );
ui.escKeyHidesMainWindow->setChecked( p.escKeyHidesMainWindow ); ui.escKeyHidesMainWindow->setChecked( p.escKeyHidesMainWindow );
ui.darkMode->addItem( tr( "On" ), QVariant::fromValue( Config::Dark::On ) ); ui.darkMode->addItem( tr( "On" ), QVariant::fromValue( Config::Dark::On ) );
@ -294,7 +295,7 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
ui.pronounceOnLoadMain->setChecked( p.pronounceOnLoadMain ); ui.pronounceOnLoadMain->setChecked( p.pronounceOnLoadMain );
ui.pronounceOnLoadPopup->setChecked( p.pronounceOnLoadPopup ); ui.pronounceOnLoadPopup->setChecked( p.pronounceOnLoadPopup );
ui.internalPlayerBackend->addItems( Config::InternalPlayerBackend::nameList() ); ui.internalPlayerBackend->addItems( InternalPlayerBackend::nameList() );
// Make sure that exactly one radio button in the group is checked and that // Make sure that exactly one radio button in the group is checked and that
// on_useExternalPlayer_toggled() is called. // on_useExternalPlayer_toggled() is called.
@ -306,7 +307,7 @@ Preferences::Preferences( QWidget * parent, Config::Class & cfg_ ):
int index = ui.internalPlayerBackend->findText( p.internalPlayerBackend.uiName() ); int index = ui.internalPlayerBackend->findText( p.internalPlayerBackend.uiName() );
if ( index < 0 ) { // The specified backend is unavailable. if ( index < 0 ) { // The specified backend is unavailable.
index = ui.internalPlayerBackend->findText( Config::InternalPlayerBackend::defaultBackend().uiName() ); index = ui.internalPlayerBackend->findText( InternalPlayerBackend::defaultBackend().uiName() );
} }
Q_ASSERT( index >= 0 && "Logic error: the default backend must be present in the backend name list." ); Q_ASSERT( index >= 0 && "Logic error: the default backend must be present in the backend name list." );
ui.internalPlayerBackend->setCurrentIndex( index ); ui.internalPlayerBackend->setCurrentIndex( index );
@ -441,6 +442,7 @@ Config::Preferences Preferences::getPreferences()
p.doubleClickTranslates = ui.doubleClickTranslates->isChecked(); p.doubleClickTranslates = ui.doubleClickTranslates->isChecked();
p.selectWordBySingleClick = ui.selectBySingleClick->isChecked(); p.selectWordBySingleClick = ui.selectBySingleClick->isChecked();
p.autoScrollToTargetArticle = ui.autoScrollToTargetArticle->isChecked(); p.autoScrollToTargetArticle = ui.autoScrollToTargetArticle->isChecked();
p.targetArticleAtFirst = ui.targetArticleAtFirst->isChecked();
p.escKeyHidesMainWindow = ui.escKeyHidesMainWindow->isChecked(); p.escKeyHidesMainWindow = ui.escKeyHidesMainWindow->isChecked();
p.darkMode = ui.darkMode->currentData().value< Config::Dark >(); p.darkMode = ui.darkMode->currentData().value< Config::Dark >();

View file

@ -169,6 +169,16 @@ however, the article from the topmost dictionary is shown.</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="1">
<widget class="QCheckBox" name="targetArticleAtFirst">
<property name="text">
<string>Place the target article at the first place.</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QGroupBox" name="enableTrayIcon"> <widget class="QGroupBox" name="enableTrayIcon">
<property name="toolTip"> <property name="toolTip">