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