not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / kxkb / kxkbconfig.cpp
blobd90bd84a7a5add637d32e71e88c4b5ae3bcf6694
1 /*
2 * Copyright (C) 2006 Andriy Rysin (rysin@kde.org)
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.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include <assert.h>
22 #include <QRegExp>
23 #include <QHash>
25 #include <ksharedconfig.h>
26 #include <kconfiggroup.h>
27 #include <kdebug.h>
29 #include "kxkbconfig.h"
30 #include "x11helper.h"
33 static const char* switchModes[SWITCH_POLICY_COUNT] = {
34 "Global", "Desktop", "WinClass", "Window"
37 const LayoutUnit DEFAULT_LAYOUT_UNIT = LayoutUnit("us", "");
38 const char* DEFAULT_MODEL = "pc104";
40 const char* KxkbConfig::OPTIONS_SEPARATOR = ",";
42 KxkbConfig::KxkbConfig() {
43 m_layouts.append( DEFAULT_LAYOUT_UNIT );
46 int KxkbConfig::getDefaultLayout()
48 if( m_layouts.size() == 0 )
49 return 0; //DEFAULT_LAYOUT_UNIT;
51 return 0; //m_layouts[0];
54 bool KxkbConfig::load(int loadMode)
56 // kDebug() << "Reading configuration";
57 KConfigGroup config(KSharedConfig::openConfig( "kxkbrc", KConfig::NoGlobals ), "Layout");
59 // m_enableXkbOptions = config.readEntry("EnableXkbOptions", false);
61 m_useKxkb = config.readEntry("Use", false);
62 kDebug() << "Use kxkb" << m_useKxkb;
64 if( m_useKxkb == false && loadMode == LOAD_ACTIVE_OPTIONS )
65 return true;
67 m_indicatorOnly = config.readEntry("IndicatorOnly", false);
68 kDebug() << "Indicator only" << m_indicatorOnly;
70 m_showSingle = config.readEntry("ShowSingle", false);
71 m_showFlag = config.readEntry("ShowFlag", true);
73 m_model = config.readEntry("Model", DEFAULT_MODEL);
74 kDebug() << "Model:" << m_model;
76 QStringList layoutList;
77 layoutList = config.readEntry("LayoutList", layoutList);
79 if( layoutList.count() == 0 )
80 layoutList.append("us");
82 m_layouts.clear();
83 for(QStringList::ConstIterator it = layoutList.constBegin(); it != layoutList.constEnd() ; ++it) {
84 LayoutUnit layoutUnit(*it);
85 m_layouts.append( layoutUnit );
86 kDebug() << " added layout" << layoutUnit.toPair();
89 // kDebug() << "Found " << m_layouts.count() << " layouts, default is " << m_layouts[getDefaultLayout()].toPair();
91 QStringList displayNamesList;
92 displayNamesList = config.readEntry("DisplayNames", displayNamesList);
93 int i=0;
94 for(QStringList::ConstIterator it = displayNamesList.constBegin(); it != displayNamesList.constEnd() ; ++it) {
95 if( i < m_layouts.count() ) {
96 m_layouts[i].setDisplayName(*it);
97 i++;
101 QString layoutOwner = config.readEntry("SwitchMode", "Global");
103 if( layoutOwner == "WinClass" ) {
104 m_switchingPolicy = SWITCH_POLICY_WIN_CLASS;
106 else if( layoutOwner == "Window" ) {
107 m_switchingPolicy = SWITCH_POLICY_WINDOW;
109 else if( layoutOwner == "Desktop" ) {
110 m_switchingPolicy = SWITCH_POLICY_DESKTOP;
112 else /*if( layoutOwner == "Global" )*/ {
113 m_switchingPolicy = SWITCH_POLICY_GLOBAL;
116 // if( m_layouts.count() < 2 && m_switchingPolicy != SWITCH_POLICY_GLOBAL ) {
117 // kWarning() << "Layout count is less than 2, using Global switching policy" ;
118 // m_switchingPolicy = SWITCH_POLICY_GLOBAL;
119 // }
121 kDebug() << "Layout owner mode" << layoutOwner;
123 #ifdef STICKY_SWITCHING
124 m_stickySwitching = config.readEntry("StickySwitching", false);
125 m_stickySwitchingDepth = config.readEntry("StickySwitchingDepth", "2").toInt();
126 if( m_stickySwitchingDepth < 2 )
127 m_stickySwitchingDepth = 2;
129 if( m_stickySwitching == true ) {
130 if( m_layouts.count() < 3 ) {
131 kWarning() << "Layout count is less than 3, sticky switching will be off" ;
132 m_stickySwitching = false;
134 else
135 if( (int)m_layouts.count() - 1 < m_stickySwitchingDepth ) {
136 kWarning() << "Sticky switching depth is more than layout count -1, adjusting..." ;
137 m_stickySwitchingDepth = m_layouts.count() - 1;
140 #else
141 m_stickySwitching = false; //TODO: so far we can't do sticky with xkb switching groups...
142 #endif
144 m_resetOldOptions = config.readEntry("ResetOldOptions", true);
145 QString options = config.readEntry("Options", "");
146 m_options = options.split(OPTIONS_SEPARATOR, QString::SkipEmptyParts);
147 kDebug() << "Xkb options:" /*(enabled=" << m_enableXkbOptions << "): "*/ << m_options;
149 return true;
152 static QString addNum(const QString& str, int n)
154 QString format("%1%2");
155 if( str.length() >= 3 ) return format.arg(str.left(2)).arg(n);
156 return format.arg(str).arg(n);
159 void KxkbConfig::updateDisplayNames()
161 for(int i=0; i<m_layouts.count(); i++) {
162 LayoutUnit& lu = m_layouts[i];
163 int cnt = 1;
164 for(int j=i; j<m_layouts.count(); j++) {
165 LayoutUnit& lu2 = m_layouts[j];
166 if( i != j && lu.layout == lu2.layout ) {
167 ++cnt;
168 lu.setDisplayName( addNum(lu.layout, 1) );
169 lu2.setDisplayName( addNum(lu2.layout, cnt) );
175 void KxkbConfig::setConfiguredLayouts(XkbConfig xkbConfig)
177 kDebug() << "resetting layouts to " << xkbConfig.layouts.count() << " active in X server";
178 m_layouts.clear();
179 m_layouts << xkbConfig.layouts;
180 m_options.clear();
181 m_options << xkbConfig.options;
182 //TODO: update model
183 updateDisplayNames();
186 void KxkbConfig::save()
188 KConfigGroup config(KSharedConfig::openConfig( "kxkbrc", KConfig::NoGlobals ), "Layout");
190 config.writeEntry("Model", m_model);
192 // config.writeEntry("EnableXkbOptions", m_enableXkbOptions );
193 config.writeEntry("IndicatorOnly", m_indicatorOnly );
194 config.writeEntry("ResetOldOptions", m_resetOldOptions);
195 config.writeEntry("Options", m_options.join(OPTIONS_SEPARATOR) );
197 QStringList layoutList;
198 QStringList displayNamesList;
200 QList<LayoutUnit>::ConstIterator it;
201 for(it = m_layouts.constBegin(); it != m_layouts.constEnd(); ++it) {
202 const LayoutUnit& layoutUnit = *it;
204 layoutList.append( layoutUnit.toPair() );
206 QString displayName = layoutUnit.getDisplayName();
207 kDebug() << " displayName " << layoutUnit.toPair() << " : " << displayName;
208 //if( displayName.isEmpty() == false && displayName != layoutUnit.layout ) {
209 // displayName = QString("%1:%2").arg(layoutUnit.toPair(), displayName);
210 displayNamesList.append( displayName );
214 config.writeEntry("LayoutList", layoutList);
215 kDebug() << "Saving Layouts: " << layoutList;
217 // if( displayNamesList.empty() == false )
218 config.writeEntry("DisplayNames", displayNamesList);
219 // else
220 // config.deleteEntry("DisplayNames");
222 config.writeEntry("Use", m_useKxkb);
223 config.writeEntry("ShowSingle", m_showSingle);
224 config.writeEntry("ShowFlag", m_showFlag);
226 config.writeEntry("SwitchMode", switchModes[m_switchingPolicy]);
228 #ifdef STICKY_SWITCHING
229 config.writeEntry("StickySwitching", m_stickySwitching);
230 config.writeEntry("StickySwitchingDepth", m_stickySwitchingDepth);
231 #endif
233 config.sync();
236 void KxkbConfig::setDefaults()
238 m_model = DEFAULT_MODEL;
240 // m_enableXkbOptions = false;
241 m_resetOldOptions = false;
242 m_options.clear();
244 m_layouts.clear();
245 m_layouts.append( DEFAULT_LAYOUT_UNIT );
247 m_useKxkb = false;
248 m_indicatorOnly = false;
249 m_showSingle = false;
250 m_showFlag = true;
252 m_switchingPolicy = SWITCH_POLICY_GLOBAL;
254 m_stickySwitching = false;
255 m_stickySwitchingDepth = 2;
258 QStringList KxkbConfig::getLayoutStringList(/*bool compact*/)
260 QStringList layoutList;
261 for(QList<LayoutUnit>::ConstIterator it = m_layouts.constBegin(); it != m_layouts.constEnd(); ++it) {
262 const LayoutUnit& layoutUnit = *it;
263 layoutList.append( layoutUnit.toPair() );
265 return layoutList;
269 QString LayoutUnit::getDefaultDisplayName(const QString& layout, const QString& /*variant*/)
271 return layout.left(MAX_LABEL_LEN);
272 // if( layoutUnit.variant.isEmpty() )
273 // return getDefaultDisplayName( layoutUnit.layout );
275 // QString displayName = layoutUnit.layout.left(2);
276 // if( single == false )
277 // displayName += layoutUnit.variant.left(1);
278 // return displayName;
282 * @brief Gets the single layout part of a layout(variant) string
283 * @param[in] layvar String in form layout(variant) to parse
284 * @return The layout found in the string
286 const QString LayoutUnit::parseLayout(const QString &layvar)
288 static const char* LAYOUT_PATTERN = "[a-zA-Z0-9_/-]*";
289 QString varLine = layvar.trimmed();
290 QRegExp rx(LAYOUT_PATTERN);
291 int pos = rx.indexIn(varLine, 0);
292 int len = rx.matchedLength();
293 // check for errors
294 if( pos < 0 || len < 2 )
295 return "";
296 // kDebug() << "getLayout: " << varLine.mid(pos, len);
297 return varLine.mid(pos, len);
301 * @brief Gets the single variant part of a layout(variant) string
302 * @param[in] layvar String in form layout(variant) to parse
303 * @return The variant found in the string, no check is performed
305 const QString LayoutUnit::parseVariant(const QString &layvar)
307 static const char* VARIANT_PATTERN = "\\([a-zA-Z0-9_-]*\\)";
308 QString varLine = layvar.trimmed();
309 QRegExp rx(VARIANT_PATTERN);
310 int pos = rx.indexIn(varLine, 0);
311 int len = rx.matchedLength();
312 // check for errors
313 if( pos < 2 || len < 2 )
314 return "";
315 return varLine.mid(pos+1, len-2);