1/*
2 This source file is part of Konsole, a terminal emulator.
3
4 Copyright 2007-2008 by Robert Knight <robertknight@gmail.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20*/
21
22#ifndef PROFILE_H
23#define PROFILE_H
24
25// Qt
26#include <QtCore/QHash>
27#include <QtCore/QStringList>
28#include <QtCore/QVariant>
29#include <QtGui/QFont>
30#include <QtGui/QColor>
31
32// KDE
33#include <KSharedPtr>
34
35// Konsole
36#include "konsole_export.h"
37
38namespace Konsole
39{
40class ProfileGroup;
41
42/**
43 * Represents a terminal set-up which can be used to
44 * set the initial state of new terminal sessions or applied
45 * to existing sessions. Profiles consist of a number of named
46 * properties, which can be retrieved using property() and
47 * set using setProperty(). isPropertySet() can be used to check
48 * whether a particular property has been set in a profile.
49 *
50 * Profiles support a simple form of inheritance. When a new Profile
51 * is constructed, a pointer to a parent profile can be passed to
52 * the constructor. When querying a particular property of a profile
53 * using property(), the profile will return its own value for that
54 * property if one has been set or otherwise it will return the
55 * parent's value for that property.
56 *
57 * Profiles can be loaded from disk using ProfileReader instances
58 * and saved to disk using ProfileWriter instances.
59 */
60class KONSOLEPRIVATE_EXPORT Profile : public QSharedData
61{
62 friend class KDE4ProfileReader;
63 friend class KDE4ProfileWriter;
64 friend class ProfileGroup;
65
66public:
67 typedef KSharedPtr<Profile> Ptr;
68 typedef KSharedPtr<ProfileGroup> GroupPtr;
69
70 /**
71 * This enum describes the available properties
72 * which a Profile may consist of.
73 *
74 * Properties can be set using setProperty() and read
75 * using property()
76 */
77 enum Property {
78 /** (QString) Path to the profile's configuration file on-disk. */
79 Path,
80 /** (QString) The descriptive name of this profile. */
81 Name,
82 /** (QString) The untranslated name of this profile.
83 * Warning: this is an internal property. Do not touch it.
84 */
85 UntranslatedName,
86 /** (QString) The name of the icon associated with this profile.
87 * This is used in menus and tabs to represent the profile.
88 */
89 Icon,
90 /** (QString) The command to execute ( excluding arguments ) when
91 * creating a new terminal session using this profile.
92 */
93 Command,
94 /** (QStringList) The arguments which are passed to the program
95 * specified by the Command property when creating a new terminal
96 * session using this profile.
97 */
98 Arguments,
99 /** (QStringList) Additional environment variables (in the form of
100 * NAME=VALUE pairs) which are passed to the program specified by
101 * the Command property when creating a new terminal session using
102 * this profile.
103 */
104 Environment,
105 /** (QString) The initial working directory for sessions created
106 * using this profile.
107 */
108 Directory,
109 /** (QString) The format used for tab titles when running normal
110 * commands.
111 */
112 LocalTabTitleFormat,
113 /** (QString) The format used for tab titles when the session is
114 * running a remote command (eg. SSH)
115 */
116 RemoteTabTitleFormat,
117 /** (bool) Specifies whether show hint for terminal size after
118 * resizing the application window.
119 */
120 ShowTerminalSizeHint,
121 /** (QFont) The font to use in terminal displays using this profile. */
122 Font,
123 /** (QString) The name of the color scheme to use in terminal
124 * displays using this profile.
125 * Color schemes are managed by the ColorSchemeManager class.
126 */
127 ColorScheme,
128 /** (QString) The name of the key bindings.
129 * Key bindings are managed by the KeyboardTranslatorManager class.
130 */
131 KeyBindings,
132 /** (HistoryModeEnum) Specifies the storage type used for keeping
133 * the output produced by terminal sessions using this profile.
134 *
135 * See Enum::HistoryModeEnum
136 */
137 HistoryMode,
138 /** (int) Specifies the number of lines of output to remember in
139 * terminal sessions using this profile. Once the limit is reached,
140 * the oldest lines are lost if the HistoryMode property is
141 * FixedSizeHistory
142 */
143 HistorySize,
144 /** (ScrollBarPositionEnum) Specifies the position of the scroll bar
145 * in terminal displays using this profile.
146 *
147 * See Enum::ScrollBarPositionEnum
148 */
149 ScrollBarPosition,
150 /** (bool) Specifies whether the PageUp/Down will scroll the full
151 * height or half height.
152 */
153 ScrollFullPage,
154 /** (bool) Specifies whether the terminal will enable Bidirectional
155 * text display
156 */
157 BidiRenderingEnabled,
158 /** (bool) Specifies whether text in terminal displays is allowed
159 * to blink.
160 */
161 BlinkingTextEnabled,
162 /** (bool) Specifies whether the flow control keys (typically Ctrl+S,
163 * Ctrl+Q) have any effect. Also known as Xon/Xoff
164 */
165 FlowControlEnabled,
166 /** (int) Specifies the pixels between the terminal lines.
167 */
168 LineSpacing,
169 /** (bool) Specifies whether the cursor blinks ( in a manner similar
170 * to text editing applications )
171 */
172 BlinkingCursorEnabled,
173 /** (bool) If true, terminal displays use a fixed color to draw the
174 * cursor, specified by the CustomCursorColor property. Otherwise
175 * the cursor changes color to match the character underneath it.
176 */
177 UseCustomCursorColor,
178 /** (CursorShapeEnum) The shape used by terminal displays to
179 * represent the cursor.
180 *
181 * See Enum::CursorShapeEnum
182 */
183 CursorShape,
184 /** (QColor) The color used by terminal displays to draw the cursor.
185 * Only applicable if the UseCustomCursorColor property is true.
186 */
187 CustomCursorColor,
188 /** (QString) A string consisting of the characters used to delimit
189 * words when selecting text in the terminal display.
190 */
191 WordCharacters,
192 /** (TripleClickModeEnum) Specifies which part of current line should
193 * be selected with triple click action.
194 *
195 * See Enum::TripleClickModeEnum
196 */
197 TripleClickMode,
198 /** (bool) If true, text that matches a link or an email address is
199 * underlined when hovered by the mouse pointer.
200 */
201 UnderlineLinksEnabled,
202 /** (bool) If true, links can be opened by direct mouse click.*/
203 OpenLinksByDirectClickEnabled,
204 /** (bool) If true, control key must be pressed to click and drag selected text. */
205 CtrlRequiredForDrag,
206 /** (bool) If true, automatically copy selected text into the clipboard */
207 AutoCopySelectedText,
208 /** (bool) If true, trailing spaces are trimmed in selected text */
209 TrimTrailingSpacesInSelectedText,
210 /** (bool) If true, middle mouse button pastes from X Selection */
211 PasteFromSelectionEnabled,
212 /** (bool) If true, middle mouse button pastes from Clipboard */
213 PasteFromClipboardEnabled,
214 /** (MiddleClickPasteModeEnum) Specifies the source from which mouse
215 * middle click pastes data.
216 *
217 * See Enum::MiddleClickPasteModeEnum
218 */
219 MiddleClickPasteMode,
220 /** (String) Default text codec */
221 DefaultEncoding,
222 /** (bool) Whether fonts should be aliased or not */
223 AntiAliasFonts,
224 /** (bool) Whether character with intense colors should be rendered
225 * in bold font or just in bright color. */
226 BoldIntense,
227 /** (bool) Whether new sessions should be started in the same
228 * directory as the currently active session.
229 */
230 StartInCurrentSessionDir,
231 /** (int) Specifies the threshold of detected silence in seconds. */
232 SilenceSeconds,
233 /** (BellModeEnum) Specifies the behavior of bell.
234 *
235 * See Enum::BellModeEnum
236 */
237 BellMode,
238 /** (int) Specifies the preferred columns. */
239 TerminalColumns,
240 /** (int) Specifies the preferred rows. */
241 TerminalRows,
242 /** Index of profile in the File Menu
243 * WARNING: this is currently an internal field, which is
244 * expected to be zero on disk. Do not modify it manually.
245 *
246 * In future, the format might be #.#.# to account for levels
247 */
248 MenuIndex,
249 /** (bool) If true, mouse wheel scroll with Ctrl key pressed
250 * increases/decreases the terminal font size.
251 */
252 MouseWheelZoomEnabled
253 };
254
255 /**
256 * Constructs a new profile
257 *
258 * @param parent The parent profile. When querying the value of a
259 * property using property(), if the property has not been set in this
260 * profile then the parent's value for the property will be returned.
261 */
262 explicit Profile(Ptr parent = Ptr());
263 virtual ~Profile();
264
265 /**
266 * Copies all properties except Name and Path from the specified @p
267 * profile into this profile
268 *
269 * @param profile The profile to copy properties from
270 * @param differentOnly If true, only properties in @p profile which have
271 * a different value from this profile's current value (either set via
272 * setProperty() or inherited from the parent profile) will be set.
273 */
274 void clone(Ptr profile, bool differentOnly = true);
275
276 /**
277 * Changes the parent profile. When calling the property() method,
278 * if the specified property has not been set for this profile,
279 * the parent's value for the property will be returned instead.
280 */
281 void setParent(Ptr parent);
282
283 /** Returns the parent profile. */
284 const Ptr parent() const;
285
286 /** Returns this profile as a group or null if this profile is not a
287 * group.
288 */
289 const GroupPtr asGroup() const;
290 GroupPtr asGroup();
291
292 /**
293 * Returns the current value of the specified @p property, cast to type T.
294 * Internally properties are stored using the QVariant type and cast to T
295 * using QVariant::value<T>();
296 *
297 * If the specified @p property has not been set in this profile,
298 * and a non-null parent was specified in the Profile's constructor,
299 * the parent's value for @p property will be returned.
300 */
301 template <class T>
302 T property(Property property) const;
303
304 /** Sets the value of the specified @p property to @p value. */
305 virtual void setProperty(Property property, const QVariant& value);
306 /** Returns true if the specified property has been set in this Profile
307 * instance.
308 */
309 virtual bool isPropertySet(Property property) const;
310
311 /** Returns a map of the properties set in this Profile instance. */
312 virtual QHash<Property, QVariant> setProperties() const;
313
314 /** Returns true if no properties have been set in this Profile instance. */
315 bool isEmpty() const;
316
317 /**
318 * Returns true if this is a 'hidden' profile which should not be
319 * displayed in menus or saved to disk.
320 *
321 * This is used for the fallback profile, in case there are no profiles on
322 * disk which can be loaded, or for overlay profiles created to handle
323 * command-line arguments which change profile properties.
324 */
325 bool isHidden() const;
326
327 /** Specifies whether this is a hidden profile. See isHidden() */
328 void setHidden(bool hidden);
329
330 //
331 // Convenience methods for property() and setProperty() go here
332 //
333
334 /** Convenience method for property<QString>(Profile::Path) */
335 QString path() const {
336 return property<QString>(Profile::Path);
337 }
338
339 /** Convenience method for property<QString>(Profile::Name) */
340 QString name() const {
341 return property<QString>(Profile::Name);
342 }
343
344 /** Convenience method for property<QString>(Profile::UntranslatedName) */
345 QString untranslatedName() const {
346 return property<QString>(Profile::UntranslatedName);
347 }
348
349 /** Convenience method for property<QString>(Profile::Directory) */
350 QString defaultWorkingDirectory() const {
351 return property<QString>(Profile::Directory);
352 }
353
354 /** Convenience method for property<QString>(Profile::Icon) */
355 QString icon() const {
356 return property<QString>(Profile::Icon);
357 }
358
359 /** Convenience method for property<QString>(Profile::Command) */
360 QString command() const {
361 return property<QString>(Profile::Command);
362 }
363
364 /** Convenience method for property<QStringList>(Profile::Arguments) */
365 QStringList arguments() const {
366 return property<QStringList>(Profile::Arguments);
367 }
368
369 /** Convenience method for property<QString>(Profile::LocalTabTitleFormat) */
370 QString localTabTitleFormat() const {
371 return property<QString>(Profile::LocalTabTitleFormat);
372 }
373
374 /** Convenience method for property<QString>(Profile::RemoteTabTitleFormat) */
375 QString remoteTabTitleFormat() const {
376 return property<QString>(Profile::RemoteTabTitleFormat);
377 }
378
379 /** Convenience method for property<bool>(Profile::ShowTerminalSizeHint) */
380 bool showTerminalSizeHint() const {
381 return property<bool>(Profile::ShowTerminalSizeHint);
382 }
383
384 /** Convenience method for property<QFont>(Profile::Font) */
385 QFont font() const {
386 return property<QFont>(Profile::Font);
387 }
388
389 /** Convenience method for property<QString>(Profile::ColorScheme) */
390 QString colorScheme() const {
391 return property<QString>(Profile::ColorScheme);
392 }
393
394 /** Convenience method for property<QStringList>(Profile::Environment) */
395 QStringList environment() const {
396 return property<QStringList>(Profile::Environment);
397 }
398
399 /** Convenience method for property<QString>(Profile::KeyBindings) */
400 QString keyBindings() const {
401 return property<QString>(Profile::KeyBindings);
402 }
403
404 /** Convenience method for property<QString>(Profile::HistorySize) */
405 int historySize() const {
406 return property<int>(Profile::HistorySize);
407 }
408
409 /** Convenience method for property<bool>(Profile::BidiRenderingEnabled) */
410 bool bidiRenderingEnabled() const {
411 return property<bool>(Profile::BidiRenderingEnabled);
412 }
413
414 /** Convenience method for property<bool>(Profile::LineSpacing) */
415 int lineSpacing() const {
416 return property<int>(Profile::LineSpacing);
417 }
418
419
420 /** Convenience method for property<bool>(Profile::BlinkingTextEnabled) */
421 bool blinkingTextEnabled() const {
422 return property<bool>(Profile::BlinkingTextEnabled);
423 }
424
425 /** Convenience method for property<bool>(Profile::MouseWheelZoomEnabled) */
426 bool mouseWheelZoomEnabled() const {
427 return property<bool>(Profile::MouseWheelZoomEnabled);
428 }
429
430 /** Convenience method for property<bool>(Profile::BlinkingCursorEnabled) */
431 bool blinkingCursorEnabled() const {
432 return property<bool>(Profile::BlinkingCursorEnabled);
433 }
434
435 /** Convenience method for property<bool>(Profile::FlowControlEnabled) */
436 bool flowControlEnabled() const {
437 return property<bool>(Profile::FlowControlEnabled);
438 }
439
440 /** Convenience method for property<bool>(Profile::UseCustomCursorColor) */
441 bool useCustomCursorColor() const {
442 return property<bool>(Profile::UseCustomCursorColor);
443 }
444
445 /** Convenience method for property<bool>(Profile::CustomCursorColor) */
446 QColor customCursorColor() const {
447 return property<QColor>(Profile::CustomCursorColor);
448 }
449
450 /** Convenience method for property<QString>(Profile::WordCharacters) */
451 QString wordCharacters() const {
452 return property<QString>(Profile::WordCharacters);
453 }
454
455 /** Convenience method for property<bool>(Profile::UnderlineLinksEnabled) */
456 bool underlineLinksEnabled() const {
457 return property<bool>(Profile::UnderlineLinksEnabled);
458 }
459
460 bool autoCopySelectedText() const {
461 return property<bool>(Profile::AutoCopySelectedText);
462 }
463
464 /** Convenience method for property<QString>(Profile::DefaultEncoding) */
465 QString defaultEncoding() const {
466 return property<QString>(Profile::DefaultEncoding);
467 }
468
469 /** Convenience method for property<bool>(Profile::AntiAliasFonts) */
470 bool antiAliasFonts() const {
471 return property<bool>(Profile::AntiAliasFonts);
472 }
473
474 /** Convenience method for property<bool>(Profile::BoldIntense) */
475 bool boldIntense() const {
476 return property<bool>(Profile::BoldIntense);
477 }
478
479 /** Convenience method for property<bool>(Profile::StartInCurrentSessionDir) */
480 bool startInCurrentSessionDir() const {
481 return property<bool>(Profile::StartInCurrentSessionDir);
482 }
483
484 /** Convenience method for property<QString>(Profile::SilenceSeconds) */
485 int silenceSeconds() const {
486 return property<int>(Profile::SilenceSeconds);
487 }
488
489 /** Convenience method for property<QString>(Profile::TerminalColumns) */
490 int terminalColumns() const {
491 return property<int>(Profile::TerminalColumns);
492 }
493
494 /** Convenience method for property<QString>(Profile::TerminalRows) */
495 int terminalRows() const {
496 return property<int>(Profile::TerminalRows);
497 }
498
499 /** Convenience method for property<QString>(Profile::MenuIndex) */
500 QString menuIndex() const {
501 return property<QString>(Profile::MenuIndex);
502 }
503
504 int menuIndexAsInt() const;
505
506 /** Return a list of all properties names and their type
507 * (for use with -p option).
508 */
509 const QStringList propertiesInfoList() const;
510
511 /**
512 * Returns the element from the Property enum associated with the
513 * specified @p name.
514 *
515 * @param name The name of the property to look for, this is case
516 * insensitive.
517 */
518 static Property lookupByName(const QString& name);
519
520private:
521 struct PropertyInfo;
522 // Defines a new property, this property is then available
523 // to all Profile instances.
524 static void registerProperty(const PropertyInfo& info);
525
526 // fills the table with default names for profile properties
527 // the first time it is called.
528 // subsequent calls return immediately
529 static void fillTableWithDefaultNames();
530
531 // returns true if the property can be inherited
532 static bool canInheritProperty(Property property);
533
534 QHash<Property, QVariant> _propertyValues;
535 Ptr _parent;
536
537 bool _hidden;
538
539 static QHash<QString, PropertyInfo> PropertyInfoByName;
540 static QHash<Property, PropertyInfo> PropertyInfoByProperty;
541
542 // Describes a property. Each property has a name and group
543 // which is used when saving/loading the profile.
544 struct PropertyInfo {
545 Property property;
546 const char* name;
547 const char* group;
548 QVariant::Type type;
549 };
550 static const PropertyInfo DefaultPropertyNames[];
551};
552
553inline bool Profile::canInheritProperty(Property aProperty)
554{
555 return aProperty != Name && aProperty != Path;
556}
557
558template <class T>
559inline T Profile::property(Property aProperty) const
560{
561 return property<QVariant>(aProperty).value<T>();
562}
563template <>
564inline QVariant Profile::property(Property aProperty) const
565{
566 if (_propertyValues.contains(aProperty)) {
567 return _propertyValues[aProperty];
568 } else if (_parent && canInheritProperty(aProperty)) {
569 return _parent->property<QVariant>(aProperty);
570 } else {
571 return QVariant();
572 }
573}
574
575/**
576 * A profile which contains a number of default settings for various
577 * properties. This can be used as a parent for other profiles or a
578 * fallback in case a profile cannot be loaded from disk.
579 */
580class FallbackProfile : public Profile
581{
582public:
583 FallbackProfile();
584};
585
586/**
587 * A composite profile which allows a group of profiles to be treated as one.
588 * When setting a property, the new value is applied to all profiles in the
589 * group. When reading a property, if all profiles in the group have the same
590 * value then that value is returned, otherwise the result is null.
591 *
592 * Profiles can be added to the group using addProfile(). When all profiles
593 * have been added updateValues() must be called
594 * to sync the group's property values with those of the group's profiles.
595 *
596 * The Profile::Name and Profile::Path properties are unique to individual
597 * profiles, setting these properties on a ProfileGroup has no effect.
598 */
599class KONSOLEPRIVATE_EXPORT ProfileGroup : public Profile
600{
601public:
602 typedef KSharedPtr<ProfileGroup> Ptr;
603
604 /** Construct a new profile group, which is hidden by default. */
605 explicit ProfileGroup(Profile::Ptr parent = Profile::Ptr());
606
607 /** Add a profile to the group. Calling setProperty() will update this
608 * profile. When creating a group, add the profiles to the group then
609 * call updateValues() to make the group's property values reflect the
610 * profiles currently in the group.
611 */
612 void addProfile(Profile::Ptr profile) {
613 _profiles.append(profile);
614 }
615
616 /** Remove a profile from the group. Calling setProperty() will no longer
617 * affect this profile. */
618 void removeProfile(Profile::Ptr profile) {
619 _profiles.removeAll(profile);
620 }
621
622 /** Returns the profiles in this group .*/
623 QList<Profile::Ptr> profiles() const {
624 return _profiles;
625 }
626
627 /**
628 * Updates the property values in this ProfileGroup to match those from
629 * the group's profiles()
630 *
631 * For each available property, if each profile in the group has the same
632 * value then the ProfileGroup will use that value for the property.
633 * Otherwise the value for the property will be set to a null QVariant
634 *
635 * Some properties such as the name and the path of the profile
636 * will always be set to null if the group has more than one profile.
637 */
638 void updateValues();
639
640 /** Sets the value of @p property in each of the group's profiles to
641 * @p value.
642 */
643 void setProperty(Property property, const QVariant& value);
644
645private:
646 QList<Profile::Ptr> _profiles;
647};
648inline ProfileGroup::ProfileGroup(Profile::Ptr profileParent)
649 : Profile(profileParent)
650{
651 setHidden(true);
652}
653inline const Profile::GroupPtr Profile::asGroup() const
654{
655 const Profile::GroupPtr ptr(dynamic_cast<ProfileGroup*>(
656 const_cast<Profile*>(this)));
657 return ptr;
658}
659inline Profile::GroupPtr Profile::asGroup()
660{
661 return Profile::GroupPtr(dynamic_cast<ProfileGroup*>(this));
662}
663
664/**
665 * Parses an input string consisting of property names
666 * and assigned values and returns a table of properties
667 * and values.
668 *
669 * The input string will typically look like this:
670 *
671 * @code
672 * PropertyName=Value;PropertyName=Value ...
673 * @endcode
674 *
675 * For example:
676 *
677 * @code
678 * Icon=konsole;Directory=/home/bob
679 * @endcode
680 */
681class KONSOLEPRIVATE_EXPORT ProfileCommandParser
682{
683public:
684 /**
685 * Parses an input string consisting of property names
686 * and assigned values and returns a table of
687 * properties and values.
688 */
689 QHash<Profile::Property, QVariant> parse(const QString& input);
690};
691}
692Q_DECLARE_METATYPE(Konsole::Profile::Ptr)
693
694#endif // PROFILE_H
695