Česky
Kamil Dudka

emulT9 (C++, Qt4)

File detail

Name:Downloadengine.h [Download]
Location: emulT9 > src
Size:11.2 KB
Last modification:2007-08-27 01:12

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