00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "kshortcutsdialog_p.h"
00030 #include "kaction_p.h"
00031
00032 #include <QApplication>
00033 #include <QHeaderView>
00034 #include <QKeyEvent>
00035 #include <QLabel>
00036 #include <QPainter>
00037 #include <QTreeWidgetItemIterator>
00038
00039 #include "kaction.h"
00040
00041 #include "kdebug.h"
00042
00043
00044
00045
00046 KShortcutsEditorDelegate::KShortcutsEditorDelegate(QTreeWidget *parent, bool allowLetterShortcuts)
00047 : KExtendableItemDelegate(parent),
00048 m_allowLetterShortcuts(allowLetterShortcuts),
00049 m_editor(0)
00050 {
00051 Q_ASSERT(qobject_cast<QAbstractItemView *>(parent));
00052
00053 QPixmap pixmap( 16, 16 );
00054 pixmap.fill( QColor( Qt::transparent ) );
00055 QPainter p( &pixmap );
00056 QStyleOption option;
00057 option.rect = pixmap.rect();
00058
00059 bool isRtl = QApplication::isRightToLeft();
00060 QApplication::style()->drawPrimitive( isRtl ? QStyle::PE_IndicatorArrowLeft : QStyle::PE_IndicatorArrowRight, &option, &p );
00061 setExtendPixmap( pixmap );
00062
00063 pixmap.fill( QColor( Qt::transparent ) );
00064 QApplication::style()->drawPrimitive( QStyle::PE_IndicatorArrowDown, &option, &p );
00065 setContractPixmap( pixmap );
00066
00067 parent->installEventFilter(this);
00068
00069
00070
00071 connect(parent, SIGNAL(clicked(QModelIndex)), this, SLOT(itemActivated(QModelIndex)));
00072
00073
00074 connect(parent, SIGNAL(collapsed(QModelIndex)), this, SLOT(itemCollapsed(QModelIndex)));
00075 }
00076
00077
00078 void KShortcutsEditorDelegate::stealShortcut(
00079 const QKeySequence &seq,
00080 KAction *action)
00081 {
00082 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
00083
00084
00085 QTreeWidgetItemIterator it(view, QTreeWidgetItemIterator::NoChildren);
00086
00087 for (; (*it); ++it) {
00088 KShortcutsEditorItem* item = dynamic_cast<KShortcutsEditorItem *>(*it);
00089 if (item && item->data(0, ObjectRole).value<QObject*>() == action) {
00090
00091
00092
00093 KShortcut cut = action->shortcut();
00094 if ( cut.primary().matches(seq) != QKeySequence::NoMatch
00095 || seq.matches(cut.primary()) != QKeySequence::NoMatch) {
00096 item->setKeySequence(LocalPrimary, QKeySequence());
00097 }
00098
00099 if ( cut.alternate().matches(seq) != QKeySequence::NoMatch
00100 || seq.matches(cut.alternate()) != QKeySequence::NoMatch) {
00101 item->setKeySequence(LocalAlternate, QKeySequence());
00102 }
00103 break;
00104 }
00105 }
00106
00107 }
00108
00109
00110 QSize KShortcutsEditorDelegate::sizeHint(const QStyleOptionViewItem &option,
00111 const QModelIndex &index) const
00112 {
00113 QSize ret(KExtendableItemDelegate::sizeHint(option, index));
00114 ret.rheight() += 4;
00115 return ret;
00116 }
00117
00118
00119
00120 void KShortcutsEditorDelegate::itemActivated(QModelIndex index)
00121 {
00122
00123 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
00124
00125 KShortcutsEditorItem *item = KShortcutsEditorPrivate::itemFromIndex(view, index);
00126 if (!item) {
00127
00128 return;
00129 }
00130
00131 int column = index.column();
00132 if (column == Name) {
00133
00134
00135 if (!view->header()->isSectionHidden(LocalPrimary)) {
00136 column = LocalPrimary;
00137 } else if (!view->header()->isSectionHidden(GlobalPrimary)) {
00138 column = GlobalPrimary;
00139 } else {
00140
00141 }
00142 index = index.sibling(index.row(), column);
00143 view->selectionModel()->select(index, QItemSelectionModel::SelectCurrent);
00144 }
00145
00146
00147 if (!index.data(ShowExtensionIndicatorRole).value<bool>()) {
00148 return;
00149 }
00150
00151 if (!isExtended(index)) {
00152
00153 if (m_editingIndex.isValid()) {
00154 QModelIndex idx = index.sibling(m_editingIndex.row(), Name);
00155 KShortcutsEditorItem *oldItem = KShortcutsEditorPrivate::itemFromIndex(view, idx);
00156 Q_ASSERT(oldItem);
00157
00158 oldItem->setNameBold(false);
00159 contractItem(m_editingIndex);
00160 }
00161
00162 m_editingIndex = index;
00163 QWidget *viewport = static_cast<QAbstractItemView*>(parent())->viewport();
00164
00165 if (column >= LocalPrimary && column <= GlobalAlternate) {
00166 ShortcutEditWidget *editor = new ShortcutEditWidget(viewport,
00167 index.data(DefaultShortcutRole).value<QKeySequence>(),
00168 index.data(ShortcutRole).value<QKeySequence>(),
00169 m_allowLetterShortcuts);
00170 if (column==GlobalPrimary) {
00171 QObject *action = index.data(ObjectRole).value<QObject*>();
00172 connect(
00173 action, SIGNAL(globalShortcutChanged(QKeySequence)),
00174 editor, SLOT(setKeySequence(QKeySequence)));
00175 editor->setMultiKeyShortcutsAllowed(false);
00176 KAction *kaction = qobject_cast<KAction*>(action);
00177 if (kaction) {
00178 editor->setComponentName(kaction->d->componentData.componentName());
00179 }
00180 }
00181
00182 m_editor = editor;
00183
00184 if (column == GlobalPrimary || column == GlobalAlternate) {
00185 editor->setCheckForConflictsAgainst(
00186 KKeySequenceWidget::LocalShortcuts
00187 | KKeySequenceWidget::GlobalShortcuts
00188 | KKeySequenceWidget::StandardShortcuts );
00189 }
00190
00191 editor->setCheckActionCollections(m_checkActionCollections);
00192
00193 connect(m_editor, SIGNAL(keySequenceChanged(const QKeySequence &)),
00194 this, SLOT(keySequenceChanged(const QKeySequence &)));
00195 connect(m_editor, SIGNAL(stealShortcut(const QKeySequence &, KAction*)),
00196 this, SLOT(stealShortcut(const QKeySequence&, KAction*)));
00197
00198 } else if (column == RockerGesture) {
00199 m_editor = new QLabel("A lame placeholder", viewport);
00200
00201 } else if (column == ShapeGesture) {
00202 m_editor = new QLabel("<i>A towel</i>", viewport);
00203
00204 } else
00205 return;
00206
00207 m_editor->installEventFilter(this);
00208 item->setNameBold(true);
00209 extendItem(m_editor, index);
00210
00211 } else {
00212
00213 item->setNameBold(false);
00214 contractItem(index);
00215 view->selectionModel()->select(index, QItemSelectionModel::Clear);
00216 m_editingIndex = QModelIndex();
00217 m_editor = 0;
00218 }
00219 }
00220
00221
00222
00223 void KShortcutsEditorDelegate::itemCollapsed(QModelIndex index)
00224 {
00225 if (!m_editingIndex.isValid())
00226 return;
00227
00228 const QAbstractItemModel *model = index.model();
00229 for (int row=0; row<model->rowCount(index);++row) {
00230 QModelIndex rowIndex = model->index(row,0,index);
00231
00232 for (int col=0; col<index.model()->columnCount(index);++col) {
00233 QModelIndex colIndex = model->index(row,col,index);
00234
00235 if (colIndex == m_editingIndex) {
00236 itemActivated(m_editingIndex);
00237 }
00238
00239 }
00240
00241 }
00242
00243 }
00244
00245
00246
00247 void KShortcutsEditorDelegate::hiddenBySearchLine(QTreeWidgetItem *item, bool hidden)
00248 {
00249 if (!hidden || !item) {
00250 return;
00251 }
00252 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
00253 QTreeWidgetItem *editingItem = KShortcutsEditorPrivate::itemFromIndex(view, m_editingIndex);
00254 if (editingItem == item) {
00255 itemActivated(m_editingIndex);
00256 }
00257 }
00258
00259
00260 bool KShortcutsEditorDelegate::eventFilter(QObject *o, QEvent *e)
00261 {
00262 if (o == m_editor) {
00263
00264
00265
00266
00267
00268 switch (e->type()) {
00269 case QEvent::MouseButtonPress:
00270 case QEvent::MouseButtonRelease:
00271 case QEvent::MouseButtonDblClick:
00272 return true;
00273 default:
00274 return false;
00275 }
00276 } else if (o == parent()) {
00277
00278
00279
00280
00281
00282 if (e->type() != QEvent::KeyPress) {
00283 return false;
00284 }
00285 QKeyEvent *ke = static_cast<QKeyEvent *>(e);
00286 QTreeWidget *view = static_cast<QTreeWidget *>(parent());
00287 QItemSelectionModel *selection = view->selectionModel();
00288 QModelIndex index = selection->currentIndex();
00289
00290 switch (ke->key()) {
00291 case Qt::Key_Space:
00292 case Qt::Key_Select:
00293
00294
00295 itemActivated(index);
00296 return true;
00297 case Qt::Key_Left:
00298 index = index.sibling(index.row(), index.column() - 1);
00299 break;
00300 case Qt::Key_Right:
00301 index = index.sibling(index.row(), index.column() + 1);
00302 break;
00303 case Qt::Key_Up:
00304 case Qt::Key_Down: {
00305
00306
00307
00308 QTreeWidgetHack *hView = static_cast<QTreeWidgetHack *>(view);
00309 QTreeWidgetItem *item = hView->itemFromIndex(index);
00310 int column = index.column();
00311 if (ke->key() == Qt::Key_Up) {
00312 item = hView->itemAbove(item);
00313 } else {
00314 item = hView->itemBelow(item);
00315 }
00316 if (!item) {
00317 break;
00318 }
00319 do {
00320 index = hView->indexFromItem(item, column--);
00321 } while (!index.isValid() && column >= 0);
00322
00323 break; }
00324 default:
00325 return false;
00326 }
00327
00328 if (index.isValid()) {
00329 selection->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
00330
00331
00332 view->scrollTo(index, QAbstractItemView::PositionAtCenter);
00333 }
00334 return true;
00335 }
00336 return false;
00337 }
00338
00339
00340
00341 void KShortcutsEditorDelegate::keySequenceChanged(const QKeySequence &seq)
00342 {
00343 QVariant ret = QVariant::fromValue(seq);
00344 emit shortcutChanged(ret, m_editingIndex);
00345 }
00346
00347
00348 void KShortcutsEditorDelegate::setCheckActionCollections(
00349 const QList<KActionCollection*> checkActionCollections )
00350 {
00351 m_checkActionCollections = checkActionCollections;
00352 }
00353
00354
00355 void KShortcutsEditorDelegate::shapeGestureChanged(const KShapeGesture &gest)
00356 {
00357
00358 QVariant ret = QVariant::fromValue(gest);
00359 emit shortcutChanged(ret, m_editingIndex);
00360 }
00361
00362
00363
00364 void KShortcutsEditorDelegate::rockerGestureChanged(const KRockerGesture &gest)
00365 {
00366 QVariant ret = QVariant::fromValue(gest);
00367 emit shortcutChanged(ret, m_editingIndex);
00368 }
00369