mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-27 19:24:08 +00:00
Some more TTS from Timon Wong
This commit is contained in:
parent
9cc2c89087
commit
9e416c360c
|
@ -698,6 +698,11 @@ void ArticleView::linkHovered ( const QString & link, const QString & , const QS
|
||||||
msg = tr( "Audio" );
|
msg = tr( "Audio" );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if ( url.scheme() == "gdtts" )
|
||||||
|
{
|
||||||
|
msg = tr( "TTS Voice" );
|
||||||
|
}
|
||||||
|
else
|
||||||
if ( url.scheme() == "gdpicture" )
|
if ( url.scheme() == "gdpicture" )
|
||||||
{
|
{
|
||||||
msg = tr( "Picture" );
|
msg = tr( "Picture" );
|
||||||
|
@ -964,14 +969,13 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
|
||||||
{
|
{
|
||||||
QString itemMd5Id = QString( QCryptographicHash::hash(
|
QString itemMd5Id = QString( QCryptographicHash::hash(
|
||||||
i->id.toUtf8(),
|
i->id.toUtf8(),
|
||||||
QCryptographicHash::Md5 ).toHex());
|
QCryptographicHash::Md5 ).toHex() );
|
||||||
|
|
||||||
if ( itemMd5Id == md5Id ) {
|
if ( itemMd5Id == md5Id )
|
||||||
|
{
|
||||||
SpeechClient * speechClient = new SpeechClient( i->id, this );
|
SpeechClient * speechClient = new SpeechClient( i->id, this );
|
||||||
connect( speechClient, SIGNAL( finished() ), speechClient, SLOT( deleteLater() ) );
|
connect( speechClient, SIGNAL( finished() ), speechClient, SLOT( deleteLater() ) );
|
||||||
if ( !speechClient->tell( text ) ) {
|
speechClient->tell( text );
|
||||||
delete speechClient;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
1
guids.c
1
guids.c
|
@ -10,6 +10,7 @@ DEFINE_GUID(IID_IUIAutomationTreeWalker, 0x4042c624, 0x389c, 0x4afc, 0xa6, 0x30
|
||||||
|
|
||||||
DEFINE_GUID(CLSID_SpVoice, 0x96749377, 0x3391, 0x11D2, 0x9e, 0xe3, 0x00, 0xc0, 0x4f, 0x79, 0x73, 0x96);
|
DEFINE_GUID(CLSID_SpVoice, 0x96749377, 0x3391, 0x11D2, 0x9e, 0xe3, 0x00, 0xc0, 0x4f, 0x79, 0x73, 0x96);
|
||||||
DEFINE_GUID(IID_ISpVoice, 0x6C44DF74, 0x72B9, 0x4992, 0xa1, 0xec, 0xef, 0x99, 0x6e, 0x04, 0x22, 0xd4);
|
DEFINE_GUID(IID_ISpVoice, 0x6C44DF74, 0x72B9, 0x4992, 0xa1, 0xec, 0xef, 0x99, 0x6e, 0x04, 0x22, 0xd4);
|
||||||
|
DEFINE_GUID(CLSID_SpObjectToken, 0xEF411752, 0x3736, 0x4CB4, 0x9c, 0x8c, 0x8e, 0xf4, 0xcc, 0xb5, 0x8e, 0xfe);
|
||||||
DEFINE_GUID(IID_ISpObjectToken, 0x14056589, 0xE16C, 0x11D2, 0xbb, 0x90, 0x00, 0xc0, 0x4f, 0x8e, 0xe6, 0xc0);
|
DEFINE_GUID(IID_ISpObjectToken, 0x14056589, 0xE16C, 0x11D2, 0xbb, 0x90, 0x00, 0xc0, 0x4f, 0x8e, 0xe6, 0xc0);
|
||||||
DEFINE_GUID(CLSID_SpObjectTokenCategory, 0xA910187F, 0x0C7A, 0x45AC, 0x92, 0xcc, 0x59, 0xed, 0xaf, 0xb7, 0x7b, 0x53);
|
DEFINE_GUID(CLSID_SpObjectTokenCategory, 0xA910187F, 0x0C7A, 0x45AC, 0x92, 0xcc, 0x59, 0xed, 0xaf, 0xb7, 0x7b, 0x53);
|
||||||
DEFINE_GUID(IID_ISpObjectTokenCategory, 0x2D3D3845, 0x39AF, 0x4850, 0xbb, 0xf9, 0x40, 0xb4, 0x97, 0x80, 0x01, 0x1d);
|
DEFINE_GUID(IID_ISpObjectTokenCategory, 0x2D3D3845, 0x39AF, 0x4850, 0xbb, 0xf9, 0x40, 0xb4, 0x97, 0x80, 0x01, 0x1d);
|
||||||
|
|
1
sapi.hh
1
sapi.hh
|
@ -172,6 +172,7 @@ typedef enum SPRUNSTATE
|
||||||
EXTERN_C const IID CLSID_SpVoice;
|
EXTERN_C const IID CLSID_SpVoice;
|
||||||
EXTERN_C const IID IID_ISpVoice;
|
EXTERN_C const IID IID_ISpVoice;
|
||||||
EXTERN_C const IID IID_ISpObjectToken;
|
EXTERN_C const IID IID_ISpObjectToken;
|
||||||
|
EXTERN_C const IID CLSID_SpObjectToken;
|
||||||
EXTERN_C const IID IID_IEnumSpObjectTokens;
|
EXTERN_C const IID IID_IEnumSpObjectTokens;
|
||||||
EXTERN_C const IID IID_ISpEventSource;
|
EXTERN_C const IID IID_ISpEventSource;
|
||||||
EXTERN_C const IID IID_ISpNotifySource;
|
EXTERN_C const IID IID_ISpNotifySource;
|
||||||
|
|
|
@ -23,12 +23,12 @@ public:
|
||||||
static Engines availableEngines();
|
static Engines availableEngines();
|
||||||
|
|
||||||
const Engine & engine() const;
|
const Engine & engine() const;
|
||||||
bool tell( QString const & text ) const;
|
bool tell( QString const & text );
|
||||||
bool say( QString const & text ) const;
|
bool say( QString const & text );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void started( bool ok );
|
||||||
void finished();
|
void finished();
|
||||||
void finished(SpeechClient *client);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void timerEvent( QTimerEvent * evt );
|
virtual void timerEvent( QTimerEvent * evt );
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
#include "speechclient.hh"
|
#include "speechclient.hh"
|
||||||
#include <QtCore>
|
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "speechhlp.hh"
|
#include "speechhlp.hh"
|
||||||
|
|
||||||
|
#include <QtCore>
|
||||||
|
|
||||||
struct SpeechClient::InternalData
|
struct SpeechClient::InternalData
|
||||||
{
|
{
|
||||||
InternalData( QString const & engineId ):
|
InternalData( QString const & engineId ):
|
||||||
waitingFinish( false )
|
waitingFinish( false )
|
||||||
{
|
{
|
||||||
sp = speechCreate( reinterpret_cast<const wchar_t*>( engineId.utf16() ) );
|
sp = speechCreate( engineId.toStdWString().c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
~InternalData()
|
~InternalData()
|
||||||
|
@ -19,27 +20,17 @@ struct SpeechClient::InternalData
|
||||||
|
|
||||||
SpeechHelper sp;
|
SpeechHelper sp;
|
||||||
Engine engine;
|
Engine engine;
|
||||||
typedef QPointer<SpeechClient> Ptr;
|
|
||||||
static QList<Ptr> ptrs;
|
|
||||||
bool waitingFinish;
|
bool waitingFinish;
|
||||||
};
|
};
|
||||||
|
|
||||||
QList<SpeechClient::InternalData::Ptr> SpeechClient::InternalData::ptrs =
|
|
||||||
QList<SpeechClient::InternalData::Ptr>();
|
|
||||||
|
|
||||||
SpeechClient::SpeechClient( QString const & engineId, QObject * parent ):
|
SpeechClient::SpeechClient( QString const & engineId, QObject * parent ):
|
||||||
QObject( parent ),
|
QObject( parent ),
|
||||||
internalData( new InternalData( engineId ) )
|
internalData( new InternalData( engineId ) )
|
||||||
{
|
{
|
||||||
Engine engine;
|
|
||||||
engine.id = QString::fromWCharArray( speechEngineId( internalData->sp ) );
|
|
||||||
engine.name = QString::fromWCharArray( speechEngineName( internalData->sp ) );
|
|
||||||
internalData->ptrs.push_back( this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SpeechClient::~SpeechClient()
|
SpeechClient::~SpeechClient()
|
||||||
{
|
{
|
||||||
internalData->ptrs.removeAll( this );
|
|
||||||
delete internalData;
|
delete internalData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +39,7 @@ static bool enumEngines( void * /* token */,
|
||||||
const wchar_t * name,
|
const wchar_t * name,
|
||||||
void * userData )
|
void * userData )
|
||||||
{
|
{
|
||||||
SpeechClient::Engines *pEngines = (SpeechClient::Engines *)userData;
|
SpeechClient::Engines * pEngines = ( SpeechClient::Engines * )userData;
|
||||||
SpeechClient::Engine engine =
|
SpeechClient::Engine engine =
|
||||||
{
|
{
|
||||||
QString::fromWCharArray( id ),
|
QString::fromWCharArray( id ),
|
||||||
|
@ -70,7 +61,7 @@ const SpeechClient::Engine & SpeechClient::engine() const
|
||||||
return internalData->engine;
|
return internalData->engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpeechClient::tell( QString const & text ) const
|
bool SpeechClient::tell( QString const & text )
|
||||||
{
|
{
|
||||||
if ( !speechAvailable( internalData->sp ) )
|
if ( !speechAvailable( internalData->sp ) )
|
||||||
return false;
|
return false;
|
||||||
|
@ -78,17 +69,27 @@ bool SpeechClient::tell( QString const & text ) const
|
||||||
if ( internalData->waitingFinish )
|
if ( internalData->waitingFinish )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
internalData->waitingFinish = true;
|
bool ok = speechTell( internalData->sp, text.toStdWString().c_str() );
|
||||||
const_cast<SpeechClient *>( this )->startTimer( 50 );
|
emit started( ok );
|
||||||
return speechTell( internalData->sp, reinterpret_cast<const wchar_t*>( text.utf16() ) );
|
|
||||||
|
if ( ok )
|
||||||
|
{
|
||||||
|
internalData->waitingFinish = true;
|
||||||
|
startTimer( 50 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit finished();
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SpeechClient::say( QString const & text ) const
|
bool SpeechClient::say( QString const & text )
|
||||||
{
|
{
|
||||||
if ( !speechAvailable( internalData->sp ) )
|
if ( !speechAvailable( internalData->sp ) )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return speechSay( internalData->sp, reinterpret_cast<const wchar_t*>( text.utf16() ) );
|
return speechSay( internalData->sp, text.toStdWString().c_str() );
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpeechClient::timerEvent( QTimerEvent * evt )
|
void SpeechClient::timerEvent( QTimerEvent * evt )
|
||||||
|
@ -100,9 +101,8 @@ void SpeechClient::timerEvent( QTimerEvent * evt )
|
||||||
|
|
||||||
if ( speechTellFinished( internalData->sp ) )
|
if ( speechTellFinished( internalData->sp ) )
|
||||||
{
|
{
|
||||||
killTimer( evt->timerId() ) ;
|
killTimer( evt->timerId() ) ;
|
||||||
internalData->waitingFinish = false;
|
internalData->waitingFinish = false;
|
||||||
emit finished();
|
emit finished();
|
||||||
emit finished( this );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
44
speechhlp.cc
44
speechhlp.cc
|
@ -1,5 +1,6 @@
|
||||||
#define WINVER 0x0500 // At least WinXP required
|
#define WINVER 0x0500 // At least WinXP required
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
#include "speechhlp.hh"
|
#include "speechhlp.hh"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -15,12 +16,13 @@ struct _SpeechHelper
|
||||||
wstring engineName;
|
wstring engineName;
|
||||||
bool willInvokeCoUninitialize;
|
bool willInvokeCoUninitialize;
|
||||||
|
|
||||||
_SpeechHelper() : willInvokeCoUninitialize(false)
|
_SpeechHelper() :
|
||||||
|
willInvokeCoUninitialize(false)
|
||||||
{
|
{
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||||
willInvokeCoUninitialize = (hr != RPC_E_CHANGED_MODE);
|
willInvokeCoUninitialize = (hr != RPC_E_CHANGED_MODE);
|
||||||
CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void**)&voice );
|
CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void**)&voice);
|
||||||
}
|
}
|
||||||
|
|
||||||
~_SpeechHelper()
|
~_SpeechHelper()
|
||||||
|
@ -33,25 +35,33 @@ struct _SpeechHelper
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool findByEngineName(void *token, const wchar_t *id, const wchar_t *name, void *userData)
|
|
||||||
{
|
|
||||||
SpeechHelper sp = (SpeechHelper)userData;
|
|
||||||
if (sp->engineId == id)
|
|
||||||
{
|
|
||||||
sp->voice->SetVoice((ISpObjectToken *)token);
|
|
||||||
sp->engineName = name;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpeechHelper speechCreate(const wchar_t *engineId)
|
SpeechHelper speechCreate(const wchar_t *engineId)
|
||||||
{
|
{
|
||||||
SpeechHelper sp = new _SpeechHelper();
|
SpeechHelper sp = new _SpeechHelper();
|
||||||
|
HRESULT hr;
|
||||||
|
ISpObjectToken * spToken;
|
||||||
|
|
||||||
|
hr = SpGetTokenFromId(engineId, &spToken);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
if (SUCCEEDED(hr) && sp->voice)
|
||||||
|
{
|
||||||
|
sp->voice->SetVoice(spToken);
|
||||||
|
|
||||||
|
WCHAR * engineName = NULL;
|
||||||
|
SpGetDescription( spToken, &engineName );
|
||||||
|
sp->engineId = engineId;
|
||||||
|
if (engineName)
|
||||||
|
{
|
||||||
|
sp->engineName = engineName;
|
||||||
|
CoTaskMemFree(engineName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
spToken->Release();
|
||||||
|
}
|
||||||
|
|
||||||
sp->engineId = engineId;
|
|
||||||
speechEnumerateAvailableEngines(findByEngineName, sp);
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
29
sphelper.hh
29
sphelper.hh
|
@ -28,6 +28,30 @@ inline void SpHexFromUlong(WCHAR * psz, ULONG ul)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline HRESULT SpGetTokenFromId(
|
||||||
|
const WCHAR * pszTokenId,
|
||||||
|
ISpObjectToken ** ppToken,
|
||||||
|
BOOL fCreateIfNotExist = FALSE)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
ISpObjectToken * cpToken;
|
||||||
|
hr = CoCreateInstance(CLSID_SpObjectToken, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
IID_ISpObjectToken, (void**)&cpToken);
|
||||||
|
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
hr = cpToken->SetId(NULL, pszTokenId, fCreateIfNotExist);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
{
|
||||||
|
*ppToken = cpToken;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cpToken->Release();
|
||||||
|
}
|
||||||
|
|
||||||
|
return hr;
|
||||||
|
}
|
||||||
|
|
||||||
inline HRESULT SpGetCategoryFromId(
|
inline HRESULT SpGetCategoryFromId(
|
||||||
const WCHAR * pszCategoryId,
|
const WCHAR * pszCategoryId,
|
||||||
ISpObjectTokenCategory ** ppCategory,
|
ISpObjectTokenCategory ** ppCategory,
|
||||||
|
@ -80,6 +104,8 @@ inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescrip
|
||||||
{
|
{
|
||||||
WCHAR szLangId[10];
|
WCHAR szLangId[10];
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
|
|
||||||
|
#if _SAPI_VER >= 0x053
|
||||||
WCHAR* pRegKeyPath = 0;
|
WCHAR* pRegKeyPath = 0;
|
||||||
WCHAR* pszTemp = 0;
|
WCHAR* pszTemp = 0;
|
||||||
HKEY Handle = NULL;
|
HKEY Handle = NULL;
|
||||||
|
@ -190,6 +216,9 @@ inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescrip
|
||||||
|
|
||||||
// If running on OSes released before Windows Vista query the localized string from the registry
|
// If running on OSes released before Windows Vista query the localized string from the registry
|
||||||
// If RegLoadMUIStringW failed to retrieved the localized Engine name retrieve the localized string from the fallback (Default) attribute
|
// If RegLoadMUIStringW failed to retrieved the localized Engine name retrieve the localized string from the fallback (Default) attribute
|
||||||
|
#else
|
||||||
|
hr = E_FAIL;
|
||||||
|
#endif // _SAPI_VER >= 0x053
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
{
|
{
|
||||||
// Free memory allocated above if necessary
|
// Free memory allocated above if necessary
|
||||||
|
|
|
@ -32,7 +32,7 @@ void TextToSpeechSource::on_addVoiceEngine_clicked()
|
||||||
if ( ui.availableVoiceEngines->count() == 0 )
|
if ( ui.availableVoiceEngines->count() == 0 )
|
||||||
{
|
{
|
||||||
QMessageBox::information( this, tr( "No TTS voice available" ),
|
QMessageBox::information( this, tr( "No TTS voice available" ),
|
||||||
tr( "Cannot find available TTS voice.<br>"
|
tr( "Cannot find availble TTS voice.<br>"
|
||||||
"Please make sure that at least one TTS engine installed on your computer already." ) );
|
"Please make sure that at least one TTS engine installed on your computer already." ) );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -54,8 +54,9 @@ void TextToSpeechSource::on_removeVoiceEngine_clicked()
|
||||||
voiceEnginesModel.getCurrentVoiceEngines()[ current.row() ].name ),
|
voiceEnginesModel.getCurrentVoiceEngines()[ current.row() ].name ),
|
||||||
QMessageBox::Ok,
|
QMessageBox::Ok,
|
||||||
QMessageBox::Cancel ) == QMessageBox::Ok )
|
QMessageBox::Cancel ) == QMessageBox::Ok )
|
||||||
|
{
|
||||||
voiceEnginesModel.removeVoiceEngine( current.row() );
|
voiceEnginesModel.removeVoiceEngine( current.row() );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextToSpeechSource::on_previewVoice_clicked()
|
void TextToSpeechSource::on_previewVoice_clicked()
|
||||||
|
@ -66,23 +67,17 @@ void TextToSpeechSource::on_previewVoice_clicked()
|
||||||
|
|
||||||
QString engineId = ui.availableVoiceEngines->itemData( idx ).toString();
|
QString engineId = ui.availableVoiceEngines->itemData( idx ).toString();
|
||||||
QString text = ui.previewText->text();
|
QString text = ui.previewText->text();
|
||||||
SpeechClient *speechClient = new SpeechClient( engineId, this );
|
SpeechClient * speechClient = new SpeechClient( engineId, this );
|
||||||
|
|
||||||
ui.previewVoice->setEnabled( false );
|
connect( speechClient, SIGNAL( started( bool ) ), ui.previewVoice, SLOT( setDisabled( bool ) ) );
|
||||||
connect( speechClient, SIGNAL( finished( SpeechClient * ) ),
|
connect( speechClient, SIGNAL( finished() ), this, SLOT( previewVoiceFinished() ) );
|
||||||
this, SLOT( previewVoiceFinished( SpeechClient * ) ) );
|
connect( speechClient, SIGNAL( finished() ), speechClient, SLOT( deleteLater() ) );
|
||||||
if ( !speechClient->tell( text ) ) {
|
speechClient->tell( text );
|
||||||
ui.previewVoice->setEnabled( true );
|
|
||||||
delete speechClient;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextToSpeechSource::previewVoiceFinished( SpeechClient * speechClient )
|
void TextToSpeechSource::previewVoiceFinished()
|
||||||
{
|
{
|
||||||
ui.previewVoice->setEnabled( true );
|
ui.previewVoice->setDisabled( false );
|
||||||
|
|
||||||
if (speechClient)
|
|
||||||
speechClient->deleteLater();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextToSpeechSource::fitSelectedVoiceEnginesColumns()
|
void TextToSpeechSource::fitSelectedVoiceEnginesColumns()
|
||||||
|
@ -100,7 +95,7 @@ VoiceEnginesModel::VoiceEnginesModel( QWidget * parent,
|
||||||
|
|
||||||
void VoiceEnginesModel::removeVoiceEngine( int index )
|
void VoiceEnginesModel::removeVoiceEngine( int index )
|
||||||
{
|
{
|
||||||
beginRemoveRows( QModelIndex(), index, index );
|
beginRemoveRows( QModelIndex(), index, index );
|
||||||
voiceEngines.erase( voiceEngines.begin() + index );
|
voiceEngines.erase( voiceEngines.begin() + index );
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
@ -111,9 +106,9 @@ void VoiceEnginesModel::addNewVoiceEngine( QString const & id, QString const & n
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Config::VoiceEngine v;
|
Config::VoiceEngine v;
|
||||||
v.enabled = true;
|
v.enabled = true;
|
||||||
v.id = id;
|
v.id = id;
|
||||||
v.name = name;
|
v.name = name;
|
||||||
|
|
||||||
beginInsertRows( QModelIndex(), voiceEngines.size(), voiceEngines.size() );
|
beginInsertRows( QModelIndex(), voiceEngines.size(), voiceEngines.size() );
|
||||||
voiceEngines.push_back( v );
|
voiceEngines.push_back( v );
|
||||||
|
@ -136,14 +131,15 @@ Qt::ItemFlags VoiceEnginesModel::flags( QModelIndex const & index ) const
|
||||||
|
|
||||||
if ( index.isValid() )
|
if ( index.isValid() )
|
||||||
{
|
{
|
||||||
switch ( index.column() ) {
|
switch ( index.column() )
|
||||||
case kColumnEnabled:
|
{
|
||||||
result |= Qt::ItemIsUserCheckable;
|
case kColumnEnabled:
|
||||||
break;
|
result |= Qt::ItemIsUserCheckable;
|
||||||
case kColumnEngineName:
|
break;
|
||||||
case kColumnIcon:
|
case kColumnEngineName:
|
||||||
result |= Qt::ItemIsEditable;
|
case kColumnIcon:
|
||||||
break;
|
result |= Qt::ItemIsEditable;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,7 +164,7 @@ QVariant VoiceEnginesModel::headerData( int section, Qt::Orientation /*orientati
|
||||||
{
|
{
|
||||||
if ( role == Qt::DisplayRole )
|
if ( role == Qt::DisplayRole )
|
||||||
{
|
{
|
||||||
switch( section )
|
switch ( section )
|
||||||
{
|
{
|
||||||
case kColumnEnabled:
|
case kColumnEnabled:
|
||||||
return tr( "Enabled" );
|
return tr( "Enabled" );
|
||||||
|
@ -211,7 +207,7 @@ QVariant VoiceEnginesModel::data( QModelIndex const & index, int role ) const
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoiceEnginesModel::setData( QModelIndex const & index, const QVariant & value,
|
bool VoiceEnginesModel::setData( QModelIndex const & index, const QVariant & value,
|
||||||
int role )
|
int role )
|
||||||
{
|
{
|
||||||
if ( index.row() >= voiceEngines.size() )
|
if ( index.row() >= voiceEngines.size() )
|
||||||
return false;
|
return false;
|
||||||
|
@ -276,8 +272,10 @@ void VoiceEngineEditor::setEngineId( QString const & engineId )
|
||||||
{
|
{
|
||||||
// Find index for the id
|
// Find index for the id
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
for ( int i = 0; i < count(); ++i ) {
|
for ( int i = 0; i < count(); ++i )
|
||||||
if ( engineId == itemData(i).toString() ) {
|
{
|
||||||
|
if ( engineId == itemData( i ).toString() )
|
||||||
|
{
|
||||||
idx = i;
|
idx = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -285,22 +283,22 @@ void VoiceEngineEditor::setEngineId( QString const & engineId )
|
||||||
setCurrentIndex( idx );
|
setCurrentIndex( idx );
|
||||||
}
|
}
|
||||||
|
|
||||||
VoiceEngineItemDelegate::VoiceEngineItemDelegate( SpeechClient::Engines const & engines, QObject *parent ) :
|
VoiceEngineItemDelegate::VoiceEngineItemDelegate( SpeechClient::Engines const & engines, QObject * parent ) :
|
||||||
QStyledItemDelegate( parent ),
|
QStyledItemDelegate( parent ),
|
||||||
engines( engines )
|
engines( engines )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget * VoiceEngineItemDelegate::createEditor( QWidget *parent,
|
QWidget * VoiceEngineItemDelegate::createEditor( QWidget * parent,
|
||||||
QStyleOptionViewItem const & option,
|
QStyleOptionViewItem const & option,
|
||||||
QModelIndex const & index ) const
|
QModelIndex const & index ) const
|
||||||
{
|
{
|
||||||
if( index.column() != VoiceEnginesModel::kColumnEngineName )
|
if ( index.column() != VoiceEnginesModel::kColumnEngineName )
|
||||||
return QStyledItemDelegate::createEditor( parent, option, index );
|
return QStyledItemDelegate::createEditor( parent, option, index );
|
||||||
return new VoiceEngineEditor( engines, parent );
|
return new VoiceEngineEditor( engines, parent );
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceEngineItemDelegate::setEditorData( QWidget *uncastedEditor, const QModelIndex & index ) const
|
void VoiceEngineItemDelegate::setEditorData( QWidget * uncastedEditor, const QModelIndex & index ) const
|
||||||
{
|
{
|
||||||
VoiceEngineEditor * editor = qobject_cast< VoiceEngineEditor * >( uncastedEditor );
|
VoiceEngineEditor * editor = qobject_cast< VoiceEngineEditor * >( uncastedEditor );
|
||||||
if ( !editor )
|
if ( !editor )
|
||||||
|
@ -312,7 +310,7 @@ void VoiceEngineItemDelegate::setEditorData( QWidget *uncastedEditor, const QMod
|
||||||
editor->setEngineId( engineId );
|
editor->setEngineId( engineId );
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceEngineItemDelegate::setModelData( QWidget *uncastedEditor, QAbstractItemModel * model,
|
void VoiceEngineItemDelegate::setModelData( QWidget * uncastedEditor, QAbstractItemModel * model,
|
||||||
const QModelIndex & index ) const
|
const QModelIndex & index ) const
|
||||||
{
|
{
|
||||||
VoiceEngineEditor * editor = qobject_cast< VoiceEngineEditor * >( uncastedEditor );
|
VoiceEngineEditor * editor = qobject_cast< VoiceEngineEditor * >( uncastedEditor );
|
||||||
|
|
|
@ -93,7 +93,7 @@ private slots:
|
||||||
void on_addVoiceEngine_clicked();
|
void on_addVoiceEngine_clicked();
|
||||||
void on_removeVoiceEngine_clicked();
|
void on_removeVoiceEngine_clicked();
|
||||||
void on_previewVoice_clicked();
|
void on_previewVoice_clicked();
|
||||||
void previewVoiceFinished( SpeechClient * speechClient );
|
void previewVoiceFinished();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::TextToSpeechSource ui;
|
Ui::TextToSpeechSource ui;
|
||||||
|
|
|
@ -7,21 +7,24 @@
|
||||||
#include "utf8.hh"
|
#include "utf8.hh"
|
||||||
#include "wstring_qt.hh"
|
#include "wstring_qt.hh"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
|
||||||
namespace VoiceEngines {
|
namespace VoiceEngines
|
||||||
|
{
|
||||||
|
|
||||||
using namespace Dictionary;
|
using namespace Dictionary;
|
||||||
|
using std::string;
|
||||||
|
using std::map;
|
||||||
|
|
||||||
namespace StringConv {
|
inline string toMd5( QByteArray const & b )
|
||||||
|
|
||||||
inline QString toMd5( QByteArray const & b )
|
|
||||||
{
|
{
|
||||||
return QString( QCryptographicHash::hash( b, QCryptographicHash::Md5 ).toHex() );
|
return string( QCryptographicHash::hash( b, QCryptographicHash::Md5 ).toHex().constData() );
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class VoiceEnginesDictionary: public Dictionary::Class
|
class VoiceEnginesDictionary: public Dictionary::Class
|
||||||
|
@ -34,7 +37,7 @@ public:
|
||||||
|
|
||||||
VoiceEnginesDictionary( Config::VoiceEngine const & voiceEngine ):
|
VoiceEnginesDictionary( Config::VoiceEngine const & voiceEngine ):
|
||||||
Dictionary::Class(
|
Dictionary::Class(
|
||||||
StringConv::toMd5( voiceEngine.id.toUtf8() ).toStdString(),
|
toMd5( voiceEngine.id.toUtf8() ),
|
||||||
vector< string >() ),
|
vector< string >() ),
|
||||||
voiceEngine( voiceEngine )
|
voiceEngine( voiceEngine )
|
||||||
{
|
{
|
||||||
|
@ -67,10 +70,10 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
sptr< WordSearchRequest > VoiceEnginesDictionary::prefixMatch( wstring const & /*word*/,
|
sptr< WordSearchRequest > VoiceEnginesDictionary::prefixMatch( wstring const & /*word*/,
|
||||||
unsigned long /*maxResults*/ )
|
unsigned long /*maxResults*/ )
|
||||||
throw( std::exception )
|
throw( std::exception )
|
||||||
{
|
{
|
||||||
WordSearchRequestInstant *sr = new WordSearchRequestInstant();
|
WordSearchRequestInstant * sr = new WordSearchRequestInstant();
|
||||||
sr->setUncertain( true );
|
sr->setUncertain( true );
|
||||||
return sr;
|
return sr;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +105,7 @@ sptr< Dictionary::DataRequest > VoiceEnginesDictionary::getArticle(
|
||||||
|
|
||||||
sptr< DataRequestInstant > ret = new DataRequestInstant( true );
|
sptr< DataRequestInstant > ret = new DataRequestInstant( true );
|
||||||
ret->getData().resize( result.size() );
|
ret->getData().resize( result.size() );
|
||||||
memcpy( &(ret->getData().front()), result.data(), result.size() );
|
memcpy( &( ret->getData().front() ), result.data(), result.size() );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,12 +126,12 @@ void VoiceEnginesDictionary::loadIcon() throw()
|
||||||
}
|
}
|
||||||
|
|
||||||
vector< sptr< Dictionary::Class > > makeDictionaries(
|
vector< sptr< Dictionary::Class > > makeDictionaries(
|
||||||
Config::VoiceEngines const & voiceEngines )
|
Config::VoiceEngines const & voiceEngines )
|
||||||
throw( std::exception )
|
throw( std::exception )
|
||||||
{
|
{
|
||||||
vector< sptr< Dictionary::Class > > result;
|
vector< sptr< Dictionary::Class > > result;
|
||||||
|
|
||||||
for( Config::VoiceEngines::const_iterator i = voiceEngines.begin(); i != voiceEngines.end(); ++i )
|
for ( Config::VoiceEngines::const_iterator i = voiceEngines.begin(); i != voiceEngines.end(); ++i )
|
||||||
{
|
{
|
||||||
if ( i->enabled )
|
if ( i->enabled )
|
||||||
result.push_back( new VoiceEnginesDictionary( *i ) );
|
result.push_back( new VoiceEnginesDictionary( *i ) );
|
||||||
|
|
Loading…
Reference in a new issue