• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

Konsole

Profile.cpp

Go to the documentation of this file.
00001 /*
00002     This source file is part of Konsole, a terminal emulator.
00003 
00004     Copyright 2006-2008 by Robert Knight <robertknight@gmail.com>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00019     02110-1301  USA.
00020 */
00021 
00022 // Own
00023 #include "Profile.h"
00024 
00025 // Qt
00026 #include <QtCore/QFile>
00027 #include <QtCore/QFileInfo>
00028 #include <QtCore/QTextCodec>
00029 
00030 // KDE
00031 #include <KConfigGroup>
00032 #include <KDesktopFile>
00033 #include <KGlobal>
00034 #include <KGlobalSettings>
00035 #include <KLocale>
00036 #include <KDebug>
00037 #include <KStandardDirs>
00038 
00039 // System
00040 #include <unistd.h>
00041 
00042 // Konsole
00043 #include "ShellCommand.h"
00044 
00045 using namespace Konsole;
00046 
00047 // mappings between property enum values and names
00048 //
00049 // multiple names are defined for some property values,
00050 // in these cases, the "proper" string name comes first,
00051 // as that is used when reading/writing profiles from/to disk
00052 //
00053 // the other names are usually shorter versions for convenience
00054 // when parsing konsoleprofile commands
00055 static const char* GENERAL_GROUP = "General";
00056 static const char* KEYBOARD_GROUP = "Keyboard";
00057 static const char* APPEARANCE_GROUP = "Appearance";
00058 static const char* SCROLLING_GROUP = "Scrolling";
00059 static const char* TERMINAL_GROUP = "Terminal Features";
00060 static const char* CURSOR_GROUP = "Cursor Options";
00061 static const char* INTERACTION_GROUP = "Interaction Options";
00062 static const char* ENCODING_GROUP = "Encoding Options";
00063 
00064 const Profile::PropertyInfo Profile::DefaultPropertyNames[] =
00065 {
00066     // General
00067       { Path , "Path" , 0 , QVariant::String }
00068     , { Name , "Name" , GENERAL_GROUP , QVariant::String }
00069     , { Title , "Title" , 0 , QVariant::String }
00070     , { Icon , "Icon" , GENERAL_GROUP , QVariant::String }
00071     , { Command , "Command" , 0 , QVariant::String }
00072     , { Arguments , "Arguments" , 0 , QVariant::StringList }
00073     , { Environment , "Environment" , GENERAL_GROUP , QVariant::StringList }
00074     , { Directory , "Directory" , GENERAL_GROUP , QVariant::String }
00075     , { LocalTabTitleFormat , "LocalTabTitleFormat" , GENERAL_GROUP , QVariant::String }
00076     , { LocalTabTitleFormat , "tabtitle" , 0 , QVariant::String }
00077     , { RemoteTabTitleFormat , "RemoteTabTitleFormat" , GENERAL_GROUP , QVariant::String }
00078     , { ShowMenuBar , "ShowMenuBar" , GENERAL_GROUP , QVariant::Bool }
00079     , { TabBarMode , "TabBarMode" , GENERAL_GROUP , QVariant::Int }
00080     , { TabBarPosition , "TabBarPosition" , GENERAL_GROUP , QVariant::Int }
00081     , { StartInCurrentSessionDir , "StartInCurrentSessionDir" , GENERAL_GROUP , QVariant::Bool }
00082     , { ShowNewAndCloseTabButtons, "ShowNewAndCloseTabButtons" , GENERAL_GROUP , QVariant::Bool }
00083 
00084     // Appearance
00085     , { Font , "Font" , APPEARANCE_GROUP , QVariant::Font }
00086     , { ColorScheme , "ColorScheme" , APPEARANCE_GROUP , QVariant::String }
00087     , { ColorScheme , "colors" , 0 , QVariant::String }
00088     , { AntiAliasFonts, "AntiAliasFonts" , APPEARANCE_GROUP , QVariant::Bool }
00089     
00090     // Keyboard
00091     , { KeyBindings , "KeyBindings" , KEYBOARD_GROUP , QVariant::String }
00092     
00093     // Scrolling
00094     , { HistoryMode , "HistoryMode" , SCROLLING_GROUP , QVariant::Int }
00095     , { HistorySize , "HistorySize" , SCROLLING_GROUP , QVariant::Int } 
00096     , { ScrollBarPosition , "ScrollBarPosition" , SCROLLING_GROUP , QVariant::Int }
00097    
00098        // Terminal Features
00099     , { BlinkingTextEnabled , "BlinkingTextEnabled" , TERMINAL_GROUP , QVariant::Bool }
00100     , { FlowControlEnabled , "FlowControlEnabled" , TERMINAL_GROUP , QVariant::Bool }
00101     , { AllowProgramsToResizeWindow , "AllowProgramsToResizeWindow" , TERMINAL_GROUP , QVariant::Bool }
00102     , { BidiRenderingEnabled , "BidiRenderingEnabled" , TERMINAL_GROUP , QVariant::Bool }
00103     , { BlinkingCursorEnabled , "BlinkingCursorEnabled" , TERMINAL_GROUP , QVariant::Bool }
00104     
00105     // Cursor 
00106     , { UseCustomCursorColor , "UseCustomCursorColor" , CURSOR_GROUP , QVariant::Bool}
00107     , { CursorShape , "CursorShape" , CURSOR_GROUP , QVariant::Int}
00108     , { CustomCursorColor , "CustomCursorColor" , CURSOR_GROUP , QVariant::Color }
00109 
00110     // Interaction
00111     , { WordCharacters , "WordCharacters" , INTERACTION_GROUP , QVariant::String }
00112 
00113     // Encoding
00114     , { DefaultEncoding , "DefaultEncoding" , ENCODING_GROUP , QVariant::String }
00115 
00116     , { (Property)0 , 0 , 0, QVariant::Invalid }
00117 };
00118 
00119 QHash<QString,Profile::PropertyInfo> Profile::_propertyInfoByName;
00120 QHash<Profile::Property,Profile::PropertyInfo> Profile::_infoByProperty;
00121 
00122 void Profile::fillTableWithDefaultNames()
00123 {
00124     static bool filledDefaults = false;
00125 
00126     if ( filledDefaults )
00127         return;
00128 
00129     const PropertyInfo* iter = DefaultPropertyNames;
00130     while ( iter->name != 0 )
00131     {
00132        registerProperty(*iter);
00133        iter++;
00134     }
00135 
00136    filledDefaults = true; 
00137 }
00138 
00139 FallbackProfile::FallbackProfile()
00140  : Profile()
00141 {
00142     // Fallback settings
00143     setProperty(Name,i18n("Shell"));
00144     // magic path for the fallback profile which is not a valid 
00145     // non-directory file name
00146     setProperty(Path,"FALLBACK/"); 
00147     setProperty(Command,qgetenv("SHELL"));
00148     setProperty(Icon,"utilities-terminal");
00149     setProperty(Arguments,QStringList() << qgetenv("SHELL"));
00150     setProperty(Environment,QStringList() << "TERM=xterm");
00151     setProperty(LocalTabTitleFormat,"%d : %n");
00152     setProperty(RemoteTabTitleFormat,"%H (%u)");
00153     setProperty(TabBarMode,AlwaysShowTabBar);
00154     setProperty(TabBarPosition,TabBarBottom);
00155     setProperty(ShowMenuBar,true);
00156     setProperty(StartInCurrentSessionDir,true);
00157     setProperty(ShowNewAndCloseTabButtons,false);
00158 
00159     setProperty(KeyBindings,"default");
00160     setProperty(ColorScheme,"DarkPastels");
00161     setProperty(Font,KGlobalSettings::fixedFont());
00162 
00163     setProperty(HistoryMode,FixedSizeHistory);
00164     setProperty(HistorySize,1000);
00165     setProperty(ScrollBarPosition,ScrollBarRight);
00166     
00167     setProperty(FlowControlEnabled,true);
00168     setProperty(AllowProgramsToResizeWindow,true);
00169     setProperty(BlinkingTextEnabled,true);
00170     
00171     setProperty(BlinkingCursorEnabled,false);
00172     setProperty(BidiRenderingEnabled,false);
00173     setProperty(CursorShape,BlockCursor);
00174     setProperty(UseCustomCursorColor,false);
00175     setProperty(CustomCursorColor,Qt::black);
00176 
00177     setProperty(DefaultEncoding,QString(QTextCodec::codecForLocale()->name()));
00178     setProperty(AntiAliasFonts,true);
00179 
00180     // default taken from KDE 3
00181     setProperty(WordCharacters,":@-./_~?&=%+#");
00182 
00183     // Fallback should not be shown in menus
00184     setHidden(true);
00185 }
00186 Profile::Profile(Profile::Ptr parent)
00187     : _parent(parent)
00188      ,_hidden(false)
00189 {
00190 }
00191 void Profile::clone(Profile::Ptr profile, bool differentOnly)
00192 {
00193     const PropertyInfo* properties = DefaultPropertyNames;
00194     while (properties->name != 0)
00195     {
00196         Property current = properties->property;
00197         QVariant otherValue = profile->property<QVariant>(current);
00198         switch (current)
00199         {
00200             case Name:
00201             case Path:
00202                 break;
00203             default:
00204                 if (!differentOnly || 
00205                     property<QVariant>(current) != 
00206                     otherValue)
00207                 {
00208                     setProperty(current,otherValue);
00209                 }
00210         }
00211         properties++;
00212     }
00213 }
00214 Profile::~Profile()
00215 {
00216 }
00217 bool Profile::isHidden() const { return _hidden; }
00218 void Profile::setHidden(bool hidden) { _hidden = hidden; }
00219 
00220 void Profile::setParent(Profile::Ptr parent) { _parent = parent; }
00221 const Profile::Ptr Profile::parent() const { return _parent; }
00222 
00223 bool Profile::isEmpty() const
00224 {
00225     return _propertyValues.isEmpty();
00226 }
00227 QHash<Profile::Property,QVariant> Profile::setProperties() const
00228 {
00229     return _propertyValues;
00230 }
00231 void Profile::setProperty(Property property , const QVariant& value)
00232 {
00233     _propertyValues.insert(property,value);
00234 }
00235 bool Profile::isPropertySet(Property property) const
00236 {
00237     return _propertyValues.contains(property);
00238 }
00239 
00240 bool Profile::isNameRegistered(const QString& name) 
00241 {
00242     // insert default names into table the first time this is called
00243     fillTableWithDefaultNames();
00244 
00245     return _propertyInfoByName.contains(name);
00246 }
00247 
00248 Profile::Property Profile::lookupByName(const QString& name)
00249 {
00250     // insert default names into table the first time this is called
00251     fillTableWithDefaultNames();
00252 
00253     return _propertyInfoByName[name.toLower()].property;
00254 }
00255 QString Profile::primaryNameForProperty(Property property)
00256 {
00257     // insert default names into table the first time this is called
00258     fillTableWithDefaultNames();
00259 
00260     return _infoByProperty[property].name;
00261 }
00262 QList<QString> Profile::namesForProperty(Property property)
00263 {
00264     // insert default names into table the first time this is called
00265     fillTableWithDefaultNames();
00266 
00267     return QList<QString>() << primaryNameForProperty(property);
00268 }
00269 void Profile::registerProperty(const PropertyInfo& info) 
00270 {
00271     _propertyInfoByName.insert(QString(info.name).toLower(),info);
00272 
00273     // only allow one property -> name map
00274     // (multiple name -> property mappings are allowed though)
00275     if ( !_infoByProperty.contains(info.property) )
00276         _infoByProperty.insert(info.property,info);
00277 }
00278 
00279 QString KDE4ProfileWriter::getPath(const Profile::Ptr info)
00280 {
00281     QString newPath;
00282 
00283     if ( info->isPropertySet(Profile::Path) && 
00284          info->path().startsWith(KGlobal::dirs()->saveLocation("data", "konsole/")) )
00285     {
00286         newPath = info->path();
00287     }
00288     else
00289     {
00290         // use the profile name + ".profile" and save it in $KDEHOME
00291         newPath = KGlobal::dirs()->saveLocation("data","konsole/") + info->name() + ".profile";
00292     }
00293 
00294     kDebug(1211) << "Saving profile under name: " << newPath;
00295 
00296     return newPath;
00297 }
00298 void KDE4ProfileWriter::writeProperties(KConfig& config,
00299                                         const Profile::Ptr profile,
00300                                         const Profile::PropertyInfo* properties) 
00301 {
00302     const char* groupName = 0;
00303     KConfigGroup group;
00304     
00305     while (properties->name != 0)    
00306     {
00307         if (properties->group != 0)
00308         {
00309             if (groupName == 0 || strcmp(groupName,properties->group) != 0)
00310             {
00311                 group = config.group(properties->group);
00312                 groupName = properties->group;
00313             }
00314 
00315             if ( profile->isPropertySet(properties->property) )
00316                 group.writeEntry(QString(properties->name),
00317                             profile->property<QVariant>(properties->property));
00318         }
00319 
00320         properties++;
00321     }
00322 }
00323 bool KDE4ProfileWriter::writeProfile(const QString& path , const Profile::Ptr profile)
00324 {
00325     KConfig config(path,KConfig::NoGlobals);
00326 
00327     KConfigGroup general = config.group(GENERAL_GROUP);
00328 
00329     // Parent profile if set, when loading the profile in future, the parent
00330     // must be loaded as well if it exists.
00331     if ( profile->parent() )
00332         general.writeEntry("Parent",profile->parent()->path());
00333 
00334     if (    profile->isPropertySet(Profile::Command) 
00335          || profile->isPropertySet(Profile::Arguments) )
00336         general.writeEntry("Command",
00337                 ShellCommand(profile->command(),profile->arguments()).fullCommand());
00338 
00339     // Write remaining properties
00340     writeProperties(config,profile,Profile::DefaultPropertyNames);
00341 
00342     return true;
00343 }
00344 
00345 QStringList KDE4ProfileReader::findProfiles()
00346 {
00347     return KGlobal::dirs()->findAllResources("data","konsole/*.profile",
00348             KStandardDirs::NoDuplicates);
00349 }
00350 void KDE4ProfileReader::readProperties(const KConfig& config, Profile::Ptr profile,
00351                                        const Profile::PropertyInfo* properties)
00352 {
00353     const char* groupName = 0;
00354     KConfigGroup group;
00355 
00356     while (properties->name != 0)
00357     {
00358         if (properties->group != 0)
00359         {
00360             if (groupName == 0 || strcmp(groupName,properties->group) != 0)
00361             {
00362                 group = config.group(properties->group);
00363                 groupName = properties->group;
00364             }
00365         
00366             QString name(properties->name);
00367 
00368             if (group.hasKey(name))
00369                 profile->setProperty(properties->property,
00370                                      group.readEntry(name,QVariant(properties->type)));
00371 
00372         }
00373         
00374         properties++;
00375     }
00376 }
00377 
00378 bool KDE4ProfileReader::readProfile(const QString& path , Profile::Ptr profile , QString& parentProfile)
00379 {
00380     if (!QFile::exists(path))
00381         return false;
00382 
00383     KConfig config(path,KConfig::NoGlobals);
00384 
00385     KConfigGroup general = config.group(GENERAL_GROUP);
00386     if (general.hasKey("Parent"))
00387         parentProfile = general.readEntry("Parent");
00388 
00389     if ( general.hasKey("Command") )
00390     {
00391         ShellCommand shellCommand(general.readEntry("Command"));
00392 
00393         profile->setProperty(Profile::Command,shellCommand.command());
00394         profile->setProperty(Profile::Arguments,shellCommand.arguments());
00395     }
00396 
00397     // Read remaining properties
00398     readProperties(config,profile,Profile::DefaultPropertyNames);
00399 
00400     return true;
00401 }
00402 QStringList KDE3ProfileReader::findProfiles()
00403 {
00404     return KGlobal::dirs()->findAllResources("data", "konsole/*.desktop", 
00405             KStandardDirs::NoDuplicates);
00406 }
00407 bool KDE3ProfileReader::readProfile(const QString& path , Profile::Ptr profile , QString& parentProfile)
00408 {
00409     if (!QFile::exists(path))
00410         return false;
00411 
00412     // KDE 3 profiles do not have parents
00413     parentProfile.clear();
00414 
00415     KDesktopFile* desktopFile = new KDesktopFile(path);
00416     KConfigGroup* config = new KConfigGroup( desktopFile->desktopGroup() );
00417 
00418     if ( config->hasKey("Name") )
00419         profile->setProperty(Profile::Name,config->readEntry("Name"));
00420 
00421     kDebug() << "reading KDE 3 profile " << profile->name();
00422 
00423     if ( config->hasKey("Icon") )
00424         profile->setProperty(Profile::Icon,config->readEntry("Icon"));
00425     if ( config->hasKey("Exec") )
00426     {
00427         const QString& fullCommand = config->readEntry("Exec");
00428         ShellCommand shellCommand(fullCommand);
00429     
00430         profile->setProperty(Profile::Command,shellCommand.command());
00431         profile->setProperty(Profile::Arguments,shellCommand.arguments());
00432     }
00433     if ( config->hasKey("Schema") )
00434     {
00435         profile->setProperty(Profile::ColorScheme,config->readEntry("Schema").replace
00436                                             (".schema",QString()));        
00437     }
00438     if ( config->hasKey("defaultfont") )
00439     {
00440         profile->setProperty(Profile::Font,config->readEntry("defaultfont"));
00441     }
00442     if ( config->hasKey("KeyTab") )
00443     {
00444         profile->setProperty(Profile::KeyBindings,config->readEntry("KeyTab"));
00445     }
00446     if ( config->hasKey("Term") )
00447     {
00448         profile->setProperty(Profile::Environment,
00449                 QStringList() << "TERM="+config->readEntry("Term"));
00450     }
00451     if ( config->hasKey("Cwd") )
00452     {
00453         profile->setProperty(Profile::Directory,config->readEntry("Cwd"));
00454     }
00455 
00456     delete desktopFile;
00457     delete config;
00458 
00459     return true;
00460 }
00461 
00462 QHash<Profile::Property,QVariant> ProfileCommandParser::parse(const QString& input)
00463 {
00464     QHash<Profile::Property,QVariant> changes;
00465 
00466     // regular expression to parse profile change requests.
00467     //
00468     // format: property=value;property=value ...
00469     //
00470     // where 'property' is a word consisting only of characters from A-Z
00471     // where 'value' is any sequence of characters other than a semi-colon
00472     //
00473     static QRegExp regExp("([a-zA-Z]+)=([^;]+)");
00474 
00475     int offset = 0;
00476     while ( regExp.indexIn(input,offset) != -1 )
00477     {
00478         if ( regExp.capturedTexts().count() == 3 )
00479         {
00480             Profile::Property property = Profile::lookupByName(
00481                                                 regExp.capturedTexts()[1]);
00482             const QString value = regExp.capturedTexts()[2];
00483             changes.insert(property,value);
00484         }
00485 
00486         offset = input.indexOf(';',offset) + 1;
00487         if ( offset == 0 )
00488             break;
00489     }
00490 
00491     return changes;
00492 }
00493 
00494 void ProfileGroup::updateValues()
00495 {
00496     const PropertyInfo* properties = Profile::DefaultPropertyNames;
00497     while (properties->name != 0)
00498     {
00499         // the profile group does not store a value for some properties
00500         // (eg. name, path) if even they are equal between profiles - 
00501         //
00502         // the exception is when the group has only one profile in which
00503         // case it behaves like a standard Profile
00504         if (_profiles.count() > 1 && 
00505             !canInheritProperty(properties->property))
00506         {
00507             properties++;
00508             continue;
00509         }
00510 
00511         QVariant value;
00512         for (int i=0;i<_profiles.count();i++)
00513         {   
00514             QVariant profileValue = _profiles[i]->property<QVariant>(properties->property);
00515             if (value.isNull())
00516                 value = profileValue; 
00517             else if (value != profileValue)
00518             {
00519                 value = QVariant();
00520                 break;
00521             }
00522         }   
00523         Profile::setProperty(properties->property,value);
00524         properties++;
00525     }
00526 }
00527 void ProfileGroup::setProperty(Property property, const QVariant& value)
00528 {
00529     if (_profiles.count() > 1 && !canInheritProperty(property))
00530         return;
00531 
00532     Profile::setProperty(property,value);
00533     foreach(Profile::Ptr profile,_profiles)
00534         profile->setProperty(property,value);
00535 }
00536 
00537 
00538 

Konsole

Skip menu "Konsole"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • Konsole
  • Libraries
  •   libkonq
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal