diff options
Diffstat (limited to 'kxkb/kcmlayout.cpp')
| -rw-r--r-- | kxkb/kcmlayout.cpp | 417 | 
1 files changed, 352 insertions, 65 deletions
| diff --git a/kxkb/kcmlayout.cpp b/kxkb/kcmlayout.cpp index baadfd7e0..a2b5d8e12 100644 --- a/kxkb/kcmlayout.cpp +++ b/kxkb/kcmlayout.cpp @@ -24,6 +24,7 @@  #include <kdebug.h>  #include <tdeapplication.h>  #include <kiconloader.h> +#include <tdemessagebox.h>  #include <dcopref.h>  #include <dcopclient.h> @@ -99,7 +100,8 @@ static TQListViewItem* copyLVI(const TQListViewItem* src, TQListView* parent)  LayoutConfig::LayoutConfig(TQWidget *parent, const char *name)    : TDECModule(parent, name), -    m_rules(NULL) +    m_rules(NULL), +    m_forceGrpOverwrite(false)  {    TQVBoxLayout *main = new TQVBoxLayout(this, 0, KDialog::spacingHint()); @@ -232,6 +234,7 @@ void LayoutConfig::initUI() {  			widget->comboHotkey->insertItem(i18n(hkDesc));  		}  	} +	widget->comboHotkey->insertItem(i18n("None"));  	widget->comboHotkey->insertItem(i18n("Other..."));  	// display KXKB switching options @@ -243,7 +246,7 @@ void LayoutConfig::initUI() {  	widget->radFlagOnly->setChecked( showFlag && !showLabel );  	widget->radLabelOnly->setChecked( !showFlag && showLabel ); -	widget->checkResetOld->setChecked(m_kxkbConfig.m_resetOldOptions); +	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 ); @@ -280,15 +283,22 @@ void LayoutConfig::initUI() {  	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 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]; + +		if (optionKey == "grp") { +			foundGrp = true; +		} +  		OptionListItem *item = m_optionGroups[i18n(optionKey.latin1())];  		if (item != NULL) { @@ -304,8 +314,15 @@ void LayoutConfig::initUI() {  		}  	} +	if (!foundGrp) { +		OptionListItem *grpNone = itemForOption("grp:none"); +		if (grpNone) { +			grpNone->setOn(true); +		} +	} +  	updateOptionsCommand(); -	updateHotkeyCombo(); +	updateHotkeyCombo(true);  	emit TDECModule::changed( false );  } @@ -315,7 +332,7 @@ void LayoutConfig::save()  	TQString model = lookupLocalized(m_rules->models(), widget->comboModel->currentText());  	m_kxkbConfig.m_model = model; -	m_kxkbConfig.m_resetOldOptions = widget->checkResetOld->isChecked(); +	m_kxkbConfig.m_resetOldOptions = widget->radXkbOverwrite->isOn();  	m_kxkbConfig.m_options = createOptionString();  	m_kxkbConfig.m_useThemeColors = widget->radLabelUseTheme->isChecked(); @@ -373,6 +390,35 @@ void LayoutConfig::save()  	m_kxkbConfig.save(); +	// We might need to unset previous hotkey options +	if (m_forceGrpOverwrite) +	{ +		// First get all the server's options +		TQStringList srvOptions = TQStringList::split(",", XKBExtension::getServerOptions()); +		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::setXkbOptions(xkbOptions)) +		{ +			kdWarning() << "[LayoutConfig::save] Could not overwrite previous grp: options!" << endl; +		} + +		m_forceGrpOverwrite = false; +	} +  	// Get current layout from Kxkb  	if (!kapp->dcopClient()->isAttached())  		kapp->dcopClient()->attach(); @@ -405,6 +451,8 @@ void LayoutConfig::save()  		}  	} +	updateHotkeyCombo(); +  	emit TDECModule::changed( false );  } @@ -518,6 +566,7 @@ void LayoutConfig::variantChanged()  	if( selectedVariant == DEFAULT_VARIANT_NAME )  		selectedVariant = "";  	selLayout->setText(LAYOUT_COLUMN_VARIANT, selectedVariant); +	updateLayoutCommand();  }  // helper @@ -598,12 +647,12 @@ TQWidget* LayoutConfig::makeOptionsTab()    listView->clear();    connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(changed())); -  connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(updateOptionsCommand())); +  connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(resolveConflicts(TQListViewItem *)));    connect(listView, TQT_SIGNAL(clicked(TQListViewItem *)), TQT_SLOT(updateHotkeyCombo())); -  connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(changed())); -  connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateOptionsCommand())); -  connect(widget->checkResetOld, TQT_SIGNAL(toggled(bool)), TQT_SLOT(updateHotkeyCombo())); +  connect(widget->xkbOptsMode, TQT_SIGNAL(released(int)), TQT_SLOT(changed())); +  connect(widget->xkbOptsMode, TQT_SIGNAL(released(int)), TQT_SLOT(updateOptionsCommand())); +  connect(widget->xkbOptsMode, TQT_SIGNAL(released(int)), TQT_SLOT(updateHotkeyCombo()));    //Create controllers for all options    TQDictIterator<char> it(m_rules->options()); @@ -613,13 +662,20 @@ TQWidget* LayoutConfig::makeOptionsTab()      if (!it.currentKey().contains(':'))      {        if( it.currentKey() == "ctrl" || it.currentKey() == "caps" -          || it.currentKey() == "altwin" || it.currentKey() == "grp") { +          || it.currentKey() == "altwin") {          parent = new OptionListItem(listView, i18n( 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, i18n(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() ),              TQCheckListItem::CheckBoxController, it.currentKey()); @@ -643,12 +699,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 ) +        if ( parent->type() == TQCheckListItem::CheckBoxController +             || key.startsWith("grp:"))              new OptionListItem(parent, i18n(text.utf8()), -                TQCheckListItem::RadioButton, key); +                TQCheckListItem::CheckBox, key);          else              new OptionListItem(parent, i18n(text.utf8()), -                TQCheckListItem::CheckBox, key); +                TQCheckListItem::RadioButton, key);        }      }    } @@ -662,14 +719,19 @@ 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() @@ -726,38 +788,268 @@ void LayoutConfig::updateLayoutCommand()    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[i18n("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[i18n("grp")];      if (grpItem == NULL) {          kdWarning() << "LayoutConfig: cannot find grp item group" << endl;          return;      } -    OptionListItem *child = (OptionListItem*)grpItem->firstChild(); -    while (child) { -        if (child->isOn()) { -            bool found = false; -            for (int i = 0; i < widget->comboHotkey->count(); ++i) { -                if (child->text() == widget->comboHotkey->text(i)) { -                    widget->comboHotkey->setCurrentItem(i); -                    found = true; -                } +    TQStringList hotkeys; + +    // Get server options first +    if (initial || widget->xkbOptsMode->selectedId() == 1) +    { +        TQStringList opts = TQStringList::split(",", XKBExtension::getServerOptions()); +        for (TQStringList::Iterator it = opts.begin(); it != opts.end(); ++it) +        { +            TQString option(*it); + +            if (!option.startsWith("grp:")) +            { +                continue;              } -            if (!found) { -                int other = widget->comboHotkey->count() - 1; -                widget->comboHotkey->changeItem(i18n("Other (%1)...").arg(child->text()), -                                                other); -                widget->comboHotkey->setCurrentItem(other); + +            // 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() { -    TQString hkDesc = widget->comboHotkey->currentText(); +    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[i18n("grp")];      if (grpItem == NULL) { @@ -767,21 +1059,17 @@ void LayoutConfig::hotkeyComboChanged() {      OptionListItem *child = (OptionListItem*)grpItem->firstChild();      while (child) { -        child->setOn(child->text() == hkDesc); +        child->setOn(hotkeys.contains(child->text()));          child = (OptionListItem*)child->nextSibling();      } -    // Other... -    if (widget->comboHotkey->count() - 1 == widget->comboHotkey->currentItem()) { -        OptionListItem *none = grpItem->findChildItem("none"); -        if (none) { -            none->setOn(true); -        } -        widget->tabWidget->setCurrentPage(2); -        widget->listOptions->setCurrentItem(none); -        widget->listOptions->ensureItemVisible(none); +    if (widget->comboHotkey->currentItem() == other) { +        widget->tabWidget->setCurrentPage(3); +        widget->listOptions->ensureItemVisible(grpItem);          widget->listOptions->setFocus();      } + +    m_forceGrpOverwrite = true;  }  void LayoutConfig::changed() @@ -831,6 +1119,20 @@ void LayoutConfig::loadRules()  	//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()  { @@ -838,32 +1140,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; @@ -931,7 +1218,7 @@ extern "C"  			kapp->startServiceByDesktopName("kxkb");  		}  		else { -			if (!XKBExtension::setXkbOptions(m_kxkbConfig.getXkbOptions())) { +			if (!XKBExtension::setXkbOptions(m_kxkbConfig.getKXkbOptions())) {  				kdDebug() << "Setting XKB options failed!" << endl;  			}  		} | 
