// Returns iSeq index if cut2 has a sequence of equal or higher priority to a sequence in cut. // else -1 static int keyConflict(const KShortcut &cut, const KShortcut &cut2) { for(uint iSeq = 0; iSeq < cut.count(); iSeq++) { for(uint iSeq2 = 0; iSeq2 < cut2.count(); iSeq2++) { if(cut.seq(iSeq) == cut2.seq(iSeq2)) return iSeq; } } return -1; }
void starter::addShortcut(const KShortcut &cut) { // in case of empty shortcut, remove the entry from the list and return if (!short(cut.keyCodeQt())) { ShortcutList::Iterator it; for ( it = shortcutList.begin(); it != shortcutList.end(); ++it ) if (it.data() == configDialog->categoryList->currentText()) { shortcutList.remove(it); break; } configDialog->buttonShortcut->setShortcut(KShortcut::null(), false); return; } // generate MyKey short state = 0; if (cut.seq(0).key(0).modFlags() & KKey::CTRL) state |= Qt::ControlButton; if (cut.seq(0).key(0).modFlags() & KKey::ALT) state |= Qt::AltButton; if (cut.seq(0).key(0).modFlags() & KKey::SHIFT) state |= Qt::ShiftButton; MyKey key(cut.seq(0).keyCodeQt(), state); // Test if this is a valid shotrcut, i.e. contains 'ctrl' or 'alt', returns iff not if (!(state & Qt::ControlButton || state & Qt::AltButton)) { KMessageBox::sorry(this, i18n("<qt>To ensure usefull behaviour of the searchline, the shortcut <b>must contain</b> a metabutton, i.e. <b>'ctrl' and/or 'alt'</b></qt>"), i18n("Sorry, invalid Shortcut")); return; } // test if the cut was allready bound to another category and ask the user whta to do (return iff not rebind) ShortcutList::Iterator it = shortcutList.find(key); if ((it != shortcutList.end() && KMessageBox::questionYesNo(this, i18n("<qt>The selected shortcut is allready bound to the category \"%1\".<br>Do you want to <b>rebind</b> it?</qt>").arg(it.data()), i18n("Rebind Shortcut?")) == KMessageBox::No)) return; // if rebind (it is not end and we did not return ;) remove the old shortcut if (it != shortcutList.end()) { shortcutList.remove(it); } // test if another shortcut is bound to this category and remove it in case for ( it = shortcutList.begin(); it != shortcutList.end(); ++it ) if (it.data() == configDialog->categoryList->currentText()) { shortcutList.remove(it); break; } // add new shortcut/category map entry shortcutList[key] = configDialog->categoryList->currentText(); // update UI configDialog->buttonShortcut->setShortcut(cut, false); }
// public static bool kpTool::containsSingleKeyTrigger (const KShortcut &shortcut, KShortcut *shortcutWithoutSingleKeyTriggers) { if (shortcutWithoutSingleKeyTriggers) *shortcutWithoutSingleKeyTriggers = shortcut; KShortcut newShortcut; bool needNewShortcut = false; for (int i = 0; i < (int) shortcut.count (); i++) { const KKeySequence seq = shortcut.seq (i); if (containsSingleKeyTrigger (seq)) { needNewShortcut = true; } else { newShortcut.append (seq); } } if (needNewShortcut && shortcutWithoutSingleKeyTriggers) *shortcutWithoutSingleKeyTriggers = newShortcut; return needNewShortcut; }
bool KKeyChooser::isKeyPresentLocally(const KShortcut &cut, KKeyChooserItem *ignoreItem, bool bWarnUser) { if(cut.toString().isEmpty()) return false; // Search for shortcut conflicts with other actions in the // lists we're configuring. for(QListViewItemIterator it(d->pList); it.current(); ++it) { KKeyChooserItem *pItem2 = dynamic_cast< KKeyChooserItem * >(it.current()); if(pItem2 && pItem2 != ignoreItem) { int iSeq = keyConflict(cut, pItem2->shortcut()); if(iSeq > -1) { if(bWarnUser) { if(!promptForReassign(cut.seq(iSeq), pItem2->text(0), Application, this)) return true; // else remove the shortcut from it KShortcut cut2 = pItem2->shortcut(); removeFromShortcut(cut2, cut); pItem2->setShortcut(cut2); updateButtons(); emit keyChange(); } } } } return false; }
void KKeyChooser::setShortcut(const KShortcut &cut) { kdDebug(125) << "KKeyChooser::setShortcut( " << cut.toString() << " )" << endl; KKeyChooserItem *pItem = dynamic_cast< KKeyChooserItem * >(d->pList->currentItem()); if(!pItem) return; for(uint i = 0; i < cut.count(); i++) { const KKeySequence &seq = cut.seq(i); const KKey &key = seq.key(0); if(!d->bAllowLetterShortcuts && key.modFlags() == 0 && key.sym() < 0x3000 && QChar(key.sym()).isLetterOrNumber()) { QString s = i18n( "In order to use the '%1' key as a shortcut, " "it must be combined with the " "Win, Alt, Ctrl, and/or Shift keys.") .arg(QChar(key.sym())); KMessageBox::sorry(this, s, i18n("Invalid Shortcut Key")); return; } } // If key isn't already in use, if(!isKeyPresent(cut)) { // Set new key code pItem->setShortcut(cut); // Update display updateButtons(); emit keyChange(); } }
// public static QString kpTool::toolTipForTextAndShortcut (const QString &text, const KShortcut &shortcut) { for (int i = 0; i < (int) shortcut.count (); i++) { const KKeySequence seq = shortcut.seq (i); if (seq.count () == 1 && containsSingleKeyTrigger (seq)) { return i18n ("<Tool Name> (<Single Accel Key>)", "%1 (%2)") .arg (text, seq.toString ()); } } return text; }
QString KKeyChooserItem::text(int iCol) const { if(iCol == 0) { // Quick HACK to get rid of '&'s. QString s = m_pList->label(m_iAction); QString s2; for(uint i = 0; i < s.length(); i++) if(s[i] != '&' || (i + 1 < s.length() && s[i + 1] == '&')) s2 += s[i]; return s2; } else if(iCol <= (int)m_cut.count()) return m_cut.seq(iCol - 1).toString(); else return QString::null; }
bool KKeyChooser::checkStandardShortcutsConflict(const KShortcut &cut, bool bWarnUser, QWidget *parent) { // For each key sequence in the shortcut, for(uint i = 0; i < cut.count(); i++) { const KKeySequence &seq = cut.seq(i); KStdAccel::StdAccel id = KStdAccel::findStdAccel(seq); if(id != KStdAccel::AccelNone && keyConflict(cut, KStdAccel::shortcut(id)) > -1) { if(bWarnUser) { if(!promptForReassign(seq, KStdAccel::label(id), Standard, parent)) return true; removeStandardShortcut(KStdAccel::label(id), dynamic_cast< KKeyChooser * >(parent), KStdAccel::shortcut(id), cut); } } } return false; }
bool KKeyChooser::checkGlobalShortcutsConflict(const KShortcut &cut, bool bWarnUser, QWidget *parent, const QMap< QString, KShortcut > &map, const QString &ignoreAction) { QMap< QString, KShortcut >::ConstIterator it; for(it = map.begin(); it != map.end(); ++it) { int iSeq = keyConflict(cut, (*it)); if(iSeq > -1) { if(ignoreAction.isEmpty() || it.key() != ignoreAction) { if(bWarnUser) { if(!promptForReassign(cut.seq(iSeq), it.key(), Global, parent)) return true; removeGlobalShortcut(it.key(), dynamic_cast< KKeyChooser * >(parent), (*it), cut); } } } } return false; }
void KKbdAccessExtensions::displayAccessKeys() { // Build a list of valid access keys that don't collide with shortcuts. QString availableAccessKeys = "ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890"; QPtrList<KXMLGUIClient> allClients = d->mainWindow->factory()->clients(); QPtrListIterator<KXMLGUIClient> it( allClients ); KXMLGUIClient *client; while( (client=it.current()) !=0 ) { ++it; KActionPtrList actions = client->actionCollection()->actions(); for (int j = 0; j < (int)actions.count(); j++) { KAction* action = actions[j]; KShortcut sc = action->shortcut(); for (int i = 0; i < (int)sc.count(); i++) { KKeySequence seq = sc.seq(i); if (seq.count() == 1) { QString s = seq.toString(); if (availableAccessKeys.contains(s)) availableAccessKeys.remove(s); } } } } // Find all visible, focusable widgets and create a QLabel for each. Don't exceed // available list of access keys. QWidgetList* allWidgets = kapp->allWidgets(); QWidget* widget = allWidgets->first(); int accessCount = 0; int maxAccessCount = availableAccessKeys.length(); int overlap = 20; QPoint prevGlobalPos = QPoint(-overlap, -overlap); while (widget && (accessCount < maxAccessCount)) { if (widget->isVisible() && widget->isFocusEnabled() ) { QRect r = widget->rect(); QPoint p(r.x(), r.y()); // Don't display an access key if within overlap pixels of previous one. QPoint globalPos = widget->mapToGlobal(p); QPoint diffPos = globalPos - prevGlobalPos; if (diffPos.manhattanLength() > overlap) { accessCount++; QLabel* lab=new QLabel(widget, "", widget, 0, Qt::WDestructiveClose); lab->setPalette(QToolTip::palette()); lab->setLineWidth(2); lab->setFrameStyle(QFrame::Box | QFrame::Plain); lab->setMargin(3); lab->adjustSize(); lab->move(p); if (!d->accessKeyLabels) { d->accessKeyLabels = new QPtrList<QLabel>; d->accessKeyLabels->setAutoDelete(true); } d->accessKeyLabels->append(lab); prevGlobalPos = globalPos; } } widget = allWidgets->next(); } if (accessCount > 0) { // Sort the access keys from left to right and down the screen. QValueList<KSortedLabel> sortedLabels; for (int i = 0; i < accessCount; i++) sortedLabels.append(KSortedLabel(d->accessKeyLabels->at(i))); qHeapSort( sortedLabels ); // Assign access key labels. for (int i = 0; i < accessCount; i++) { QLabel* lab = sortedLabels[i].label(); QChar s = availableAccessKeys[i]; lab->setText(s); lab->adjustSize(); lab->show(); } } }
// Removes the sequences in cut2 from cut1 static void removeFromShortcut(KShortcut &cut1, const KShortcut &cut2) { for(uint iSeq2 = 0; iSeq2 < cut2.count(); iSeq2++) cut1.remove(cut2.seq(iSeq2)); }