summaryrefslogtreecommitdiffstats
path: root/kxkb
diff options
context:
space:
mode:
Diffstat (limited to 'kxkb')
-rw-r--r--kxkb/CMakeL10n.txt6
-rw-r--r--kxkb/CMakeLists.txt8
-rw-r--r--kxkb/eventsrc13
-rw-r--r--kxkb/extension.cpp477
-rw-r--r--kxkb/extension.h84
-rw-r--r--kxkb/kcmlayout.cpp905
-rw-r--r--kxkb/kcmlayout.h24
-rw-r--r--kxkb/kcmlayoutwidget.ui795
-rw-r--r--kxkb/kcmmisc.cpp35
-rw-r--r--kxkb/kcmmisc.h2
-rw-r--r--kxkb/kxkb.cpp532
-rw-r--r--kxkb/kxkb.h57
-rw-r--r--kxkb/kxkbbindings.cpp11
-rw-r--r--kxkb/kxkbconfig.cpp354
-rw-r--r--kxkb/kxkbconfig.h101
-rw-r--r--kxkb/kxkbtraywindow.cpp143
-rw-r--r--kxkb/kxkbtraywindow.h85
-rw-r--r--kxkb/layoutmap.cpp17
-rw-r--r--kxkb/layoutmap.h8
-rw-r--r--kxkb/layoutunit.h64
-rw-r--r--kxkb/pixmap.cpp307
-rw-r--r--kxkb/pixmap.h48
-rw-r--r--kxkb/rules.cpp99
-rw-r--r--kxkb/rules.h20
-rw-r--r--kxkb/x11helper.cpp111
-rw-r--r--kxkb/x11helper.h2
26 files changed, 2837 insertions, 1471 deletions
diff --git a/kxkb/CMakeL10n.txt b/kxkb/CMakeL10n.txt
index 0238bd7e3..66ed038d9 100644
--- a/kxkb/CMakeL10n.txt
+++ b/kxkb/CMakeL10n.txt
@@ -27,3 +27,9 @@ tde_l10n_create_template(
SOURCES *.desktop
DESTINATION "${CMAKE_SOURCE_DIR}/translations"
)
+
+tde_l10n_create_template(
+ CATALOG "desktop_files/kxkb-eventsrc/"
+ SOURCES eventsrc
+ DESTINATION "${CMAKE_SOURCE_DIR}/translations"
+) \ No newline at end of file
diff --git a/kxkb/CMakeLists.txt b/kxkb/CMakeLists.txt
index b8bb14912..83ca72be7 100644
--- a/kxkb/CMakeLists.txt
+++ b/kxkb/CMakeLists.txt
@@ -33,6 +33,12 @@ tde_create_translated_desktop(
PO_DIR kxkb-desktops
)
+tde_create_translated_desktop(
+ SOURCE eventsrc
+ DESTINATION ${DATA_INSTALL_DIR}/kxkb
+ PO_DIR kxkb-eventsrc
+)
+
install( FILES kxkb_groups DESTINATION ${CONFIG_INSTALL_DIR} )
tde_create_translated_desktop(
@@ -61,5 +67,5 @@ tde_add_tdeinit_executable( kxkb AUTOMOC
extension.cpp x11helper.cpp rules.cpp kxkbconfig.cpp
pixmap.cpp layoutmap.cpp kxkb.cpp kxkbtraywindow.cpp
kxkb.skel
- LINK tdeui-shared ${XKBFILE_LIBRARIES}
+ LINK tdeui-shared ${XKBFILE_LIBRARIES} ${TDEHW_LIBRARIES}
)
diff --git a/kxkb/eventsrc b/kxkb/eventsrc
new file mode 100644
index 000000000..1e06d70c3
--- /dev/null
+++ b/kxkb/eventsrc
@@ -0,0 +1,13 @@
+[!Global!]
+IconName=kxkb
+Comment=TDE Keyboard Tool
+
+[LayoutChange]
+Name=Keyboard layout switch
+Comment=The keyboard layout was switched
+default_presentation=16
+
+[Error]
+Name=Keyboard layout switching error
+Comment=Error while attempting to switch the keyboard layout
+default_presentation=16 \ No newline at end of file
diff --git a/kxkb/extension.cpp b/kxkb/extension.cpp
index 616167944..0fada6932 100644
--- a/kxkb/extension.cpp
+++ b/kxkb/extension.cpp
@@ -1,3 +1,32 @@
+/*******************************************************************************
+
+ Xkb extension for KXkb
+ Copyright © 2009-2025 Trinity Desktop project
+ Copyright © 2001 S.R. Haque <srhaque@iee.org>
+
+ Derived from an original by Matthias H�zer-Klpfel released under the QPL.
+
+ Some portions come from kkbswitch released under the GNU GPL v2 (or later).
+ Copyright © 2001 Leonid Zeitlin <lz@europe.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*******************************************************************************/
+
+#include <stdlib.h>
#include <string.h>
#include <errno.h>
@@ -5,87 +34,96 @@
#include <tqmap.h>
#include <tqfile.h>
#include <tqdir.h>
+#include <tqtimer.h>
#include <kdebug.h>
-#include <kstandarddirs.h>
-#include <kprocess.h>
+#include <tdeapplication.h>
+#include <tdestandarddirs.h>
+#include <tdeprocess.h>
+#include <dcopclient.h>
#include <X11/Xatom.h>
#include <X11/Xos.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include <X11/extensions/XKBfile.h>
+#include <X11/extensions/XKBrules.h>
#include <X11/extensions/XKBgeom.h>
#include <X11/extensions/XKM.h>
#include "extension.h"
-
-TQMap<TQString, FILE*> XKBExtension::fileCache; //TODO: move to class?
-
+extern "C"
+{
+ static int IgnoreXError(Display *, XErrorEvent *) { return 0; }
+}
static TQString getLayoutKey(const TQString& layout, const TQString& variant)
{
return layout + "." + variant;
}
-TQString XKBExtension::getPrecompiledLayoutFilename(const TQString& layoutKey)
-{
- TQString compiledLayoutFileName = m_tempDir + layoutKey + ".xkm";
- return compiledLayoutFileName;
-}
+static XKBExtension *xkbExtension = nullptr;
-XKBExtension::XKBExtension(Display *d)
+XKBExtension *XKBExtension::the()
{
- if ( d == NULL )
- d = tqt_xdisplay();
- m_dpy = d;
-
-// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" );
-// m_tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0];
- m_tempDir = locateLocal("tmp", "");
+ if (!xkbExtension)
+ {
+ xkbExtension = new XKBExtension;
+ if (!xkbExtension->init())
+ {
+ kdFatal() << "xkb initialization failed, exiting..." << endl;
+ ::exit(1);
+ }
+ }
+ return xkbExtension;
}
bool XKBExtension::init()
{
- // Verify the Xlib has matching XKB extension.
-
- int major = XkbMajorVersion;
- int minor = XkbMinorVersion;
-
- if (!XkbLibraryVersion(&major, &minor))
- {
- kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor <<
- " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
- return false;
- }
-
- // Verify the X server has matching XKB extension.
-
- int opcode_rtrn;
- int error_rtrn;
- int xkb_opcode;
- if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &xkb_opcode, &error_rtrn,
- &major, &minor))
- {
- kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor <<
- " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
- return false;
- }
-
- // Do it, or face horrible memory corrupting bugs
- ::XkbInitAtoms(NULL);
-
- return true;
-}
+ m_configureFilterCounter = 0;
-void XKBExtension::reset()
-{
- for(TQMap<TQString, FILE*>::ConstIterator it = fileCache.begin(); it != fileCache.end(); it++) {
- fclose(*it);
-// remove( TQFile::encodeName(getPrecompiledLayoutFileName(*it)) );
+ kdDebug() << "[kxkb-extension] Initializing Xkb extension" << endl;
+ m_dpy = tqt_xdisplay();
+
+ // Verify the Xlib has matching XKB extension.
+ int major = XkbMajorVersion;
+ int minor = XkbMinorVersion;
+
+ if (!XkbLibraryVersion(&major, &minor))
+ {
+ kdError() << "[kxkb-extension] Xlib XKB extension " << major << '.' << minor <<
+ " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
+ return false;
}
- fileCache.clear();
+
+ // Verify the X server has matching XKB extension.
+ int opcode_rtrn;
+ int error_rtrn;
+ if (!XkbQueryExtension(m_dpy, &opcode_rtrn, &m_xkb_opcode, &error_rtrn, &major, &minor))
+ {
+ kdError() << "[kxkb-extension] X server XKB extension " << major << '.' << minor <<
+ " != " << XkbMajorVersion << '.' << XkbMinorVersion << endl;
+ return false;
+ }
+
+ enableConfigureFilter();
+
+ // Do it, or face horrible memory corrupting bugs
+ ::XkbInitAtoms(nullptr);
+
+ // Watch for interesting events
+ XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbStateNotify,
+ XkbAllStateComponentsMask, XkbGroupStateMask);
+
+ XkbSelectEventDetails(m_dpy, XkbUseCoreKbd, XkbNewKeyboardNotify,
+ XkbAllNewKeyboardEventsMask, XkbAllNewKeyboardEventsMask);
+
+
+ m_tempDir = locateLocal("tmp", "");
+
+ disableConfigureFilter();
+ return true;
}
XKBExtension::~XKBExtension()
@@ -94,245 +132,158 @@ XKBExtension::~XKBExtension()
deletePrecompiledLayouts();*/
}
-bool XKBExtension::setXkbOptions(const TQString& options, bool resetOld)
+void XKBExtension::enableConfigureFilter()
{
- if (options.isEmpty())
- return true;
-
- TQString exe = TDEGlobal::dirs()->findExe("setxkbmap");
- if (exe.isEmpty())
- return false;
-
- TDEProcess p;
- p << exe;
- if( resetOld )
- p << "-option";
- p << "-option" << options;
-
- p.start(TDEProcess::Block);
+ ++m_configureFilterCounter;
+}
- return p.normalExit() && (p.exitStatus() == 0);
+void XKBExtension::disableConfigureFilter()
+{
+ // Without this protection in place KXkb would react to configuration
+ // changes caused by itself
+ TQTimer::singleShot(500, this, TQ_SLOT(slotReleaseConfigureLock()));
}
-bool XKBExtension::setLayout(const TQString& model,
- const TQString& layout, const TQString& variant,
- const TQString& includeGroup, bool useCompiledLayouts)
+void XKBExtension::slotReleaseConfigureLock()
{
- if( useCompiledLayouts == false ) {
- return setLayoutInternal( model, layout, variant, includeGroup );
- }
-
- const TQString layoutKey = getLayoutKey(layout, variant);
-
- bool res;
- if( fileCache.contains(layoutKey) ) {
- res = setCompiledLayout( layoutKey );
- kdDebug() << "[kxkb-extension] setCompiledLayout " << layoutKey << ": " << res << endl;
-
- if( res )
- return res;
- }
-// else {
- res = setLayoutInternal( model, layout, variant, includeGroup );
- kdDebug() << "[kxkb-extension] setRawLayout " << layoutKey << ": " << res << endl;
- if( res )
- compileCurrentLayout( layoutKey );
-
-// }
- return res;
+ --m_configureFilterCounter;
}
-// private
-bool XKBExtension::setLayoutInternal(const TQString& model,
- const TQString& layout, const TQString& variant,
- const TQString& includeGroup)
+bool XKBExtension::setXkbOptions(const XkbOptions options)
{
- if ( layout.isEmpty() )
- return false;
+ enableConfigureFilter();
TQString exe = TDEGlobal::dirs()->findExe("setxkbmap");
- if( exe.isEmpty() ) {
- kdError() << "[kxkb-extension] Can't find setxkbmap" << endl;
+ if (exe.isEmpty())
+ {
return false;
}
- TQString fullLayout = layout;
- TQString fullVariant = variant;
- if( includeGroup.isEmpty() == false ) {
- fullLayout = includeGroup;
- fullLayout += ",";
- fullLayout += layout;
-
-// fullVariant = baseVar;
- fullVariant = ",";
- fullVariant += variant;
- }
-
- TDEProcess p;
- p << exe;
-// p << "-rules" << rule;
- if( model.isEmpty() == false )
- p << "-model" << model;
- p << "-layout" << fullLayout;
- if( !fullVariant.isNull() && !fullVariant.isEmpty() )
- p << "-variant" << fullVariant;
-
- p.start(TDEProcess::Block);
-
- // reload system-wide hotkey-setup keycode -> keysym maps
- TQString modmapFileName = TDEGlobal::dirs()->findResource( "data", "kxkb/system.xmodmap" );
- if ( TQFile::exists( modmapFileName ) ) {
- TDEProcess pXmodmap;
- pXmodmap << "xmodmap" << modmapFileName;
- pXmodmap.start(TDEProcess::Block);
- }
-
- if ( TQFile::exists( TQDir::home().path() + "/.Xmodmap" ) ) {
- TDEProcess pXmodmapHome;
- pXmodmapHome << "xmodmap" << TQDir::home().path() + "/.Xmodmap";
- pXmodmapHome.start(TDEProcess::Block);
- }
-
- return p.normalExit() && (p.exitStatus() == 0);
+ TDEProcess p;
+ p << exe;
+
+ if (!options.layouts.isEmpty())
+ {
+ p << "-layout";
+ p << options.layouts;
+ }
+
+ if (!options.variants.isEmpty())
+ {
+ p << "-variant";
+ p << options.variants;
+ }
+
+ if (!options.model.isEmpty()) {
+ p << "-model";
+ p << options.model;
+ }
+
+ if (options.resetOld) {
+ p << "-option";
+ }
+
+ if (!options.options.isEmpty()) {
+ if (options.resetOld)
+ {
+ p << "-option" << options.options;
+ }
+ else
+ {
+ // Avoid duplication of options in Append mode
+ XkbOptions _opt = getServerOptions();
+ TQStringList srvOptions = TQStringList::split(",", _opt.options);
+ TQStringList kxkbOptions = TQStringList::split(",", options.options);
+ TQStringList newOptions;
+ for (TQStringList::Iterator it = kxkbOptions.begin(); it != kxkbOptions.end(); ++it)
+ {
+ TQString option(*it);
+ if (!srvOptions.contains(option))
+ {
+ newOptions << option;
+ }
+ }
+ if (!newOptions.isEmpty()) {
+ p << "-option" << newOptions.join(",");
+ }
+ }
+ }
+
+ if (p.args().count() < 2)
+ {
+ // Either the user has not configured any Xkb options or these options
+ // are already set and we are in append mode so we want to avoid
+ // duplicates
+ kdWarning() << "[setXkbOptions] No options need to be set" << endl;
+ slotReleaseConfigureLock(); // immediately release the lock
+ return true;
+ }
+
+ p << "-synch";
+
+ kdDebug() << "[setXkbOptions] Command: " << p.args() << endl;
+
+ p.start(TDEProcess::Block);
+
+ disableConfigureFilter();
+
+ return p.normalExit() && (p.exitStatus() == 0);
+}
+
+XkbOptions XKBExtension::getServerOptions()
+{
+ XkbOptions options;
+ XkbRF_VarDefsRec vd;
+ if (XkbRF_GetNamesProp(tqt_xdisplay(), nullptr, &vd))
+ {
+ options.model = vd.model;
+ options.layouts = vd.layout;
+ options.variants = vd.variant;
+ options.options = vd.options;
+ }
+ return options;
}
bool XKBExtension::setGroup(unsigned int group)
{
kdDebug() << "[kxkb-extension] Setting group " << group << endl;
- return XkbLockGroup( m_dpy, XkbUseCoreKbd, group );
+ return XkbLockGroup(m_dpy, XkbUseCoreKbd, group);
}
-unsigned int XKBExtension::getGroup() const
+uint XKBExtension::getGroup() const
{
XkbStateRec xkbState;
- XkbGetState( m_dpy, XkbUseCoreKbd, &xkbState );
+ XkbGetState(m_dpy, XkbUseCoreKbd, &xkbState);
return xkbState.group;
}
-/**
- * @brief Gets the current layout in its binary compiled form
- * and write it to the file specified by 'fileName'
- * @param[in] fileName file to store compiled layout to
- * @return true if no problem, false otherwise
- */
-bool XKBExtension::compileCurrentLayout(const TQString &layoutKey)
+bool XKBExtension::kcmlayoutRunning()
{
- XkbFileInfo result;
- memset(&result, 0, sizeof(result));
- result.type = XkmKeymapFile;
- XkbReadFromServer(m_dpy, XkbAllMapComponentsMask, XkbAllMapComponentsMask, &result);
-
- const TQString fileName = getPrecompiledLayoutFilename(layoutKey);
-
- kdDebug() << "[kxkb-extension] compiling layout " << this << " cache size: " << fileCache.count() << endl;
- if( fileCache.contains(layoutKey) ) {
- kdDebug() << "[kxkb-extension] trashing old compiled layout for " << fileName << endl;
- if( fileCache[ layoutKey ] != NULL )
- fclose( fileCache[ layoutKey ] ); // recompiling - trash the old file
- fileCache.remove(fileName);
- }
-
- FILE *output = fopen(TQFile::encodeName(fileName), "w");
-
- if ( output == NULL )
- {
- kdWarning() << "[kxkb-extension] Could not open " << fileName << " to precompile: " << strerror(errno) << endl;
- XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
- return false;
- }
-
- if( !XkbWriteXKMFile(output, &result) ) {
- kdWarning() << "[kxkb-extension] Could not write compiled layout to " << fileName << endl;
- fclose(output);
- return false;
- }
-
- fclose(output); // TODO: can we change mode w/out reopening?
- FILE *input = fopen(TQFile::encodeName(fileName), "r");
- fileCache[ layoutKey ] = input;
-
- XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
- return true;
+ return tdeApp->dcopClient()->isApplicationRegistered("TDECModuleProxy-keyboard_layout");
}
-/**
- * @brief takes layout from its compiled binary snapshot in file
- * and sets it as current
- * TODO: cache layout in memory rather than in file
- */
-bool XKBExtension::setCompiledLayout(const TQString &layoutKey)
-{
- FILE *input = NULL;
-
- if( fileCache.contains(layoutKey) ) {
- input = fileCache[ layoutKey ];
- }
-
- if( input == NULL ) {
- kdWarning() << "[kxkb-extension] setCompiledLayout trying to reopen xkb file" << endl; // should never happen
- const TQString fileName = getPrecompiledLayoutFilename(layoutKey);
- input = fopen(TQFile::encodeName(fileName), "r");
-
- // FILE *input = fopen(TQFile::encodeName(fileName), "r");
- if ( input == NULL ) {
- kdDebug() << "[kxkb-extension] Unable to open " << fileName << ": " << strerror(errno) << endl;
- fileCache.remove(layoutKey);
- return false;
+// Examines an X Event passed to it and takes actions if the event is of
+// interest to KXkb
+void XKBExtension::processXEvent(XEvent *event) {
+ if (event->type == m_xkb_opcode)
+ {
+ XkbEvent *xkb_event = (XkbEvent*)event;
+ if (xkb_event->any.xkb_type == XkbStateNotify && xkb_event->state.changed & XkbGroupStateMask)
+ {
+ emit groupChanged((uint)xkb_event->state.group);
}
- }
- else {
- rewind(input);
- }
- XkbFileInfo result;
- memset(&result, 0, sizeof(result));
- if ((result.xkb = XkbAllocKeyboard())==NULL) {
- kdWarning() << "[kxkb-extension] Unable to allocate memory for keyboard description" << endl;
-// fclose(input);
-// fileCache.remove(layoutKey);
- return false;
+ else if (xkb_event->any.xkb_type == XkbNewKeyboardNotify)
+ {
+ if (m_configureFilterCounter > 0 || kcmlayoutRunning())
+ {
+ return;
+ }
+ enableConfigureFilter();
+ emit optionsChanged();
+ disableConfigureFilter();
+ }
}
-
- unsigned retVal = XkmReadFile(input, 0, XkmKeymapLegal, &result);
- if (retVal == XkmKeymapLegal)
- {
- // this means reading the Xkm didn't manage to read any section
- kdWarning() << "[kxkb-extension] Unable to load map from file" << endl;
- XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
- fclose(input);
- fileCache.remove(layoutKey);
- return false;
- }
-
- // fclose(input); // don't close - goes in cache
-
- if (XkbChangeKbdDisplay(m_dpy, &result) == Success)
- {
- if (!XkbWriteToServer(&result))
- {
- kdWarning() << "[kxkb-extension] Unable to write the keyboard layout to X display" << endl;
- XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
- return false;
- }
- }
- else
- {
- kdWarning() << "[kxkb-extension] Unable prepare the keyboard layout for X display" << endl;
- }
-
- XkbFreeKeyboard(result.xkb, XkbAllControlsMask, True);
- return true;
}
-
-// Deletes the precompiled layouts stored in temporary files
-// void XKBExtension::deletePrecompiledLayouts()
-// {
-// TQMapConstIterator<LayoutUnit, TQString> it, end;
-// end = m_compiledLayoutFileNames.end();
-// for (it = m_compiledLayoutFileNames.begin(); it != end; ++it)
-// {
-// unlink(TQFile::encodeName(it.data()));
-// }
-// m_compiledLayoutFileNames.clear();
-// }
+#include "extension.moc"
diff --git a/kxkb/extension.h b/kxkb/extension.h
index bf4293d2b..e8c9c7d7c 100644
--- a/kxkb/extension.h
+++ b/kxkb/extension.h
@@ -1,37 +1,83 @@
+/*******************************************************************************
+
+ Xkb extension for KXkb
+ Copyright © 2009-2025 Trinity Desktop project
+ Copyright © 2001 S.R. Haque <srhaque@iee.org>
+
+ Derived from an original by Matthias H�zer-Klpfel released under the QPL.
+
+ Some portions come from kkbswitch released under the GNU GPL v2 (or later).
+ Copyright © 2001 Leonid Zeitlin <lz@europe.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+
+*******************************************************************************/
+
#ifndef __EXTENSION_H__
#define __EXTENSION_H__
#include <X11/Xlib.h>
+#include <tqobject.h>
-class XKBExtension
+#include "kxkbconfig.h"
+
+class XKBExtension : public TQObject
{
+ TQ_OBJECT
+
public:
- XKBExtension(Display *display=NULL);
+ static XKBExtension *the();
~XKBExtension();
+
+ XKBExtension(XKBExtension const&) = delete;
+ void operator=(XKBExtension const&) = delete;
+
bool init();
- void reset();
- static bool setXkbOptions(const TQString& options, bool resetOldOptions);
- bool setLayout(const TQString& model,
- const TQString& layout, const TQString& variant,
- const TQString& includeGroup, bool useCompiledLayouts=true);
- bool setGroup(unsigned int group);
- unsigned int getGroup() const;
+ bool setXkbOptions(const XkbOptions options);
+ bool setGroup(uint group);
+
+ uint getGroup() const;
+ XkbOptions getServerOptions();
+
+ void processXEvent(XEvent *ev);
+
+ void enableConfigureFilter();
+ void disableConfigureFilter();
+
+ bool kcmlayoutRunning();
+
+private slots:
+ void slotReleaseConfigureLock();
+
+protected:
+ XKBExtension() {}
private:
- Display *m_dpy;
+ Display *m_dpy;
TQString m_tempDir;
+ int m_keycode;
static TQMap<TQString, FILE*> fileCache;
-
- bool setLayoutInternal(const TQString& model,
- const TQString& layout, const TQString& variant,
- const TQString& includeGroup);
- bool compileCurrentLayout(const TQString& layoutKey);
- bool setCompiledLayout(const TQString& layoutKey);
-
- TQString getPrecompiledLayoutFilename(const TQString& layoutKey);
-// void deletePrecompiledLayouts();
+ int m_configureFilterCounter;
+ int m_xkb_opcode;
+
+signals:
+ void groupChanged(uint group);
+ void optionsChanged();
};
#endif
diff --git a/kxkb/kcmlayout.cpp b/kxkb/kcmlayout.cpp
index a306f0a33..d9efb9e57 100644
--- a/kxkb/kcmlayout.cpp
+++ b/kxkb/kcmlayout.cpp
@@ -13,15 +13,23 @@
#include <tqlistview.h>
#include <tqbuttongroup.h>
#include <tqspinbox.h>
+#include <tqvbox.h>
+#include <tqtimer.h>
+#include <tdefontrequester.h>
+#include <kcolorbutton.h>
#include <kkeydialog.h>
#include <tdeglobal.h>
#include <tdeconfig.h>
#include <tdelocale.h>
-#include <kstandarddirs.h>
+#include <tdestandarddirs.h>
#include <kdebug.h>
#include <tdeapplication.h>
#include <kiconloader.h>
+#include <tdemessagebox.h>
+#include <tdeglobalaccel.h>
+#include <dcopref.h>
+#include <dcopclient.h>
#include "extension.h"
#include "kxkbconfig.h"
@@ -29,6 +37,7 @@
#include "pixmap.h"
#include "kcmmisc.h"
#include "kcmlayoutwidget.h"
+#include "x11helper.h"
#include "kcmlayout.h"
#include "kcmlayout.moc"
@@ -39,8 +48,7 @@ enum {
LAYOUT_COLUMN_NAME = 1,
LAYOUT_COLUMN_MAP = 2,
LAYOUT_COLUMN_VARIANT = 3,
- LAYOUT_COLUMN_INCLUDE = 4,
- LAYOUT_COLUMN_DISPLAY_NAME = 5,
+ LAYOUT_COLUMN_DISPLAY_NAME = 4,
SRC_LAYOUT_COLUMN_COUNT = 3,
DST_LAYOUT_COLUMN_COUNT = 6
};
@@ -95,60 +103,79 @@ static TQListViewItem* copyLVI(const TQListViewItem* src, TQListView* parent)
LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
- : TDECModule(parent, name),
- m_rules(NULL)
+ : TDECModule(parent, name),
+ m_rules(NULL),
+ m_forceGrpOverwrite(false)
{
+ X11Helper::initializeTranslations();
+
+ m_icoMgr = new LayoutIconManager(&m_kxkbConfig);
+
TQVBoxLayout *main = new TQVBoxLayout(this, 0, KDialog::spacingHint());
widget = new LayoutConfigWidget(this, "widget");
- main->addWidget(TQT_TQWIDGET(widget));
+ main->addWidget(widget);
- connect( TQT_TQOBJECT(widget->chkEnable), TQT_SIGNAL( toggled( bool )), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( TQT_TQOBJECT(widget->chkShowSingle), TQT_SIGNAL( toggled( bool )), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( TQT_TQOBJECT(widget->chkShowFlag), TQT_SIGNAL( toggled( bool )), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( TQT_TQOBJECT(widget->comboModel), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(changed()));
+ connect( widget->chkEnable, TQ_SIGNAL( toggled( bool )), this, TQ_SLOT(changed()));
+ connect( widget->chkShowSingle, TQ_SIGNAL( toggled( bool )), this, TQ_SLOT(changed()));
- connect( TQT_TQOBJECT(widget->listLayoutsSrc), TQT_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&, int)),
- TQT_TQOBJECT(this), TQT_SLOT(add()));
- connect( TQT_TQOBJECT(widget->btnAdd), TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(add()));
- connect( TQT_TQOBJECT(widget->btnRemove), TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(remove()));
+ connect( widget->comboHotkey, TQ_SIGNAL(activated(int)), this, TQ_SLOT(hotkeyComboChanged()));
+ connect( widget->comboHotkey, TQ_SIGNAL(activated(int)), this, TQ_SLOT(updateOptionsCommand()));
+ connect( widget->comboHotkey, TQ_SIGNAL(activated(int)), this, TQ_SLOT(changed()));
+ connect( widget->comboModel, TQ_SIGNAL(activated(int)), this, TQ_SLOT(changed()));
- connect( TQT_TQOBJECT(widget->comboVariant), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( TQT_TQOBJECT(widget->comboVariant), TQT_SIGNAL(activated(int)), TQT_TQOBJECT(this), TQT_SLOT(variantChanged()));
- connect( TQT_TQOBJECT(widget->listLayoutsDst), TQT_SIGNAL(selectionChanged(TQListViewItem *)),
- TQT_TQOBJECT(this), TQT_SLOT(layoutSelChanged(TQListViewItem *)));
+ connect( widget->listLayoutsSrc, TQ_SIGNAL(doubleClicked(TQListViewItem*,const TQPoint&, int)),
+ this, TQ_SLOT(add()));
+ connect( widget->btnAdd, TQ_SIGNAL(clicked()), this, TQ_SLOT(add()));
+ connect( widget->btnRemove, TQ_SIGNAL(clicked()), this, TQ_SLOT(remove()));
- connect( widget->editDisplayName, TQT_SIGNAL(textChanged(const TQString&)), TQT_TQOBJECT(this), TQT_SLOT(displayNameChanged(const TQString&)));
+ connect( widget->comboVariant, TQ_SIGNAL(activated(int)), this, TQ_SLOT(changed()));
+ connect( widget->comboVariant, TQ_SIGNAL(activated(int)), this, TQ_SLOT(variantChanged()));
+ connect( widget->listLayoutsDst, TQ_SIGNAL(selectionChanged(TQListViewItem *)),
+ this, TQ_SLOT(layoutSelChanged(TQListViewItem *)));
- connect( widget->chkLatin, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( widget->chkLatin, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(latinChanged()));
+ connect( widget->editDisplayName, TQ_SIGNAL(textChanged(const TQString&)), this, TQ_SLOT(displayNameChanged(const TQString&)));
widget->btnUp->setIconSet(SmallIconSet("1uparrow"));
- connect( widget->btnUp, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( widget->btnUp, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(moveUp()));
+ connect( widget->btnUp, TQ_SIGNAL(clicked()), this, TQ_SLOT(changed()));
+ connect( widget->btnUp, TQ_SIGNAL(clicked()), this, TQ_SLOT(moveUp()));
widget->btnDown->setIconSet(SmallIconSet("1downarrow"));
- connect( widget->btnDown, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( widget->btnDown, TQT_SIGNAL(clicked()), TQT_TQOBJECT(this), TQT_SLOT(moveDown()));
+ connect( widget->btnDown, TQ_SIGNAL(clicked()), this, TQ_SLOT(changed()));
+ connect( widget->btnDown, TQ_SIGNAL(clicked()), this, TQ_SLOT(moveDown()));
+
+ connect( widget->grpStyle, TQ_SIGNAL( clicked( int ) ), TQ_SLOT(changed()));
+ connect( widget->grpSwitching, TQ_SIGNAL( clicked( int ) ), TQ_SLOT(changed()));
+ connect( widget->grpLabel, TQ_SIGNAL( clicked( int ) ), TQ_SLOT(changed()));
+
+ connect( widget->chkFitToBox, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ connect( widget->chkDimFlag, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
- connect( widget->grpSwitching, TQT_SIGNAL( clicked( int ) ), TQT_SLOT(changed()));
+ connect( widget->bgColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed()));
+ connect( widget->fgColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed()));
+ connect( widget->chkBgTransparent, TQ_SIGNAL( toggled(bool) ), this, TQ_SLOT(changed()));
+ connect( widget->labelFont, TQ_SIGNAL( fontSelected(const TQFont&) ), this, TQ_SLOT(changed()));
+ connect( widget->chkLabelShadow, TQ_SIGNAL( toggled( bool ) ), this, TQ_SLOT(changed()));
+ connect( widget->shColor, TQ_SIGNAL( changed(const TQColor&) ), this, TQ_SLOT(changed()));
- connect( widget->chkEnableSticky, TQT_SIGNAL(toggled(bool)), TQT_TQOBJECT(this), TQT_SLOT(changed()));
- connect( widget->spinStickyDepth, TQT_SIGNAL(valueChanged(int)), TQT_TQOBJECT(this), TQT_SLOT(changed()));
+ connect( widget->chkBevel, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+
+ connect( widget->chkEnableSticky, TQ_SIGNAL(toggled(bool)), this, TQ_SLOT(changed()));
+ connect( widget->spinStickyDepth, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(changed()));
+
+ connect(widget->chkEnableNotify, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed()));
+ connect(widget->chkNotifyUseKMilo, TQ_SIGNAL(toggled(bool)), TQ_SLOT(changed()));
+ connect(widget->chkEnableNotify, TQ_SIGNAL(toggled(bool)), widget->chkNotifyUseKMilo, TQ_SLOT(setEnabled(bool)));
widget->listLayoutsSrc->setColumnText(LAYOUT_COLUMN_FLAG, "");
widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_FLAG, "");
- widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_INCLUDE, "");
// widget->listLayoutsDst->setColumnText(LAYOUT_COLUMN_DISPLAY_NAME, "");
widget->listLayoutsSrc->setColumnWidth(LAYOUT_COLUMN_FLAG, 28);
widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_FLAG, 28);
- widget->listLayoutsDst->header()->setResizeEnabled(FALSE, LAYOUT_COLUMN_INCLUDE);
- widget->listLayoutsDst->header()->setResizeEnabled(FALSE, LAYOUT_COLUMN_DISPLAY_NAME);
- widget->listLayoutsDst->setColumnWidthMode(LAYOUT_COLUMN_INCLUDE, TQListView::Manual);
- widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_INCLUDE, 0);
+ widget->listLayoutsDst->header()->setResizeEnabled(false, LAYOUT_COLUMN_DISPLAY_NAME);
// widget->listLayoutsDst->setColumnWidth(LAYOUT_COLUMN_DISPLAY_NAME, 0);
-
+
widget->listLayoutsDst->setSorting(-1);
#if 0
widget->listLayoutsDst->setResizeMode(TQListView::LastColumn);
@@ -159,48 +186,63 @@ LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)
//Read rules - we _must_ read _before_ creating xkb-options comboboxes
loadRules();
- makeOptionsTab();
+ // Load global shortcuts
+#define NOSLOTS
+ keys = new TDEGlobalAccel(this);
+#include "kxkbbindings.cpp"
+ keys->readSettings();
- load();
+ makeOptionsTab();
+ makeShortcutsTab();
+ TQTimer::singleShot(0, this, TQ_SLOT(load()));
}
LayoutConfig::~LayoutConfig()
{
- delete m_rules;
+ delete m_rules;
+ delete m_icoMgr;
}
void LayoutConfig::load()
{
- m_kxkbConfig.load(KxkbConfig::LOAD_ALL);
+ bool modified = false;
+ m_kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
- initUI();
+ // Check if the active settings are different from the saved settings
+ if (m_kxkbConfig.m_useKxkb)
+ {
+ XkbOptions options = XKBExtension::the()->getServerOptions();
+ modified = m_kxkbConfig.setFromXkbOptions(options);
+ }
+
+ m_kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
+ keys->readSettings();
+ initUI(modified);
}
-
-void LayoutConfig::initUI() {
+
+void LayoutConfig::initUI(bool modified) {
const char* modelName = m_rules->models()[m_kxkbConfig.m_model];
if( modelName == NULL )
modelName = DEFAULT_MODEL;
-
+
widget->comboModel->setCurrentText(i18n(modelName));
TQValueList<LayoutUnit> otherLayouts = m_kxkbConfig.m_layouts;
widget->listLayoutsDst->clear();
-// to optimize we should have gone from it.end to it.begin
+ // to optimize we should have gone from it.end to it.begin
TQValueList<LayoutUnit>::ConstIterator it;
for (it = otherLayouts.begin(); it != otherLayouts.end(); ++it ) {
TQListViewItemIterator src_it( widget->listLayoutsSrc );
LayoutUnit layoutUnit = *it;
-
+
for ( ; src_it.current(); ++src_it ) {
TQListViewItem* srcItem = src_it.current();
-
if ( layoutUnit.layout == src_it.current()->text(LAYOUT_COLUMN_MAP) ) { // check if current config knows about this layout
TQListViewItem* newItem = copyLVI(srcItem, widget->listLayoutsDst);
-
+
newItem->setText(LAYOUT_COLUMN_VARIANT, layoutUnit.variant);
- newItem->setText(LAYOUT_COLUMN_INCLUDE, layoutUnit.includeGroup);
newItem->setText(LAYOUT_COLUMN_DISPLAY_NAME, layoutUnit.displayName);
widget->listLayoutsDst->insertItem(newItem);
newItem->moveItem(widget->listLayoutsDst->lastItem());
@@ -210,12 +252,55 @@ void LayoutConfig::initUI() {
}
}
+ // initialize hotkey combo
+ TQDict<char> allOptions = m_rules->options();
+
+ TQStringList commonHotkeys;
+ commonHotkeys << "alt_shift_toggle" << "ctrl_shift_toggle"
+ << "win_space_toggle" << "alt_space_toggle"
+ << "caps_toggle" << "menu_toggle"
+ << "lwin_toggle" << "rwin_toggle";
+
+ for (TQStringList::ConstIterator hk = commonHotkeys.begin(); hk != commonHotkeys.end(); ++hk ) {
+ const char *hkOpt = tqstrdup(TQString("grp:" + (*hk)).ascii());
+ const char *hkDesc = allOptions[hkOpt];
+ if (hkDesc != 0) { // the option exists
+ widget->comboHotkey->insertItem(XkbRules::trOpt(hkDesc));
+ }
+ }
+ widget->comboHotkey->insertItem(i18n("None"));
+ widget->comboHotkey->insertItem(i18n("Other..."));
+
// display KXKB switching options
widget->chkShowSingle->setChecked(m_kxkbConfig.m_showSingle);
- widget->chkShowFlag->setChecked(m_kxkbConfig.m_showFlag);
- widget->chkEnableOptions->setChecked( m_kxkbConfig.m_enableXkbOptions );
- widget->checkResetOld->setChecked(m_kxkbConfig.m_resetOldOptions);
+ bool showFlag = m_kxkbConfig.m_showFlag;
+ bool showLabel = m_kxkbConfig.m_showLabel;
+ widget->radFlagLabel->setChecked( showFlag && showLabel );
+ widget->radFlagOnly->setChecked( showFlag && !showLabel );
+ widget->radLabelOnly->setChecked( !showFlag && showLabel );
+ widget->chkFitToBox->setChecked(m_kxkbConfig.m_fitToBox);
+ widget->chkDimFlag->setChecked(m_kxkbConfig.m_dimFlag);
+
+ widget->xkbOptsMode->setButton(m_kxkbConfig.m_resetOldOptions ? 0 : 1);
+
+ widget->grpLabel->setButton( ( m_kxkbConfig.m_useThemeColors ? 0 : 1 ) );
+ widget->bgColor->setColor( m_kxkbConfig.m_colorBackground );
+ widget->fgColor->setColor( m_kxkbConfig.m_colorLabel );
+ widget->chkBgTransparent->setChecked( m_kxkbConfig.m_bgTransparent );
+ widget->labelFont->setFont( m_kxkbConfig.m_labelFont );
+ widget->chkLabelShadow->setChecked( m_kxkbConfig.m_labelShadow );
+ widget->shColor->setColor( m_kxkbConfig.m_colorShadow );
+
+ widget->chkBevel->setChecked(m_kxkbConfig.m_bevel);
+
+ widget->grpLabel->setDisabled(showFlag && !showLabel);
+ widget->grpLabelColors->setDisabled(m_kxkbConfig.m_useThemeColors);
+ widget->labelBgColor->setDisabled(showFlag);
+ widget->bgColor->setDisabled(showFlag);
+ widget->chkBgTransparent->setDisabled(showFlag);
+ widget->grpFlag->setEnabled(showFlag);
+ widget->chkDimFlag->setEnabled(showFlag && showLabel);
switch( m_kxkbConfig.m_switchingPolicy ) {
default:
@@ -234,21 +319,32 @@ void LayoutConfig::initUI() {
widget->spinStickyDepth->setEnabled(m_kxkbConfig.m_stickySwitching);
widget->spinStickyDepth->setValue( m_kxkbConfig.m_stickySwitchingDepth);
+ widget->chkEnableNotify->setChecked(m_kxkbConfig.m_enableNotify);
+ widget->chkNotifyUseKMilo->setChecked(m_kxkbConfig.m_notifyUseKMilo);
+ widget->chkNotifyUseKMilo->setEnabled(m_kxkbConfig.m_enableNotify);
+
updateStickyLimit();
widget->chkEnable->setChecked( m_kxkbConfig.m_useKxkb );
widget->grpLayouts->setEnabled( m_kxkbConfig.m_useKxkb );
- widget->optionsFrame->setEnabled( m_kxkbConfig.m_useKxkb );
+ widget->swOptsFrame->setEnabled( m_kxkbConfig.m_useKxkb );
+ widget->indOptsFrame->setEnabled( m_kxkbConfig.m_useKxkb );
// display xkb options
- TQStringList options = TQStringList::split(',', m_kxkbConfig.m_options);
- for (TQStringList::ConstIterator it = options.begin(); it != options.end(); ++it)
+ TQStringList activeOptions = TQStringList::split(',', m_kxkbConfig.m_options);
+ bool foundGrp = false;
+ for (TQStringList::ConstIterator it = activeOptions.begin(); it != activeOptions.end(); ++it)
{
TQString option = *it;
TQString optionKey = option.mid(0, option.find(':'));
TQString optionName = m_rules->options()[option];
- OptionListItem *item = m_optionGroups[i18n(optionKey.latin1())];
-
+
+ if (optionKey == "grp") {
+ foundGrp = true;
+ }
+
+ OptionListItem *item = m_optionGroups[optionKey];
+
if (item != NULL) {
OptionListItem *child = item->findChildItem( option );
@@ -262,8 +358,16 @@ void LayoutConfig::initUI() {
}
}
+ if (!foundGrp) {
+ OptionListItem *grpNone = itemForOption("grp:none");
+ if (grpNone) {
+ grpNone->setOn(true);
+ }
+ }
+
updateOptionsCommand();
- emit TDECModule::changed( false );
+ updateHotkeyCombo(true);
+ emit TDECModule::changed(modified);
}
@@ -272,26 +376,35 @@ void LayoutConfig::save()
TQString model = lookupLocalized(m_rules->models(), widget->comboModel->currentText());
m_kxkbConfig.m_model = model;
- m_kxkbConfig.m_enableXkbOptions = widget->chkEnableOptions->isChecked();
- m_kxkbConfig.m_resetOldOptions = widget->checkResetOld->isChecked();
+ m_kxkbConfig.m_resetOldOptions = widget->radXkbOverwrite->isOn();
m_kxkbConfig.m_options = createOptionString();
+ m_kxkbConfig.m_fitToBox = widget->chkFitToBox->isChecked();
+ m_kxkbConfig.m_dimFlag = widget->chkDimFlag->isChecked();
+
+ m_kxkbConfig.m_useThemeColors = widget->radLabelUseTheme->isChecked();
+ m_kxkbConfig.m_colorBackground = widget->bgColor->color();
+ m_kxkbConfig.m_colorLabel = widget->fgColor->color();
+ m_kxkbConfig.m_bgTransparent = widget->chkBgTransparent->isChecked();
+ m_kxkbConfig.m_labelFont = widget->labelFont->font();
+ m_kxkbConfig.m_labelShadow = widget->chkLabelShadow->isChecked();
+ m_kxkbConfig.m_colorShadow = widget->shColor->color();
+
+ m_kxkbConfig.m_bevel = widget->chkBevel->isChecked();
+
TQListViewItem *item = widget->listLayoutsDst->firstChild();
TQValueList<LayoutUnit> layouts;
while (item) {
TQString layout = item->text(LAYOUT_COLUMN_MAP);
TQString variant = item->text(LAYOUT_COLUMN_VARIANT);
- TQString includes = item->text(LAYOUT_COLUMN_INCLUDE);
TQString displayName = item->text(LAYOUT_COLUMN_DISPLAY_NAME);
-
+
LayoutUnit layoutUnit(layout, variant);
- layoutUnit.includeGroup = includes;
layoutUnit.displayName = displayName;
layouts.append( layoutUnit );
-
+
item = item->nextSibling();
- kdDebug() << "To save: layout " << layoutUnit.toPair()
- << ", inc: " << layoutUnit.includeGroup
+ kdDebug() << "To save: layout " << layoutUnit.toPair()
<< ", disp: " << layoutUnit.displayName << endl;
}
m_kxkbConfig.m_layouts = layouts;
@@ -303,7 +416,9 @@ void LayoutConfig::save()
m_kxkbConfig.m_useKxkb = widget->chkEnable->isChecked();
m_kxkbConfig.m_showSingle = widget->chkShowSingle->isChecked();
- m_kxkbConfig.m_showFlag = widget->chkShowFlag->isChecked();
+
+ m_kxkbConfig.m_showFlag = ( widget->radFlagLabel->isChecked() || widget->radFlagOnly->isChecked() );
+ m_kxkbConfig.m_showLabel = ( widget->radFlagLabel->isChecked() || widget->radLabelOnly->isChecked() );
int modeId = widget->grpSwitching->id(widget->grpSwitching->selected());
switch( modeId ) {
@@ -322,9 +437,79 @@ void LayoutConfig::save()
m_kxkbConfig.m_stickySwitching = widget->chkEnableSticky->isChecked();
m_kxkbConfig.m_stickySwitchingDepth = widget->spinStickyDepth->value();
+ m_kxkbConfig.m_enableNotify = widget->chkEnableNotify->isChecked();
+ m_kxkbConfig.m_notifyUseKMilo = widget->chkNotifyUseKMilo->isChecked();
+
m_kxkbConfig.save();
-
- kapp->tdeinitExec("kxkb");
+
+ // We might need to unset previous hotkey options
+ if (m_forceGrpOverwrite)
+ {
+ // First get all the server's options
+ XkbOptions _opt = XKBExtension::the()->getServerOptions();
+ TQStringList srvOptions = TQStringList::split(",", _opt.options);
+ TQStringList newOptions;
+
+ // Then remove all grp: options
+ for (TQStringList::Iterator it = srvOptions.begin(); it != srvOptions.end(); ++it)
+ {
+ TQString opt(*it);
+ if (!opt.startsWith("grp:"))
+ {
+ newOptions << opt;
+ }
+ }
+
+ XkbOptions xkbOptions;
+ xkbOptions.options = newOptions.join(",");
+ xkbOptions.resetOld = true;
+
+ if (!XKBExtension::the()->setXkbOptions(xkbOptions))
+ {
+ kdWarning() << "[LayoutConfig::save] Could not overwrite previous grp: options!" << endl;
+ }
+
+ m_forceGrpOverwrite = false;
+ }
+
+ // Save and apply global shortcuts
+ m_keyChooser->commitChanges();
+ keys->writeSettings(0, true);
+
+ // Get current layout from Kxkb
+ if (!tdeApp->dcopClient()->isAttached())
+ tdeApp->dcopClient()->attach();
+
+ DCOPRef kxkbref("kxkb", "kxkb");
+ DCOPReply reply = kxkbref.call( "getCurrentLayout" );
+
+ TQString currentLayout;
+ if ( reply.isValid() ) {
+ reply.get(currentLayout);
+ } else {
+ kdDebug() << "Warning: cannot get current layout! (invalid DCOP reply from Kxkb)" << endl;
+ }
+
+ // Cause Kxkb to reread configuration
+ tdeApp->tdeinitExecWait("kxkb");
+
+ // If previous call was valid, try to change layout
+ if ( reply.isValid() ) {
+ DCOPReply successReply = kxkbref.call( "setLayout", currentLayout );
+
+ if ( successReply.isValid() ) {
+ bool success;
+ successReply.get(success);
+
+ if ( ! success )
+ kdDebug() << "Warning: restoring previous layout failed!" << endl;
+ } else {
+ kdDebug() << "Warning: cannot restore previous layout! (invalid DCOP reply from Kxkb)" << endl;
+ }
+ }
+
+ updateHotkeyCombo();
+
emit TDECModule::changed( false );
}
@@ -347,11 +532,11 @@ void LayoutConfig::updateStickyLimit()
{
int layoutsCnt = widget->listLayoutsDst->childCount();
int maxDepth = layoutsCnt - 1;
-
+
if( maxDepth < 2 ) {
maxDepth = 2;
}
-
+
widget->spinStickyDepth->setMaxValue(maxDepth);
/* if( value > maxDepth )
setValue(maxDepth);*/
@@ -366,9 +551,6 @@ void LayoutConfig::add()
// Create a copy of the sel widget, as one might add the same layout more
// than one time, with different variants.
TQListViewItem* toadd = copyLVI(sel, widget->listLayoutsDst);
-
- // Turn on "Include Latin layout" for new language by default (bnc:204402)
- toadd->setText(LAYOUT_COLUMN_INCLUDE, "us");
widget->listLayoutsDst->insertItem(toadd);
if( widget->listLayoutsDst->childCount() > 1 )
@@ -376,12 +558,12 @@ void LayoutConfig::add()
// disabling temporary: does not work reliable in Qt :(
// widget->listLayoutsDst->setSelected(sel, true);
// layoutSelChanged(sel);
-
+
updateStickyLimit();
changed();
}
-void LayoutConfig::remove()
+void LayoutConfig::remove()
{
TQListViewItem* sel = widget->listLayoutsDst->selectedItem();
TQListViewItem* newSel = 0;
@@ -430,17 +612,18 @@ void LayoutConfig::moveDown()
void LayoutConfig::variantChanged()
{
- TQListViewItem* selLayout = widget->listLayoutsDst->selectedItem();
- if( selLayout == NULL ) {
- widget->comboVariant->clear();
- widget->comboVariant->setEnabled(false);
- return;
- }
+ TQListViewItem* selLayout = widget->listLayoutsDst->selectedItem();
+ if( selLayout == NULL ) {
+ widget->comboVariant->clear();
+ widget->comboVariant->setEnabled(false);
+ return;
+ }
TQString selectedVariant = widget->comboVariant->currentText();
if( selectedVariant == DEFAULT_VARIANT_NAME )
selectedVariant = "";
selLayout->setText(LAYOUT_COLUMN_VARIANT, selectedVariant);
+ updateLayoutCommand();
}
// helper
@@ -456,15 +639,15 @@ void LayoutConfig::displayNameChanged(const TQString& newDisplayName)
TQListViewItem* selLayout = widget->listLayoutsDst->selectedItem();
if( selLayout == NULL )
return;
-
+
const LayoutUnit layoutUnitKey = getLayoutUnitKey( selLayout );
LayoutUnit& layoutUnit = *m_kxkbConfig.m_layouts.find(layoutUnitKey);
-
+
TQString oldName = selLayout->text(LAYOUT_COLUMN_DISPLAY_NAME);
-
+
if( oldName.isEmpty() )
oldName = KxkbConfig::getDefaultDisplayName( layoutUnit );
-
+
if( oldName != newDisplayName ) {
kdDebug() << "setting label for " << layoutUnit.toPair() << " : " << newDisplayName << endl;
selLayout->setText(LAYOUT_COLUMN_DISPLAY_NAME, newDisplayName);
@@ -479,33 +662,10 @@ void LayoutConfig::updateIndicator(TQListViewItem* selLayout)
{
}
-
-void LayoutConfig::latinChanged()
-{
- TQListViewItem* selLayout = widget->listLayoutsDst->selectedItem();
- if ( !selLayout ) {
- widget->chkLatin->setChecked( false );
- widget->chkLatin->setEnabled( false );
- return;
- }
-
- TQString include;
- if( widget->chkLatin->isChecked() )
- include = "us";
- else
- include = "";
- selLayout->setText(LAYOUT_COLUMN_INCLUDE, include);
-
- LayoutUnit layoutUnitKey = getLayoutUnitKey(selLayout);
- kdDebug() << "layout " << layoutUnitKey.toPair() << ", inc: " << include << endl;
-}
-
void LayoutConfig::layoutSelChanged(TQListViewItem *sel)
{
widget->comboVariant->clear();
widget->comboVariant->setEnabled( sel != NULL );
- widget->chkLatin->setChecked( false );
- widget->chkLatin->setEnabled( sel != NULL );
if( sel == NULL ) {
updateLayoutCommand();
@@ -516,28 +676,13 @@ void LayoutConfig::layoutSelChanged(TQListViewItem *sel)
LayoutUnit layoutUnitKey = getLayoutUnitKey(sel);
TQString kbdLayout = layoutUnitKey.layout;
- // TODO: need better algorithm here for determining if needs us group
- if ( ! m_rules->isSingleGroup(kbdLayout)
- || kbdLayout.startsWith("us") || kbdLayout.startsWith("en") ) {
- widget->chkLatin->setEnabled( false );
- }
- else {
- TQString inc = sel->text(LAYOUT_COLUMN_INCLUDE);
- if ( inc.startsWith("us") || inc.startsWith("en") ) {
- widget->chkLatin->setChecked(true);
- }
- else {
- widget->chkLatin->setChecked(false);
- }
- }
-
TQStringList vars = m_rules->getAvailableVariants(kbdLayout);
kdDebug() << "layout " << kbdLayout << " has " << vars.count() << " variants" << endl;
-
+
if( vars.count() > 0 ) {
vars.prepend(DEFAULT_VARIANT_NAME);
widget->comboVariant->insertStringList(vars);
-
+
TQString variant = sel->text(LAYOUT_COLUMN_VARIANT);
if( variant != NULL && variant.isEmpty() == false ) {
widget->comboVariant->setCurrentText(variant);
@@ -558,13 +703,13 @@ TQWidget* LayoutConfig::makeOptionsTab()
listView->setColumnText( 0, i18n( "Options" ) );
listView->clear();
- connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(changed()));
- connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(updateOptionsCommand()));
-
- connect(widget->chkEnableOptions, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed()));
+ connect(listView, TQ_SIGNAL(clicked(TQListViewItem *)), TQ_SLOT(changed()));
+ connect(listView, TQ_SIGNAL(clicked(TQListViewItem *)), TQ_SLOT(resolveConflicts(TQListViewItem *)));
+ connect(listView, TQ_SIGNAL(clicked(TQListViewItem *)), TQ_SLOT(updateHotkeyCombo()));
- connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed()));
- connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateOptionsCommand()));
+ connect(widget->xkbOptsMode, TQ_SIGNAL(released(int)), TQ_SLOT(changed()));
+ connect(widget->xkbOptsMode, TQ_SIGNAL(released(int)), TQ_SLOT(updateOptionsCommand()));
+ connect(widget->xkbOptsMode, TQ_SIGNAL(released(int)), TQ_SLOT(updateHotkeyCombo()));
//Create controllers for all options
TQDictIterator<char> it(m_rules->options());
@@ -574,19 +719,26 @@ TQWidget* LayoutConfig::makeOptionsTab()
if (!it.currentKey().contains(':'))
{
if( it.currentKey() == "ctrl" || it.currentKey() == "caps"
- || it.currentKey() == "altwin" ) {
- parent = new OptionListItem(listView, i18n( it.current() ),
+ || it.currentKey() == "altwin") {
+ parent = new OptionListItem(listView, XkbRules::trOpt( it.current() ),
TQCheckListItem::RadioButtonController, it.currentKey());
OptionListItem *item = new OptionListItem(parent, i18n( "None" ),
TQCheckListItem::RadioButton, "none");
item->setState(TQCheckListItem::On);
}
+ else if (it.currentKey() == "grp") {
+ parent = new OptionListItem(listView, XkbRules::trOpt(it.current()),
+ TQCheckListItem::RadioButtonController, it.currentKey());
+ parent->setSelectable(false);
+ OptionListItem *item = new OptionListItem(parent, i18n("None"),
+ TQCheckListItem::CheckBox, "grp:none");
+ }
else {
- parent = new OptionListItem(listView, i18n( it.current() ),
+ parent = new OptionListItem(listView, XkbRules::trOpt( it.current() ),
TQCheckListItem::CheckBoxController, it.currentKey());
}
parent->setOpen(true);
- m_optionGroups.insert(i18n(it.currentKey().local8Bit()), parent);
+ m_optionGroups.insert(it.currentKey(), parent);
}
}
@@ -604,12 +756,13 @@ TQWidget* LayoutConfig::makeOptionsTab()
// workaroung for mistake in rules file for xkb options in XFree 4.2.0
TQString text(it.current());
text = text.replace( "Cap$", "Caps." );
- if( parent->type() == TQCheckListItem::RadioButtonController )
- new OptionListItem(parent, i18n(text.utf8()),
- TQCheckListItem::RadioButton, key);
- else
- new OptionListItem(parent, i18n(text.utf8()),
+ if ( parent->type() == TQCheckListItem::CheckBoxController
+ || key.startsWith("grp:"))
+ new OptionListItem(parent, XkbRules::trOpt(text),
TQCheckListItem::CheckBox, key);
+ else
+ new OptionListItem(parent, XkbRules::trOpt(text),
+ TQCheckListItem::RadioButton, key);
}
}
}
@@ -619,68 +772,369 @@ TQWidget* LayoutConfig::makeOptionsTab()
return listView;
}
+TQWidget* LayoutConfig::makeShortcutsTab() {
+ m_keyChooser = new KKeyChooser(keys, widget->tabShortcuts, false, false);
+ connect(m_keyChooser, TQ_SIGNAL(keyChange()), this, TQ_SLOT(changed()));
+ widget->tabShortcuts->layout()->add(m_keyChooser);
+ return m_keyChooser;
+}
+
void LayoutConfig::updateOptionsCommand()
{
TQString setxkbmap;
TQString options = createOptionString();
+ bool overwrite = widget->radXkbOverwrite->isOn();
if( !options.isEmpty() ) {
setxkbmap = "setxkbmap -option "; //-rules " + m_rule
- if( widget->checkResetOld->isChecked() )
+ if (overwrite)
setxkbmap += "-option ";
setxkbmap += options;
}
+ else if (overwrite) {
+ setxkbmap = "setxkbmap -option";
+ }
widget->editCmdLineOpt->setText(setxkbmap);
+ widget->editCmdLineOpt->setDisabled(setxkbmap.isEmpty());
}
void LayoutConfig::updateLayoutCommand()
{
- TQString setxkbmap;
- TQString layoutDisplayName;
- TQListViewItem* sel = widget->listLayoutsDst->selectedItem();
-
- if( sel != NULL ) {
- TQString kbdLayout = sel->text(LAYOUT_COLUMN_MAP);
- TQString variant = widget->comboVariant->currentText();
- if( variant == DEFAULT_VARIANT_NAME )
- variant = "";
-
- setxkbmap = "setxkbmap"; //-rules " + m_rule
- setxkbmap += " -model " + lookupLocalized(m_rules->models(), widget->comboModel->currentText())
- + " -layout ";
- setxkbmap += kbdLayout;
- if( widget->chkLatin->isChecked() )
- setxkbmap += ",us";
-
-/* LayoutUnit layoutUnitKey = getLayoutUnitKey(sel);
- layoutDisplayName = m_kxkbConfig.getLayoutDisplayName( *m_kxkbConfig.m_layouts.find(layoutUnitKey) );*/
- layoutDisplayName = sel->text(LAYOUT_COLUMN_DISPLAY_NAME);
- if( layoutDisplayName.isEmpty() ) {
- int count = 0;
- TQListViewItem *item = widget->listLayoutsDst->firstChild();
- while (item) {
- TQString layout_ = item->text(LAYOUT_COLUMN_MAP);
- if( layout_ == kbdLayout )
- ++count;
- item = item->nextSibling();
- }
- bool single = count < 2;
- layoutDisplayName = m_kxkbConfig.getDefaultDisplayName(LayoutUnit(kbdLayout, variant), single);
- }
- kdDebug() << "disp: '" << layoutDisplayName << "'" << endl;
-
- if( !variant.isEmpty() ) {
- setxkbmap += " -variant ";
- if( widget->chkLatin->isChecked() )
- setxkbmap += ",";
- setxkbmap += variant;
+ TQString setxkbmap = "setxkbmap";
+ setxkbmap += " -model " + lookupLocalized(m_rules->models(),
+ widget->comboModel->currentText());
+ TQStringList layoutCodes;
+ TQStringList layoutVariants;
+ TQListViewItem *item = widget->listLayoutsDst->firstChild();
+ while (item) {
+ layoutCodes << item->text(LAYOUT_COLUMN_MAP);
+
+ TQString layoutVariant = item->text(LAYOUT_COLUMN_VARIANT);
+ if (layoutVariant == DEFAULT_VARIANT_NAME) {
+ layoutVariant = "";
}
+ layoutVariants << layoutVariant;
+
+ item = item->nextSibling();
}
-
+
+ setxkbmap += " -layout " + layoutCodes.join(",");
+
+ if( !layoutVariants.isEmpty() ) {
+ setxkbmap += " -variant " + layoutVariants.join(",");
+ }
+
widget->editCmdLine->setText(setxkbmap);
-
+
+ /* update display name field */
+ TQListViewItem *sel = widget->listLayoutsDst->selectedItem();
+ if (!sel) {
+ return;
+ }
+ TQString selLayoutCode = sel->text(LAYOUT_COLUMN_MAP);
+ TQString selLayoutVariant = widget->comboVariant->currentText();
+ TQString selDisplayName = sel->text(LAYOUT_COLUMN_DISPLAY_NAME);
+ if (selDisplayName.isEmpty()) {
+ int count = 0;
+ TQListViewItem *item = widget->listLayoutsDst->firstChild();
+ while (item) {
+ TQString layoutCode_ = item->text(LAYOUT_COLUMN_MAP);
+ if (layoutCode_ == selLayoutCode) {
+ ++count;
+ }
+ item = item->nextSibling();
+ }
+ bool single = count < 2;
+ selDisplayName = m_kxkbConfig.getDefaultDisplayName(LayoutUnit(selLayoutCode, selLayoutVariant), single);
+ }
+
widget->editDisplayName->setEnabled( sel != NULL );
- widget->editDisplayName->setText(layoutDisplayName);
+ widget->editDisplayName->setText(selDisplayName);
+}
+
+void LayoutConfig::checkConflicts(OptionListItem *current,
+ TQStringList conflicting,
+ TQStringList &conflicts)
+{
+ if (!current || conflicting.count() < 2 ||
+ !conflicting.contains(current->optionName()))
+ {
+ return;
+ }
+ TQStringList::Iterator it;
+ for (it = conflicting.begin(); it != conflicting.end(); ++it) {
+ TQString option(*it);
+ if (option == current->optionName()) {
+ continue;
+ }
+
+ OptionListItem *item = itemForOption(option);
+ if (item && item->isOn()) {
+ conflicts << item->text();
+ }
+ }
+}
+
+void LayoutConfig::resolveConflicts(TQListViewItem *lvi) {
+ OptionListItem *current = (OptionListItem*)lvi;
+
+ kdDebug() << "resolveConflicts : " << current->optionName() << endl;
+
+ if (current->optionName().startsWith("grp:")) {
+ OptionListItem *grpItem = m_optionGroups["grp"];
+ if (grpItem == NULL) {
+ kdWarning() << "LayoutConfig: cannot find grp item group" << endl;
+ return;
+ }
+
+ OptionListItem *noneItem = grpItem->findChildItem("grp:none");
+ if (!noneItem) {
+ kdDebug() << "LayoutConfig: unable to find None item for grp!" << endl;
+ }
+ else {
+ // Option "none" selected, uncheck all other options immediately
+ if (current->optionName() == "grp:none") {
+ if (current->isOn()) {
+ OptionListItem *child = (OptionListItem*)grpItem->firstChild();
+ while (child) {
+ if (child != current) {
+ child->setOn(false);
+ }
+ child = (OptionListItem*)child->nextSibling();
+ }
+ }
+ else {
+ current->setOn(true);
+ }
+ updateOptionsCommand();
+ return;
+ }
+
+ // If no options are selected then select "none"
+ bool notNone = false;
+ OptionListItem *child = (OptionListItem*)grpItem->firstChild();
+ while (child) {
+ if (child->isOn() && child->optionName() != "none") {
+ notNone = true;
+ break;
+ }
+ child = (OptionListItem*)child->nextSibling();
+ }
+
+ noneItem->setOn(!notNone);
+ }
+ }
+
+ TQStringList conflicts;
+ OptionListItem *conflict;
+
+ TQStringList conflicting;
+ /* Might be incomplete */
+ // Space
+ conflicting << "grp:win_space_toggle"
+ << "grp:alt_space_toggle"
+ << "grp:ctrl_space_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Shift
+ conflicting.clear();
+ conflicting << "grp:ctrl_shift_toggle"
+ << "grp:alt_shift_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Control
+ conflicting.clear();
+ conflicting << "grp:ctrl_select"
+ << "grp:ctrl_alt_toggle"
+ << "grp:ctrl_shift_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Left Ctrl
+ conflicting.clear();
+ conflicting << "grp:lctrl_toggle"
+ << "grp:lctrl_lshift_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Right Ctrl
+ conflicting.clear();
+ conflicting << "grp:rctrl_toggle"
+ << "grp:rctrl_rshift_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Win
+ conflicting.clear();
+ conflicting << "grp:win_space_toggle"
+ << "grp:win_switch"
+ << "win_menu_select";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Left Alt
+ conflicting.clear();
+ conflicting << "grp:lalt_toggle"
+ << "grp:lalt_lshift_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Right Alt
+ conflicting.clear();
+ conflicting << "grp:ralt_toggle"
+ << "grp:ralt_rshift_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ // Caps Lock
+ conflicting.clear();
+ conflicting << "grp:caps_toggle"
+ << "grp:caps_select"
+ << "grp:caps_switch"
+ << "grp:alt_caps_toggle";
+ checkConflicts(current, conflicting, conflicts);
+
+ if (conflicts.count()) {
+ TQString curText = current->text();
+ int confirm = KMessageBox::warningYesNoList(this,
+ i18n("<qt>The option <b>%1</b> might conflict with "
+ "other options that you have already enabled.<br>"
+ "Are you sure that you really want to enable "
+ "<b>%2</b>?</qt>")
+ .arg(curText).arg(curText),
+ conflicts,
+ i18n("Conflicting options"));
+ if (confirm == KMessageBox::No) {
+ current->setOn(false);
+ }
+ }
+ updateOptionsCommand();
+}
+
+// Synchronizes Xkb grp options --> hotkeys combobox
+void LayoutConfig::updateHotkeyCombo() {
+ updateHotkeyCombo(false);
+}
+
+void LayoutConfig::updateHotkeyCombo(bool initial) {
+ OptionListItem *grpItem = m_optionGroups["grp"];
+ if (grpItem == NULL) {
+ kdWarning() << "LayoutConfig: cannot find grp item group" << endl;
+ return;
+ }
+
+ TQStringList hotkeys;
+
+ // Get server options first
+ if (initial || widget->xkbOptsMode->selectedId() == 1)
+ {
+ XkbOptions _opt = XKBExtension::the()->getServerOptions();
+ TQStringList opts = TQStringList::split(",", _opt.options);
+ for (TQStringList::Iterator it = opts.begin(); it != opts.end(); ++it)
+ {
+ TQString option(*it);
+
+ if (!option.startsWith("grp:"))
+ {
+ continue;
+ }
+
+ // Get description from existing item
+ // This spares us the trouble of querying Xkb rules second time
+ OptionListItem *item = itemForOption(option);
+ if (!item)
+ {
+ kdWarning() << "[updateHotkeyCombo] server has set unknown option: "
+ << option << endl;
+ continue;
+ }
+
+ TQString optionName = item->text();
+ if (!hotkeys.contains(optionName) && option != "grp:none")
+ {
+ hotkeys << optionName;
+ }
+ }
+ }
+
+ OptionListItem *child = (OptionListItem*)grpItem->firstChild();
+ while (child) {
+ TQString optionText = child->text();
+ if (child->isOn() && !hotkeys.contains(optionText) && child->optionName() != "grp:none") {
+ hotkeys << optionText;
+ }
+ child = (OptionListItem*)child->nextSibling();
+ }
+
+ if (!hotkeys.count()) {
+ OptionListItem *noneItem = itemForOption("grp:none");
+ if (noneItem)
+ {
+ hotkeys << noneItem->text();
+ }
+ else
+ {
+ kdWarning() << "[updateHotkeyCombo] cannot find grp:none item!" << endl;
+ hotkeys << widget->comboHotkey->text(0); // fallback
+ }
+ }
+
+ int other = widget->comboHotkey->count() - 1;
+ widget->comboHotkey->changeItem(i18n("Custom..."), other);
+ if (hotkeys.count() < 2) {
+ bool found = false;
+ for (int i = 0; i < widget->comboHotkey->count(); ++i) {
+ if (hotkeys[0] == widget->comboHotkey->text(i)) {
+ widget->comboHotkey->setCurrentItem(i);
+ found = true;
+ }
+ }
+ if (!found) {
+ widget->comboHotkey->changeItem(i18n("Other (%1)").arg(hotkeys[0]),
+ other);
+ widget->comboHotkey->setCurrentItem(other);
+ }
+ }
+ else {
+ widget->comboHotkey->changeItem(i18n("Multiple (%1)").arg(hotkeys.join("; ")),
+ other);
+ widget->comboHotkey->setCurrentItem(other);
+ }
+}
+
+// Synchronizes hotkeys combobox --> Xkb grp options
+void LayoutConfig::hotkeyComboChanged() {
+ TQStringList hotkeys;
+ int other = widget->comboHotkey->count() - 1;
+
+ if (widget->comboHotkey->currentItem() != other) {
+ hotkeys << widget->comboHotkey->currentText();
+ }
+ else {
+ TQString otherStr = widget->comboHotkey->text(other);
+ int i1 = otherStr.find("(");
+ if (i1 != -1) { // custom hotkey(s) set
+ ++i1;
+ int i2 = otherStr.findRev(")");
+ if (i2 != -1) {
+ hotkeys = TQStringList::split("; ", otherStr.mid(i1, i2-i1));
+ }
+ }
+ }
+
+ OptionListItem *grpItem = m_optionGroups["grp"];
+ if (grpItem == NULL) {
+ kdWarning() << "LayoutConfig: cannot find grp item group" << endl;
+ return;
+ }
+
+ OptionListItem *child = (OptionListItem*)grpItem->firstChild();
+ while (child) {
+ child->setOn(hotkeys.contains(child->text()));
+ child = (OptionListItem*)child->nextSibling();
+ }
+
+ if (widget->comboHotkey->currentItem() == other) {
+ widget->tabWidget->setCurrentPage(4);
+ widget->listOptions->ensureItemVisible(grpItem);
+ widget->listOptions->setFocus();
+ }
+
+ m_forceGrpOverwrite = true;
}
void LayoutConfig::changed()
@@ -704,7 +1158,7 @@ void LayoutConfig::loadRules()
++it;
}
modelsList.sort();
-
+
widget->comboModel->clear();
widget->comboModel->insertStringList(modelsList);
widget->comboModel->setCurrentItem(0);
@@ -713,23 +1167,37 @@ void LayoutConfig::loadRules()
widget->listLayoutsSrc->clear();
widget->listLayoutsDst->clear();
TQDictIterator<char> it2(m_rules->layouts());
-
+
while (it2.current())
{
TQString layout = it2.currentKey();
TQString layoutName = it2.current();
TQListViewItem *item = new TQListViewItem(widget->listLayoutsSrc);
-
- item->setPixmap(LAYOUT_COLUMN_FLAG, LayoutIcon::getInstance().findPixmap(layout, true));
+
+ item->setPixmap(LAYOUT_COLUMN_FLAG, m_icoMgr->find(layout, PIXMAP_STYLE_CONTEXTMENU));
item->setText(LAYOUT_COLUMN_NAME, i18n(layoutName.latin1()));
item->setText(LAYOUT_COLUMN_MAP, layout);
++it2;
}
widget->listLayoutsSrc->setSorting(LAYOUT_COLUMN_NAME); // from Qt3 TQListView sorts by language
-
+
//TODO: reset options and xkb options
}
+OptionListItem* LayoutConfig::itemForOption(TQString option) {
+ if (!option.contains(':')) {
+ return nullptr;
+ }
+
+ TQString optionKey = option.mid(0, option.find(':'));
+ OptionListItem *item = m_optionGroups[optionKey];
+
+ if( !item ) {
+ kdDebug() << "WARNING: skipping empty group for " << option << endl;
+ return nullptr;
+ }
+ return (OptionListItem*)item->findChildItem(option);
+}
TQString LayoutConfig::createOptionString()
{
@@ -737,32 +1205,17 @@ TQString LayoutConfig::createOptionString()
for (TQDictIterator<char> it(m_rules->options()); it.current(); ++it)
{
TQString option(it.currentKey());
-
- if (option.contains(':')) {
-
- TQString optionKey = option.mid(0, option.find(':'));
- OptionListItem *item = m_optionGroups[optionKey];
-
- if( !item ) {
- kdDebug() << "WARNING: skipping empty group for " << it.currentKey()
- << endl;
- continue;
- }
-
- OptionListItem *child = item->findChildItem( option );
-
- if ( child ) {
- if ( child->state() == TQCheckListItem::On ) {
- TQString selectedName = child->optionName();
- if ( !selectedName.isEmpty() && selectedName != "none" ) {
- if (!options.isEmpty())
- options.append(',');
- options.append(selectedName);
- }
- }
+ OptionListItem *child = itemForOption(option);
+ if (!child) {
+ continue;
+ }
+ if ( child->state() == TQCheckListItem::On ) {
+ TQString selectedName = child->optionName();
+ if ( !selectedName.isEmpty() && selectedName != "none" ) {
+ if (!options.isEmpty())
+ options.append(',');
+ options.append(selectedName);
}
- else
- kdDebug() << "Empty option button for group " << it.currentKey() << endl;
}
}
return options;
@@ -809,33 +1262,29 @@ OptionListItem * OptionListItem::findChildItem( const TQString& optionName )
extern "C"
{
- KDE_EXPORT TDECModule *create_keyboard_layout(TQWidget *parent, const char *)
+ TDE_EXPORT TDECModule *create_keyboard_layout(TQWidget *parent, const char *)
{
return new LayoutConfig(parent, "kcmlayout");
}
-
- KDE_EXPORT TDECModule *create_keyboard(TQWidget *parent, const char *)
+
+ TDE_EXPORT TDECModule *create_keyboard(TQWidget *parent, const char *)
{
return new KeyboardConfig(parent, "kcmlayout");
}
-
- KDE_EXPORT void init_keyboard()
+
+ TDE_EXPORT void init_keyboard()
{
KeyboardConfig::init_keyboard();
-
+
KxkbConfig m_kxkbConfig;
m_kxkbConfig.load(KxkbConfig::LOAD_INIT_OPTIONS);
-
+
if( m_kxkbConfig.m_useKxkb == true ) {
- kapp->startServiceByDesktopName("kxkb");
+ tdeApp->startServiceByDesktopName("kxkb");
}
else {
- // Even if the layouts have been disabled we still want to set Xkb options
- // user can always switch them off now in the "Options" tab
- if( m_kxkbConfig.m_enableXkbOptions ) {
- if( !XKBExtension::setXkbOptions(m_kxkbConfig.m_options, m_kxkbConfig.m_resetOldOptions) ) {
- kdDebug() << "Setting XKB options failed!" << endl;
- }
+ if (!XKBExtension::the()->setXkbOptions(m_kxkbConfig.getKXkbOptions())) {
+ kdDebug() << "Setting XKB options failed!" << endl;
}
}
}
@@ -916,10 +1365,10 @@ extern "C"
I18N_NOOP( "Left Alt key changes group" );
I18N_NOOP( "Left Ctrl key changes group" );
I18N_NOOP( "Compose Key" );
-
+
//these seem to be new in XFree86 4.4.0
I18N_NOOP("Shift with numpad keys works as in MS Windows.");
- I18N_NOOP("Special keys (Ctrl+Alt+<key>) handled in a server.");
+ I18N_NOOP("Special keys (Ctrl+Alt+&lt;key&gt;) handled in a server.");
I18N_NOOP("Miscellaneous compatibility options");
I18N_NOOP("Right Control key works as Right Alt");
diff --git a/kxkb/kcmlayout.h b/kxkb/kcmlayout.h
index 987fff2b0..0d2e153b2 100644
--- a/kxkb/kcmlayout.h
+++ b/kxkb/kcmlayout.h
@@ -11,52 +11,66 @@
class OptionListItem;
+class LayoutIconManager;
class LayoutConfigWidget;
class XkbRules;
class LayoutConfig : public TDECModule
{
- Q_OBJECT
+ TQ_OBJECT
public:
LayoutConfig(TQWidget *parent = 0L, const char *name = 0L);
virtual ~LayoutConfig();
+ void initUI(bool modified = false);
+ virtual TQString handbookDocPath() const;
+
+public slots:
void load();
void save();
void defaults();
- void initUI();
- virtual TQString handbookDocPath() const;
-
+
protected:
TQString createOptionString();
void updateIndicator(TQListViewItem* selLayout);
+ OptionListItem* itemForOption(TQString option);
protected slots:
void moveUp();
void moveDown();
+ void hotkeyComboChanged();
void variantChanged();
void displayNameChanged(const TQString& name);
- void latinChanged();
void layoutSelChanged(TQListViewItem *);
void loadRules();
void updateLayoutCommand();
void updateOptionsCommand();
+ void updateHotkeyCombo();
+ void updateHotkeyCombo(bool initial);
void add();
void remove();
+ void resolveConflicts(TQListViewItem *lvi);
void changed();
private:
+ LayoutIconManager *m_icoMgr;
LayoutConfigWidget* widget;
XkbRules *m_rules;
KxkbConfig m_kxkbConfig;
TQDict<OptionListItem> m_optionGroups;
+ bool m_forceGrpOverwrite;
+ KKeyChooser *m_keyChooser;
+ TDEGlobalAccel *keys;
TQWidget* makeOptionsTab();
+ TQWidget* makeShortcutsTab();
void updateStickyLimit();
static LayoutUnit getLayoutUnitKey(TQListViewItem *sel);
+ void checkConflicts(OptionListItem *current, TQStringList conflicting,
+ TQStringList &conflicts);
};
diff --git a/kxkb/kcmlayoutwidget.ui b/kxkb/kcmlayoutwidget.ui
index 2830c10e9..52cab2e88 100644
--- a/kxkb/kcmlayoutwidget.ui
+++ b/kxkb/kcmlayoutwidget.ui
@@ -8,8 +8,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>709</width>
- <height>563</height>
+ <width>700</width>
+ <height>600</height>
</rect>
</property>
<property name="sizePolicy">
@@ -22,8 +22,8 @@
</property>
<property name="minimumSize">
<size>
- <width>600</width>
- <height>510</height>
+ <width>700</width>
+ <height>600</height>
</size>
</property>
<grid>
@@ -76,7 +76,7 @@
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="TQLabel" row="2" column="0" rowspan="1" colspan="2">
+ <widget class="TQLabel" row="0" column="0" rowspan="1" colspan="2">
<property name="name">
<cstring>textLabel1_4</cstring>
</property>
@@ -86,7 +86,7 @@
</widget>
<widget class="TQLabel" row="2" column="2" rowspan="1" colspan="3">
<property name="name">
- <cstring>textLabel1_4_2</cstring>
+ <cstring>labelLayouts</cstring>
</property>
<property name="text">
<string>Active layouts:</string>
@@ -94,7 +94,7 @@
</widget>
<widget class="TQLabel" row="0" column="2" rowspan="1" colspan="3">
<property name="name">
- <cstring>textLabel1_2</cstring>
+ <cstring>labelModel</cstring>
</property>
<property name="text">
<string>Keyboard &amp;model:</string>
@@ -167,17 +167,6 @@
</column>
<column>
<property name="text">
- <string>5</string>
- </property>
- <property name="clickable">
- <bool>false</bool>
- </property>
- <property name="resizable">
- <bool>false</bool>
- </property>
- </column>
- <column>
- <property name="text">
<string>Label</string>
</property>
<property name="clickable">
@@ -266,7 +255,7 @@
<cstring>editCmdLine</cstring>
</property>
</widget>
- <widget class="TQListView" row="3" column="0" rowspan="5" colspan="2">
+ <widget class="TQListView" row="1" column="0" rowspan="6" colspan="2">
<column>
<property name="text">
<string></string>
@@ -327,20 +316,6 @@
<string>This is the command which is executed when switching to the selected layout. It may help you if you want to debug layout switching, or if you want to switch layouts without the help of TDE.</string>
</property>
</widget>
- <widget class="TQCheckBox" row="7" column="2" rowspan="1" colspan="3">
- <property name="name">
- <cstring>chkLatin</cstring>
- </property>
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>Include latin layout</string>
- </property>
- <property name="whatsThis" stdset="0">
- <string>If after you switch to this layout some keyboard shortcuts based on latin keys do not work try to enable this option.</string>
- </property>
- </widget>
<widget class="TQLabel" row="6" column="2">
<property name="name">
<cstring>textLabel1_6</cstring>
@@ -423,35 +398,68 @@
</widget>
<widget class="TQWidget">
<property name="name">
- <cstring>tab</cstring>
+ <cstring>tabShortcuts</cstring>
</property>
<attribute name="title">
- <string>Switching Options</string>
+ <string>Keyboard Shortcuts</string>
</attribute>
- <grid>
- <property name="name">
- <cstring>unnamed</cstring>
- </property>
- <spacer row="1" column="0">
+ <vbox>
+ <widget class="TQLabel">
<property name="name">
- <cstring>spacer1</cstring>
+ <cstring>labelHotkey</cstring>
</property>
- <property name="orientation">
- <enum>Vertical</enum>
+ <property name="text">
+ <string>&lt;qt&gt;&lt;b&gt;Key combination to switch layout (X11):&lt;/b&gt;&lt;/qt&gt;</string>
</property>
- <property name="sizeType">
- <enum>Expanding</enum>
+ <property name="buddy" stdset="0">
+ <cstring>comboHotkey</cstring>
</property>
- <property name="sizeHint">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
+ </widget>
+ <widget class="TQComboBox">
+ <property name="name">
+ <cstring>comboHotkey</cstring>
</property>
- </spacer>
- <widget class="TQFrame" row="0" column="0">
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here you can choose the key combination you want to use to switch to the next layout. This list includes only the most common variants. If you choose "Other...", then you will be redirected to the "Options" tab where you can pick from all the available variants. Note that if you have selected Append Mode in the Xkb Options tab this option is not available; you have to use the Xkb Options tab instead.</string>
+ </property>
+ </widget>
+ <widget class="KSeparator">
<property name="name">
- <cstring>optionsFrame</cstring>
+ <cstring>switchingGrpSeparator</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>labelHotkey</cstring>
+ </property>
+ <property name="text">
+ <string>&lt;qt&gt;&lt;b&gt;TDE shortcuts to switch layout:&lt;/b&gt;&lt;/qt&gt;</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>comboHotkey</cstring>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Switching Options</string>
+ </attribute>
+ <vbox>
+ <widget class="TQFrame">
+ <property name="name">
+ <cstring>swOptsFrame</cstring>
</property>
<property name="frameShape">
<enum>StyledPanel</enum>
@@ -462,11 +470,8 @@
<property name="lineWidth">
<number>0</number>
</property>
- <grid>
- <property name="name">
- <cstring>unnamed</cstring>
- </property>
- <widget class="TQButtonGroup" row="2" column="0">
+ <vbox>
+ <widget class="TQButtonGroup">
<property name="name">
<cstring>grpSwitching</cstring>
</property>
@@ -512,21 +517,7 @@
</widget>
</vbox>
</widget>
- <widget class="TQCheckBox" row="1" column="0" rowspan="1" colspan="2">
- <property name="name">
- <cstring>chkShowFlag</cstring>
- </property>
- <property name="text">
- <string>Show country flag</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- <property name="whatsThis" stdset="0">
- <string>Shows country flag on background of layout name in tray icon</string>
- </property>
- </widget>
- <widget class="TQGroupBox" row="2" column="1">
+ <widget class="TQGroupBox">
<property name="name">
<cstring>grpBoxStickySwitching</cstring>
</property>
@@ -537,7 +528,7 @@
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="TQCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <widget class="TQCheckBox" row="0" column="0" rowspan="1" colspan="3">
<property name="name">
<cstring>chkEnableSticky</cstring>
</property>
@@ -548,7 +539,41 @@
<string>If you have more than two layouts and turn this option on, switching with the keyboard shortcut or clicking on the kxkb indicator will only cycle through the last few layouts. You can specify the number of layouts to rotate below. You can still access all layouts by right-clicking on the kxkb indicator.</string>
</property>
</widget>
- <widget class="TQLabel" row="1" column="0">
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="1" column="1">
<property name="name">
<cstring>textLabel1_5</cstring>
</property>
@@ -562,7 +587,7 @@
<cstring>spinBox1</cstring>
</property>
</widget>
- <widget class="TQSpinBox" row="1" column="1">
+ <widget class="TQSpinBox" row="1" column="2">
<property name="name">
<cstring>spinStickyDepth</cstring>
</property>
@@ -575,20 +600,479 @@
<property name="minValue">
<number>2</number>
</property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
</widget>
</grid>
</widget>
- <widget class="TQCheckBox" row="0" column="0" rowspan="1" colspan="2">
+ <widget class="TQGroupBox">
<property name="name">
- <cstring>chkShowSingle</cstring>
+ <cstring>grpBoxNotifications</cstring>
</property>
- <property name="text">
- <string>Show indicator for single layout</string>
+ <property name="title">
+ <string>Notifications</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>chkEnableNotify</cstring>
+ </property>
+ <property name="text">
+ <string>Enable keyboard layout notification</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If this option is enabled, a little notification will pop up on the screen displaying the name of the currently selected layout whenever it changes.</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>chkNotifyUseKMilo</cstring>
+ </property>
+ <property name="text">
+ <string>Use KMilo for notifications, if available</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If this option is enabled and KMilo is available, it will be used to display the notifications instead of the standard notification system. If KMilo is not available, notifications will be showed via the standard TDE notification system.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </vbox>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
+ </widget>
+ <widget class="TQWidget">
+ <property name="name">
+ <cstring>tab</cstring>
+ </property>
+ <attribute name="title">
+ <string>Indicator Options</string>
+ </attribute>
+ <vbox>
+ <widget class="TQFrame">
+ <property name="name">
+ <cstring>indOptsFrame</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Raised</enum>
+ </property>
+ <property name="lineWidth">
+ <number>0</number>
+ </property>
+ <grid>
+ <widget class="TQButtonGroup" row="0" column="0">
+ <property name="name">
+ <cstring>grpStyle</cstring>
+ </property>
+ <property name="title">
+ <string>Indicator Style</string>
+ </property>
+ <property name="exclusive">
+ <bool>true</bool>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here you can choose the way your keyboard layout indicator will look.</string>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radFlagLabel</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Both Flag and Label</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radFlagOnly</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Flag Only</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radLabelOnly</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Label Only</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQButtonGroup" row="1" column="0" colspan="2">
+ <property name="name">
+ <cstring>grpLabel</cstring>
+ </property>
+ <property name="title">
+ <string>Label Style</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here you can choose the way the label of your keyboard layout indicator will be displayed. These options are relevant even when labels are disabled, for locales where the flag is missing.</string>
+ </property>
+ <grid>
+ <widget class="TQRadioButton" row="0" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>radLabelUseTheme</cstring>
+ </property>
+ <property name="text">
+ <string>Use &amp;theme colors</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="TQRadioButton" row="1" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>radLabelUseCustom</cstring>
+ </property>
+ <property name="text">
+ <string>Use c&amp;ustom colors</string>
+ </property>
+ <property name="checked">
+ <bool>false</bool>
+ </property>
+ </widget>
+ <widget class="TQFrame" row="2" column="0" colspan="3">
+ <property name="name">
+ <cstring>grpLabelColors</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <grid>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <spacer row="0" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="0" column="1">
+ <property name="name">
+ <cstring>labelBgColor</cstring>
+ </property>
+ <property name="text">
+ <string>Background color:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This color will be used as the indicator's background unless the indicator was set to display a flag.</string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="0" column="2">
+ <property name="name">
+ <cstring>bgColor</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This color will be used as the indicator's background unless the indicator was set to display a flag.</string>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer row="0" column="3">
+ <property name="name">
+ <cstring>spacer23</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <spacer row="1" column="0">
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Fixed</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="TQLabel" row="1" column="1">
+ <property name="name">
+ <cstring>labelFgColor</cstring>
+ </property>
+ <property name="text">
+ <string>Text color:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This color will be used to draw the language label on the indicator.</string>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="1" column="2">
+ <property name="name">
+ <cstring>fgColor</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This color will be used to draw the language label on the indicator.</string>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer row="1" column="3">
+ <property name="name">
+ <cstring>spacer23</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQCheckBox" row="4" column="0" rowspan="1" colspan="4">
+ <property name="name">
+ <cstring>chkBgTransparent</cstring>
+ </property>
+ <property name="text">
+ <string>Transparent background</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Check this to remove the indicator's background. Only applicable in "Label only" mode.</string>
+ </property>
+ </widget>
+ <widget class="KSeparator" row="5" column="0" rowspan="1" colspan="3">
+ <property name="name">
+ <cstring>separator1</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="6" column="0">
+ <property name="name">
+ <cstring>labelFontRequester</cstring>
+ </property>
+ <property name="text">
+ <string>Label font:</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>This is the font which will be used by the layout indicator to draw the label.</string>
+ </property>
+ </widget>
+ <widget class="TDEFontRequester" row="6" column="1" colspan="2">
+ <property name="name">
+ <cstring>labelFont</cstring>
+ </property>
+ </widget>
+ <widget class="TQCheckBox" row="7" column="0">
+ <property name="name">
+ <cstring>chkLabelShadow</cstring>
+ </property>
+ <property name="text">
+ <string>Enable shadow</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Draw a drop shadow behind the language label. In some cases this option can improve readability.</string>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="KColorButton" row="7" column="1">
+ <property name="name">
+ <cstring>shColor</cstring>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>The drop shadow behind the language label will be of this color.</string>
+ </property>
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <spacer row="7" column="2">
+ <property name="name">
+ <cstring>spacer23</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </grid>
+ </widget>
+ <widget class="TQButtonGroup" row="2" column="0" column="0" colspan="2">
+ <property name="name">
+ <cstring>grpFlag</cstring>
</property>
+ <property name="title">
+ <string>Flag Style</string>
+ </property>
+ <vbox>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>chkFitToBox</cstring>
+ </property>
+ <property name="text">
+ <string>Stretc&amp;h flag</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If this option is enabled, the flag will be stretched to fit the tray indicator size.</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>chkDimFlag</cstring>
+ </property>
+ <property name="text">
+ <string>Dim flag to make the label more visible</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ <widget class="TQButtonGroup" row="0" column="1">
+ <property name="name">
+ <cstring>grpMisc</cstring>
+ </property>
+ <property name="title">
+ <string>Miscellaneous</string>
+ </property>
+ <vbox>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>chkShowSingle</cstring>
+ </property>
+ <property name="text">
+ <string>Show indicator for single layout</string>
+ </property>
+ </widget>
+ <widget class="TQCheckBox">
+ <property name="name">
+ <cstring>chkBevel</cstring>
+ </property>
+ <property name="text">
+ <string>Show indicator bevel</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>If this option is enabled, the layout indicator will be drawn with a thin 3D bevel around it.</string>
+ </property>
+ </widget>
+ </vbox>
</widget>
</grid>
</widget>
- </grid>
+ <spacer>
+ <property name="name">
+ <cstring>spacer1</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>Expanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </vbox>
</widget>
<widget class="TQWidget">
<property name="name">
@@ -601,17 +1085,6 @@
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="TQCheckBox">
- <property name="name">
- <cstring>chkEnableOptions</cstring>
- </property>
- <property name="text">
- <string>&amp;Enable xkb options</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
<widget class="TQGroupBox">
<property name="name">
<cstring>groupBox3_2</cstring>
@@ -626,15 +1099,7 @@
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="TQCheckBox" row="0" column="0" rowspan="1" colspan="2">
- <property name="name">
- <cstring>checkResetOld</cstring>
- </property>
- <property name="text">
- <string>&amp;Reset old options</string>
- </property>
- </widget>
- <widget class="TQLabel" row="2" column="0">
+ <widget class="TQLabel" row="1" column="0">
<property name="name">
<cstring>textLabel1_3_2</cstring>
</property>
@@ -642,7 +1107,7 @@
<string>Command:</string>
</property>
</widget>
- <widget class="TQLineEdit" row="2" column="1">
+ <widget class="TQLineEdit" row="1" column="1">
<property name="name">
<cstring>editCmdLineOpt</cstring>
</property>
@@ -650,7 +1115,7 @@
<bool>true</bool>
</property>
</widget>
- <widget class="TQListView" row="1" column="0" rowspan="1" colspan="2">
+ <widget class="TQListView" row="0" column="0" rowspan="1" colspan="2">
<column>
<property name="text">
<string>Options</string>
@@ -668,6 +1133,41 @@
</widget>
</grid>
</widget>
+ <widget class="TQButtonGroup">
+ <property name="name">
+ <cstring>xkbOptsMode</cstring>
+ </property>
+ <property name="title">
+ <string>Options Mode</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Here you can choose how the options you select here will be applied: in addition to, or instead of existing options.</string>
+ </property>
+ <vbox>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radXkbOverwrite</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Overwrite existing options (recommended)</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Overwrite any existing Xkb options that might have been previously set by another program or from a script (e.g. via setxkbmap). This is the recommended option.</string>
+ </property>
+ </widget>
+ <widget class="TQRadioButton">
+ <property name="name">
+ <cstring>radXkbAppend</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Append to existing options</string>
+ </property>
+ <property name="whatsThis" stdset="0">
+ <string>Append the selected options to any existing Xkb options that might have been previously set by another program or from a script (e.g. via setxkbmap). Only use this if you really need to.</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
</vbox>
</widget>
</widget>
@@ -681,9 +1181,15 @@
<slot>setEnabled(bool)</slot>
</connection>
<connection>
- <sender>chkEnableOptions</sender>
+ <sender>chkEnable</sender>
<signal>toggled(bool)</signal>
- <receiver>groupBox3_2</receiver>
+ <receiver>swOptsFrame</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>chkEnable</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>indOptsFrame</receiver>
<slot>setEnabled(bool)</slot>
</connection>
<connection>
@@ -699,15 +1205,90 @@
<slot>setEnabled(bool)</slot>
</connection>
<connection>
- <sender>chkEnable</sender>
+ <sender>radLabelUseCustom</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>grpLabelColors</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>chkLabelShadow</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>shColor</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radFlagOnly</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>grpLabel</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radLabelOnly</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>chkBgTransparent</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radLabelOnly</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>bgColor</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radLabelOnly</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>labelBgColor</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radFlagLabel</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>bgColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radFlagLabel</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>labelBgColor</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>chkEnableNotify</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>chkNotifyUseKMilo</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radFlagOnly</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>grpFlag</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radFlagLabel</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>grpFlag</receiver>
+ <slot>setEnabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radLabelOnly</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>grpFlag</receiver>
+ <slot>setDisabled(bool)</slot>
+ </connection>
+ <connection>
+ <sender>radFlagLabel</sender>
<signal>toggled(bool)</signal>
- <receiver>optionsFrame</receiver>
+ <receiver>chkDimFlag</receiver>
<slot>setEnabled(bool)</slot>
</connection>
</connections>
<includes>
<include location="local" impldecl="in implementation">kiconloader.h</include>
<include location="local" impldecl="in implementation">kdialogbase.h</include>
+ <include location="local" impldecl="in implementation">kcolorbutton.h</include>
+ <include location="local" impldecl="in implementation">kseparator.h</include>
+ <include location="local" impldecl="in implementation">tdefontrequester.h</include>
</includes>
<pixmapfunction>SmallIcon</pixmapfunction>
<layoutdefaults spacing="6" margin="11"/>
diff --git a/kxkb/kcmmisc.cpp b/kxkb/kcmmisc.cpp
index 358d10450..0fb62a466 100644
--- a/kxkb/kcmmisc.cpp
+++ b/kxkb/kcmmisc.cpp
@@ -42,12 +42,13 @@
#include <knuminput.h>
#include <tdeapplication.h>
#include <tdeglobal.h>
-#include <kstandarddirs.h>
-#include <kprocess.h>
+#include <tdestandarddirs.h>
+#include <tdeprocess.h>
#include <kdialog.h>
#include "kcmmisc.h"
#include "kcmmiscwidget.h"
+#include "x11helper.h"
#include <X11/Xlib.h>
KeyboardConfig::KeyboardConfig (TQWidget * parent, const char *)
@@ -60,25 +61,27 @@ KeyboardConfig::KeyboardConfig (TQWidget * parent, const char *)
lay->addStretch();
ui->click->setRange(0, 100, 10);
- ui->delay->setRange(100, 5000, 50, false);
+ ui->delay->setRange(0, 5000, 10, false);
ui->rate->setRange(5, 50, 5, false);
- ui->delaySlider->setRange(1000, 50000);
+ // Values multiplied by 10 compated to the integer input field
+ ui->delaySlider->setRange(0, 50000);
ui->delaySlider->setSteps(50, 500);
ui->delaySlider->setTickInterval(2500);
+ // Values multiplied by 100 compated to the integer input field
ui->rateSlider->setRange(500, 5000);
- ui->rateSlider->setSteps(50, 500);
+ ui->rateSlider->setSteps(100, 500);
ui->rateSlider->setTickInterval(500);
- connect(ui->repeatBox, TQT_SIGNAL(clicked()), this, TQT_SLOT(changed()));
- connect(ui->delay, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(delaySpinboxChanged(int)));
- connect(ui->delaySlider, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(delaySliderChanged(int)));
- connect(ui->rate, TQT_SIGNAL(valueChanged(double)), this, TQT_SLOT(rateSpinboxChanged(double)));
- connect(ui->rateSlider, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(rateSliderChanged(int)));
+ connect(ui->repeatBox, TQ_SIGNAL(clicked()), this, TQ_SLOT(changed()));
+ connect(ui->delay, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(delaySpinboxChanged(int)));
+ connect(ui->delaySlider, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(delaySliderChanged(int)));
+ connect(ui->rate, TQ_SIGNAL(valueChanged(double)), this, TQ_SLOT(rateSpinboxChanged(double)));
+ connect(ui->rateSlider, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(rateSliderChanged(int)));
- connect(ui->click, TQT_SIGNAL(valueChanged(int)), this, TQT_SLOT(changed()));
- connect(ui->numlockGroup, TQT_SIGNAL(released(int)), this, TQT_SLOT(changed()));
+ connect(ui->click, TQ_SIGNAL(valueChanged(int)), this, TQ_SLOT(changed()));
+ connect(ui->numlockGroup, TQ_SIGNAL(released(int)), this, TQ_SLOT(changed()));
#if !defined(HAVE_XTEST) && !defined(HAVE_XKB)
ui->numlockGroup->setDisabled( true );
@@ -126,7 +129,7 @@ void KeyboardConfig::load()
XKeyboardState kbd;
- XGetKeyboardControl(kapp->getDisplay(), &kbd);
+ XGetKeyboardControl(tdeApp->getDisplay(), &kbd);
config.setGroup("Keyboard");
bool key = config.readBoolEntry("KeyboardRepeating", true);
@@ -153,7 +156,7 @@ void KeyboardConfig::save()
kbd.key_click_percent = clickVolume;
kbd.auto_repeat_mode = keyboardRepeat;
- XChangeKeyboardControl(kapp->getDisplay(),
+ XChangeKeyboardControl(tdeApp->getDisplay(),
KBKeyClickPercent | KBAutoRepeatMode,
&kbd);
if( keyboardRepeat ) {
@@ -535,12 +538,12 @@ void KeyboardConfig::init_keyboard()
XKeyboardState kbd;
XKeyboardControl kbdc;
- XGetKeyboardControl(kapp->getDisplay(), &kbd);
+ XGetKeyboardControl(tdeApp->getDisplay(), &kbd);
bool key = config->readBoolEntry("KeyboardRepeating", true);
kbdc.key_click_percent = config->readNumEntry("ClickVolume", kbd.key_click_percent);
kbdc.auto_repeat_mode = (key ? AutoRepeatModeOn : AutoRepeatModeOff);
- XChangeKeyboardControl(kapp->getDisplay(),
+ XChangeKeyboardControl(tdeApp->getDisplay(),
KBKeyClickPercent | KBAutoRepeatMode,
&kbdc);
diff --git a/kxkb/kcmmisc.h b/kxkb/kcmmisc.h
index d57714295..db4dad84d 100644
--- a/kxkb/kcmmisc.h
+++ b/kxkb/kcmmisc.h
@@ -32,7 +32,7 @@ class KeyboardConfigWidget;
class KeyboardConfig : public TDECModule
{
- Q_OBJECT
+ TQ_OBJECT
public:
KeyboardConfig( TQWidget *parent=0, const char* name=0);
diff --git a/kxkb/kxkb.cpp b/kxkb/kxkb.cpp
index 2db4fb60f..6aa5b8ee2 100644
--- a/kxkb/kxkb.cpp
+++ b/kxkb/kxkb.cpp
@@ -24,29 +24,35 @@ DESCRIPTION
*/
#include <unistd.h>
-#include <stdlib.h>
#include <assert.h>
#include <tqregexp.h>
#include <tqfile.h>
#include <tqstringlist.h>
#include <tqimage.h>
+#include <tqtimer.h>
#include <tdeaboutdata.h>
#include <tdecmdlineargs.h>
+#ifdef WITH_TDEHWLIB
+#include <tdehardwaredevices.h>
+#endif
#include <tdeglobal.h>
-#include <kglobalaccel.h>
+#include <tdeglobalaccel.h>
#include <tdelocale.h>
-#include <kprocess.h>
+#include <tdeprocess.h>
#include <twinmodule.h>
#include <twin.h>
#include <tdetempfile.h>
-#include <kstandarddirs.h>
+#include <tdestandarddirs.h>
#include <kipc.h>
#include <tdeaction.h>
#include <tdepopupmenu.h>
#include <kdebug.h>
#include <tdeconfig.h>
+#include <knotifyclient.h>
+#include <dcopclient.h>
+#include <dcopref.h>
#include "x11helper.h"
#include "kxkb.h"
@@ -59,227 +65,337 @@ DESCRIPTION
KXKBApp::KXKBApp(bool allowStyles, bool GUIenabled)
- : KUniqueApplication(allowStyles, GUIenabled),
+ : TDEUniqueApplication(allowStyles, GUIenabled),
m_prevWinId(X11Helper::UNKNOWN_WINDOW_ID),
- m_rules(NULL),
- m_tray(NULL),
- kWinModule(NULL),
- m_forceSetXKBMap( false )
+ m_rules(nullptr),
+ m_tray(nullptr),
+ kWinModule(nullptr)
{
- m_extension = new XKBExtension();
- if( !m_extension->init() ) {
- kdDebug() << "xkb initialization failed, exiting..." << endl;
- ::exit(1);
- }
-
- // keep in sync with kcmlayout.cpp
- keys = new TDEGlobalAccel(TQT_TQOBJECT(this));
-#include "kxkbbindings.cpp"
- keys->updateConnections();
+ X11Helper::initializeTranslations();
+ XKBExtension *xkb = XKBExtension::the();
+ connect(xkb, TQ_SIGNAL(groupChanged(uint)), this, TQ_SLOT(slotGroupChanged(uint)));
+ connect(xkb, TQ_SIGNAL(optionsChanged()), this, TQ_SLOT(slotSyncXkbOptions()));
m_layoutOwnerMap = new LayoutMap(kxkbConfig);
- connect( this, TQT_SIGNAL(settingsChanged(int)), TQT_SLOT(slotSettingsChanged(int)) );
+ // keep in sync with kcmlayout.cpp
+ keys = new TDEGlobalAccel(this);
+#include "kxkbbindings.cpp"
+
+ connect( this, TQ_SIGNAL(settingsChanged(int)), TQ_SLOT(slotSettingsChanged(int)) );
addKipcEventMask( KIPC::SettingsChanged );
-}
+#if WITH_TDEHWLIB
+ TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
+ connect(hwdevices, TQ_SIGNAL(hardwareAdded(TDEGenericDevice*)), this, TQ_SLOT(hardwareChanged(TDEGenericDevice*)));
+ connect(hwdevices, TQ_SIGNAL(hardwareRemoved(TDEGenericDevice*)), this, TQ_SLOT(hardwareChanged(TDEGenericDevice*)));
+ connect(hwdevices, TQ_SIGNAL(hardwareUpdated(TDEGenericDevice*)), this, TQ_SLOT(hardwareChanged(TDEGenericDevice*)));
+#endif
+}
KXKBApp::~KXKBApp()
{
-// deletePrecompiledLayouts();
-
- delete keys;
- delete m_tray;
- delete m_rules;
- delete m_extension;
+ delete m_tray;
+ delete m_rules;
delete m_layoutOwnerMap;
delete kWinModule;
+ delete keys;
}
int KXKBApp::newInstance()
{
- m_extension->reset();
-
- if( settingsRead() )
- layoutApply();
-
+ readSettings();
return 0;
}
-bool KXKBApp::settingsRead()
+void KXKBApp::readSettings()
{
- kxkbConfig.load( KxkbConfig::LOAD_ACTIVE_OPTIONS );
+ // Xkb options
+ kxkbConfig.load(KxkbConfig::LOAD_INIT_OPTIONS);
+
+ if (!kxkbConfig.m_useKxkb)
+ {
+ kdDebug() << "kxkb is disabled, applying xkb options and exiting" << endl;
+ applyXkbOptions();
+ quit();
+ return;
+ }
+
+ kdDebug() << "applying xkb options and layouts" << endl;
+ kxkbConfig.load(KxkbConfig::LOAD_ALL_OPTIONS);
+ applyXkbOptions();
+
+ // Active window watcher
+ m_prevWinId = X11Helper::UNKNOWN_WINDOW_ID;
+
+ if (kxkbConfig.m_switchingPolicy == SWITCH_POLICY_GLOBAL)
+ {
+ delete kWinModule;
+ kWinModule = nullptr;
+ }
+
+ else
+ {
+ TQDesktopWidget desktopWidget;
+ if (desktopWidget.numScreens() > 1 && !desktopWidget.isVirtualDesktop())
+ {
+ kdWarning() << "With non-virtual desktop only global switching policy supported on non-primary screens" << endl;
+ //TODO: find out how to handle that
+ }
- if( kxkbConfig.m_enableXkbOptions ) {
- kdDebug() << "Setting XKB options " << kxkbConfig.m_options << endl;
- if( !m_extension->setXkbOptions(kxkbConfig.m_options, kxkbConfig.m_resetOldOptions) ) {
- kdDebug() << "Setting XKB options failed!" << endl;
+ if (!kWinModule)
+ {
+ kWinModule = new KWinModule(nullptr, KWinModule::INFO_DESKTOP);
+ connect(kWinModule, TQ_SIGNAL(activeWindowChanged(WId)), TQ_SLOT(windowChanged(WId)));
}
+
+ m_prevWinId = kWinModule->activeWindow();
+ kdDebug() << "Active window " << m_prevWinId << endl;
}
- if ( kxkbConfig.m_useKxkb == false ) {
- kapp->quit();
- return false;
+ // Init layout owner map
+ m_layoutOwnerMap->reset();
+ m_layoutOwnerMap->setCurrentWindow( m_prevWinId );
+
+ // Init rules
+ if (!m_rules)
+ {
+ m_rules = new XkbRules(false);
}
-
- m_prevWinId = X11Helper::UNKNOWN_WINDOW_ID;
-
- if( kxkbConfig.m_switchingPolicy == SWITCH_POLICY_GLOBAL ) {
- delete kWinModule;
- kWinModule = NULL;
- }
- else {
- TQDesktopWidget desktopWidget;
- if( desktopWidget.numScreens() > 1 && desktopWidget.isVirtualDesktop() == false ) {
- kdWarning() << "With non-virtual desktop only global switching policy supported on non-primary screens" << endl;
- //TODO: find out how to handle that
- }
-
- if( kWinModule == NULL ) {
- kWinModule = new KWinModule(0, KWinModule::INFO_DESKTOP);
- connect(kWinModule, TQT_SIGNAL(activeWindowChanged(WId)), TQT_SLOT(windowChanged(WId)));
- }
- m_prevWinId = kWinModule->activeWindow();
- kdDebug() << "Active window " << m_prevWinId << endl;
- }
-
- m_layoutOwnerMap->reset();
- m_layoutOwnerMap->setCurrentWindow( m_prevWinId );
-
- if( m_rules == NULL )
- m_rules = new XkbRules(false);
-
- for(int ii=0; ii<(int)kxkbConfig.m_layouts.count(); ii++) {
- LayoutUnit& layoutUnit = kxkbConfig.m_layouts[ii];
- layoutUnit.defaultGroup = m_rules->getDefaultGroup(layoutUnit.layout, layoutUnit.includeGroup);
- kdDebug() << "default group for " << layoutUnit.toPair() << " is " << layoutUnit.defaultGroup << endl;
- }
-
- m_currentLayout = kxkbConfig.getDefaultLayout();
-
- if( kxkbConfig.m_layouts.count() == 1 ) {
- TQString layoutName = m_currentLayout.layout;
- TQString variantName = m_currentLayout.variant;
- TQString includeName = m_currentLayout.includeGroup;
- int group = m_currentLayout.defaultGroup;
-
- if( !m_extension->setLayout(kxkbConfig.m_model, layoutName, variantName, includeName, false)
- || !m_extension->setGroup( group ) ) {
- kdDebug() << "Error switching to single layout " << m_currentLayout.toPair() << endl;
- // TODO: alert user
- }
-
- if( kxkbConfig.m_showSingle == false ) {
- kapp->quit();
- return false;
- }
- }
- else {
-// initPrecompiledLayouts();
- }
- initTray();
-
- TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
- keys->readSettings();
- keys->updateConnections();
+ // Init layouts
+ for (int i = 0; i < kxkbConfig.m_layouts.count(); i++)
+ {
+ LayoutUnit& layoutUnit = kxkbConfig.m_layouts[i];
+ }
+
+ m_currentLayout = kxkbConfig.m_layouts[0];
+ setLayout(m_currentLayout);
+
+ kdDebug() << "default layout is " << m_currentLayout.toPair() << endl;
- return true;
+ if (kxkbConfig.m_layouts.count() == 1 && !kxkbConfig.m_showSingle)
+ {
+ quit();
+ return;
+ }
+
+ TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
+
+ // Init tray
+ if (!m_tray)
+ {
+ m_tray = new KxkbSystemTray(&kxkbConfig);
+ connect(m_tray, TQ_SIGNAL(menuActivated(int)), this, TQ_SLOT(menuActivated(int)));
+ connect(m_tray, TQ_SIGNAL(toggled()), this, TQ_SLOT(nextLayout()));
+ }
+
+ m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
+ m_tray->setCurrentLayout(m_currentLayout);
+ m_tray->show();
+
+ // Init keybindings
+ keys->readSettings();
+ keys->updateConnections();
}
-void KXKBApp::initTray()
+void KXKBApp::applyXkbOptions()
{
- if( !m_tray )
- {
- KSystemTray* sysTray = new KxkbSystemTray();
- TDEPopupMenu* popupMenu = sysTray->contextMenu();
- // popupMenu->insertTitle( kapp->miniIcon(), kapp->caption() );
-
- m_tray = new KxkbLabelController(sysTray, popupMenu);
- connect(popupMenu, TQT_SIGNAL(activated(int)), this, TQT_SLOT(menuActivated(int)));
- connect(sysTray, TQT_SIGNAL(toggled()), this, TQT_SLOT(toggled()));
- }
-
- m_tray->setShowFlag(kxkbConfig.m_showFlag);
- m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
- m_tray->setCurrentLayout(m_currentLayout);
- m_tray->show();
+ XkbOptions options = kxkbConfig.getKXkbOptions();
+ if (!XKBExtension::the()->setXkbOptions(options)) {
+ kdWarning() << "Setting XKB options failed!" << endl;
+ }
}
-// This function activates the keyboard layout specified by the
-// configuration members (m_currentLayout)
-void KXKBApp::layoutApply()
+void KXKBApp::hardwareChanged(TDEGenericDevice *dev)
{
- setLayout(m_currentLayout);
+# if WITH_TDEHWLIB
+ if (dev->type() == TDEGenericDeviceType::Keyboard)
+ {
+ TQTimer::singleShot(500, this, TQ_SLOT(applyXkbOptions()));
+ }
+# endif
}
// kdcop
bool KXKBApp::setLayout(const TQString& layoutPair)
{
- const LayoutUnit layoutUnitKey(layoutPair);
- if( kxkbConfig.m_layouts.contains(layoutUnitKey) ) {
- return setLayout( *kxkbConfig.m_layouts.find(layoutUnitKey) );
- }
- return false;
+ return setLayout((LayoutUnit)layoutPair);
}
-
// Activates the keyboard layout specified by 'layoutUnit'
-bool KXKBApp::setLayout(const LayoutUnit& layoutUnit, int group)
+bool KXKBApp::setLayout(const LayoutUnit& layoutUnit)
{
- bool res = false;
-
- if( group == -1 )
- group = layoutUnit.defaultGroup;
-
- res = m_extension->setLayout(kxkbConfig.m_model,
- layoutUnit.layout, layoutUnit.variant,
- layoutUnit.includeGroup);
- if( res )
- m_extension->setGroup(group); // not checking for ret - not important
-
- if( res )
- m_currentLayout = layoutUnit;
+ const int group = kxkbConfig.m_layouts.findIndex(layoutUnit);
+ if (group >= 0) {
+ return setLayout(group);
+ }
+ return false;
+}
- if (m_tray) {
- if( res )
- m_tray->setCurrentLayout(layoutUnit);
- else
- m_tray->setError(layoutUnit.toPair());
- }
+// Activates the keyboard layout specified by group number
+bool KXKBApp::setLayout(const uint group)
+{
+ // If this group is already set, just show the notification and return
+ if (XKBExtension::the()->getGroup() == group) {
+ if (kxkbConfig.m_enableNotify) {
+ showLayoutNotification();
+ }
+ return true;
+ }
+
+ bool ok = XKBExtension::the()->setGroup(group);
+ if (!ok) {
+ TQString layout = kxkbConfig.m_layouts[group].toPair();
+ if (m_tray) {
+ m_tray->setError(layout);
+ }
- return res;
+ if (kxkbConfig.m_enableNotify) {
+ showErrorNotification(layout);
+ }
+ }
+ return ok;
}
-void KXKBApp::toggled()
+void KXKBApp::nextLayout()
{
- const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit;
- setLayout(layout);
+ const LayoutUnit& layout = m_layoutOwnerMap->getNextLayout().layoutUnit;
+ setLayout(layout);
+}
+
+void KXKBApp::prevLayout()
+{
+ const LayoutUnit& layout = m_layoutOwnerMap->getPrevLayout().layoutUnit;
+ setLayout(layout);
}
void KXKBApp::menuActivated(int id)
{
- if( KxkbLabelController::START_MENU_ID <= id
- && id < KxkbLabelController::START_MENU_ID + (int)kxkbConfig.m_layouts.count() )
- {
- const LayoutUnit& layout = kxkbConfig.m_layouts[id - KxkbLabelController::START_MENU_ID];
- m_layoutOwnerMap->setCurrentLayout( layout );
- setLayout( layout );
- }
- else if (id == KxkbLabelController::CONFIG_MENU_ID)
+ if (id >= KxkbSystemTray::START_MENU_ID &&
+ id < KxkbSystemTray::START_MENU_ID + kxkbConfig.m_layouts.count())
+ {
+ setLayout(id - KxkbSystemTray::START_MENU_ID);
+ }
+ else if (id == KxkbSystemTray::CONFIG_MENU_ID)
{
TDEProcess p;
p << "tdecmshell" << "keyboard_layout";
p.start(TDEProcess::DontCare);
- }
- else if (id == KxkbLabelController::HELP_MENU_ID)
- {
- TDEApplication::kApplication()->invokeHelp(0, "kxkb");
- }
- else
+ }
+ else if (id == KxkbSystemTray::HELP_MENU_ID)
+ {
+ invokeHelp(0, "kxkb");
+ }
+ else
+ {
+ quit();
+ }
+}
+
+void KXKBApp::slotGroupChanged(uint group)
+{
+ if (!kxkbConfig.m_layouts.count()) {
+ kdError() << "[kxkb] no layout found!" << endl;
+ return;
+ }
+
+ if (group >= kxkbConfig.m_layouts.count()) {
+ kdError() << "[kxkb] unknown group requested: " << group << endl;
+ if (m_tray)
+ {
+ m_tray->setError(i18n("Unknown"));
+ }
+ if (kxkbConfig.m_enableNotify)
+ {
+ showErrorNotification(i18n("Unknown"));
+ }
+ return;
+ }
+
+ m_currentLayout = kxkbConfig.m_layouts[group];
+ m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
+
+ if (m_tray) {
+ m_tray->setCurrentLayout(m_currentLayout);
+ }
+
+ if (kxkbConfig.m_enableNotify) {
+ showLayoutNotification();
+ }
+}
+
+void KXKBApp::slotSyncXkbOptions()
+{
+ // Make sure the X11 server has had enough time to apply the change
+ TQTimer::singleShot(100, this, TQ_SLOT(syncXkbOptions()));
+}
+
+void KXKBApp::syncXkbOptions()
+{
+ XkbOptions options = XKBExtension::the()->getServerOptions();
+ if (kxkbConfig.setFromXkbOptions(options))
{
- quit();
+ m_layoutOwnerMap->reset();
+ if (m_tray)
+ {
+ m_tray->initLayoutList(kxkbConfig.m_layouts, *m_rules);
+ }
}
+ slotGroupChanged(XKBExtension::the()->getGroup());
+}
+
+void KXKBApp::showLayoutNotification()
+{
+ bool useKMilo = kxkbConfig.m_notifyUseKMilo && isKMiloAvailable(),
+ notificationSent = false;
+
+ TQString layoutName(m_rules->getLayoutName(m_currentLayout));
+
+ if (useKMilo) {
+ DCOPRef kmilo("kded", "kmilod");
+ if (kmilo.send("displayText(TQString,TQPixmap)", layoutName, miniIcon())) {
+ notificationSent = true;
+ }
+ }
+
+ if (!notificationSent) {
+ WId wid = (m_tray ? m_tray->winId() : 0);
+ KNotifyClient::event(wid, "LayoutChange", layoutName);
+ }
+}
+
+void KXKBApp::showErrorNotification(TQString layout) {
+ bool useKMilo = kxkbConfig.m_notifyUseKMilo && isKMiloAvailable(),
+ notificationSent = false;
+
+ if (useKMilo) {
+ DCOPRef kmilo("kded", "kmilod");
+ if (kmilo.send("displayText(TQString,TQPixmap)", i18n("Error changing keyboard layout to '%1'").arg(layout), miniIcon())) {
+ notificationSent = true;
+ }
+ }
+
+ if (!notificationSent) {
+ WId wid = (m_tray ? m_tray->winId() : 0);
+ KNotifyClient::event(wid, "Error");
+ }
+}
+
+bool KXKBApp::isKMiloAvailable() {
+ QCStringList modules;
+ TQCString replyType;
+ TQByteArray replyData;
+ if (dcopClient()->call("kded", "kded", "loadedModules()",
+ TQByteArray(), replyType, replyData))
+ {
+ if (replyType == "QCStringList") {
+ TQDataStream reply(replyData, IO_ReadOnly);
+ reply >> modules;
+ return modules.contains("kmilod");
+ }
+ }
+ return false;
}
// TODO: we also have to handle deleted windows
@@ -291,88 +407,44 @@ void KXKBApp::windowChanged(WId winId)
return;
}
- int group = m_extension->getGroup();
-
kdDebug() << "old WinId: " << m_prevWinId << ", new WinId: " << winId << endl;
-
- if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout/group from previous window
-// kdDebug() << "storing " << m_currentLayout.toPair() << ":" << group << " for " << m_prevWinId << endl;
+
+ if( m_prevWinId != X11Helper::UNKNOWN_WINDOW_ID ) { // saving layout from previous window
// m_layoutOwnerMap->setCurrentWindow(m_prevWinId);
m_layoutOwnerMap->setCurrentLayout(m_currentLayout);
- m_layoutOwnerMap->setCurrentGroup(group);
}
-
+
m_prevWinId = winId;
if( winId != X11Helper::UNKNOWN_WINDOW_ID ) {
m_layoutOwnerMap->setCurrentWindow(winId);
const LayoutState& layoutState = m_layoutOwnerMap->getCurrentLayout();
-
+
if( layoutState.layoutUnit != m_currentLayout ) {
- kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << ":" << group << " for " << winId << endl;
- setLayout( layoutState.layoutUnit, layoutState.group );
- }
- else if( layoutState.group != group ) { // we need to change only the group
- m_extension->setGroup(layoutState.group);
+ kdDebug() << "switching to " << layoutState.layoutUnit.toPair() << " for " << winId << endl;
+ setLayout(layoutState.layoutUnit);
}
}
}
-
void KXKBApp::slotSettingsChanged(int category)
{
- if ( category != TDEApplication::SETTINGS_SHORTCUTS)
- return;
-
- TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
- keys->readSettings();
- keys->updateConnections();
+ if (category == TDEApplication::SETTINGS_SHORTCUTS) {
+ TDEGlobal::config()->reparseConfiguration(); // kcontrol modified kdeglobals
+ keys->readSettings();
+ keys->updateConnections();
+ }
}
-/*
- Viki (onscreen keyboard) has problems determining some modifiers states
- when kxkb uses precompiled layouts instead of setxkbmap. Probably a bug
- in the xkb functions used for the precompiled layouts *shrug*.
-*/
-void KXKBApp::forceSetXKBMap( bool set )
-{
- if( m_forceSetXKBMap == set )
- return;
- m_forceSetXKBMap = set;
- layoutApply();
+bool KXKBApp::x11EventFilter(XEvent *e) {
+ // let the extension process the event and emit signals if necessary
+ XKBExtension::the()->processXEvent(e);
+ return TDEApplication::x11EventFilter(e);
}
-/*Precompiles the keyboard layouts for faster activation later.
-This is done by loading each one of them and then dumping the compiled
-map from the X server into our local buffer.*/
-// void KXKBApp::initPrecompiledLayouts()
-// {
-// TQStringList dirs = TDEGlobal::dirs()->findDirs ( "tmp", "" );
-// TQString tempDir = dirs.count() == 0 ? "/tmp/" : dirs[0];
-//
-// TQValueList<LayoutUnit>::ConstIterator end = kxkbConfig.m_layouts.end();
-//
-// for (TQValueList<LayoutUnit>::ConstIterator it = kxkbConfig.m_layouts.begin(); it != end; ++it)
-// {
-// LayoutUnit layoutUnit(*it);
-// // const char* baseGr = m_includes[layout];
-// // int group = m_rules->getGroup(layout, baseGr);
-// // if( m_extension->setLayout(m_model, layout, m_variants[layout], group, baseGr) ) {
-// TQString compiledLayoutFileName = tempDir + layoutUnit.layout + "." + layoutUnit.variant + ".xkm";
-// // if( m_extension->getCompiledLayout(compiledLayoutFileName) )
-// m_compiledLayoutFileNames[layoutUnit.toPair()] = compiledLayoutFileName;
-// // }
-// // else {
-// // kdDebug() << "Error precompiling layout " << layout << endl;
-// // }
-// }
-// }
-
-
-const char * DESCRIPTION =
- I18N_NOOP("A utility to switch keyboard maps");
-
-extern "C" KDE_EXPORT int kdemain(int argc, char *argv[])
+const char *DESCRIPTION = I18N_NOOP("A utility to switch keyboard maps");
+
+extern "C" TDE_EXPORT int kdemain(int argc, char *argv[])
{
TDEAboutData about("kxkb", I18N_NOOP("TDE Keyboard Tool"), "1.0",
DESCRIPTION, TDEAboutData::License_LGPL,
diff --git a/kxkb/kxkb.h b/kxkb/kxkb.h
index 18949ba75..803057f61 100644
--- a/kxkb/kxkb.h
+++ b/kxkb/kxkb.h
@@ -31,7 +31,12 @@ DESCRIPTION
#include <tqdict.h>
#include <tqptrqueue.h>
-#include <kuniqueapplication.h>
+#include <tdeuniqueapplication.h>
+#ifdef WITH_TDEHWLIB
+#include <tdegenericdevice.h>
+#else
+#define TDEGenericDevice void
+#endif
#include "kxkbtraywindow.h"
#include "kxkbconfig.h"
@@ -47,50 +52,60 @@ class LayoutMap;
and switching layouts
*/
-class KXKBApp : public KUniqueApplication
+class KXKBApp : public TDEUniqueApplication
{
- Q_OBJECT
+ TQ_OBJECT
K_DCOP
public:
- KXKBApp(bool allowStyles=true, bool GUIenabled=true);
- ~KXKBApp();
+ KXKBApp(bool allowStyles=true, bool GUIenabled=true);
+ ~KXKBApp();
- virtual int newInstance();
+ virtual int newInstance();
- bool setLayout(const LayoutUnit& layoutUnit, int group=-1);
+ bool setLayout(const LayoutUnit& layoutUnit);
+ bool setLayout(const uint group);
k_dcop:
- bool setLayout(const TQString& layoutPair);
- TQString getCurrentLayout() { return m_currentLayout.toPair(); }
- TQStringList getLayoutsList() { return kxkbConfig.getLayoutStringList(); }
- void forceSetXKBMap( bool set );
+ bool setLayout(const TQString& layoutPair);
+ TQString getCurrentLayout() { return m_currentLayout.toPair(); }
+ TQStringList getLayoutsList() { return kxkbConfig.getLayoutStringList(); }
+
+public slots:
+ void nextLayout();
+ void prevLayout();
protected slots:
void menuActivated(int id);
- void toggled();
void windowChanged(WId winId);
+ void slotGroupChanged(uint group);
void slotSettingsChanged(int category);
+ void showLayoutNotification();
+ void showErrorNotification(TQString layout);
+
+ void hardwareChanged(TDEGenericDevice *dev);
+
+ void readSettings();
+ void applyXkbOptions();
+ void slotSyncXkbOptions();
+ void syncXkbOptions();
-protected:
- // Read settings, and apply them.
- bool settingsRead();
- void layoutApply();
-
private:
- void initTray();
+ void initTray();
+ bool x11EventFilter(XEvent *e);
+ bool isKMiloAvailable();
private:
- KxkbConfig kxkbConfig;
+ KxkbConfig kxkbConfig;
WId m_prevWinId; // for tricky part of saving xkb group
LayoutMap* m_layoutOwnerMap;
- LayoutUnit m_currentLayout;
+ LayoutUnit m_currentLayout;
XKBExtension *m_extension;
XkbRules *m_rules;
- KxkbLabelController *m_tray;
+ KxkbSystemTray *m_tray;
TDEGlobalAccel *keys;
KWinModule* kWinModule;
bool m_forceSetXKBMap;
diff --git a/kxkb/kxkbbindings.cpp b/kxkb/kxkbbindings.cpp
index fad480f7c..02da8a4ea 100644
--- a/kxkb/kxkbbindings.cpp
+++ b/kxkb/kxkbbindings.cpp
@@ -1,12 +1,13 @@
#ifndef NOSLOTS
# define DEF( name, key3, key4, fnSlot ) \
- keys->insert( name, i18n(name), TQString(), key3, key4, TQT_TQOBJECT(this), TQT_SLOT(fnSlot) )
+ keys->insert( name, i18n(name), TQString(), key3, key4, this, TQ_SLOT(fnSlot) )
#else
# define DEF( name, key3, key4, fnSlot ) \
- keys->insert( name, i18n(name), TQString(), key3, key4 )
+ keys->insert( name, i18n(name), TQString(), key3, key4, 0, 0 )
#endif
- keys->insert( "Program:kxkb", i18n("Keyboard") );
- DEF( I18N_NOOP("Switch to Next Keyboard Layout"), ALT+CTRL+Qt::Key_K, KKey::QtWIN+CTRL+Qt::Key_K, toggled() );
+ keys->insert( "Program:kxkb", i18n("Keyboard") );
+ DEF( I18N_NOOP("Switch to Next Keyboard Layout"), TDEShortcut(), TDEShortcut(), nextLayout() );
+ DEF( I18N_NOOP("Switch to Previous Keyboard Layout"), TDEShortcut(), TDEShortcut(), prevLayout() );
-#undef DEF
+#undef DEF \ No newline at end of file
diff --git a/kxkb/kxkbconfig.cpp b/kxkb/kxkbconfig.cpp
index 517f0ccdd..fd86f049a 100644
--- a/kxkb/kxkbconfig.cpp
+++ b/kxkb/kxkbconfig.cpp
@@ -1,7 +1,7 @@
//
// C++ Implementation: kxkbconfig
//
-// Description:
+// Description:
//
//
// Author: Andriy Rysin <rysin@kde.org>, (C) 2006
@@ -30,209 +30,225 @@ static const char* switchModes[SWITCH_POLICY_COUNT] = {
const LayoutUnit DEFAULT_LAYOUT_UNIT = LayoutUnit("us", "");
const char* DEFAULT_MODEL = "pc104";
-LayoutUnit KxkbConfig::getDefaultLayout()
+void KxkbConfig::load(int loadMode)
{
- if( m_layouts.size() == 0 )
- return DEFAULT_LAYOUT_UNIT;
-
- return m_layouts[0];
-}
+ // INITIAL OPTIONS (loaded regardless of whether KXkb is enabled)
-bool KxkbConfig::load(int loadMode)
-{
TDEConfig *config = new TDEConfig("kxkbrc", true, false);
config->setGroup("Layout");
-// Even if the layouts have been disabled we still want to set Xkb options
-// user can always switch them off now in the "Options" tab
- m_enableXkbOptions = config->readBoolEntry("EnableXkbOptions", false);
-
- if( m_enableXkbOptions == true || loadMode == LOAD_ALL ) {
- m_resetOldOptions = config->readBoolEntry("ResetOldOptions", false);
- m_options = config->readEntry("Options", "");
- kdDebug() << "Xkb options (enabled=" << m_enableXkbOptions << "): " << m_options << endl;
- }
-
m_useKxkb = config->readBoolEntry("Use", false);
- kdDebug() << "Use kxkb " << m_useKxkb << endl;
- if( (m_useKxkb == false && loadMode == LOAD_ACTIVE_OPTIONS )
- || loadMode == LOAD_INIT_OPTIONS )
- return true;
+ m_resetOldOptions = config->readBoolEntry("ResetOldOptions", true);
+ m_options = config->readEntry("Options", "");
+
+ if (loadMode == LOAD_INIT_OPTIONS)
+ {
+ return;
+ }
+
+ // BASIC OPTIONS (passed to setxkbmap)
m_model = config->readEntry("Model", DEFAULT_MODEL);
- kdDebug() << "Model: " << m_model << endl;
-
+
+ // Layouts
TQStringList layoutList;
- if( config->hasKey("LayoutList") ) {
+ if (config->hasKey("LayoutList"))
+ {
layoutList = config->readListEntry("LayoutList");
}
- else { // old config
+ else
+ { // old config
TQString mainLayout = config->readEntry("Layout", DEFAULT_LAYOUT_UNIT.toPair());
layoutList = config->readListEntry("Additional");
layoutList.prepend(mainLayout);
}
- if( layoutList.count() == 0 )
+
+ if (layoutList.count() == 0)
+ {
layoutList.append("us");
-
+ }
+
+ TQStringList::ConstIterator it;
+
m_layouts.clear();
- for(TQStringList::ConstIterator it = layoutList.begin(); it != layoutList.end() ; ++it) {
+ for (it = layoutList.begin(); it != layoutList.end(); ++it)
+ {
m_layouts.append( LayoutUnit(*it) );
- kdDebug() << " layout " << LayoutUnit(*it).toPair() << " in list: " << m_layouts.contains( LayoutUnit(*it) ) << endl;
+ kdDebug() << " layout " << LayoutUnit(*it).toPair() << " in list: " << m_layouts.contains(LayoutUnit(*it)) << endl;
}
- kdDebug() << "Found " << m_layouts.count() << " layouts, default is " << getDefaultLayout().toPair() << endl;
-
+ kdDebug() << "Found " << m_layouts.count() << " layouts" << endl;
+
+ // Display names
TQStringList displayNamesList = config->readListEntry("DisplayNames", ',');
- for(TQStringList::ConstIterator it = displayNamesList.begin(); it != displayNamesList.end() ; ++it) {
+ for (it = displayNamesList.begin(); it != displayNamesList.end() ; ++it)
+ {
TQStringList displayNamePair = TQStringList::split(':', *it );
- if( displayNamePair.count() == 2 ) {
- LayoutUnit layoutUnit( displayNamePair[0] );
- if( m_layouts.contains( layoutUnit ) ) {
+ if (displayNamePair.count() == 2)
+ {
+ LayoutUnit layoutUnit(displayNamePair[0]);
+ if (m_layouts.contains(layoutUnit))
+ {
m_layouts[m_layouts.findIndex(layoutUnit)].displayName = displayNamePair[1].left(3);
}
}
}
-// m_includes.clear();
- if( X11Helper::areSingleGroupsSupported() ) {
- if( config->hasKey("IncludeGroups") ) {
- TQStringList includeList = config->readListEntry("IncludeGroups", ',');
- for(TQStringList::ConstIterator it = includeList.begin(); it != includeList.end() ; ++it) {
- TQStringList includePair = TQStringList::split(':', *it );
- if( includePair.count() == 2 ) {
- LayoutUnit layoutUnit( includePair[0] );
- if( m_layouts.contains( layoutUnit ) ) {
- m_layouts[m_layouts.findIndex(layoutUnit)].includeGroup = includePair[1];
- kdDebug() << "Got inc group: " << includePair[0] << ": " << includePair[1] << endl;
- }
- }
- }
- }
- else { //old includes format
- kdDebug() << "Old includes..." << endl;
- TQStringList includeList = config->readListEntry("Includes");
- for(TQStringList::ConstIterator it = includeList.begin(); it != includeList.end() ; ++it) {
- TQString layoutName = LayoutUnit::parseLayout( *it );
- LayoutUnit layoutUnit( layoutName, "" );
- kdDebug() << "old layout for inc: " << layoutUnit.toPair() << " included " << m_layouts.contains( layoutUnit ) << endl;
- if( m_layouts.contains( layoutUnit ) ) {
- TQString variantName = LayoutUnit::parseVariant(*it);
- m_layouts[m_layouts.findIndex(layoutUnit)].includeGroup = variantName;
- kdDebug() << "Got inc group: " << layoutUnit.toPair() << ": " << variantName << endl;
- }
- }
- }
+ if (loadMode == LOAD_BASIC_OPTIONS)
+ {
+ return;
}
+ // ALL OTHER OPTIONS (of interest only to KXkb itself)
+
+ // Tray indicator
m_showSingle = config->readBoolEntry("ShowSingle", false);
+
m_showFlag = config->readBoolEntry("ShowFlag", true);
-
+ m_showLabel = config->readBoolEntry("ShowLabel", true);
+
+ m_fitToBox = config->readBoolEntry("FitFlagToBox", true);
+
+ m_useThemeColors = config->readBoolEntry("UseThemeColors", false);
+ m_colorBackground = config->readColorEntry("ColorBackground", new TQColor(TQt::gray));
+ m_bgTransparent = config->readBoolEntry("BgTransparent", false);
+ m_colorLabel = config->readColorEntry("ColorLabel", new TQColor(TQt::white));
+
+ m_labelFont = config->readFontEntry("LabelFont", new TQFont("sans", 10, TQFont::Bold));
+ m_labelShadow = config->readBoolEntry("LabelShadow", true);
+ m_colorShadow = config->readColorEntry("ColorShadow", new TQColor(TQt::black));
+
+ m_dimFlag = config->readBoolEntry("DimFlag", true);
+ m_bevel = config->readBoolEntry("IndicatorBevel", false);
+
+ // Switching policy
TQString layoutOwner = config->readEntry("SwitchMode", "Global");
- if( layoutOwner == "WinClass" ) {
+ if (layoutOwner == "WinClass")
+ {
m_switchingPolicy = SWITCH_POLICY_WIN_CLASS;
}
- else if( layoutOwner == "Window" ) {
+ else if (layoutOwner == "Window")
+ {
m_switchingPolicy = SWITCH_POLICY_WINDOW;
}
- else /*if( layoutOwner == "Global" )*/ {
+ else
+ {
m_switchingPolicy = SWITCH_POLICY_GLOBAL;
}
-
- if( m_layouts.count() < 2 && m_switchingPolicy != SWITCH_POLICY_GLOBAL ) {
+
+ if (m_layouts.count() < 2 && m_switchingPolicy != SWITCH_POLICY_GLOBAL)
+ {
kdWarning() << "Layout count is less than 2, using Global switching policy" << endl;
m_switchingPolicy = SWITCH_POLICY_GLOBAL;
}
-
+
kdDebug() << "Layout owner mode " << layoutOwner << endl;
-
+
+ // Sticky switching
m_stickySwitching = config->readBoolEntry("StickySwitching", false);
- m_stickySwitchingDepth = config->readEntry("StickySwitchingDepth", "2").toInt();
- if( m_stickySwitchingDepth < 2 )
+ m_stickySwitchingDepth = config->readNumEntry("StickySwitchingDepth", 2);
+ if (m_stickySwitchingDepth < 2)
+ {
m_stickySwitchingDepth = 2;
+ }
- if( m_stickySwitching == true ) {
- if( m_layouts.count() < 3 ) {
+ if (m_stickySwitching)
+ {
+ if (m_layouts.count() < 3)
+ {
kdWarning() << "Layout count is less than 3, sticky switching will be off" << endl;
m_stickySwitching = false;
}
- else
- if( (int)m_layouts.count() - 1 < m_stickySwitchingDepth ) {
+ else if (m_layouts.count() - 1 < m_stickySwitchingDepth)
+ {
kdWarning() << "Sticky switching depth is more than layout count -1, adjusting..." << endl;
m_stickySwitchingDepth = m_layouts.count() - 1;
}
}
- delete config;
+ // Notifications
+ config->setGroup("Notifications");
+ m_enableNotify = config->readBoolEntry("Enable", false);
+ m_notifyUseKMilo = config->readBoolEntry("UseKMilo", true);
- return true;
+ delete config;
}
-void KxkbConfig::save()
+void KxkbConfig::save()
{
TDEConfig *config = new TDEConfig("kxkbrc", false, false);
config->setGroup("Layout");
- config->writeEntry("Model", m_model);
+ config->writeEntry("Use", m_useKxkb);
- config->writeEntry("EnableXkbOptions", m_enableXkbOptions );
config->writeEntry("ResetOldOptions", m_resetOldOptions);
config->writeEntry("Options", m_options );
+ config->writeEntry("Model", m_model);
+
+ // Layouts
TQStringList layoutList;
- TQStringList includeList;
TQStringList displayNamesList;
-
+
TQValueList<LayoutUnit>::ConstIterator it;
- for(it = m_layouts.begin(); it != m_layouts.end(); ++it) {
+ for (it = m_layouts.begin(); it != m_layouts.end(); ++it) {
const LayoutUnit& layoutUnit = *it;
-
- layoutList.append( layoutUnit.toPair() );
-
- if( layoutUnit.includeGroup.isEmpty() == false ) {
- TQString incGroupUnit = TQString("%1:%2").arg(layoutUnit.toPair(), layoutUnit.includeGroup);
- includeList.append( incGroupUnit );
- }
-
- TQString displayName( layoutUnit.displayName );
- kdDebug() << " displayName " << layoutUnit.toPair() << " : " << displayName << endl;
- if( displayName.isEmpty() == false && displayName != layoutUnit.layout ) {
+ layoutList.append(layoutUnit.toPair());
+
+ // Display name
+ TQString displayName(layoutUnit.displayName);
+ if (!displayName.isEmpty() && displayName != layoutUnit.layout)
+ {
displayName = TQString("%1:%2").arg(layoutUnit.toPair(), displayName);
- displayNamesList.append( displayName );
+ displayNamesList.append(displayName);
}
}
-
config->writeEntry("LayoutList", layoutList);
- kdDebug() << "Saving Layouts: " << layoutList << endl;
-
- config->writeEntry("IncludeGroups", includeList);
- kdDebug() << "Saving includeGroups: " << includeList << endl;
-
-// if( displayNamesList.empty() == false )
- config->writeEntry("DisplayNames", displayNamesList);
-// else
-// config->deleteEntry("DisplayNames");
+ config->writeEntry("DisplayNames", displayNamesList);
- config->writeEntry("Use", m_useKxkb);
+ // Tray indicator
config->writeEntry("ShowSingle", m_showSingle);
+
config->writeEntry("ShowFlag", m_showFlag);
+ config->writeEntry("ShowLabel", m_showLabel);
+
+ config->writeEntry("FitFlagToBox", m_fitToBox);
+ config->writeEntry("UseThemeColors", m_useThemeColors);
+ config->writeEntry("ColorBackground", m_colorBackground);
+ config->writeEntry("BgTransparent", m_bgTransparent);
+ config->writeEntry("ColorLabel", m_colorLabel);
+
+ config->writeEntry("LabelFont", m_labelFont);
+ config->writeEntry("LabelShadow", m_labelShadow);
+ config->writeEntry("ColorShadow", m_colorShadow);
+
+ config->writeEntry("DimFlag", m_dimFlag);
+ config->writeEntry("IndicatorBevel", m_bevel);
+
+ // Switching policy
config->writeEntry("SwitchMode", switchModes[m_switchingPolicy]);
-
+
+ // Sticky switching
config->writeEntry("StickySwitching", m_stickySwitching);
config->writeEntry("StickySwitchingDepth", m_stickySwitchingDepth);
- // remove old options
+ // Notifications
+ config->setGroup("Notifications");
+ config->writeEntry("Enable", m_enableNotify);
+ config->writeEntry("UseKMilo", m_notifyUseKMilo);
+
+ // remove old options
config->deleteEntry("Variants");
config->deleteEntry("Includes");
config->deleteEntry("Encoding");
config->deleteEntry("AdditionalEncodings");
config->deleteEntry("Additional");
config->deleteEntry("Layout");
-
- config->sync();
+ config->sync();
delete config;
}
@@ -240,8 +256,7 @@ void KxkbConfig::setDefaults()
{
m_model = DEFAULT_MODEL;
- m_enableXkbOptions = false;
- m_resetOldOptions = false;
+ m_resetOldOptions = true;
m_options = "";
m_layouts.clear();
@@ -250,13 +265,85 @@ void KxkbConfig::setDefaults()
m_useKxkb = false;
m_showSingle = false;
m_showFlag = true;
+ m_fitToBox = true;
+ m_dimFlag = true;
+
+ m_bevel = false;
m_switchingPolicy = SWITCH_POLICY_GLOBAL;
-
+
m_stickySwitching = false;
m_stickySwitchingDepth = 2;
}
+bool KxkbConfig::setFromXkbOptions(XkbOptions options)
+{
+ XkbOptions curOptions = getKXkbOptions();
+
+ bool modified = false;
+
+ // We need to fix the variants string if it is empty, otherwise the
+ // comparison below will often wrongly assume that the variants have
+ // changed
+ if (options.variants.isEmpty())
+ {
+ options.variants = ""; // ensure the string is empty but not null
+ for (int i = 0; i < options.layouts.contains(","); ++i)
+ {
+ options.variants += ",";
+ }
+ }
+
+ // Check if keyboard layout options have changed
+ if ((options.model != curOptions.model && !options.model.isNull()))
+ {
+ modified = true;
+ m_model = options.model;
+ }
+
+ if ((options.layouts != curOptions.layouts) || (options.variants != curOptions.variants))
+ {
+ modified = true;
+ m_layouts.clear();
+
+ TQStringList layouts = TQStringList::split(",", options.layouts, true);
+ TQStringList variants = TQStringList::split(",", options.variants, true);
+ TQStringList::Iterator lit = layouts.begin();
+ TQStringList::Iterator vit = variants.begin();
+
+ if (layouts.empty())
+ {
+ layouts << "us";
+ }
+
+ while (lit != layouts.end())
+ {
+ TQString layout = *lit;
+ TQString variant = vit != variants.end() ? *vit : TQString::null;
+ m_layouts.append(LayoutUnit(layout, variant));
+
+ ++lit;
+ if (vit != variants.end())
+ {
+ ++vit;
+ }
+ }
+ }
+
+ TQStringList serverOpts = TQStringList::split(",", options.options);
+ TQStringList kxkbOpts = TQStringList::split(",", curOptions.options);
+ serverOpts.sort();
+ kxkbOpts.sort();
+
+ if (serverOpts != kxkbOpts)
+ {
+ modified = true;
+ m_options = options.options;
+ }
+
+ return modified;
+}
+
TQStringList KxkbConfig::getLayoutStringList(/*bool compact*/)
{
TQStringList layoutList;
@@ -271,7 +358,7 @@ TQStringList KxkbConfig::getLayoutStringList(/*bool compact*/)
TQString KxkbConfig::getDefaultDisplayName(const TQString& code_)
{
TQString displayName;
-
+
if( code_.length() <= 2 ) {
displayName = code_;
}
@@ -281,13 +368,13 @@ TQString KxkbConfig::getDefaultDisplayName(const TQString& code_)
TQString rightCode;
if( sepPos != -1 )
rightCode = code_.mid(sepPos+1);
-
+
if( rightCode.length() > 0 )
displayName = leftCode.left(2) + rightCode.left(1).lower();
else
displayName = leftCode.left(3);
}
-
+
return displayName;
}
@@ -295,13 +382,36 @@ TQString KxkbConfig::getDefaultDisplayName(const LayoutUnit& layoutUnit, bool si
{
if( layoutUnit.variant == "" )
return getDefaultDisplayName( layoutUnit.layout );
-
+
TQString displayName = layoutUnit.layout.left(2);
if( single == false )
displayName += layoutUnit.variant.left(1);
return displayName;
}
+const XkbOptions KxkbConfig::getKXkbOptions() {
+ XkbOptions options;
+ TQStringList layouts;
+ TQStringList variants;
+ for (TQValueList<LayoutUnit>::ConstIterator it = m_layouts.begin(); it != m_layouts.end(); ++it) {
+ const LayoutUnit& layoutUnit = *it;
+ layouts << layoutUnit.layout;
+ variants << layoutUnit.variant;
+ }
+ options.layouts = layouts.join(",");
+ options.variants = variants.join(",");
+ options.options = m_options;
+ options.resetOld = m_resetOldOptions;
+ options.model = m_model;
+
+ if (options.model.isEmpty())
+ {
+ options.model = DEFAULT_MODEL;
+ }
+
+ return options;
+}
+
/**
* @brief Gets the single layout part of a layout(variant) string
* @param[in] layvar String in form layout(variant) to parse
diff --git a/kxkb/kxkbconfig.h b/kxkb/kxkbconfig.h
index 82fe610c9..7d02fd3a3 100644
--- a/kxkb/kxkbconfig.h
+++ b/kxkb/kxkbconfig.h
@@ -1,7 +1,7 @@
//
// C++ Interface: kxkbconfig
//
-// Description:
+// Description:
//
//
// Author: Andriy Rysin <rysin@kde.org>, (C) 2006
@@ -14,74 +14,30 @@
#include <tqstring.h>
#include <tqstringlist.h>
+#include <tqcolor.h>
+#include <tqfont.h>
#include <tqptrqueue.h>
#include <tqmap.h>
+#include "layoutunit.h"
+
+struct XkbOptions {
+ TQString layouts;
+ TQString variants;
+ TQString model;
+ TQString options;
+ bool resetOld;
+};
/* Utility classes for per-window/per-application layout implementation
*/
-enum SwitchingPolicy {
+enum SwitchingPolicy {
SWITCH_POLICY_GLOBAL = 0,
SWITCH_POLICY_WIN_CLASS = 1,
SWITCH_POLICY_WINDOW = 2,
SWITCH_POLICY_COUNT = 3
};
-
-
-inline TQString createPair(TQString key, TQString value)
-{
- if( value.isEmpty() )
- return key;
- return TQString("%1(%2)").arg(key, value);
-}
-
-struct LayoutUnit {
- TQString layout;
- TQString variant;
- TQString includeGroup;
- TQString displayName;
- int defaultGroup;
-
- LayoutUnit() {}
-
- LayoutUnit(TQString layout_, TQString variant_):
- layout(layout_),
- variant(variant_)
- {}
-
- LayoutUnit(TQString pair) {
- setFromPair( pair );
- }
-
- void setFromPair(const TQString& pair) {
- layout = parseLayout(pair);
- variant = parseVariant(pair);
- }
-
- TQString toPair() const {
- return createPair(layout, variant);
- }
-
- bool operator<(const LayoutUnit& lu) const {
- return layout<lu.layout ||
- (layout==lu.layout && variant<lu.variant);
- }
-
- bool operator!=(const LayoutUnit& lu) const {
- return layout!=lu.layout || variant!=lu.variant;
- }
-
- bool operator==(const LayoutUnit& lu) const {
-// kdDebug() << layout << "==" << lu.layout << "&&" << variant << "==" << lu.variant << endl;
- return layout==lu.layout && variant==lu.variant;
- }
-
-//private:
- static const TQString parseLayout(const TQString &layvar);
- static const TQString parseVariant(const TQString &layvar);
-};
-
extern const LayoutUnit DEFAULT_LAYOUT_UNIT;
extern const char* DEFAULT_MODEL;
@@ -89,32 +45,47 @@ extern const char* DEFAULT_MODEL;
class KxkbConfig
{
public:
- enum { LOAD_INIT_OPTIONS, LOAD_ACTIVE_OPTIONS, LOAD_ALL };
-
+ enum { LOAD_INIT_OPTIONS, LOAD_BASIC_OPTIONS, LOAD_ALL_OPTIONS };
+
bool m_useKxkb;
bool m_showSingle;
bool m_showFlag;
+ bool m_showLabel;
+ bool m_fitToBox;
+ bool m_dimFlag;
+ bool m_bevel;
bool m_enableXkbOptions;
bool m_resetOldOptions;
SwitchingPolicy m_switchingPolicy;
bool m_stickySwitching;
int m_stickySwitchingDepth;
-
+ bool m_enableNotify;
+ bool m_notifyUseKMilo;
+
+ bool m_useThemeColors;
+ TQColor m_colorBackground;
+ bool m_bgTransparent;
+ TQColor m_colorLabel;
+ TQFont m_labelFont;
+ bool m_labelShadow;
+ TQColor m_colorShadow;
+
TQString m_model;
TQString m_options;
TQValueList<LayoutUnit> m_layouts;
- LayoutUnit getDefaultLayout();
-
- bool load(int loadMode);
+ void load(int loadMode);
void save();
void setDefaults();
-
+
TQStringList getLayoutStringList(/*bool compact*/);
static TQString getDefaultDisplayName(const TQString& code_);
static TQString getDefaultDisplayName(const LayoutUnit& layoutUnit, bool single=false);
-private:
+ bool setFromXkbOptions(XkbOptions options);
+ const XkbOptions getKXkbOptions();
+
+private:
static const TQMap<TQString, TQString> parseIncludesMap(const TQStringList& pairList);
};
diff --git a/kxkb/kxkbtraywindow.cpp b/kxkb/kxkbtraywindow.cpp
index ec91df670..7871f443a 100644
--- a/kxkb/kxkbtraywindow.cpp
+++ b/kxkb/kxkbtraywindow.cpp
@@ -1,7 +1,7 @@
//
// C++ Implementation: kxkbtraywindow
//
-// Description:
+// Description:
//
//
// Author: Andriy Rysin <rysin@kde.org>, (C) 2006
@@ -17,114 +17,101 @@
#include <kiconloader.h>
#include <tdepopupmenu.h>
#include <tdeaction.h>
-#include <kuniqueapplication.h>
#include "kxkbtraywindow.h"
#include "pixmap.h"
#include "rules.h"
-#include "kxkbconfig.h"
-
-KxkbLabelController::KxkbLabelController(TQLabel* label_, TQPopupMenu* contextMenu_) :
- label(label_),
- contextMenu(contextMenu_),
- m_menuStartIndex(contextMenu_->count()),
- m_prevLayoutCount(0)
+KxkbSystemTray::KxkbSystemTray(KxkbConfig *kxkbConfig)
+ : KSystemTray(nullptr),
+ m_prevLayoutCount(0)
{
-// kdDebug() << "Creating KxkbLabelController with " << label_ << ", " << contextMenu_ << endl;
-// kdDebug() << "Creating KxkbLabelController with startMenuIndex " << m_menuStartIndex << endl;
+ m_icoMgr = new LayoutIconManager(kxkbConfig);
}
-void KxkbLabelController::setToolTip(const TQString& tip)
+KxkbSystemTray::~KxkbSystemTray()
{
- TQToolTip::remove(label);
- TQToolTip::add(label, tip);
+ delete m_icoMgr;
}
-void KxkbLabelController::setPixmap(const TQPixmap& pixmap)
+void KxkbSystemTray::setToolTip(const TQString& tip)
{
- TDEIconEffect iconeffect;
- label->setPixmap( iconeffect.apply(pixmap, TDEIcon::Panel, TDEIcon::DefaultState) );
+ TQToolTip::remove(this);
+ TQToolTip::add(this, tip);
}
-
-void KxkbLabelController::setCurrentLayout(const LayoutUnit& layoutUnit)
+void KxkbSystemTray::setPixmap(const TQPixmap& pix)
{
- setToolTip(m_descriptionMap[layoutUnit.toPair()]);
- setPixmap( LayoutIcon::getInstance().findPixmap(layoutUnit.layout, m_showFlag, layoutUnit.displayName) );
+ TDEIconEffect iconeffect;
+ KSystemTray::setPixmap(iconeffect.apply(pix, TDEIcon::Panel, TDEIcon::DefaultState));
}
+void KxkbSystemTray::setCurrentLayout(const LayoutUnit& layoutUnit)
+{
+ setToolTip(m_descriptionMap[layoutUnit.toPair()]);
+ setPixmap(m_icoMgr->find(layoutUnit.layout, PIXMAP_STYLE_INDICATOR, layoutUnit.displayName));
+}
-void KxkbLabelController::setError(const TQString& layoutInfo)
+void KxkbSystemTray::setError(const TQString& layoutInfo)
{
- TQString msg = i18n("Error changing keyboard layout to '%1'").arg(layoutInfo);
- setToolTip(msg);
+ TQString layout(layoutInfo);
+ if (layout.isNull()) {
+ layout = i18n("Unknown");
+ }
- label->setPixmap(LayoutIcon::getInstance().findPixmap("error", m_showFlag));
+ TQString msg = i18n("Error changing keyboard layout to '%1'").arg(layoutInfo);
+ setToolTip(msg);
+ setPixmap(m_icoMgr->find(ERROR_CODE, PIXMAP_STYLE_NORMAL));
}
-
-void KxkbLabelController::initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rules)
+void KxkbSystemTray::initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rules)
{
-// TDEPopupMenu* menu = contextMenu();
- TQPopupMenu* menu = contextMenu;
-// int index = menu->indexOf(0);
-
m_descriptionMap.clear();
-// menu->clear();
-// menu->insertTitle( kapp->miniIcon(), kapp->caption() );
-
- for(int ii=0; ii<m_prevLayoutCount; ++ii) {
- menu->removeItem(START_MENU_ID + ii);
- kdDebug() << "remove item: " << START_MENU_ID + ii << endl;
- }
-/* menu->removeItem(CONFIG_MENU_ID);
- menu->removeItem(HELP_MENU_ID);*/
-
+
+ int i;
+ for (i = 0; i < m_prevLayoutCount; ++i) {
+ contextMenu()->removeItem(START_MENU_ID + i);
+ }
+
TDEIconEffect iconeffect;
-
- int cnt = 0;
+
+ i = 0;
TQValueList<LayoutUnit>::ConstIterator it;
- for (it=layouts.begin(); it != layouts.end(); ++it)
+ for (it = layouts.begin(); it != layouts.end(); ++it)
{
- const TQString layoutName = (*it).layout;
- const TQString variantName = (*it).variant;
-
- const TQPixmap& layoutPixmap = LayoutIcon::getInstance().findPixmap(layoutName, m_showFlag, (*it).displayName);
+ const TQString layoutName = (*it).layout;
+ const TQString variantName = (*it).variant;
+
+ const TQPixmap& layoutPixmap = m_icoMgr->find((*it).layout, PIXMAP_STYLE_CONTEXTMENU, (*it).displayName);
const TQPixmap pix = iconeffect.apply(layoutPixmap, TDEIcon::Small, TDEIcon::DefaultState);
-
- TQString fullName = i18n((rules.layouts()[layoutName]));
- if( variantName.isEmpty() == false )
- fullName += " (" + variantName + ")";
- contextMenu->insertItem(pix, fullName, START_MENU_ID + cnt, m_menuStartIndex + cnt);
- m_descriptionMap.insert((*it).toPair(), fullName);
-
- cnt++;
+
+ TQString fullName = rules.getLayoutName((*it));
+ contextMenu()->insertItem(pix, fullName, START_MENU_ID + i, i + 1);
+
+ m_descriptionMap.insert((*it).toPair(), fullName);
+
+ ++i;
}
- m_prevLayoutCount = cnt;
-
- // if show config, if show help
- if( menu->indexOf(CONFIG_MENU_ID) == -1 ) {
- contextMenu->insertSeparator();
- contextMenu->insertItem(SmallIcon("configure"), i18n("Configure..."), CONFIG_MENU_ID);
- if( menu->indexOf(HELP_MENU_ID) == -1 )
- contextMenu->insertItem(SmallIcon("help"), i18n("Help"), HELP_MENU_ID);
- }
-
-/* if( index != -1 ) { //not first start
- menu->insertSeparator();
- TDEAction* quitAction = KStdAction::quit(this, TQT_SIGNAL(quitSelected()), actionCollection());
- if (quitAction)
- quitAction->plug(menu);
- }*/
+ m_prevLayoutCount = i;
+
+ if (contextMenu()->indexOf(CONFIG_MENU_ID) == -1) {
+ contextMenu()->insertSeparator();
+ contextMenu()->insertItem(SmallIcon("configure"), i18n("Configure..."), CONFIG_MENU_ID);
+
+ if (contextMenu()->indexOf(HELP_MENU_ID) == -1) {
+ contextMenu()->insertItem(SmallIcon("help"), i18n("Help"), HELP_MENU_ID);
+ }
+ }
+
+ connect(contextMenu(), TQ_SIGNAL(activated(int)), this, TQ_SIGNAL(menuActivated(int)));
}
-// void KxkbLabelController::mouseReleaseEvent(TQMouseEvent *ev)
-// {
-// if (ev->button() == TQMouseEvent::LeftButton)
-// emit toggled();
-// KSystemTray::mouseReleaseEvent(ev);
-// }
+void KxkbSystemTray::mouseReleaseEvent(TQMouseEvent *ev) {
+ if (ev->button() == TQt::LeftButton) {
+ emit toggled();
+ }
+ KSystemTray::mouseReleaseEvent(ev);
+}
#include "kxkbtraywindow.moc"
diff --git a/kxkb/kxkbtraywindow.h b/kxkb/kxkbtraywindow.h
index 38e42db5d..3e1ae2c05 100644
--- a/kxkb/kxkbtraywindow.h
+++ b/kxkb/kxkbtraywindow.h
@@ -1,7 +1,7 @@
//
// C++ Interface: kxkbtraywindow
//
-// Description:
+// Description:
//
//
// Author: Andriy Rysin <rysin@kde.org>, (C) 2006
@@ -17,75 +17,40 @@
#include <tqstring.h>
#include <tqvaluelist.h>
-#include "kxkbconfig.h"
+#include "layoutunit.h"
-
-class TQLabel;
-class TQPopupMenu;
class XkbRules;
+class KxkbConfig;
+class LayoutIconManager;
-/* This class is responsible for displaying flag/label for the layout,
- catching keyboard/mouse events and displaying menu when selected
-*/
-
-class KxkbLabelController: public QObject
+class KxkbSystemTray : public KSystemTray
{
-// Q_OBJECT
-
-public:
- enum { START_MENU_ID = 100, CONFIG_MENU_ID = 130, HELP_MENU_ID = 131 };
+ TQ_OBJECT
- KxkbLabelController(TQLabel *label, TQPopupMenu* contextMenu);
+ public:
+ KxkbSystemTray(KxkbConfig *kxkbConfig);
+ ~KxkbSystemTray();
+ void initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rule);
+ void setCurrentLayout(const LayoutUnit& layout);
+ void setError(const TQString& layoutInfo = TQString::null);
- void initLayoutList(const TQValueList<LayoutUnit>& layouts, const XkbRules& rule);
- void setCurrentLayout(const LayoutUnit& layout);
-// void setCurrentLayout(const TQString& layout, const TQString &variant);
- void setError(const TQString& layoutInfo="");
- void setShowFlag(bool showFlag) { m_showFlag = showFlag; }
- void show() { label->show(); }
-
-// signals:
-//
-// void menuActivated(int);
-// void toggled();
+ enum { START_MENU_ID = 100, CONFIG_MENU_ID = 130, HELP_MENU_ID = 131 };
-// protected:
-//
-// void mouseReleaseEvent(TQMouseEvent *);
+ protected:
+ void mouseReleaseEvent(TQMouseEvent *ev);
-private:
- TQLabel* label;
- TQPopupMenu* contextMenu;
-
- const int m_menuStartIndex;
- bool m_showFlag;
- int m_prevLayoutCount;
- TQMap<TQString, TQString> m_descriptionMap;
-
- void setToolTip(const TQString& tip);
- void setPixmap(const TQPixmap& pixmap);
-};
+ private slots:
+ void setToolTip(const TQString& tip);
+ void setPixmap(const TQPixmap& pix);
+ signals:
+ void menuActivated(int);
+ void toggled();
-class KxkbSystemTray : public KSystemTray
-{
- Q_OBJECT
-
- public:
- KxkbSystemTray():
- KSystemTray(NULL)
- {}
-
- void mouseReleaseEvent(TQMouseEvent *ev)
- {
- if (ev->button() == Qt::LeftButton)
- emit toggled();
- KSystemTray::mouseReleaseEvent(ev);
- }
-
- signals:
- void menuActivated(int);
- void toggled();
+ private:
+ LayoutIconManager *m_icoMgr;
+ int m_prevLayoutCount;
+ TQMap<TQString, TQString> m_descriptionMap;
};
diff --git a/kxkb/layoutmap.cpp b/kxkb/layoutmap.cpp
index 106f70950..62b44da10 100644
--- a/kxkb/layoutmap.cpp
+++ b/kxkb/layoutmap.cpp
@@ -88,19 +88,28 @@ LayoutState& LayoutMap::getNextLayout() {
layoutQueue.enqueue(layoutState);
kdDebug() << "map: Next layout: " << layoutQueue.head()->layoutUnit.toPair()
- << " group: " << layoutQueue.head()->layoutUnit.defaultGroup << " for " << m_currentWinId << endl;
+ << " for " << m_currentWinId << endl;
return *layoutQueue.head();
}
-void LayoutMap::setCurrentGroup(int group) {
- getCurrentLayout().group = group;
+LayoutState& LayoutMap::getPrevLayout() {
+ LayoutQueue& layoutQueue = getCurrentLayoutQueue(m_currentWinId);
+ for (int i = 1; i < layoutQueue.count(); ++i) {
+ LayoutState* layoutState = layoutQueue.dequeue();
+ layoutQueue.enqueue(layoutState);
+ }
+
+ kdDebug() << "map: Next layout: " << layoutQueue.head()->layoutUnit.toPair()
+ << " for " << m_currentWinId << endl;
+
+ return *layoutQueue.head();
}
void LayoutMap::setCurrentLayout(const LayoutUnit& layoutUnit) {
LayoutQueue& layoutQueue = getCurrentLayoutQueue(m_currentWinId);
kdDebug() << "map: Storing layout: " << layoutUnit.toPair()
- << " group: " << layoutUnit.defaultGroup << " for " << m_currentWinId << endl;
+ << " for " << m_currentWinId << endl;
int queueSize = (int)layoutQueue.count();
for(int ii=0; ii<queueSize; ii++) {
diff --git a/kxkb/layoutmap.h b/kxkb/layoutmap.h
index 7b0ebad61..812814fff 100644
--- a/kxkb/layoutmap.h
+++ b/kxkb/layoutmap.h
@@ -27,13 +27,11 @@
// LayoutInfo is used for sticky switching and per-window/application switching policy
struct LayoutState {
const LayoutUnit& layoutUnit;
- int group;
LayoutState(const LayoutUnit& layoutUnit_):
- layoutUnit(layoutUnit_),
- group(layoutUnit_.defaultGroup)
+ layoutUnit(layoutUnit_)
{
-// kdDebug() << "new LayoutState " << layoutUnit.toPair() << " group: " << group << endl;
+// kdDebug() << "new LayoutState " << layoutUnit.toPair() << endl;
}
};
@@ -49,8 +47,8 @@ public:
// void setConfig(const KxkbConfig& kxkbConfig);
void setCurrentLayout(const LayoutUnit& layoutUnit);
- void setCurrentGroup(int group);
LayoutState& getNextLayout();
+ LayoutState& getPrevLayout();
LayoutState& getCurrentLayout();
void setCurrentWindow(WId winId);
diff --git a/kxkb/layoutunit.h b/kxkb/layoutunit.h
new file mode 100644
index 000000000..f4d82f73f
--- /dev/null
+++ b/kxkb/layoutunit.h
@@ -0,0 +1,64 @@
+//
+//
+// Author: Andriy Rysin <rysin@kde.org>, (C) 2006
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef _LAYOUTUNIT_H
+#define _LAYOUTUNIT_H
+
+#include <tqstring.h>
+
+inline TQString createPair(TQString key, TQString value)
+{
+ if (value.isEmpty()) return key;
+ return TQString("%1(%2)").arg(key, value);
+}
+
+struct LayoutUnit {
+ TQString layout;
+ TQString variant;
+ TQString displayName;
+
+ LayoutUnit() {}
+
+ LayoutUnit(TQString layout_, TQString variant_):
+ layout(layout_),
+ variant(variant_)
+ {}
+
+ LayoutUnit(TQString pair) {
+ setFromPair( pair );
+ }
+
+ void setFromPair(const TQString& pair) {
+ layout = parseLayout(pair);
+ variant = parseVariant(pair);
+ }
+
+ TQString toPair() const {
+ return createPair(layout, variant);
+ }
+
+ bool operator<(const LayoutUnit& lu) const {
+ return layout<lu.layout ||
+ (layout==lu.layout && variant<lu.variant);
+ }
+
+ bool operator!=(const LayoutUnit& lu) const {
+ return layout!=lu.layout || variant!=lu.variant;
+ }
+
+ bool operator==(const LayoutUnit& lu) const {
+// kdDebug() << layout << "==" << lu.layout << "&&" << variant << "==" << lu.variant << endl;
+ return layout==lu.layout && variant==lu.variant;
+ }
+
+//private:
+ static const TQString parseLayout(const TQString &layvar);
+ static const TQString parseVariant(const TQString &layvar);
+};
+
+#endif // _LAYOUTUNIT_H \ No newline at end of file
diff --git a/kxkb/pixmap.cpp b/kxkb/pixmap.cpp
index 8752c258a..01866e71e 100644
--- a/kxkb/pixmap.cpp
+++ b/kxkb/pixmap.cpp
@@ -1,45 +1,69 @@
+#include <tqapplication.h>
#include <tqimage.h>
-//#include <tqbitmap.h>
+#include <tqbitmap.h>
#include <tqfont.h>
#include <tqpainter.h>
#include <tqregexp.h>
#include <tqdict.h>
+#include <tqdrawutil.h>
-#include <kstandarddirs.h>
+#include <tdestandarddirs.h>
+#include <tdeglobalsettings.h>
#include <tdelocale.h>
#include <kdebug.h>
#include "pixmap.h"
#include "x11helper.h"
-#include "kxkbconfig.h"
+const TQString LayoutIconManager::flagTemplate("l10n/%1/flag.png");
-static const int FLAG_MAX_WIDTH = 21;
-static const int FLAG_MAX_HEIGHT = 14;
-
-const TQString LayoutIcon::flagTemplate("l10n/%1/flag.png");
-const TQString& LayoutIcon::ERROR_CODE("error");
-LayoutIcon* LayoutIcon::instance;
+LayoutIconManager::LayoutIconManager(KxkbConfig *kxkbConfig)
+ : m_pixmapCache(80),
+ m_kxkbConfig(kxkbConfig)
+{
+}
+const TQPixmap& LayoutIconManager::find(const TQString& code_, int pixmapStyle, const TQString& displayName_)
+{
+ if (m_kxkbConfig->m_useThemeColors) { // use colors from color scheme
+ m_bgColor = TDEGlobalSettings::highlightColor();
+ m_fgColor = TDEGlobalSettings::highlightedTextColor();
+ } else {
+ m_bgColor = m_kxkbConfig->m_colorBackground;
+ m_fgColor = m_kxkbConfig->m_colorLabel;
+ }
-LayoutIcon& LayoutIcon::getInstance() {
- if( instance == NULL ) {
- instance = new LayoutIcon();
+ m_labelFont = m_kxkbConfig->m_labelFont;
+ m_labelShadow = m_kxkbConfig->m_labelShadow;
+ m_shColor = m_kxkbConfig->m_colorShadow;
+ m_bgTransparent = m_kxkbConfig->m_bgTransparent;
+ m_fitToBox = m_kxkbConfig->m_fitToBox;
+ m_dimFlag = m_kxkbConfig->m_dimFlag;
+ m_bevel = m_kxkbConfig->m_bevel && !m_bgTransparent && pixmapStyle == PIXMAP_STYLE_INDICATOR;
+
+ // Decide on how to style the pixmap
+ switch(pixmapStyle) {
+ case PIXMAP_STYLE_NORMAL:
+ m_showFlag = true;
+ m_showLabel = false;
+ break;
+
+ case PIXMAP_STYLE_INDICATOR:
+ m_showFlag = m_kxkbConfig->m_showFlag;
+ m_showLabel = m_kxkbConfig->m_showLabel;
+ break;
+
+ case PIXMAP_STYLE_CONTEXTMENU:
+ m_fitToBox = false; // causes white color loss
+ m_showFlag = true;
+ m_showLabel = false;
+ break;
}
- return *instance;
-}
-LayoutIcon::LayoutIcon():
- m_pixmapCache(80),
- m_labelFont("sans")
-{
- m_labelFont.setPixelSize(10);
- m_labelFont.setWeight(TQFont::Bold);
-}
+ // Label only mode is always 'fit to box'
+ if (m_showLabel && !m_showFlag)
+ m_fitToBox = true;
-const TQPixmap&
-LayoutIcon::findPixmap(const TQString& code_, bool showFlag, const TQString& displayName_)
-{
TQPixmap* pm = NULL;
if( code_ == ERROR_CODE ) {
@@ -52,61 +76,130 @@ LayoutIcon::findPixmap(const TQString& code_, bool showFlag, const TQString& dis
}
TQString displayName(displayName_);
-
- if( displayName.isEmpty() ) {
+
+ if (displayName.isEmpty()) {
displayName = KxkbConfig::getDefaultDisplayName(code_);
}
- if( displayName.length() > 3 )
+ if (displayName.length() > 3)
displayName = displayName.left(3);
- const TQString pixmapKey( showFlag ? code_ + "." + displayName : displayName );
-
- pm = m_pixmapCache[pixmapKey];
- if( pm )
- return *pm;
-
- TQString flag;
- if( showFlag ) {
- TQString countryCode = getCountryFromLayoutName( code_ );
- flag = locate("locale", flagTemplate.arg(countryCode));
+ const TQString pixmapKey(
+ TQString(m_showFlag ? "f" : "") + TQString(m_showLabel ? "l" : "") + TQString(m_labelShadow ? "s" : "") + "." +
+ TQString(m_fitToBox ? "F" : "") + TQString(m_dimFlag ? "D" : "") + TQString(m_bevel ? "B" : "") + "." +
+ m_labelFont.key() + "." + ( m_bgTransparent ? "x" : m_bgColor.name() ) + "." + m_fgColor.name() + "." + m_shColor.name() + '.' + code_ + "." + displayName
+ );
+
+ // Only use cache for indicator
+ if (pixmapStyle == PIXMAP_STYLE_INDICATOR) {
+ pm = m_pixmapCache[pixmapKey];
+ if (pm)
+ return *pm;
}
- if( flag.isEmpty() ) {
- pm = new TQPixmap(FLAG_MAX_WIDTH, FLAG_MAX_HEIGHT);
- pm->fill(Qt::gray);
+ pm = new TQPixmap(FLAG_MAX_DIM, FLAG_MAX_DIM);
+
+ TQRect r = pm->rect();
+ TQPainter p_(pm);
+
+ if (m_showFlag) {
+ TQString countryCode = getCountryFromLayoutName(code_);
+ TQString flag = locate("locale", flagTemplate.arg(countryCode));
+
+ if (flag.isEmpty()) {
+ pm->fill(m_bgColor);
+ m_showLabel = true;
+ } else {
+ TQPixmap fp(flag);
+
+ if (m_dimFlag && m_showLabel)
+ {
+ TQImage image = fp.convertToImage();
+ for (int y = 0; y < image.height(); y++)
+ {
+ for(int x = 0; x < image.width(); x++)
+ {
+ TQRgb rgb = image.pixel(x,y);
+ TQRgb dimRgb(tqRgb(tqRed(rgb) * 3/4, tqGreen(rgb) * 3/4, tqBlue(rgb) * 3/4));
+ image.setPixel(x, y, dimRgb);
+ }
+ }
+ fp.convertFromImage(image);
+ }
+
+ if (!m_fitToBox)
+ {
+ r = TQRect((FLAG_MAX_DIM - fp.width()) / 2, (FLAG_MAX_DIM - fp.height()) / 2, fp.width(), fp.height());
+ }
+
+ TQRect fr(r); // flag rect might be smaller to accomodate the bevel
+ if (m_bevel)
+ {
+ fr.setX(fr.x() + 1);
+ fr.setY(fr.y() + 1);
+ fr.setWidth(fr.width() - 1);
+ fr.setHeight(fr.height() - 1);
+ }
+
+ p_.drawPixmap(fr, fp);
+
+ // If we don't stretch the flag, we need to apply a mask to it
+ if (!m_fitToBox)
+ {
+ TQPixmap fpmask(FLAG_MAX_DIM, FLAG_MAX_DIM);
+ TQPainter fpmaskp(&fpmask);
+ fpmask.fill(TQt::white);
+ fpmaskp.fillRect(r, TQt::black);
+ TQBitmap fpmask_;
+ fpmask_ = fpmask;
+ pm->setMask((TQBitmap)fpmask_);
+ }
+ }
+ } else {
+ pm->fill(m_bgColor);
}
- else {
- pm = new TQPixmap(flag);
- dimPixmap( *pm );
-
-#if 0
- if( pm->height() < FLAG_MAX_HEIGHT ) {
- TQPixmap* pix = new TQPixmap(FLAG_MAX_WIDTH, FLAG_MAX_HEIGHT);
- pix->fill( Qt::lightGray );
-// pix->fill( TQColor(tqRgba(127,127,127,255)) );
-// TQBitmap mask;
-// mask.fill(1);
-// pix->setMask(mask);
-
- int dy = (pix->height() - pm->height()) / 2;
- copyBlt( pix, 0, dy, pm, 0, 0, -1, -1 );
-// TQPixmap* px = new TQPixmap(21, 14);
-// px->convertFromImage(img);*/
- delete pm;
- pm = pix;
+
+ if (m_showLabel) {
+ TQPainter p(pm);
+ p.setFont(m_labelFont);
+
+ if (m_labelShadow) {
+ p.setPen(m_shColor);
+ p.drawText(1, 1, pm->width(), pm->height(), TQt::AlignCenter, displayName);
+ }
+
+ p.setPen(m_fgColor);
+ p.drawText(0, 0, pm->width(), pm->height(), TQt::AlignCenter, displayName);
+
+ if( m_bgTransparent && !m_showFlag )
+ {
+ TQPixmap maskpix(pm->width(), pm->height());
+ TQPainter maskp(&maskpix);
+
+ maskpix.fill(TQt::white);
+ maskp.setPen(TQt::black);
+ maskp.setFont(m_labelFont);
+
+ maskp.drawText(0, 0, maskpix.width(), maskpix.height(), TQt::AlignCenter, displayName);
+ if( m_labelShadow )
+ {
+ maskp.drawText(1, 1, maskpix.width(), maskpix.height(), TQt::AlignCenter, displayName);
+ }
+
+ TQBitmap mask;
+ mask = maskpix;
+ pm->setMask(mask);
}
-#endif
}
- TQPainter p(pm);
- p.setFont(m_labelFont);
+ if (m_bevel)
+ {
+ TQPainter p_(pm);
+ qDrawShadePanel(&p_, r.x(), r.y(), r.width(), r.height(), tqApp->palette().active(), false, 1, nullptr);
+ }
- p.setPen(Qt::black);
- p.drawText(1, 1, pm->width(), pm->height()-2, Qt::AlignCenter, displayName);
- p.setPen(Qt::white);
- p.drawText(0, 0, pm->width(), pm->height()-2, Qt::AlignCenter, displayName);
- m_pixmapCache.insert(pixmapKey, pm);
+ if (pixmapStyle == PIXMAP_STYLE_INDICATOR)
+ m_pixmapCache.insert(pixmapKey, pm);
return *pm;
}
@@ -114,24 +207,33 @@ LayoutIcon::findPixmap(const TQString& code_, bool showFlag, const TQString& dis
/**
@brief Try to get country code from layout name in xkb before xorg 6.9.0
*/
-TQString LayoutIcon::getCountryFromLayoutName(const TQString& layoutName)
+TQString LayoutIconManager::getCountryFromLayoutName(const TQString& layoutName)
{
TQString flag;
-
+
if( X11Helper::areLayoutsClean() ) { // >= Xorg 6.9.0
if( layoutName == "mkd" )
flag = "mk";
else
- if( layoutName == "srp" ) {
- TQString csFlagFile = locate("locale", flagTemplate.arg("cs"));
- flag = csFlagFile.isEmpty() ? "yu" : "cs";
+ if( layoutName == "srp" ) {
+ TQString csFlagFile = locate("locale", flagTemplate.arg("cs"));
+ flag = csFlagFile.isEmpty() ? "yu" : "cs";
}
else
if( layoutName.endsWith("/jp") )
flag = "jp";
- else
- if( layoutName == "trq" || layoutName == "trf" || layoutName == "tralt" )
- flag = "tr";
+ else
+ if( layoutName == "trq" || layoutName == "trf" || layoutName == "tralt" )
+ flag = "tr";
+ else
+ if( layoutName == "epo" ) // Esperanto
+ flag = "eo";
+ else
+ if( layoutName == "mao" ) // Maori
+ flag = "mi";
+ else
+ if( layoutName == "brai" ) // Braille
+ flag = "braille";
else
if( layoutName.length() > 2 )
flag = "";
@@ -140,10 +242,19 @@ TQString LayoutIcon::getCountryFromLayoutName(const TQString& layoutName)
}
else {
if( layoutName == "ar" ) // Arabic - not argentina
- ;
- else
- if( layoutName == "sr" || layoutName == "cs") // Serbian language - Yugoslavia
- flag = "yu";
+ ;
+ else
+ if( layoutName == "epo" ) // Esperanto
+ flag = "eo";
+ else
+ if( layoutName == "mao" ) // Maori
+ flag = "mi";
+ else
+ if( layoutName == "brai" ) // Braille
+ flag = "braille";
+ else
+ if( layoutName == "sr" || layoutName == "cs") // Serbian language - Yugoslavia
+ flag = "yu";
else
if( layoutName == "bs" ) // Bosnian language - Bosnia
flag = "ba";
@@ -178,8 +289,8 @@ TQString LayoutIcon::getCountryFromLayoutName(const TQString& layoutName)
if( layoutName.endsWith("/jp") )
flag = "jp";
else
- if( layoutName == "ml" || layoutName == "dev" || layoutName == "gur"
- || layoutName == "guj" || layoutName == "kan" || layoutName == "ori"
+ if( layoutName == "ml" || layoutName == "dev" || layoutName == "gur"
+ || layoutName == "guj" || layoutName == "kan" || layoutName == "ori"
|| layoutName == "tel" || layoutName == "tml" || layoutName == "ben" ) // some Indian languages
flag = "in";
else {
@@ -189,8 +300,8 @@ TQString LayoutIcon::getCountryFromLayoutName(const TQString& layoutName)
if( sepPos != -1 )
rightCode = layoutName.mid(sepPos+1);
// kdDebug() << "layout name breakup: " << leftCode << ":" << rightCode << endl;
-
- if( rightCode.length() == 2
+
+ if( rightCode.length() == 2
&& TQRegExp("[A-Z][A-Z]").exactMatch(rightCode) ) {
flag = rightCode.lower();
}
@@ -199,39 +310,23 @@ TQString LayoutIcon::getCountryFromLayoutName(const TQString& layoutName)
}
}
}
-
- return flag;
-}
-
-void LayoutIcon::dimPixmap(TQPixmap& pm)
-{
- TQImage image = pm.convertToImage();
- for (int y=0; y<image.height(); y++)
- for(int x=0; x<image.width(); x++)
- {
- QRgb rgb = image.pixel(x,y);
- QRgb dimRgb(tqRgb(tqRed(rgb)*3/4, tqGreen(rgb)*3/4, tqBlue(rgb)*3/4));
- image.setPixel(x, y, dimRgb);
- }
- pm.convertFromImage(image);
+ return flag;
}
-static const char* ERROR_LABEL = "err";
-
//private
-TQPixmap* LayoutIcon::createErrorPixmap()
+TQPixmap* LayoutIconManager::createErrorPixmap()
{
TQPixmap* pm = new TQPixmap(21, 14);
- pm->fill(Qt::white);
+ pm->fill(TQt::white);
TQPainter p(pm);
p.setFont(m_labelFont);
- p.setPen(Qt::red);
- p.drawText(1, 1, pm->width(), pm->height()-2, Qt::AlignCenter, ERROR_LABEL);
- p.setPen(Qt::blue);
- p.drawText(0, 0, pm->width(), pm->height()-2, Qt::AlignCenter, ERROR_LABEL);
+ p.setPen(TQt::red);
+ p.drawText(1, 1, pm->width(), pm->height()-2, TQt::AlignCenter, ERROR_LABEL);
+ p.setPen(TQt::blue);
+ p.drawText(0, 0, pm->width(), pm->height()-2, TQt::AlignCenter, ERROR_LABEL);
m_pixmapCache.insert(ERROR_CODE, pm);
return pm;
diff --git a/kxkb/pixmap.h b/kxkb/pixmap.h
index 7070d91b2..08dee8a87 100644
--- a/kxkb/pixmap.h
+++ b/kxkb/pixmap.h
@@ -6,26 +6,36 @@
#include <tqdict.h>
#include <tqstring.h>
+#include "kxkbconfig.h"
-class LayoutIcon {
-
-private:
- static LayoutIcon* instance;
- static const TQString flagTemplate;
-
- TQDict<TQPixmap> m_pixmapCache;
- TQFont m_labelFont;
-
- LayoutIcon();
- TQPixmap* createErrorPixmap();
- void dimPixmap(TQPixmap& pixmap);
- TQString getCountryFromLayoutName(const TQString& layoutName);
-
- public:
- static const TQString& ERROR_CODE;
-
- static LayoutIcon& getInstance();
- const TQPixmap& findPixmap(const TQString& code, bool showFlag, const TQString& displayName="");
+#define ERROR_CODE "error"
+#define ERROR_LABEL "!"
+
+#define FLAG_MAX_DIM 24
+
+enum PixmapStyle {
+ PIXMAP_STYLE_NORMAL = 0,
+ PIXMAP_STYLE_INDICATOR = 1,
+ PIXMAP_STYLE_CONTEXTMENU = 2
+};
+
+class LayoutIconManager {
+ public:
+ LayoutIconManager(KxkbConfig *kxkbConfig);
+ const TQPixmap& find(const TQString& code, int pixmapStyle, const TQString& displayName = TQString::null);
+
+ private:
+ TQPixmap* createErrorPixmap();
+ TQString getCountryFromLayoutName(const TQString& layoutName);
+
+ private:
+ KxkbConfig *m_kxkbConfig;
+ static const TQString flagTemplate;
+ bool m_showFlag, m_showLabel, m_bgTransparent, m_labelShadow, m_fitToBox, m_dimFlag, m_bevel;
+ TQColor m_bgColor, m_fgColor, m_shColor;
+ TQFont m_labelFont;
+
+ TQDict<TQPixmap> m_pixmapCache;
};
#endif
diff --git a/kxkb/rules.cpp b/kxkb/rules.cpp
index 20f817602..f0f4b38b2 100644
--- a/kxkb/rules.cpp
+++ b/kxkb/rules.cpp
@@ -5,7 +5,7 @@
#include <tqstringlist.h>
#include <tqdir.h>
-#include <kstandarddirs.h>
+#include <tdestandarddirs.h>
#include <tdeglobal.h>
#include <tdelocale.h>
#include <kdebug.h>
@@ -35,8 +35,6 @@ XkbRules::XkbRules(bool layoutsOnly):
}
loadRules(rulesFile, layoutsOnly);
- loadOldLayouts(rulesFile);
- loadGroups(::locate("config", "kxkb_groups"));
}
@@ -58,84 +56,6 @@ void XkbRules::loadRules(TQString file, bool layoutsOnly)
// fixLayouts();
}
-// void XkbRules::fixLayouts() {
-// // THIS IS TEMPORARY!!!
-// // This should be fixed in XFree86 (and actually is fixed in XFree 4.2)
-// // some handcoded ones, because the X11 rule file doesn't get them correctly, or in case
-// // the rule file wasn't found
-// static struct {
-// const char * locale;
-// const char * layout;
-// } fixedLayouts[] = {
-// { "ben", "Bengali" },
-// { "ar", "Arabic" },
-// { "ir", "Farsi" },
-// { 0, 0 }
-// };
-//
-// for(int i=0; fixedLayouts[i].layout != 0; i++ ) {
-// if( m_layouts.find(fixedLayouts[i].locale) == 0 )
-// m_layouts.insert(fixedLayouts[i].locale, fixedLayouts[i].layout);
-// }
-// }
-
-bool XkbRules::isSingleGroup(const TQString& layout)
-{
- return X11Helper::areSingleGroupsSupported()
- && !m_oldLayouts.contains(layout)
- && !m_nonLatinLayouts.contains(layout);
-}
-
-
-// check $oldlayouts and $nonlatin groups for XFree 4.3 and later
-void XkbRules::loadOldLayouts(TQString rulesFile)
-{
- OldLayouts* oldLayoutsStruct = X11Helper::loadOldLayouts( rulesFile );
- m_oldLayouts = oldLayoutsStruct->oldLayouts;
- m_nonLatinLayouts = oldLayoutsStruct->nonLatinLayouts;
-}
-
-// for multi-group layouts in XFree 4.2 and older
-// or if layout is present in $oldlayout or $nonlatin groups
-void XkbRules::loadGroups(TQString file)
-{
- TQFile f(file);
- if (f.open(IO_ReadOnly))
- {
- TQTextStream ts(&f);
- TQString locale;
- unsigned int grp;
-
- while (!ts.eof()) {
- ts >> locale >> grp;
- locale.simplifyWhiteSpace();
-
- if (locale[0] == '#' || locale.left(2) == "//" || locale.isEmpty())
- continue;
-
- m_initialGroups.insert(locale, grp);
- }
-
- f.close();
- }
-}
-
-unsigned int
-XkbRules::getDefaultGroup(const TQString& layout, const TQString& includeGroup)
-{
-// check for new one-group layouts in XFree 4.3 and older
- if( isSingleGroup(layout) ) {
- if( includeGroup.isEmpty() == false )
- return 1;
- else
- return 0;
- }
-
- TQMap<TQString, unsigned int>::iterator it = m_initialGroups.find(layout);
- return it == m_initialGroups.end() ? 0 : it.data();
-}
-
-
TQStringList
XkbRules::getAvailableVariants(const TQString& layout)
{
@@ -146,11 +66,24 @@ XkbRules::getAvailableVariants(const TQString& layout)
if( result1 )
return *result1;
- bool oldLayouts = m_oldLayouts.contains(layout);
- TQStringList* result = X11Helper::getVariants(layout, X11_DIR, oldLayouts);
+ TQStringList* result = X11Helper::getVariants(layout, X11_DIR);
m_varLists.insert(layout, result);
return *result;
}
+TQString XkbRules::getLayoutName(LayoutUnit layout) const {
+ TQString fullName = i18n(m_layouts[layout.layout]);
+ if (!layout.variant.isEmpty()) {
+ fullName += " (" + layout.variant + ")";
+ }
+ return fullName;
+}
+
+TQString XkbRules::trOpt(TQString opt) {
+ // xkeyboard-config's translation is generated directly from the xml and has some querks
+ // like sustitution for the '<' and '>'. We will have to workaroung those manually:
+ TQString translated = i18n(opt.replace("<", "&lt;").replace(">", "&gt;").utf8());
+ return translated.replace("&lt;", "<").replace("&gt;", ">");
+}
diff --git a/kxkb/rules.h b/kxkb/rules.h
index a4955317e..0a68f3dbf 100644
--- a/kxkb/rules.h
+++ b/kxkb/rules.h
@@ -3,8 +3,10 @@
#include <tqstring.h>
#include <tqdict.h>
+#include <tqstringlist.h>
#include <tqmap.h>
+#include "layoutunit.h"
class XkbRules
{
@@ -15,30 +17,26 @@ public:
const TQDict<char> &models() const { return m_models; };
const TQDict<char> &layouts() const { return m_layouts; };
const TQDict<char> &options() const { return m_options; };
-
+
TQStringList getAvailableVariants(const TQString& layout);
- unsigned int getDefaultGroup(const TQString& layout, const TQString& includeGroup);
- bool isSingleGroup(const TQString& layout);
+ TQString getLayoutName(LayoutUnit layout) const;
-protected:
+ /// A helper to translate option description
+ static TQString trOpt(TQString opt);
+protected:
void loadRules(TQString filename, bool layoutsOnly=false);
- void loadGroups(TQString filename);
- void loadOldLayouts(TQString filename);
private:
TQDict<char> m_models;
TQDict<char> m_layouts;
TQDict<char> m_options;
- TQMap<TQString, unsigned int> m_initialGroups;
TQDict<TQStringList> m_varLists;
- TQStringList m_oldLayouts;
- TQStringList m_nonLatinLayouts;
-
+
TQString X11_DIR; // pseudo-constant
-
+
// void fixLayouts();
};
diff --git a/kxkb/x11helper.cpp b/kxkb/x11helper.cpp
index 1c8db4a4a..d325b32a0 100644
--- a/kxkb/x11helper.cpp
+++ b/kxkb/x11helper.cpp
@@ -1,3 +1,4 @@
+#include <tqdom.h>
#include <tqdir.h>
#include <tqstring.h>
#include <tqwindowdefs.h>
@@ -7,6 +8,8 @@
#include <tqregexp.h>
#include <kdebug.h>
+#include <tdestandarddirs.h>
+#include <tdelocale.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
@@ -119,13 +122,12 @@ X11Helper::findXkbRulesFile(TQString x11Dir, Display *dpy)
}
}
}
-
+
return rulesFile;
}
RulesInfo*
-X11Helper::loadRules(const TQString& file, bool layoutsOnly)
-{
+X11Helper::loadRules(const TQString& file, bool layoutsOnly) {
XkbRF_RulesPtr xkbRules = XkbRF_Load(TQFile::encodeName(file).data(), "", true, true);
if (xkbRules == NULL) {
@@ -151,32 +153,87 @@ X11Helper::loadRules(const TQString& file, bool layoutsOnly)
XkbRF_Free(xkbRules, true);
return rulesInfo;
}
-
+
for (int i = 0; i < xkbRules->models.num_desc; ++i)
rulesInfo->models.replace(xkbRules->models.desc[i].name, tqstrdup( xkbRules->models.desc[i].desc ) );
- for (int i = 0; i < xkbRules->options.num_desc; ++i)
- rulesInfo->options.replace(xkbRules->options.desc[i].name, tqstrdup( xkbRules->options.desc[i].desc ) );
- XkbRF_Free(xkbRules, true);
+ // Prefer XML file for Xkb options
+ if (TQFile(file + ".xml").exists()) {
+ XkbRF_Free(xkbRules, true);
+
+ TQDomDocument xmlrules("xkbrules");
+ TQFile xmlfile(file + ".xml");
+ if (!xmlfile.open(IO_ReadOnly)) {
+ return NULL;
+ }
+ if (!xmlrules.setContent(&xmlfile)) {
+ xmlfile.close();
+ return NULL;
+ }
+ xmlfile.close();
+
+ TQDomElement options = xmlrules.documentElement().namedItem("optionList").toElement();
+ TQDomNode optGroupNode = options.firstChild();
+ while (!optGroupNode.isNull()) {
+ TQDomElement optGroupElem = optGroupNode.toElement();
+ if (optGroupElem.tagName() == "group") {
+ TQDomNode optNode = optGroupElem.firstChild();
+ while (!optNode.isNull()) {
+ TQDomElement optElem = optNode.toElement();
+ if (!optElem.isNull()) {
+ // This might be either a configItem (group) or an option tag
+ // If it is an option tag, it contains a configItem that describes
+ // the option
+ if (optElem.tagName() == "option") {
+ optElem = optElem.namedItem("configItem").toElement();
+ }
+
+ TQString optName = optElem.namedItem("name").toElement().text();
+ TQString optDesc = optElem.namedItem("description").toElement().text();
+ if (optDesc.isEmpty()) {
+ optDesc = optName;
+ }
+ // Items from these 'meta' groups fall into other groups
+ // Admittedly not the best way to handle this
+ if (optName == "currencysign" || optName == "compat") break;
+
+ // HACK this should be called "compose" or else the code breaks
+ if (optName == "Compose key") optName = "compose";
+
+ rulesInfo->options.replace(optName.ascii(), tqstrdup(optDesc.ascii()));
+ }
+ optNode = optNode.nextSibling();
+ }
+ }
+ optGroupNode = optGroupNode.nextSibling();
+ }
+ }
+ else {
+ for (int i = 0; i < xkbRules->options.num_desc; ++i)
+ rulesInfo->options.replace(xkbRules->options.desc[i].name, tqstrdup( xkbRules->options.desc[i].desc ) );
+
+ XkbRF_Free(xkbRules, true);
+
+ // workaround for empty 'compose' options group description
+ if( rulesInfo->options.find("compose:menu") && !rulesInfo->options.find("compose") ) {
+ rulesInfo->options.replace("compose", I18N_NOOP("Compose Key Position"));
+ }
+ }
-// workaround for empty 'compose' options group description
- if( rulesInfo->options.find("compose:menu") && !rulesInfo->options.find("compose") ) {
- rulesInfo->options.replace("compose", "Compose Key Position");
- }
for(TQDictIterator<char> it(rulesInfo->options) ; it.current() != NULL; ++it ) {
- TQString option(it.currentKey());
- int columnPos = option.find(":");
-
- if( columnPos != -1 ) {
- TQString group = option.mid(0, columnPos);
- if( rulesInfo->options.find(group) == NULL ) {
- rulesInfo->options.replace(group, group.latin1());
- kdDebug() << "Added missing option group: " << group << endl;
- }
- }
+ // Add missing option groups
+ TQString option(it.currentKey());
+ int columnPos = option.find(":");
+
+ if( columnPos != -1 ) {
+ TQString group = option.mid(0, columnPos);
+ if( rulesInfo->options.find(group) == NULL ) {
+ rulesInfo->options.replace(group, group.latin1());
+ kdDebug() << "Added missing option group: " << group << endl;
+ }
+ }
}
-
// // workaround for empty misc options group description in XFree86 4.4.0
// if( rulesInfo->options.find("numpad:microsoft") && !rulesInfo->options.find("misc") ) {
// rulesInfo->options.replace("misc", "Miscellaneous compatibility options" );
@@ -335,3 +392,13 @@ bool X11Helper::areSingleGroupsSupported()
{
return true; //TODO:
}
+
+void X11Helper::initializeTranslations() {
+ // TDE is usually installed into some non-standard prefix and by default system-wide locale
+ // dirs are not considered when searching for gettext message catalogues, so we have to add
+ // it explicitly.
+#ifdef WITH_XKB_TRANSLATIONS
+ TDEGlobal::dirs()->addResourceDir("locale", XKB_CONFIG_LOCALE_DIR);
+ TDEGlobal::locale()->insertCatalogue("xkeyboard-config");
+#endif
+}
diff --git a/kxkb/x11helper.h b/kxkb/x11helper.h
index 042fb4ce5..8315dc446 100644
--- a/kxkb/x11helper.h
+++ b/kxkb/x11helper.h
@@ -3,6 +3,7 @@
#include <tqdict.h>
#include <tqstringlist.h>
+#include <tqwindowdefs.h>
struct RulesInfo {
@@ -36,6 +37,7 @@ public:
static bool areLayoutsClean() { return m_layoutsClean; }
static bool areSingleGroupsSupported();
+ static void initializeTranslations();
};
#endif /*X11HELPER_H_*/