PageRenderTime 50ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/Filter.h

https://gitlab.com/rmstoi/mtermite
C Header | 383 lines | 151 code | 51 blank | 181 comment | 0 complexity | a85b9343984c1557bd83f7857f8aeaab MD5 | raw file
  1. /*
  2. Copyright (C) 2007 by Robert Knight <robertknight@gmail.com>
  3. Rewritten for QT4 by e_k <e_k at users.sourceforge.net>, Copyright (C)2008
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15. 02110-1301 USA.
  16. */
  17. #ifndef FILTER_H
  18. #define FILTER_H
  19. // Qt
  20. #include <QtGui/QAction>
  21. #include <QtCore/QList>
  22. #include <QtCore/QObject>
  23. #include <QtCore/QStringList>
  24. #include <QtCore/QHash>
  25. #include <QtCore/QRegExp>
  26. // Local
  27. #include "Character.h"
  28. namespace Konsole
  29. {
  30. /**
  31. * A filter processes blocks of text looking for certain patterns (such as URLs or keywords from a list)
  32. * and marks the areas which match the filter's patterns as 'hotspots'.
  33. *
  34. * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
  35. * and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact
  36. * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
  37. * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response.
  38. *
  39. * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.
  40. * Hotspots may have more than one action, in which case the list of actions can be obtained using the
  41. * actions() method.
  42. *
  43. * Different subclasses of filter will return different types of hotspot.
  44. * Subclasses must reimplement the process() method to examine a block of text and identify sections of interest.
  45. * When processing the text they should create instances of Filter::HotSpot subclasses for sections of interest
  46. * and add them to the filter's list of hotspots using addHotSpot()
  47. */
  48. class Filter
  49. {
  50. public:
  51. /**
  52. * Represents an area of text which matched the pattern a particular filter has been looking for.
  53. *
  54. * Each hotspot has a type identifier associated with it ( such as a link or a highlighted section ),
  55. * and an action. When the user performs some activity such as a mouse-click in a hotspot area ( the exact
  56. * action will depend on what is displaying the block of text which the filter is processing ), the hotspot's
  57. * activate() method should be called. Depending on the type of hotspot this will trigger a suitable response.
  58. *
  59. * For example, if a hotspot represents a URL then a suitable action would be opening that URL in a web browser.
  60. * Hotspots may have more than one action, in which case the list of actions can be obtained using the
  61. * actions() method. These actions may then be displayed in a popup menu or toolbar for example.
  62. */
  63. class HotSpot
  64. {
  65. public:
  66. /**
  67. * Constructs a new hotspot which covers the area from (@p startLine,@p startColumn) to (@p endLine,@p endColumn)
  68. * in a block of text.
  69. */
  70. HotSpot(int startLine , int startColumn , int endLine , int endColumn);
  71. virtual ~HotSpot();
  72. enum Type
  73. {
  74. // the type of the hotspot is not specified
  75. NotSpecified,
  76. // this hotspot represents a clickable link
  77. Link,
  78. // this hotspot represents a marker
  79. Marker
  80. };
  81. /** Returns the line when the hotspot area starts */
  82. int startLine() const;
  83. /** Returns the line where the hotspot area ends */
  84. int endLine() const;
  85. /** Returns the column on startLine() where the hotspot area starts */
  86. int startColumn() const;
  87. /** Returns the column on endLine() where the hotspot area ends */
  88. int endColumn() const;
  89. /**
  90. * Returns the type of the hotspot. This is usually used as a hint for views on how to represent
  91. * the hotspot graphically. eg. Link hotspots are typically underlined when the user mouses over them
  92. */
  93. Type type() const;
  94. /**
  95. * Causes the an action associated with a hotspot to be triggered.
  96. *
  97. * @param object The object which caused the hotspot to be triggered. This is
  98. * typically null ( in which case the default action should be performed ) or
  99. * one of the objects from the actions() list. In which case the associated
  100. * action should be performed.
  101. */
  102. virtual void activate(QObject* object = 0) = 0;
  103. /**
  104. * Returns a list of actions associated with the hotspot which can be used in a
  105. * menu or toolbar
  106. */
  107. virtual QList<QAction*> actions();
  108. /**
  109. * Returns the text of a tooltip to be shown when the mouse moves over the hotspot, or
  110. * an empty string if there is no tooltip associated with this hotspot.
  111. *
  112. * The default implementation returns an empty string.
  113. */
  114. virtual QString tooltip() const;
  115. protected:
  116. /** Sets the type of a hotspot. This should only be set once */
  117. void setType(Type type);
  118. private:
  119. int _startLine;
  120. int _startColumn;
  121. int _endLine;
  122. int _endColumn;
  123. Type _type;
  124. };
  125. /** Constructs a new filter. */
  126. Filter();
  127. virtual ~Filter();
  128. /** Causes the filter to process the block of text currently in its internal buffer */
  129. virtual void process() = 0;
  130. /**
  131. * Empties the filters internal buffer and resets the line count back to 0.
  132. * All hotspots are deleted.
  133. */
  134. void reset();
  135. /** Adds a new line of text to the filter and increments the line count */
  136. //void addLine(const QString& string);
  137. /** Returns the hotspot which covers the given @p line and @p column, or 0 if no hotspot covers that area */
  138. HotSpot* hotSpotAt(int line , int column) const;
  139. /** Returns the list of hotspots identified by the filter */
  140. QList<HotSpot*> hotSpots() const;
  141. /** Returns the list of hotspots identified by the filter which occur on a given line */
  142. QList<HotSpot*> hotSpotsAtLine(int line) const;
  143. /**
  144. * TODO: Document me
  145. */
  146. void setBuffer(const QString* buffer , const QList<int>* linePositions);
  147. protected:
  148. /** Adds a new hotspot to the list */
  149. void addHotSpot(HotSpot*);
  150. /** Returns the internal buffer */
  151. const QString* buffer();
  152. /** Converts a character position within buffer() to a line and column */
  153. void getLineColumn(int position , int& startLine , int& startColumn);
  154. private:
  155. QMultiHash<int,HotSpot*> _hotspots;
  156. QList<HotSpot*> _hotspotList;
  157. const QList<int>* _linePositions;
  158. const QString* _buffer;
  159. };
  160. /**
  161. * A filter which searches for sections of text matching a regular expression and creates a new RegExpFilter::HotSpot
  162. * instance for them.
  163. *
  164. * Subclasses can reimplement newHotSpot() to return custom hotspot types when matches for the regular expression
  165. * are found.
  166. */
  167. class RegExpFilter : public Filter
  168. {
  169. public:
  170. /**
  171. * Type of hotspot created by RegExpFilter. The capturedTexts() method can be used to find the text
  172. * matched by the filter's regular expression.
  173. */
  174. class HotSpot : public Filter::HotSpot
  175. {
  176. public:
  177. HotSpot(int startLine, int startColumn, int endLine , int endColumn);
  178. virtual void activate(QObject* object = 0);
  179. /** Sets the captured texts associated with this hotspot */
  180. void setCapturedTexts(const QStringList& texts);
  181. /** Returns the texts found by the filter when matching the filter's regular expression */
  182. QStringList capturedTexts() const;
  183. private:
  184. QStringList _capturedTexts;
  185. };
  186. /** Constructs a new regular expression filter */
  187. RegExpFilter();
  188. /**
  189. * Sets the regular expression which the filter searches for in blocks of text.
  190. *
  191. * Regular expressions which match the empty string are treated as not matching
  192. * anything.
  193. */
  194. void setRegExp(const QRegExp& text);
  195. /** Returns the regular expression which the filter searches for in blocks of text */
  196. QRegExp regExp() const;
  197. /**
  198. * Reimplemented to search the filter's text buffer for text matching regExp()
  199. *
  200. * If regexp matches the empty string, then process() will return immediately
  201. * without finding results.
  202. */
  203. virtual void process();
  204. protected:
  205. /**
  206. * Called when a match for the regular expression is encountered. Subclasses should reimplement this
  207. * to return custom hotspot types
  208. */
  209. virtual RegExpFilter::HotSpot* newHotSpot(int startLine,int startColumn,
  210. int endLine,int endColumn);
  211. private:
  212. QRegExp _searchText;
  213. };
  214. class FilterObject;
  215. /** A filter which matches URLs in blocks of text */
  216. class UrlFilter : public RegExpFilter
  217. {
  218. public:
  219. /**
  220. * Hotspot type created by UrlFilter instances. The activate() method opens a web browser
  221. * at the given URL when called.
  222. */
  223. class HotSpot : public RegExpFilter::HotSpot
  224. {
  225. public:
  226. HotSpot(int startLine,int startColumn,int endLine,int endColumn);
  227. virtual ~HotSpot();
  228. virtual QList<QAction*> actions();
  229. /**
  230. * Open a web browser at the current URL. The url itself can be determined using
  231. * the capturedTexts() method.
  232. */
  233. virtual void activate(QObject* object = 0);
  234. virtual QString tooltip() const;
  235. private:
  236. enum UrlType
  237. {
  238. StandardUrl,
  239. Email,
  240. Unknown
  241. };
  242. UrlType urlType() const;
  243. FilterObject* _urlObject;
  244. };
  245. UrlFilter();
  246. protected:
  247. virtual RegExpFilter::HotSpot* newHotSpot(int,int,int,int);
  248. private:
  249. static const QRegExp FullUrlRegExp;
  250. static const QRegExp EmailAddressRegExp;
  251. // combined OR of FullUrlRegExp and EmailAddressRegExp
  252. static const QRegExp CompleteUrlRegExp;
  253. };
  254. class FilterObject : public QObject
  255. {
  256. Q_OBJECT
  257. public:
  258. FilterObject(Filter::HotSpot* filter) : _filter(filter) {}
  259. private slots:
  260. void activated();
  261. private:
  262. Filter::HotSpot* _filter;
  263. };
  264. /**
  265. * A chain which allows a group of filters to be processed as one.
  266. * The chain owns the filters added to it and deletes them when the chain itself is destroyed.
  267. *
  268. * Use addFilter() to add a new filter to the chain.
  269. * When new text to be filtered arrives, use addLine() to add each additional
  270. * line of text which needs to be processed and then after adding the last line, use
  271. * process() to cause each filter in the chain to process the text.
  272. *
  273. * After processing a block of text, the reset() method can be used to set the filter chain's
  274. * internal cursor back to the first line.
  275. *
  276. * The hotSpotAt() method will return the first hotspot which covers a given position.
  277. *
  278. * The hotSpots() and hotSpotsAtLine() method return all of the hotspots in the text and on
  279. * a given line respectively.
  280. */
  281. class FilterChain : protected QList<Filter*>
  282. {
  283. public:
  284. virtual ~FilterChain();
  285. /** Adds a new filter to the chain. The chain will delete this filter when it is destroyed */
  286. void addFilter(Filter* filter);
  287. /** Removes a filter from the chain. The chain will no longer delete the filter when destroyed */
  288. void removeFilter(Filter* filter);
  289. /** Returns true if the chain contains @p filter */
  290. bool containsFilter(Filter* filter);
  291. /** Removes all filters from the chain */
  292. void clear();
  293. /** Resets each filter in the chain */
  294. void reset();
  295. /**
  296. * Processes each filter in the chain
  297. */
  298. void process();
  299. /** Sets the buffer for each filter in the chain to process. */
  300. void setBuffer(const QString* buffer , const QList<int>* linePositions);
  301. /** Returns the first hotspot which occurs at @p line, @p column or 0 if no hotspot was found */
  302. Filter::HotSpot* hotSpotAt(int line , int column) const;
  303. /** Returns a list of all the hotspots in all the chain's filters */
  304. QList<Filter::HotSpot*> hotSpots() const;
  305. /** Returns a list of all hotspots at the given line in all the chain's filters */
  306. QList<Filter::HotSpot> hotSpotsAtLine(int line) const;
  307. };
  308. /** A filter chain which processes character images from terminal displays */
  309. class TerminalImageFilterChain : public FilterChain
  310. {
  311. public:
  312. TerminalImageFilterChain();
  313. virtual ~TerminalImageFilterChain();
  314. /**
  315. * Set the current terminal image to @p image.
  316. *
  317. * @param image The terminal image
  318. * @param lines The number of lines in the terminal image
  319. * @param columns The number of columns in the terminal image
  320. */
  321. void setImage(const Character* const image , int lines , int columns,
  322. const QVector<LineProperty>& lineProperties);
  323. private:
  324. QString* _buffer;
  325. QList<int>* _linePositions;
  326. };
  327. }
  328. #endif //FILTER_H