key composition moved to QskInputContext
This commit is contained in:
parent
4ce1780f90
commit
dfe2b875fd
|
@ -10,8 +10,8 @@ public:
|
||||||
QVector< QString > candidates;
|
QVector< QString > candidates;
|
||||||
};
|
};
|
||||||
|
|
||||||
QskHunspellCompositionModel::QskHunspellCompositionModel( QskInputContext* context ):
|
QskHunspellCompositionModel::QskHunspellCompositionModel( QObject* object ):
|
||||||
Inherited( Words, context ),
|
Inherited( Words, object ),
|
||||||
m_data( new PrivateData() )
|
m_data( new PrivateData() )
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
|
|
|
@ -14,7 +14,7 @@ class QskHunspellCompositionModel : public QskInputCompositionModel
|
||||||
using Inherited = QskInputCompositionModel;
|
using Inherited = QskInputCompositionModel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QskHunspellCompositionModel( QskInputContext* context );
|
QskHunspellCompositionModel( QObject* );
|
||||||
virtual ~QskHunspellCompositionModel() override;
|
virtual ~QskHunspellCompositionModel() override;
|
||||||
|
|
||||||
virtual int candidateCount() const override;
|
virtual int candidateCount() const override;
|
||||||
|
|
|
@ -4,13 +4,10 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#include "QskInputCompositionModel.h"
|
#include "QskInputCompositionModel.h"
|
||||||
#include "QskInputContext.h"
|
|
||||||
|
|
||||||
#include <QInputMethodQueryEvent>
|
|
||||||
|
|
||||||
QskInputCompositionModel::QskInputCompositionModel(
|
QskInputCompositionModel::QskInputCompositionModel(
|
||||||
Attributes attributes, QskInputContext* context ):
|
Attributes attributes, QObject* parent ):
|
||||||
QObject( context ),
|
QObject( parent ),
|
||||||
m_attributes( attributes )
|
m_attributes( attributes )
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -19,72 +16,9 @@ QskInputCompositionModel::~QskInputCompositionModel()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QskInputContext* QskInputCompositionModel::context() const
|
QskInputCompositionModel::Attributes QskInputCompositionModel::attributes() const
|
||||||
{
|
{
|
||||||
return qobject_cast< QskInputContext* >( parent() );
|
return m_attributes;
|
||||||
}
|
|
||||||
|
|
||||||
void QskInputCompositionModel::composeKey( const QString& text, int spaceLeft )
|
|
||||||
{
|
|
||||||
if ( candidateCount() > 0 )
|
|
||||||
{
|
|
||||||
m_preedit += text;
|
|
||||||
|
|
||||||
requestCandidates( m_preedit );
|
|
||||||
context()->sendText( m_preedit, false );
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
requestCandidates( m_preedit );
|
|
||||||
|
|
||||||
QString txt;
|
|
||||||
if ( candidateCount() == 0 )
|
|
||||||
{
|
|
||||||
txt = m_preedit.left( spaceLeft );
|
|
||||||
spaceLeft -= txt.length();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
txt = candidate( 0 );
|
|
||||||
--spaceLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
context()->sendText( txt, true );
|
|
||||||
m_preedit.clear();
|
|
||||||
resetCandidates();
|
|
||||||
|
|
||||||
if ( spaceLeft )
|
|
||||||
{
|
|
||||||
m_preedit = text;
|
|
||||||
requestCandidates( m_preedit );
|
|
||||||
|
|
||||||
if ( candidateCount() > 0 )
|
|
||||||
{
|
|
||||||
context()->sendText( m_preedit, false );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
context()->sendText( m_preedit, true );
|
|
||||||
m_preedit.clear();
|
|
||||||
resetCandidates();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskInputCompositionModel::setPreeditText( const QString& text )
|
|
||||||
{
|
|
||||||
if ( text != m_preedit )
|
|
||||||
{
|
|
||||||
m_preedit = text;
|
|
||||||
requestCandidates( m_preedit );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QskInputCompositionModel::reset()
|
|
||||||
{
|
|
||||||
m_preedit.clear();
|
|
||||||
resetCandidates();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "moc_QskInputCompositionModel.cpp"
|
#include "moc_QskInputCompositionModel.cpp"
|
||||||
|
|
|
@ -8,8 +8,6 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
class QskInputContext;
|
|
||||||
|
|
||||||
class QskInputCompositionModel : public QObject
|
class QskInputCompositionModel : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -25,43 +23,22 @@ public:
|
||||||
|
|
||||||
virtual ~QskInputCompositionModel();
|
virtual ~QskInputCompositionModel();
|
||||||
|
|
||||||
void composeKey( const QString& text, int spaceLeft );
|
virtual void requestCandidates( const QString& preedit ) = 0;
|
||||||
|
virtual void resetCandidates() = 0;
|
||||||
|
|
||||||
virtual int candidateCount() const = 0;
|
virtual int candidateCount() const = 0;
|
||||||
virtual QString candidate( int ) const = 0;
|
virtual QString candidate( int ) const = 0;
|
||||||
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
QString preeditText() const;
|
|
||||||
void setPreeditText( const QString& );
|
|
||||||
|
|
||||||
Attributes attributes() const;
|
Attributes attributes() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
QskInputCompositionModel( Attributes, QskInputContext* );
|
|
||||||
|
|
||||||
virtual void requestCandidates( const QString& preedit ) = 0;
|
|
||||||
virtual void resetCandidates() = 0;
|
|
||||||
|
|
||||||
QskInputContext* context() const;
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void candidatesChanged();
|
void candidatesChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QskInputCompositionModel( Attributes, QObject* );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QString m_preedit;
|
|
||||||
const Attributes m_attributes;
|
const Attributes m_attributes;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QString QskInputCompositionModel::preeditText() const
|
|
||||||
{
|
|
||||||
return m_preedit;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QskInputCompositionModel::Attributes
|
|
||||||
QskInputCompositionModel::attributes() const
|
|
||||||
{
|
|
||||||
return m_attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -49,22 +49,6 @@ static inline QString qskKeyString( int keyCode )
|
||||||
return QChar( keyCode );
|
return QChar( keyCode );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool qskIsControlKey( int keyCode )
|
|
||||||
{
|
|
||||||
switch ( keyCode )
|
|
||||||
{
|
|
||||||
case Qt::Key_Backspace:
|
|
||||||
case Qt::Key_Muhenkan:
|
|
||||||
case Qt::Key_Return:
|
|
||||||
case Qt::Key_Left:
|
|
||||||
case Qt::Key_Right:
|
|
||||||
case Qt::Key_Escape:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void qskSetLocale( QQuickItem* inputPanel, const QLocale& locale )
|
static void qskSetLocale( QQuickItem* inputPanel, const QLocale& locale )
|
||||||
{
|
{
|
||||||
if ( auto control = qobject_cast< QskControl* >( inputPanel ) )
|
if ( auto control = qobject_cast< QskControl* >( inputPanel ) )
|
||||||
|
@ -145,6 +129,8 @@ public:
|
||||||
|
|
||||||
QHash< uint, QskInputCompositionModel* > compositionModels;
|
QHash< uint, QskInputCompositionModel* > compositionModels;
|
||||||
|
|
||||||
|
QString preedit;
|
||||||
|
|
||||||
// the input panel is embedded in a window
|
// the input panel is embedded in a window
|
||||||
bool ownsInputPanelWindow : 1;
|
bool ownsInputPanelWindow : 1;
|
||||||
};
|
};
|
||||||
|
@ -225,7 +211,7 @@ void QskInputContext::update( Qt::InputMethodQueries queries )
|
||||||
ImhPreferNumbers = 0x8, // default to number keyboard
|
ImhPreferNumbers = 0x8, // default to number keyboard
|
||||||
ImhPreferUppercase = 0x10, // start with shift on
|
ImhPreferUppercase = 0x10, // start with shift on
|
||||||
ImhPreferLowercase = 0x20, // start with shift off
|
ImhPreferLowercase = 0x20, // start with shift off
|
||||||
ImhNoPredictiveText = 0x40, // ignored for now
|
ImhNoPredictiveText = 0x40, // not use predictive text
|
||||||
|
|
||||||
ImhDate = 0x80, // ignored for now (no date keyboard)
|
ImhDate = 0x80, // ignored for now (no date keyboard)
|
||||||
ImhTime = 0x100, // ignored for know (no time keyboard)
|
ImhTime = 0x100, // ignored for know (no time keyboard)
|
||||||
|
@ -426,6 +412,12 @@ void QskInputContext::showInputPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
update( Qt::ImQueryAll );
|
update( Qt::ImQueryAll );
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
if ( auto panel = qobject_cast< QskInputPanel* >( m_data->inputPanel ) )
|
||||||
|
panel->updateInputProxy( m_data->inputItem );
|
||||||
|
#endif
|
||||||
|
|
||||||
inputPanel->setVisible( true );
|
inputPanel->setVisible( true );
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -482,6 +474,10 @@ void QskInputContext::hideInputPanel()
|
||||||
}
|
}
|
||||||
|
|
||||||
qGuiApp->removeEventFilter( this );
|
qGuiApp->removeEventFilter( this );
|
||||||
|
|
||||||
|
m_data->preedit.clear();
|
||||||
|
if ( auto model = compositionModel() )
|
||||||
|
model->resetCandidates();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QskInputContext::isInputPanelVisible() const
|
bool QskInputContext::isInputPanelVisible() const
|
||||||
|
@ -612,7 +608,8 @@ void QskInputContext::invokeAction( QInputMethod::Action action, int value )
|
||||||
|
|
||||||
sendText( text, true );
|
sendText( text, true );
|
||||||
|
|
||||||
model->reset();
|
m_data->preedit.clear();
|
||||||
|
model->resetCandidates();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -664,6 +661,7 @@ void QskInputContext::processKey( int key )
|
||||||
if ( !( hints & Qt::ImhHiddenText ) )
|
if ( !( hints & Qt::ImhHiddenText ) )
|
||||||
model = compositionModel();
|
model = compositionModel();
|
||||||
|
|
||||||
|
auto& preedit = m_data->preedit;
|
||||||
/*
|
/*
|
||||||
First we have to handle the control keys
|
First we have to handle the control keys
|
||||||
*/
|
*/
|
||||||
|
@ -674,13 +672,12 @@ void QskInputContext::processKey( int key )
|
||||||
{
|
{
|
||||||
if ( model )
|
if ( model )
|
||||||
{
|
{
|
||||||
auto preeditText = model->preeditText();
|
if ( !preedit.isEmpty() )
|
||||||
if ( !preeditText.isEmpty() )
|
|
||||||
{
|
{
|
||||||
preeditText.chop( 1 );
|
preedit.chop( 1 );
|
||||||
sendText( preeditText, false );
|
sendText( preedit, false );
|
||||||
|
|
||||||
model->setPreeditText( preeditText );
|
model->requestCandidates( preedit );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -692,13 +689,14 @@ void QskInputContext::processKey( int key )
|
||||||
{
|
{
|
||||||
if ( model )
|
if ( model )
|
||||||
{
|
{
|
||||||
const auto preeditText = model->preeditText();
|
if ( !preedit.isEmpty() )
|
||||||
if ( !preeditText.isEmpty() )
|
|
||||||
{
|
{
|
||||||
if ( spaceLeft )
|
if ( spaceLeft )
|
||||||
sendText( preeditText.left( spaceLeft ), true );
|
sendText( preedit.left( spaceLeft ), true );
|
||||||
|
|
||||||
|
preedit.clear();
|
||||||
|
model->resetCandidates();
|
||||||
|
|
||||||
model->reset();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -715,14 +713,14 @@ void QskInputContext::processKey( int key )
|
||||||
{
|
{
|
||||||
if ( model )
|
if ( model )
|
||||||
{
|
{
|
||||||
auto preeditText = model->preeditText();
|
if ( !preedit.isEmpty() && spaceLeft)
|
||||||
if ( !preeditText.isEmpty() && spaceLeft)
|
|
||||||
{
|
{
|
||||||
preeditText = preeditText.left( spaceLeft );
|
preedit = preedit.left( spaceLeft );
|
||||||
sendText( preeditText, true );
|
sendText( preedit, true );
|
||||||
spaceLeft -= preeditText.length();
|
spaceLeft -= preedit.length();
|
||||||
|
|
||||||
model->reset();
|
preedit.clear();
|
||||||
|
model->resetCandidates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +739,19 @@ void QskInputContext::processKey( int key )
|
||||||
|
|
||||||
if ( model )
|
if ( model )
|
||||||
{
|
{
|
||||||
model->composeKey( text, spaceLeft );
|
preedit += text;
|
||||||
|
|
||||||
|
model->requestCandidates( preedit );
|
||||||
|
|
||||||
|
if ( model->candidateCount() > 0 )
|
||||||
|
{
|
||||||
|
sendText( preedit, false );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendText( preedit.left( spaceLeft ), true );
|
||||||
|
preedit.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,8 +17,8 @@ public:
|
||||||
QStringList candidates;
|
QStringList candidates;
|
||||||
};
|
};
|
||||||
|
|
||||||
QskPinyinCompositionModel::QskPinyinCompositionModel( QskInputContext* context ):
|
QskPinyinCompositionModel::QskPinyinCompositionModel( QObject* parent ):
|
||||||
Inherited( Attributes(), context ),
|
Inherited( Attributes(), parent ),
|
||||||
m_data( new PrivateData )
|
m_data( new PrivateData )
|
||||||
{
|
{
|
||||||
#if 1
|
#if 1
|
||||||
|
|
|
@ -14,7 +14,7 @@ class QskPinyinCompositionModel : public QskInputCompositionModel
|
||||||
using Inherited = QskInputCompositionModel;
|
using Inherited = QskInputCompositionModel;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QskPinyinCompositionModel( QskInputContext* );
|
QskPinyinCompositionModel( QObject* );
|
||||||
virtual ~QskPinyinCompositionModel() override;
|
virtual ~QskPinyinCompositionModel() override;
|
||||||
|
|
||||||
virtual int candidateCount() const override;
|
virtual int candidateCount() const override;
|
||||||
|
|
|
@ -125,7 +125,7 @@ public:
|
||||||
|
|
||||||
QskLinearBox* layout;
|
QskLinearBox* layout;
|
||||||
QskTextLabel* prompt;
|
QskTextLabel* prompt;
|
||||||
TextInput* textInput;
|
TextInput* inputProxy;
|
||||||
QskInputSuggestionBar* suggestionBar;
|
QskInputSuggestionBar* suggestionBar;
|
||||||
QskVirtualKeyboard* keyboard;
|
QskVirtualKeyboard* keyboard;
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
|
||||||
m_data->prompt = new QskTextLabel();
|
m_data->prompt = new QskTextLabel();
|
||||||
m_data->prompt->setVisible( false );
|
m_data->prompt->setVisible( false );
|
||||||
|
|
||||||
m_data->textInput = new TextInput();
|
m_data->inputProxy = new TextInput();
|
||||||
m_data->textInput->setVisible( m_data->hasInputProxy );
|
m_data->inputProxy->setVisible( m_data->hasInputProxy );
|
||||||
|
|
||||||
m_data->suggestionBar = new QskInputSuggestionBar();
|
m_data->suggestionBar = new QskInputSuggestionBar();
|
||||||
m_data->suggestionBar->setVisible( false );
|
m_data->suggestionBar->setVisible( false );
|
||||||
|
@ -153,7 +153,7 @@ QskInputPanel::QskInputPanel( QQuickItem* parent ):
|
||||||
auto layout = new QskLinearBox( Qt::Vertical, this );
|
auto layout = new QskLinearBox( Qt::Vertical, this );
|
||||||
|
|
||||||
layout->addItem( m_data->prompt, Qt::AlignLeft | Qt::AlignHCenter );
|
layout->addItem( m_data->prompt, Qt::AlignLeft | Qt::AlignHCenter );
|
||||||
layout->addItem( m_data->textInput, Qt::AlignLeft | Qt::AlignHCenter );
|
layout->addItem( m_data->inputProxy, Qt::AlignLeft | Qt::AlignHCenter );
|
||||||
layout->addStretch( 10 );
|
layout->addStretch( 10 );
|
||||||
layout->addItem( m_data->suggestionBar );
|
layout->addItem( m_data->suggestionBar );
|
||||||
layout->addItem( m_data->keyboard );
|
layout->addItem( m_data->keyboard );
|
||||||
|
@ -199,7 +199,7 @@ qreal QskInputPanel::heightForWidth( qreal width ) const
|
||||||
qreal height = m_data->keyboard->heightForWidth( width );
|
qreal height = m_data->keyboard->heightForWidth( width );
|
||||||
|
|
||||||
const QskControl* controls[] =
|
const QskControl* controls[] =
|
||||||
{ m_data->prompt, m_data->textInput, m_data->suggestionBar };
|
{ m_data->prompt, m_data->inputProxy, m_data->suggestionBar };
|
||||||
|
|
||||||
for ( auto control : controls )
|
for ( auto control : controls )
|
||||||
{
|
{
|
||||||
|
@ -228,7 +228,7 @@ qreal QskInputPanel::widthForHeight( qreal height ) const
|
||||||
height -= padding.top() + padding.bottom();
|
height -= padding.top() + padding.bottom();
|
||||||
|
|
||||||
const QskControl* controls[] =
|
const QskControl* controls[] =
|
||||||
{ m_data->prompt, m_data->textInput, m_data->suggestionBar };
|
{ m_data->prompt, m_data->inputProxy, m_data->suggestionBar };
|
||||||
|
|
||||||
for ( auto control : controls )
|
for ( auto control : controls )
|
||||||
{
|
{
|
||||||
|
@ -278,7 +278,7 @@ void QskInputPanel::setInputProxy( bool on )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_data->hasInputProxy = on;
|
m_data->hasInputProxy = on;
|
||||||
m_data->textInput->setVisible( on );
|
m_data->inputProxy->setVisible( on );
|
||||||
|
|
||||||
auto prompt = m_data->prompt;
|
auto prompt = m_data->prompt;
|
||||||
|
|
||||||
|
@ -288,6 +288,56 @@ void QskInputPanel::setInputProxy( bool on )
|
||||||
prompt->setVisible( false );
|
prompt->setVisible( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QskInputPanel::updateInputProxy( const QQuickItem* inputItem )
|
||||||
|
{
|
||||||
|
if ( inputItem == nullptr )
|
||||||
|
return;
|
||||||
|
|
||||||
|
QInputMethodQueryEvent event( Qt::ImQueryAll );
|
||||||
|
QCoreApplication::sendEvent( const_cast< QQuickItem* >( inputItem ), &event );
|
||||||
|
|
||||||
|
const auto proxy = m_data->inputProxy;
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImHints )
|
||||||
|
{
|
||||||
|
const auto hints = static_cast< Qt::InputMethodHints >(
|
||||||
|
event.value( Qt::ImHints ).toInt() );
|
||||||
|
|
||||||
|
const auto echoMode = ( hints & Qt::ImhHiddenText )
|
||||||
|
? QskTextInput::PasswordEchoOnEdit : QskTextInput::Normal;
|
||||||
|
|
||||||
|
proxy->setEchoMode( echoMode );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImSurroundingText )
|
||||||
|
{
|
||||||
|
const auto text = event.value( Qt::ImSurroundingText ).toString();
|
||||||
|
proxy->setText( text );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImCursorPosition )
|
||||||
|
{
|
||||||
|
const auto pos = event.value( Qt::ImCursorPosition ).toInt();
|
||||||
|
proxy->setCursorPosition( pos );
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if ( event.queries() & Qt::ImCurrentSelection )
|
||||||
|
{
|
||||||
|
const auto text = event.value( Qt::ImCursorPosition ).toString();
|
||||||
|
if ( !text.isEmpty() )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if ( event.queries() & Qt::ImMaximumTextLength )
|
||||||
|
{
|
||||||
|
const auto length = event.value( Qt::ImMaximumTextLength ).toInt();
|
||||||
|
proxy->setMaxLength( length );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool QskInputPanel::isCandidatesEnabled() const
|
bool QskInputPanel::isCandidatesEnabled() const
|
||||||
{
|
{
|
||||||
return m_data->suggestionBar->isVisible();
|
return m_data->suggestionBar->isVisible();
|
||||||
|
|
|
@ -52,6 +52,8 @@ public:
|
||||||
virtual QskAspect::Subcontrol effectiveSubcontrol(
|
virtual QskAspect::Subcontrol effectiveSubcontrol(
|
||||||
QskAspect::Subcontrol ) const override;
|
QskAspect::Subcontrol ) const override;
|
||||||
|
|
||||||
|
void updateInputProxy( const QQuickItem* );
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void inputProxyChanged( bool );
|
void inputProxyChanged( bool );
|
||||||
void inputPromptChanged( const QString& );
|
void inputPromptChanged( const QString& );
|
||||||
|
|
Loading…
Reference in New Issue