MauiKit Terminal

KeyboardTranslator.h
1/*
2 This source file is part of Konsole, a terminal emulator.
3
4 SPDX-FileCopyrightText: 2007-2008 Robert Knight <robertknight@gmail.com>
5
6 SPDX-License-Identifier: GPL-2.0-or-later
7
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
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 02110-1301 USA.
17*/
18
19#ifndef KEYBOARDTRANSLATOR_H
20#define KEYBOARDTRANSLATOR_H
21
22// Qt
23#include <QHash>
24#include <QKeySequence>
25#include <QList>
26#include <QMetaType>
27#include <QVarLengthArray>
28
29// Konsole
30// #include "konsole_export.h"
31#define KONSOLEPRIVATE_EXPORT
32
33class QIODevice;
34class QTextStream;
35
36namespace Konsole
37{
38
39/**
40 * A convertor which maps between key sequences pressed by the user and the
41 * character strings which should be sent to the terminal and commands
42 * which should be invoked when those character sequences are pressed.
43 *
44 * Konsole supports multiple keyboard translators, allowing the user to
45 * specify the character sequences which are sent to the terminal
46 * when particular key sequences are pressed.
47 *
48 * A key sequence is defined as a key code, associated keyboard modifiers
49 * (Shift,Ctrl,Alt,Meta etc.) and state flags which indicate the state
50 * which the terminal must be in for the key sequence to apply.
51 */
53{
54public:
55 /**
56 * The meaning of a particular key sequence may depend upon the state which
57 * the terminal emulation is in. Therefore findEntry() may return a different
58 * Entry depending upon the state flags supplied.
59 *
60 * This enum describes the states which may be associated with with a particular
61 * entry in the keyboard translation entry.
62 */
63 enum State {
64 /** Indicates that no special state is active */
66 /**
67 * TODO More documentation
68 */
70 /**
71 * Indicates that the terminal is in 'Ansi' mode.
72 * TODO: More documentation
73 */
75 /**
76 * TODO More documentation
77 */
79 /**
80 * Indicates that the alternate screen ( typically used by interactive programs
81 * such as screen or vim ) is active
82 */
84 /** Indicates that any of the modifier keys is active. */
86 /** Indicates that the numpad is in application mode. */
88 };
89 Q_DECLARE_FLAGS(States, State)
90
91 /**
92 * This enum describes commands which are associated with particular key sequences.
93 */
94 enum Command {
95 /** Indicates that no command is associated with this command sequence */
97 /** TODO Document me */
99 /** Scroll the terminal display up one page */
101 /** Scroll the terminal display down one page */
103 /** Scroll the terminal display up one line */
105 /** Scroll the terminal display down one line */
107 /** Toggles scroll lock mode */
109 /** Scroll the terminal display up to the start of history */
111 /** Scroll the terminal display down to the end of history */
113 /** Echos the operating system specific erase character. */
114 EraseCommand = 256
115 };
116 Q_DECLARE_FLAGS(Commands, Command)
117
118 /**
119 * Represents an association between a key sequence pressed by the user
120 * and the character sequence and commands associated with it for a particular
121 * KeyboardTranslator.
122 */
123 class Entry
124 {
125 public:
126 /**
127 * Constructs a new entry for a keyboard translator.
128 */
129 Entry();
130
131 /**
132 * Returns true if this entry is null.
133 * This is true for newly constructed entries which have no properties set.
134 */
135 bool isNull() const;
136
137 /** Returns the commands associated with this entry */
138 Command command() const;
139 /** Sets the command associated with this entry. */
140 void setCommand(Command command);
141
142 /**
143 * Returns the character sequence associated with this entry, optionally replacing
144 * wildcard '*' characters with numbers to indicate the keyboard modifiers being pressed.
145 *
146 * TODO: The numbers used to replace '*' characters are taken from the Konsole/KDE 3 code.
147 * Document them.
148 *
149 * @param expandWildCards Specifies whether wild cards (occurrences of the '*' character) in
150 * the entry should be replaced with a number to indicate the modifier keys being pressed.
151 *
152 * @param modifiers The keyboard modifiers being pressed.
153 */
154 QByteArray text(bool expandWildCards = false, Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
155
156 /** Sets the character sequence associated with this entry */
157 void setText(const QByteArray &text);
158
159 /**
160 * Returns the character sequence associated with this entry,
161 * with any non-printable characters replaced with escape sequences.
162 *
163 * eg. \\E for Escape, \\t for tab, \\n for new line.
164 *
165 * @param expandWildCards See text()
166 * @param modifiers See text()
167 */
168 QByteArray escapedText(bool expandWildCards = false, Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
169
170 /** Returns the character code ( from the Qt::Key enum ) associated with this entry */
171 int keyCode() const;
172 /** Sets the character code associated with this entry */
173 void setKeyCode(int keyCode);
174
175 /**
176 * Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry.
177 * If a modifier is set in modifierMask() but not in modifiers(), this means that the entry
178 * only matches when that modifier is NOT pressed.
179 *
180 * If a modifier is not set in modifierMask() then the entry matches whether the modifier
181 * is pressed or not.
182 */
183 Qt::KeyboardModifiers modifiers() const;
184
185 /** Returns the keyboard modifiers which are valid in this entry. See modifiers() */
186 Qt::KeyboardModifiers modifierMask() const;
187
188 /** See modifiers() */
189 void setModifiers(Qt::KeyboardModifiers modifiers);
190 /** See modifierMask() and modifiers() */
191 void setModifierMask(Qt::KeyboardModifiers modifiers);
192
193 /**
194 * Returns a bitwise-OR of the enabled state flags associated with this entry.
195 * If flag is set in stateMask() but not in state(), this means that the entry only
196 * matches when the terminal is NOT in that state.
197 *
198 * If a state is not set in stateMask() then the entry matches whether the terminal
199 * is in that state or not.
200 */
201 States state() const;
202
203 /** Returns the state flags which are valid in this entry. See state() */
204 States stateMask() const;
205
206 /** See state() */
207 void setState(States state);
208 /** See stateMask() */
209 void setStateMask(States mask);
210
211 /**
212 * Returns the key code and modifiers associated with this entry
213 * as a QKeySequence
214 */
215 // QKeySequence keySequence() const;
216
217 /**
218 * Returns this entry's conditions ( ie. its key code, modifier and state criteria )
219 * as a string.
220 */
221 QString conditionToString() const;
222
223 /**
224 * Returns this entry's result ( ie. its command or character sequence )
225 * as a string.
226 *
227 * @param expandWildCards See text()
228 * @param modifiers See text()
229 */
230 QString resultToString(bool expandWildCards = false, Qt::KeyboardModifiers modifiers = Qt::NoModifier) const;
231
232 /**
233 * Returns true if this entry matches the given key sequence, specified
234 * as a combination of @p keyCode , @p modifiers and @p state.
235 */
236 bool matches(int keyCode, Qt::KeyboardModifiers modifiers, States flags) const;
237
238 bool operator==(const Entry &rhs) const;
239
240 private:
241 void insertModifier(QString &item, int modifier) const;
242 void insertState(QString &item, int state) const;
243 QByteArray unescape(const QByteArray &text) const;
244
245 int _keyCode;
246 Qt::KeyboardModifiers _modifiers;
247 Qt::KeyboardModifiers _modifierMask;
248 States _state;
249 States _stateMask;
250
251 Command _command;
252 QByteArray _text;
253 };
254
255 /** Constructs a new keyboard translator with the given @p name */
257
258 // KeyboardTranslator(const KeyboardTranslator& other);
259
260 /** Returns the name of this keyboard translator */
261 QString name() const;
262
263 /** Sets the name of this keyboard translator */
264 void setName(const QString &name);
265
266 /** Returns the descriptive name of this keyboard translator */
267 QString description() const;
268
269 /** Sets the descriptive name of this keyboard translator */
271
272 /**
273 * Looks for an entry in this keyboard translator which matches the given
274 * key code, keyboard modifiers and state flags.
275 *
276 * Returns the matching entry if found or a null Entry otherwise ( ie.
277 * entry.isNull() will return true )
278 *
279 * @param keyCode A key code from the Qt::Key enum
280 * @param modifiers A combination of modifiers
281 * @param state Optional flags which specify the current state of the terminal
282 */
283 Entry findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state = NoState) const;
284
285 /**
286 * Adds an entry to this keyboard translator's table. Entries can be looked up according
287 * to their key sequence using findEntry()
288 */
289 void addEntry(const Entry &entry);
290
291 /**
292 * Replaces an entry in the translator. If the @p existing entry is null,
293 * then this is equivalent to calling addEntry(@p replacement)
294 */
295 void replaceEntry(const Entry &existing, const Entry &replacement);
296
297 /**
298 * Removes an entry from the table.
299 */
300 void removeEntry(const Entry &entry);
301
302 /** Returns a list of all entries in the translator. */
303 QList<Entry> entries() const;
304
305 /** The modifier code for the actual Ctrl key on this OS. */
307
308private:
309 QMultiHash<int, Entry> _entries; // entries in this keyboard translation,
310 // entries are indexed according to
311 // their keycode
312 QString _name;
313 QString _description;
314};
315Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::States)
316Q_DECLARE_OPERATORS_FOR_FLAGS(KeyboardTranslator::Commands)
317
318/**
319 * Parses the contents of a Keyboard Translator (.keytab) file and
320 * returns the entries found in it.
321 *
322 * Usage example:
323 *
324 * @code
325 * QFile source( "/path/to/keytab" );
326 * source.open( QIODevice::ReadOnly );
327 *
328 * KeyboardTranslator* translator = new KeyboardTranslator( "name-of-translator" );
329 *
330 * KeyboardTranslatorReader reader(source);
331 * while ( reader.hasNextEntry() )
332 * translator->addEntry(reader.nextEntry());
333 *
334 * source.close();
335 *
336 * if ( !reader.parseError() )
337 * {
338 * // parsing succeeded, do something with the translator
339 * }
340 * else
341 * {
342 * // parsing failed
343 * }
344 * @endcode
345 */
347{
348public:
349 /** Constructs a new reader which parses the given @p source */
351
352 /**
353 * Returns the description text.
354 * TODO: More documentation
355 */
356 QString description() const;
357
358 /** Returns true if there is another entry in the source stream */
359 bool hasNextEntry() const;
360 /** Returns the next entry found in the source stream */
361 KeyboardTranslator::Entry nextEntry();
362
363 /**
364 * Returns true if an error occurred whilst parsing the input or
365 * false if no error occurred.
366 */
367 bool parseError();
368
369 /**
370 * Parses a condition and result string for a translator entry
371 * and produces a keyboard translator entry.
372 *
373 * The condition and result strings are in the same format as in
374 */
375 static KeyboardTranslator::Entry createEntry(const QString &condition, const QString &result);
376
377private:
378 struct Token {
379 enum Type { TitleKeyword, TitleText, KeyKeyword, KeySequence, Command, OutputText };
380 Type type;
381 QString text;
382 };
383 QList<Token> tokenize(const QString &);
384 void readNext();
385 bool decodeSequence(const QString &,
386 int &keyCode,
387 Qt::KeyboardModifiers &modifiers,
388 Qt::KeyboardModifiers &modifierMask,
390 KeyboardTranslator::States &stateFlags);
391
392 static bool parseAsModifier(const QString &item, Qt::KeyboardModifier &modifier);
393 static bool parseAsStateFlag(const QString &item, KeyboardTranslator::State &state);
394 static bool parseAsKeyCode(const QString &item, int &keyCode);
395 static bool parseAsCommand(const QString &text, KeyboardTranslator::Command &command);
396
397 QIODevice *_source;
398 QString _description;
399 KeyboardTranslator::Entry _nextEntry;
400 bool _hasNext;
401};
402
403/** Writes a keyboard translation to disk. */
405{
406public:
407 /**
408 * Constructs a new writer which saves data into @p destination.
409 * The caller is responsible for closing the device when writing is complete.
410 */
413
414 /**
415 * Writes the header for the keyboard translator.
416 * @param description Description of the keyboard translator.
417 */
418 void writeHeader(const QString &description);
419 /** Writes a translator entry. */
420 void writeEntry(const KeyboardTranslator::Entry &entry);
421
422private:
423 QIODevice *_destination;
424 QTextStream *_writer;
425};
426
427/**
428 * Manages the keyboard translations available for use by terminal sessions,
429 * see KeyboardTranslator.
430 */
431class KONSOLEPRIVATE_EXPORT KeyboardTranslatorManager
432{
433public:
434 /**
435 * Constructs a new KeyboardTranslatorManager and loads the list of
436 * available keyboard translations.
437 *
438 * The keyboard translations themselves are not loaded until they are
439 * first requested via a call to findTranslator()
440 */
443
445 KeyboardTranslatorManager &operator=(const KeyboardTranslatorManager &) = delete;
446
447 /**
448 * Adds a new translator. If a translator with the same name
449 * already exists, it will be replaced by the new translator.
450 *
451 * TODO: More documentation.
452 */
453 void addTranslator(KeyboardTranslator *translator);
454
455 /**
456 * Deletes a translator. Returns true on successful deletion or false otherwise.
457 *
458 * TODO: More documentation
459 */
460 bool deleteTranslator(const QString &name);
461
462 /** Returns the default translator for Konsole. */
463 const KeyboardTranslator *defaultTranslator();
464
465 /**
466 * Returns the keyboard translator with the given name or 0 if no translator
467 * with that name exists.
468 *
469 * The first time that a translator with a particular name is requested,
470 * the on-disk .keyboard file is loaded and parsed.
471 */
472 const KeyboardTranslator *findTranslator(const QString &name);
473 /**
474 * Returns a list of the names of available keyboard translators.
475 *
476 * The first time this is called, a search for available
477 * translators is started.
478 */
479 QList<QString> allTranslators();
480
481 /** Returns the global KeyboardTranslatorManager instance. */
482 static KeyboardTranslatorManager *instance();
483
484private:
485 static const QByteArray defaultTranslatorText;
486
487 void findTranslators(); // locate the available translators
488 KeyboardTranslator *loadTranslator(const QString &name); // loads the translator
489 // with the given name
490 KeyboardTranslator *loadTranslator(QIODevice *device, const QString &name);
491
492 bool saveTranslator(const KeyboardTranslator *translator);
493 QString findTranslatorPath(const QString &name);
494
495 QHash<QString, KeyboardTranslator *> _translators; // maps translator-name -> KeyboardTranslator
496 // instance
497 bool _haveLoadedAll;
498};
499
501{
502 return _keyCode;
503}
505{
506 _keyCode = keyCode;
507}
508
510{
511 _modifiers = modifier;
512}
514{
515 return _modifiers;
516}
517
519{
520 _modifierMask = mask;
521}
523{
524 return _modifierMask;
525}
526
528{
529 return (*this == Entry());
530}
531
533{
534 _command = command;
535}
537{
538 return _command;
539}
540
542{
543 _text = unescape(text);
544}
545inline int oneOrZero(int value)
546{
547 return value ? 1 : 0;
548}
549inline QByteArray KeyboardTranslator::Entry::text(bool expandWildCards, Qt::KeyboardModifiers modifiers) const
550{
551 QByteArray expandedText = _text;
552
553 if (expandWildCards) {
554 int modifierValue = 1;
555 modifierValue += oneOrZero(modifiers & Qt::ShiftModifier);
556 modifierValue += oneOrZero(modifiers & Qt::AltModifier) << 1;
557 modifierValue += oneOrZero(modifiers & KeyboardTranslator::CTRL_MOD) << 2;
558
559 for (int i = 0; i < _text.length(); i++) {
560 if (expandedText[i] == '*')
561 expandedText[i] = '0' + modifierValue;
562 }
563 }
564
565 return expandedText;
566}
567
569{
570 _state = state;
571}
573{
574 return _state;
575}
576
578{
579 _stateMask = stateMask;
580}
582{
583 return _stateMask;
584}
585}
586
587Q_DECLARE_METATYPE(Konsole::KeyboardTranslator::Entry)
588Q_DECLARE_METATYPE(const Konsole::KeyboardTranslator *)
589
590#endif // KEYBOARDTRANSLATOR_H
Manages the keyboard translations available for use by terminal sessions, see KeyboardTranslator.
Parses the contents of a Keyboard Translator (.keytab) file and returns the entries found in it.
Writes a keyboard translation to disk.
void writeHeader(const QString &description)
Writes the header for the keyboard translator.
void writeEntry(const KeyboardTranslator::Entry &entry)
Writes a translator entry.
KeyboardTranslatorWriter(QIODevice *destination)
Constructs a new writer which saves data into destination.
Represents an association between a key sequence pressed by the user and the character sequence and c...
Command command() const
Returns the commands associated with this entry.
void setModifierMask(Qt::KeyboardModifiers modifiers)
See modifierMask() and modifiers()
Qt::KeyboardModifiers modifierMask() const
Returns the keyboard modifiers which are valid in this entry.
States state() const
Returns a bitwise-OR of the enabled state flags associated with this entry.
void setModifiers(Qt::KeyboardModifiers modifiers)
See modifiers()
int keyCode() const
Returns the character code ( from the Qt::Key enum ) associated with this entry.
States stateMask() const
Returns the state flags which are valid in this entry.
Qt::KeyboardModifiers modifiers() const
Returns a bitwise-OR of the enabled keyboard modifiers associated with this entry.
void setKeyCode(int keyCode)
Sets the character code associated with this entry.
void setCommand(Command command)
Sets the command associated with this entry.
void setStateMask(States mask)
See stateMask()
QByteArray text(bool expandWildCards=false, Qt::KeyboardModifiers modifiers=Qt::NoModifier) const
Returns the character sequence associated with this entry, optionally replacing wildcard '*' characte...
void setState(States state)
See state()
void setText(const QByteArray &text)
Sets the character sequence associated with this entry.
bool isNull() const
Returns true if this entry is null.
A convertor which maps between key sequences pressed by the user and the character strings which shou...
QString name() const
Returns the name of this keyboard translator.
Entry findEntry(int keyCode, Qt::KeyboardModifiers modifiers, States state=NoState) const
Looks for an entry in this keyboard translator which matches the given key code, keyboard modifiers a...
QString description() const
Returns the descriptive name of this keyboard translator.
static const Qt::KeyboardModifier CTRL_MOD
The modifier code for the actual Ctrl key on this OS.
void replaceEntry(const Entry &existing, const Entry &replacement)
Replaces an entry in the translator.
void setName(const QString &name)
Sets the name of this keyboard translator.
State
The meaning of a particular key sequence may depend upon the state which the terminal emulation is in...
@ AnsiState
Indicates that the terminal is in 'Ansi' mode.
@ NoState
Indicates that no special state is active.
@ AlternateScreenState
Indicates that the alternate screen ( typically used by interactive programs such as screen or vim ) ...
@ AnyModifierState
Indicates that any of the modifier keys is active.
@ NewLineState
TODO More documentation.
@ CursorKeysState
TODO More documentation.
@ ApplicationKeypadState
Indicates that the numpad is in application mode.
QList< Entry > entries() const
Returns a list of all entries in the translator.
Command
This enum describes commands which are associated with particular key sequences.
@ NoCommand
Indicates that no command is associated with this command sequence.
@ EraseCommand
Echos the operating system specific erase character.
@ ScrollPageDownCommand
Scroll the terminal display down one page.
@ ScrollDownToBottomCommand
Scroll the terminal display down to the end of history.
@ ScrollUpToTopCommand
Scroll the terminal display up to the start of history.
@ ScrollLineUpCommand
Scroll the terminal display up one line.
@ ScrollLockCommand
Toggles scroll lock mode.
@ ScrollPageUpCommand
Scroll the terminal display up one page.
@ ScrollLineDownCommand
Scroll the terminal display down one line.
KeyboardTranslator(const QString &name)
Constructs a new keyboard translator with the given name.
void setDescription(const QString &description)
Sets the descriptive name of this keyboard translator.
void addEntry(const Entry &entry)
Adds an entry to this keyboard translator's table.
void removeEntry(const Entry &entry)
Removes an entry from the table.
typedef KeyboardModifiers
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:57:30 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.