📜 ⬆️ ⬇️

SpeedReader - Qt library for speed reading

image

Foreword


Some time ago on Habré there was news about Spritz - a software implementation of fast reading techniques based on a quick change of words in a widget with a certain centering of the word itself within the widget, and a bit later another news . Since the topic is quite relevant, I, without thinking twice, decided to implement something similar and universal, with the possibility of embedding such a widget for speed reading into programs on various platforms (win, linux, mac, android). Based on this condition, Qt was chosen with its broad support for various platforms.

What happened and how to work with it is described below. Who cares, welcome.

How to use it?


1. Include header files:
#include "SpeedReader/speedreader.h" #include "SpeedReader/txtreader.h" //    TextFormatReader 

')
2. Create objects:
 TxtReader *pTxtReader = new TxtReader("path_to_file", "UTF-8"); // :       ,     SpeedReader *pSpeedReader = new SpeedReader(pTxtReader); 


3. Set reader settings:
 pSpeedReader->setReadingSpeed(300); //      pSpeedReader->setCommaPauseTime(150); //     ( ) pSpeedReader->setDotPauseTime(200); //      ( ) pSpeedReader->setCurrentPosition(0); //    


4. Put the SpeedReaderLabel widget on the form (you can put a QLabel, and then convert it into a SpeedReaderLabel). Set the color of the highlighted character:
 ui->speedReaderLabel->setSymbolColor("red"); 


5. Connect the signals of the object of the SpeedReader class to the slots of the SpeedReaderLabel widget:
 connect(pSpeedReader, SIGNAL(nextWordAvailable(QString, int)), ui->speedReaderLabel, SLOT(processNextWordAvailable(QString, int))); connect(pSpeedReader, SIGNAL(wordOffset(int)), ui->speedReaderLabel, SLOT(processWordOffset(int))); 


6. Start / stop reading:
 pSpeedReader->startReading(); pSpeedReader->stopReading(); 


7. It is also possible to intercept some optional signals from an object of the SpeedReader class, such as:
 SIGNAL(error(SpeedReaderError)) //  SIGNAL(endOfBook()) //      SIGNAL(readingProgress(double)) //   ( 0  1) 


A little about how it all works. Library core implementation


Having allocated several hours on a day off, he sat down for thinking over the idea and its programming. The following scheme was chosen: a class for switching words (SpeedReader) + a base abstract class for reading text files in different formats (TextFormatReader), from which you need to inherit specific “format readers” (for example, the simplest class reader * .txt format is implemented - TxtReader).

SpeedReader Central Class

The main task of objects of this class is to switch words with a certain speed and in general, to behave in accordance with the specified settings. Let's look at the class's public interface:
 class SpeedReader : public QObject { ... void setCurrentPosition(const int ¤tPosition); //      void setCommaPauseTime(const int &comaPauseTime); //      ( ) void setDotPauseTime(const int &dotPauseTime); //       ( ) void setReadingSpeed(int wordPerMinute); //   (  ) void setEnableShifting(const bool &enableShifting); //    (  ) //  get  QStringList getWordsToRead() const; //       int getCurrentPosition() const; int getComaPauseTime() const; int getDotPauseTime() const; int getReadingSpeed() const; int getWordsCount() const; //   ,    bool isEnableShifting() const; void startReading(); //    void stopReading(); //    ... } 


The word switching itself occurs due to the signal being sent out by an object of the SpeedReader class containing the word to be displayed in the widget. But about the widget later.

Available SpeedReader signals for processing:
 signals: //    (            .  ,   ) void nextWordAvailable(QString, int); // ,     -   void wordOffset(int); // ,       //     void readingProgress(double); // ,     ( 0  1) void error(SpeedReaderError); // ,       void endOfBook(); // ,      


TextFormatReader - a base abstract class for implementing reading various text formats

All you need to know about this class is that it has a method
 virtual QStringList getWords() = 0; 
which needs to be redefined in classes by successors. This method just parses the contents of the text format. For example, in the TxtReader class, the simplest parsing occurs in this method, namely, replacing two spaces with one space and deleting line-break characters.

 class TextFormatReader: public QObject { ... public: TextFormatReader(const QString &fileName, const QString &textCodecName); virtual QStringList getWords() = 0; //      void openBook(const QString &filePath); ... }; 


Actually, this is the core of the library.

Implementing SpeedReaderLabel widget


The widget for displaying words is a QLable heir, on which markup lines are drawn (as in the figure at the beginning of the article). The main task of the widget is to display words sent by an object of the SpeedReader class. Let's look at the widget's public interface:

 class SpeedReaderLabel : public QLabel { ... public slots: void processWordOffset(const int &verticalPointerOffset); //   nextWordAvailable  SpeedReader?     .          (.   ) void processNextWordAvailable(QString w, int shift); //   .          shift *     ... }; 


Support for other text formats (fb2, html and others)


In order to add support for other text formats, you need to create a class and inherit it from TextFormatReader:

1. It is necessary to inherit from TextFormatReader, call the constructor of the ancestor and override one method:
 #ifndef SOMEREADER_H #define SOMEREADER_H #include "textformatreader.h" class SomeReader : public TextFormatReader { public: SomeReader(const QString &fileName, const QString &textCodecName) : TextFormatReader(fileName, textCodecName) {} //     QStringList getWords(); //     }; #endif // SOMEREADER_H 


2. Override the getWords () method:
 QStringList SomeReader::getWords() { QString textToParse = this->text; // this->text - ""     //    (     ) textToParse = textToParse.replace("someTag", ""); return countWords(textToParse); //    countWords(QString text) ,      } 


3. Now you can open files of the format defined in our class:
 SomeReader *pSomeReader = new SomeReader("path_to_file", "UTF-8"); SpeedReader *pSpeedReader = new SpeedReader(pSomeReader); ... 


Well, then everything, as in the beginning of the article in the section "How to use it?".

Conclusion


As a result, a small library was developed, which will allow embedding this technology of fast reading into programs on various platforms. Let me put here a link to the project in Google Code: SpeedReader on google code . There are two folders in the repository: SpeedReader (there are library files in it) and SpeedReaderTest (the minimum working project using the library. * .Txt file must be placed in the folder with the executable compiled program file or you must specify your own path to the file). I am pleased to answer all questions in the comments, if any.

Source: https://habr.com/ru/post/216003/


All Articles