mirror of
https://github.com/xiaoyifang/goldendict-ng.git
synced 2024-11-23 20:14:05 +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" );
|
||||
}
|
||||
else
|
||||
if ( url.scheme() == "gdtts" )
|
||||
{
|
||||
msg = tr( "TTS Voice" );
|
||||
}
|
||||
else
|
||||
if ( url.scheme() == "gdpicture" )
|
||||
{
|
||||
msg = tr( "Picture" );
|
||||
|
@ -964,14 +969,13 @@ void ArticleView::openLink( QUrl const & url, QUrl const & ref,
|
|||
{
|
||||
QString itemMd5Id = QString( QCryptographicHash::hash(
|
||||
i->id.toUtf8(),
|
||||
QCryptographicHash::Md5 ).toHex());
|
||||
QCryptographicHash::Md5 ).toHex() );
|
||||
|
||||
if ( itemMd5Id == md5Id ) {
|
||||
if ( itemMd5Id == md5Id )
|
||||
{
|
||||
SpeechClient * speechClient = new SpeechClient( i->id, this );
|
||||
connect( speechClient, SIGNAL( finished() ), speechClient, SLOT( deleteLater() ) );
|
||||
if ( !speechClient->tell( text ) ) {
|
||||
delete speechClient;
|
||||
}
|
||||
speechClient->tell( text );
|
||||
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(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(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);
|
||||
|
|
1
sapi.hh
1
sapi.hh
|
@ -172,6 +172,7 @@ typedef enum SPRUNSTATE
|
|||
EXTERN_C const IID CLSID_SpVoice;
|
||||
EXTERN_C const IID IID_ISpVoice;
|
||||
EXTERN_C const IID IID_ISpObjectToken;
|
||||
EXTERN_C const IID CLSID_SpObjectToken;
|
||||
EXTERN_C const IID IID_IEnumSpObjectTokens;
|
||||
EXTERN_C const IID IID_ISpEventSource;
|
||||
EXTERN_C const IID IID_ISpNotifySource;
|
||||
|
|
|
@ -23,12 +23,12 @@ public:
|
|||
static Engines availableEngines();
|
||||
|
||||
const Engine & engine() const;
|
||||
bool tell( QString const & text ) const;
|
||||
bool say( QString const & text ) const;
|
||||
bool tell( QString const & text );
|
||||
bool say( QString const & text );
|
||||
|
||||
signals:
|
||||
void started( bool ok );
|
||||
void finished();
|
||||
void finished(SpeechClient *client);
|
||||
|
||||
protected:
|
||||
virtual void timerEvent( QTimerEvent * evt );
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
#include "speechclient.hh"
|
||||
#include <QtCore>
|
||||
|
||||
#include <windows.h>
|
||||
#include "speechhlp.hh"
|
||||
|
||||
#include <QtCore>
|
||||
|
||||
struct SpeechClient::InternalData
|
||||
{
|
||||
InternalData( QString const & engineId ):
|
||||
waitingFinish( false )
|
||||
{
|
||||
sp = speechCreate( reinterpret_cast<const wchar_t*>( engineId.utf16() ) );
|
||||
sp = speechCreate( engineId.toStdWString().c_str() );
|
||||
}
|
||||
|
||||
~InternalData()
|
||||
|
@ -19,27 +20,17 @@ struct SpeechClient::InternalData
|
|||
|
||||
SpeechHelper sp;
|
||||
Engine engine;
|
||||
typedef QPointer<SpeechClient> Ptr;
|
||||
static QList<Ptr> ptrs;
|
||||
bool waitingFinish;
|
||||
};
|
||||
|
||||
QList<SpeechClient::InternalData::Ptr> SpeechClient::InternalData::ptrs =
|
||||
QList<SpeechClient::InternalData::Ptr>();
|
||||
|
||||
SpeechClient::SpeechClient( QString const & engineId, QObject * parent ):
|
||||
QObject( parent ),
|
||||
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()
|
||||
{
|
||||
internalData->ptrs.removeAll( this );
|
||||
delete internalData;
|
||||
}
|
||||
|
||||
|
@ -48,7 +39,7 @@ static bool enumEngines( void * /* token */,
|
|||
const wchar_t * name,
|
||||
void * userData )
|
||||
{
|
||||
SpeechClient::Engines *pEngines = (SpeechClient::Engines *)userData;
|
||||
SpeechClient::Engines * pEngines = ( SpeechClient::Engines * )userData;
|
||||
SpeechClient::Engine engine =
|
||||
{
|
||||
QString::fromWCharArray( id ),
|
||||
|
@ -70,7 +61,7 @@ const SpeechClient::Engine & SpeechClient::engine() const
|
|||
return internalData->engine;
|
||||
}
|
||||
|
||||
bool SpeechClient::tell( QString const & text ) const
|
||||
bool SpeechClient::tell( QString const & text )
|
||||
{
|
||||
if ( !speechAvailable( internalData->sp ) )
|
||||
return false;
|
||||
|
@ -78,17 +69,27 @@ bool SpeechClient::tell( QString const & text ) const
|
|||
if ( internalData->waitingFinish )
|
||||
return false;
|
||||
|
||||
internalData->waitingFinish = true;
|
||||
const_cast<SpeechClient *>( this )->startTimer( 50 );
|
||||
return speechTell( internalData->sp, reinterpret_cast<const wchar_t*>( text.utf16() ) );
|
||||
bool ok = speechTell( internalData->sp, text.toStdWString().c_str() );
|
||||
emit started( ok );
|
||||
|
||||
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 ) )
|
||||
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 )
|
||||
|
@ -100,9 +101,8 @@ void SpeechClient::timerEvent( QTimerEvent * evt )
|
|||
|
||||
if ( speechTellFinished( internalData->sp ) )
|
||||
{
|
||||
killTimer( evt->timerId() ) ;
|
||||
internalData->waitingFinish = false;
|
||||
emit finished();
|
||||
emit finished( this );
|
||||
killTimer( evt->timerId() ) ;
|
||||
internalData->waitingFinish = false;
|
||||
emit finished();
|
||||
}
|
||||
}
|
||||
|
|
44
speechhlp.cc
44
speechhlp.cc
|
@ -1,5 +1,6 @@
|
|||
#define WINVER 0x0500 // At least WinXP required
|
||||
#include <windows.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "speechhlp.hh"
|
||||
#include <string>
|
||||
|
@ -15,12 +16,13 @@ struct _SpeechHelper
|
|||
wstring engineName;
|
||||
bool willInvokeCoUninitialize;
|
||||
|
||||
_SpeechHelper() : willInvokeCoUninitialize(false)
|
||||
_SpeechHelper() :
|
||||
willInvokeCoUninitialize(false)
|
||||
{
|
||||
HRESULT hr;
|
||||
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
|
||||
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()
|
||||
|
@ -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 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;
|
||||
}
|
||||
|
||||
|
|
55
sphelper.hh
55
sphelper.hh
|
@ -28,17 +28,41 @@ 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(
|
||||
const WCHAR * pszCategoryId,
|
||||
ISpObjectTokenCategory ** ppCategory,
|
||||
BOOL fCreateIfNotExist = FALSE)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
|
||||
ISpObjectTokenCategory * cpTokenCategory;
|
||||
hr = CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
|
||||
hr = CoCreateInstance(CLSID_SpObjectTokenCategory, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_ISpObjectTokenCategory, (void**)&cpTokenCategory );
|
||||
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = cpTokenCategory->SetId(pszCategoryId, fCreateIfNotExist);
|
||||
|
@ -49,21 +73,21 @@ inline HRESULT SpGetCategoryFromId(
|
|||
else
|
||||
cpTokenCategory->Release();
|
||||
}
|
||||
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
HRESULT SpEnumTokens(
|
||||
const WCHAR * pszCategoryId,
|
||||
const WCHAR * pszReqAttribs,
|
||||
const WCHAR * pszOptAttribs,
|
||||
const WCHAR * pszCategoryId,
|
||||
const WCHAR * pszReqAttribs,
|
||||
const WCHAR * pszOptAttribs,
|
||||
IEnumSpObjectTokens ** ppEnum)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
|
||||
ISpObjectTokenCategory * cpCategory;
|
||||
hr = SpGetCategoryFromId(pszCategoryId, &cpCategory);
|
||||
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = cpCategory->EnumTokens(
|
||||
|
@ -72,7 +96,7 @@ HRESULT SpEnumTokens(
|
|||
ppEnum);
|
||||
cpCategory->Release();
|
||||
}
|
||||
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -80,6 +104,8 @@ inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescrip
|
|||
{
|
||||
WCHAR szLangId[10];
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
#if _SAPI_VER >= 0x053
|
||||
WCHAR* pRegKeyPath = 0;
|
||||
WCHAR* pszTemp = 0;
|
||||
HKEY Handle = NULL;
|
||||
|
@ -101,7 +127,7 @@ inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescrip
|
|||
HMODULE hmodAdvapi32Dll = NULL;
|
||||
typedef HRESULT (WINAPI* LPFN_RegLoadMUIStringW)(HKEY, LPCWSTR, LPWSTR, DWORD, LPDWORD, DWORD, LPCWSTR);
|
||||
LPFN_RegLoadMUIStringW pfnRegLoadMUIStringW = NULL;
|
||||
|
||||
|
||||
// Delay bind with RegLoadMUIStringW since this function is not supported on previous versions of advapi32.dll
|
||||
// RegLoadMUIStringW is supported only on advapi32.dll that ships with Windows Vista and above
|
||||
// Calling RegLoadMUIStringW directly makes the loader try to resolve the function reference at load time which breaks,
|
||||
|
@ -121,7 +147,7 @@ inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescrip
|
|||
{
|
||||
hr = HRESULT_FROM_WIN32(ERROR_DLL_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
hr = pObjToken->GetId(&pszTemp);
|
||||
|
@ -151,7 +177,7 @@ inline HRESULT SpGetDescription(ISpObjectToken * pObjToken, WCHAR ** ppszDescrip
|
|||
{
|
||||
lErrorCode = ERROR_BAD_ARGUMENTS;
|
||||
}
|
||||
|
||||
|
||||
// Use MUI RegLoadMUIStringW API to load the localized string
|
||||
if(ERROR_SUCCESS == lErrorCode)
|
||||
{
|
||||
|
@ -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 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))
|
||||
{
|
||||
// Free memory allocated above if necessary
|
||||
|
|
|
@ -32,7 +32,7 @@ void TextToSpeechSource::on_addVoiceEngine_clicked()
|
|||
if ( ui.availableVoiceEngines->count() == 0 )
|
||||
{
|
||||
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." ) );
|
||||
return;
|
||||
}
|
||||
|
@ -54,8 +54,9 @@ void TextToSpeechSource::on_removeVoiceEngine_clicked()
|
|||
voiceEnginesModel.getCurrentVoiceEngines()[ current.row() ].name ),
|
||||
QMessageBox::Ok,
|
||||
QMessageBox::Cancel ) == QMessageBox::Ok )
|
||||
|
||||
voiceEnginesModel.removeVoiceEngine( current.row() );
|
||||
{
|
||||
voiceEnginesModel.removeVoiceEngine( current.row() );
|
||||
}
|
||||
}
|
||||
|
||||
void TextToSpeechSource::on_previewVoice_clicked()
|
||||
|
@ -66,23 +67,17 @@ void TextToSpeechSource::on_previewVoice_clicked()
|
|||
|
||||
QString engineId = ui.availableVoiceEngines->itemData( idx ).toString();
|
||||
QString text = ui.previewText->text();
|
||||
SpeechClient *speechClient = new SpeechClient( engineId, this );
|
||||
SpeechClient * speechClient = new SpeechClient( engineId, this );
|
||||
|
||||
ui.previewVoice->setEnabled( false );
|
||||
connect( speechClient, SIGNAL( finished( SpeechClient * ) ),
|
||||
this, SLOT( previewVoiceFinished( SpeechClient * ) ) );
|
||||
if ( !speechClient->tell( text ) ) {
|
||||
ui.previewVoice->setEnabled( true );
|
||||
delete speechClient;
|
||||
}
|
||||
connect( speechClient, SIGNAL( started( bool ) ), ui.previewVoice, SLOT( setDisabled( bool ) ) );
|
||||
connect( speechClient, SIGNAL( finished() ), this, SLOT( previewVoiceFinished() ) );
|
||||
connect( speechClient, SIGNAL( finished() ), speechClient, SLOT( deleteLater() ) );
|
||||
speechClient->tell( text );
|
||||
}
|
||||
|
||||
void TextToSpeechSource::previewVoiceFinished( SpeechClient * speechClient )
|
||||
void TextToSpeechSource::previewVoiceFinished()
|
||||
{
|
||||
ui.previewVoice->setEnabled( true );
|
||||
|
||||
if (speechClient)
|
||||
speechClient->deleteLater();
|
||||
ui.previewVoice->setDisabled( false );
|
||||
}
|
||||
|
||||
void TextToSpeechSource::fitSelectedVoiceEnginesColumns()
|
||||
|
@ -100,7 +95,7 @@ VoiceEnginesModel::VoiceEnginesModel( QWidget * parent,
|
|||
|
||||
void VoiceEnginesModel::removeVoiceEngine( int index )
|
||||
{
|
||||
beginRemoveRows( QModelIndex(), index, index );
|
||||
beginRemoveRows( QModelIndex(), index, index );
|
||||
voiceEngines.erase( voiceEngines.begin() + index );
|
||||
endRemoveRows();
|
||||
}
|
||||
|
@ -111,9 +106,9 @@ void VoiceEnginesModel::addNewVoiceEngine( QString const & id, QString const & n
|
|||
return;
|
||||
|
||||
Config::VoiceEngine v;
|
||||
v.enabled = true;
|
||||
v.id = id;
|
||||
v.name = name;
|
||||
v.enabled = true;
|
||||
v.id = id;
|
||||
v.name = name;
|
||||
|
||||
beginInsertRows( QModelIndex(), voiceEngines.size(), voiceEngines.size() );
|
||||
voiceEngines.push_back( v );
|
||||
|
@ -136,14 +131,15 @@ Qt::ItemFlags VoiceEnginesModel::flags( QModelIndex const & index ) const
|
|||
|
||||
if ( index.isValid() )
|
||||
{
|
||||
switch ( index.column() ) {
|
||||
case kColumnEnabled:
|
||||
result |= Qt::ItemIsUserCheckable;
|
||||
break;
|
||||
case kColumnEngineName:
|
||||
case kColumnIcon:
|
||||
result |= Qt::ItemIsEditable;
|
||||
break;
|
||||
switch ( index.column() )
|
||||
{
|
||||
case kColumnEnabled:
|
||||
result |= Qt::ItemIsUserCheckable;
|
||||
break;
|
||||
case kColumnEngineName:
|
||||
case kColumnIcon:
|
||||
result |= Qt::ItemIsEditable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -168,7 +164,7 @@ QVariant VoiceEnginesModel::headerData( int section, Qt::Orientation /*orientati
|
|||
{
|
||||
if ( role == Qt::DisplayRole )
|
||||
{
|
||||
switch( section )
|
||||
switch ( section )
|
||||
{
|
||||
case kColumnEnabled:
|
||||
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,
|
||||
int role )
|
||||
int role )
|
||||
{
|
||||
if ( index.row() >= voiceEngines.size() )
|
||||
return false;
|
||||
|
@ -276,8 +272,10 @@ void VoiceEngineEditor::setEngineId( QString const & engineId )
|
|||
{
|
||||
// Find index for the id
|
||||
int idx = -1;
|
||||
for ( int i = 0; i < count(); ++i ) {
|
||||
if ( engineId == itemData(i).toString() ) {
|
||||
for ( int i = 0; i < count(); ++i )
|
||||
{
|
||||
if ( engineId == itemData( i ).toString() )
|
||||
{
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
|
@ -285,22 +283,22 @@ void VoiceEngineEditor::setEngineId( QString const & engineId )
|
|||
setCurrentIndex( idx );
|
||||
}
|
||||
|
||||
VoiceEngineItemDelegate::VoiceEngineItemDelegate( SpeechClient::Engines const & engines, QObject *parent ) :
|
||||
VoiceEngineItemDelegate::VoiceEngineItemDelegate( SpeechClient::Engines const & engines, QObject * parent ) :
|
||||
QStyledItemDelegate( parent ),
|
||||
engines( engines )
|
||||
{
|
||||
}
|
||||
|
||||
QWidget * VoiceEngineItemDelegate::createEditor( QWidget *parent,
|
||||
QWidget * VoiceEngineItemDelegate::createEditor( QWidget * parent,
|
||||
QStyleOptionViewItem const & option,
|
||||
QModelIndex const & index ) const
|
||||
{
|
||||
if( index.column() != VoiceEnginesModel::kColumnEngineName )
|
||||
if ( index.column() != VoiceEnginesModel::kColumnEngineName )
|
||||
return QStyledItemDelegate::createEditor( parent, option, index );
|
||||
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 );
|
||||
if ( !editor )
|
||||
|
@ -312,7 +310,7 @@ void VoiceEngineItemDelegate::setEditorData( QWidget *uncastedEditor, const QMod
|
|||
editor->setEngineId( engineId );
|
||||
}
|
||||
|
||||
void VoiceEngineItemDelegate::setModelData( QWidget *uncastedEditor, QAbstractItemModel * model,
|
||||
void VoiceEngineItemDelegate::setModelData( QWidget * uncastedEditor, QAbstractItemModel * model,
|
||||
const QModelIndex & index ) const
|
||||
{
|
||||
VoiceEngineEditor * editor = qobject_cast< VoiceEngineEditor * >( uncastedEditor );
|
||||
|
|
|
@ -93,7 +93,7 @@ private slots:
|
|||
void on_addVoiceEngine_clicked();
|
||||
void on_removeVoiceEngine_clicked();
|
||||
void on_previewVoice_clicked();
|
||||
void previewVoiceFinished( SpeechClient * speechClient );
|
||||
void previewVoiceFinished();
|
||||
|
||||
private:
|
||||
Ui::TextToSpeechSource ui;
|
||||
|
|
|
@ -7,21 +7,24 @@
|
|||
#include "utf8.hh"
|
||||
#include "wstring_qt.hh"
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
#include <QUrl>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QCryptographicHash>
|
||||
|
||||
namespace VoiceEngines {
|
||||
namespace VoiceEngines
|
||||
{
|
||||
|
||||
using namespace Dictionary;
|
||||
using std::string;
|
||||
using std::map;
|
||||
|
||||
namespace StringConv {
|
||||
|
||||
inline QString toMd5( QByteArray const & b )
|
||||
inline string 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
|
||||
|
@ -34,7 +37,7 @@ public:
|
|||
|
||||
VoiceEnginesDictionary( Config::VoiceEngine const & voiceEngine ):
|
||||
Dictionary::Class(
|
||||
StringConv::toMd5( voiceEngine.id.toUtf8() ).toStdString(),
|
||||
toMd5( voiceEngine.id.toUtf8() ),
|
||||
vector< string >() ),
|
||||
voiceEngine( voiceEngine )
|
||||
{
|
||||
|
@ -67,10 +70,10 @@ protected:
|
|||
};
|
||||
|
||||
sptr< WordSearchRequest > VoiceEnginesDictionary::prefixMatch( wstring const & /*word*/,
|
||||
unsigned long /*maxResults*/ )
|
||||
unsigned long /*maxResults*/ )
|
||||
throw( std::exception )
|
||||
{
|
||||
WordSearchRequestInstant *sr = new WordSearchRequestInstant();
|
||||
WordSearchRequestInstant * sr = new WordSearchRequestInstant();
|
||||
sr->setUncertain( true );
|
||||
return sr;
|
||||
}
|
||||
|
@ -102,7 +105,7 @@ sptr< Dictionary::DataRequest > VoiceEnginesDictionary::getArticle(
|
|||
|
||||
sptr< DataRequestInstant > ret = new DataRequestInstant( true );
|
||||
ret->getData().resize( result.size() );
|
||||
memcpy( &(ret->getData().front()), result.data(), result.size() );
|
||||
memcpy( &( ret->getData().front() ), result.data(), result.size() );
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -123,12 +126,12 @@ void VoiceEnginesDictionary::loadIcon() throw()
|
|||
}
|
||||
|
||||
vector< sptr< Dictionary::Class > > makeDictionaries(
|
||||
Config::VoiceEngines const & voiceEngines )
|
||||
Config::VoiceEngines const & voiceEngines )
|
||||
throw( std::exception )
|
||||
{
|
||||
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 )
|
||||
result.push_back( new VoiceEnginesDictionary( *i ) );
|
||||
|
|
Loading…
Reference in a new issue