emulT9 (C++, Qt4)
File detail
Source code
#ifndef ENGINE_H
#define ENGINE_H
#include <QTimer>
#include <QSet>
#include <QShortcut>
#include "ui_main.h"
/**
* Keyboard keys enumeration
*/
typedef enum {
KEY_NULL,
KEY_LEFT, KEY_C, KEY_RIGHT,
KEY_DOT, KEY_ABC, KEY_DEF,
KEY_GHI, KEY_JKL, KEY_MNO,
KEY_PQRS, KEY_TUV, KEY_WXYZ,
KEY_SHIFT, KEY_ROT, KEY_GAP,
} EKey;
/**
* This class handles mobile keyboard keys enumeration
* It emits keyPressed(int) signal on key pressed
*/
class KeyScan: public QObject {
Q_OBJECT
public:
KeyScan(QMainWindow *mainWnd);
/// Connect object to main window ui.
void connectToDesign (Ui::MainWindow &design);
private slots:
void buttLeftClicked(); void buttCClicked(); void buttRightClicked();
void butt11Clicked(); void butt12Clicked(); void butt13Clicked();
void butt21Clicked(); void butt22Clicked(); void butt23Clicked();
void butt31Clicked(); void butt32Clicked(); void butt33Clicked();
void butt41Clicked(); void butt42Clicked(); void butt43Clicked();
signals:
/// Signal is emitted on key pressed. int is key enumeration code.
void keyPressed(int);
private:
QShortcut _sc4;
QShortcut _sc6;
};
/**
* This class manages statistics counting and displaying.
*/
class StopWatch: public QObject {
Q_OBJECT
public:
static const int iPeriod= 100; ///< 10 ticks per seccond
StopWatch();
/// Connect object to main window ui.
void connectToDesign (Ui::MainWindow &design);
public slots:
void start(); ///< Start stopwatch.
void stop(); ///< Stop stopwatch.
void reset(); ///< Reset all statistics.
void keyPressed(); ///< Count keyboard hit to statistics.
void textSizeChanged(int); ///< Effective text size changed to 'int'
private slots:
void tick();
void update();
private:
QLabel *_labelTime;
QLabel *_labelHitsPerMin;
QLabel *_labelCharsPerMin;
QTimer _qTimer;
int _iTicks;
int _iHits;
int _iTextSize;
QTextEdit *_textEdit;
};
/**
* Shift key universal handler.
*/
class AlphaSwitcher {
public:
AlphaSwitcher();
void init(); ///< Reset shift state.
void toggle(); ///< Toggle shift state.
void notify(); ///< Notify that character was written.
/// \return Current shift state (for next character only).
bool isUpper() const { return _state!= AS_LOW; }
/// \return Mobile-style shift status string.
QString getStatus() const;
/// \return translated (uppered/lowered) character.
QChar translate (QChar);
private:
enum { AS_LOW, AS_FIRST, AS_HIGH } _state;
};
/**
* Base element of std mobile typer. Ring buffer actualy.
*/
class Rotator {
public:
Rotator (const QString &rotStr); ///< \param rotStr String containing characters to rotate.
void reset(); ///< Reset internal iterator to initial position.
void rotate(); ///< Increment internal iterator.
QChar getCurrent(); ///< \return Return character at current position.
private:
QString _str; ///< String containing characters to rotate
int _iNow; ///< Internal iterator
};
/**
* Base element of T9 typer. Ring buffer actualy.
*/
class RotatorT9 {
public:
bool empty() { return _list.empty(); } ///< \return Return true if rotator is empty.
void add(const QString &word); ///< \param word Word to add to rotator.
void reset() { _now= _list.begin(); } ///< Reset internal iterator to initial position.
void rotate(); ///< Increment internal iterator.
QString getCurrent(); ///< \return Return string at current position.
private:
QList<QString> _list; ///< Implementation of string list
QList<QString>::iterator _now; ///< Internal iterator.
};
/**
* Engine of T9 writer - dictionary.
*/
class DictionaryT9 {
public:
/**
* Convert key code to hash code.
* \param key Key enumeration code.
* \return Return hash code (hash character).
*/
static QChar keyToHashChar(EKey key);
/**
* Convert any writable character to hash code.
* \param c Writable character to convert.
* \return Return hash code (hash character).
*/
static QChar charToHashChar(QChar c);
/**
* Convert any writable word to hash string (character after character).
* \param word Writable word to convert.
* \return Return hash string.
*/
static QString wordToHash(const QString &word);
/**
* Add word to dictionary.
* \param word Word to add.
*/
void add(const QString &word);
/**
* This method is an entry point to T9 query system. This creates an rotator
* containing all suitable word parts for given hash string.
* \param hash Hash string to lookup.
* \return Return pointert to (on heap) allocated RotatorT9 object
* containing all suitable word parts.
*/
RotatorT9 *createRotator(const QString &hash);
protected:
typedef QSet<QString> TSet; ///< Set of strings equivalent by hash strings
typedef QMap<QString, QSet<QString> > THashTable; ///< Hash-string to setOfWords mapping type
THashTable _hashTable; ///< Internal hash table implementation
};
/**
* Extension to DictionaryT9. It implements dictionary load/save from/to file.
*/
class FileDictionaryT9: public DictionaryT9 {
public:
/// Default file name to load/save dictionary (staticly defined in engine.cpp)
static const char *szDefFileName;
/**
* Build T9 dictionary from file szFileName and merge with current dictionary.
* \param szFileName File name to load. szDefFileName is used by default.
*/
void load (const char *szFileName= szDefFileName);
/**
* Save current dictionary to file szFileName. The output format can differ from original.
* \param szFileName File name to save to. szDefFileName is used by default.
*/
void save (const char *szFileName= szDefFileName);
};
/**
* Auto-loading (and auto-saving) extension to DictionaryT9.
* It includes base-characters set.
*/
class AutoLoadSaveDictionaryT9: public FileDictionaryT9 {
public:
AutoLoadSaveDictionaryT9(); ///< Load dictionary during construction.
~AutoLoadSaveDictionaryT9(); ///< Save dictionary during object destruction.
};
/**
* Generic typer. Abstract class.
*/
class Typer {
public:
virtual ~Typer() {} ///< Always use virtual destructor.
virtual QString getStatusPrefix() =0; ///< Typer-specific status message.
/**
* Entry point to typer. This method is called on key pressed.
* \param key Key enumeration code.
*/
virtual void keyPressed (EKey key) =0;
/**
* Stop rotating and write current definitly.
*/
virtual void flush() =0;
};
/**
* High-level typer interface. This object directly communicate with application UI.
*/
class TyperWrapper: public QObject {
Q_OBJECT
public:
TyperWrapper();
~TyperWrapper();
/// Connect object to main window ui.
void connectToDesign (Ui::MainWindow &design);
/**
* Set timer base. After iTimer msec after last suggestion flush() will be called.
* \param iTimer Timer base [msec].
*/
void setTimer (int iTimer);
/**
* Translate (upper/lower) given character.
* \param c Character to translate.
* \return Return translated character.
*/
QChar translate (QChar c) { return _alphaSwitch.translate(c); }
/// Notify that character was written (for AlphaSwitcher)
void notify();
/// \return Current shift state (for next character only).
bool isUpper() const { return _alphaSwitch.isUpper(); }
/// Put suggestion to text area.
void putSuggest (const QString &);
public slots:
void keyPressed (int); ///< Key pressed slot.
void init(); ///< Typing restored.
void flush(); ///< Write current now!
void clear(); ///< Delete all data
void setT9 (bool); ///< Typer type switch
signals:
void textSizeChanged(int); ///< Effective text size changed to 'int'
protected:
friend class TyperT9;
AlphaSwitcher _alphaSwitch; ///< Universal shift-key handler.
AutoLoadSaveDictionaryT9 _dictT9; ///< Build T9 dictionary just once.
void updateStatus(); ///< Update engine status widget.
private:
QTextEdit *_textEdit; ///< pointer to text area
QLabel *_labelEngineStatus; ///< pointer to engine status widget
Typer *_currentTyper; ///< selected typer
QTimer _timer; ///< internal timer implementation
int _iTimer; ///< timer base [msec]
QString _strSuggest; ///< lastly suggested string
bool _bSuggest; ///< now suggesting
bool _bAtEnd; ///< extra carret displayed
int _lastKey; ///< last key pressed
int _iSelBegin; ///< Selection begin
int _iSelEnd; ///< Selection end
int _iTextSize; ///< Last text size
void showCarret(); ///< Show extra carret
void hideCarret(); ///< Hide extra carret
void startTimer(); ///< Start timer now
void advertiseTextSize(); ///< Emit textSizeChanged signal
};
/**
* Standart mobile typer
*/
class TyperStd: public Typer {
public:
TyperStd (TyperWrapper *parent); ///< \param parent Pointer to typer wrapper object
~TyperStd();
virtual void keyPressed (EKey key);
virtual void flush();
virtual QString getStatusPrefix();
private:
TyperWrapper *_parent;
EKey _lastKey;
Rotator *_currentRotator; ///< Current rotator. 0 if not rotating.
void putSuggest(); ///< Display suggested letter to user.
};
/**
* T9 typer
*/
class TyperT9: public Typer {
public:
TyperT9 (TyperWrapper *parent); ///< \param parent Pointer to typer wrapper object
~TyperT9();
virtual void keyPressed (EKey key);
virtual void flush();
virtual QString getStatusPrefix();
private:
TyperWrapper *_parent;
DictionaryT9 &_dict; ///< Reference to DictionaryT9 object inside typer wrapper
RotatorT9 *_currentRotator; ///< Current rotator. 0 if not rotating.
QString _hashString; ///< Current hash string
QVector<bool> _isUpperVector; ///< Vector containg shift-key state history.
void putSuggest(); ///< Display suggested string to user.
};
/**
* Application engine. Design pattern facade.
*/
class Engine: public QObject {
Q_OBJECT
public:
Engine(QMainWindow *parent); ///< Pointer to parent object (for connection).
/// Connect to main window UI.
void connectToDesign (Ui::MainWindow &design);
/**
* Set timer base.
* \param iTimer Timer base. [msec]
*/
void setTimer(int iTimer) { _typer.setTimer (iTimer); }
private:
KeyScan _keyScan; ///< Keyboard enumeration handler.
StopWatch _stopWatch; ///< Statistics handling.
TyperWrapper _typer; ///< Generic typer wrapper.
};
#endif