Changeset View
Changeset View
Standalone View
Standalone View
plugins/quickopen/quickopenwidget.cpp
Show All 15 Lines | |||||
16 | * | 16 | * | ||
17 | * You should have received a copy of the GNU General Public | 17 | * You should have received a copy of the GNU General Public | ||
18 | * License along with this program; if not, write to the | 18 | * License along with this program; if not, write to the | ||
19 | * Free Software Foundation, Inc., | 19 | * Free Software Foundation, Inc., | ||
20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 20 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
21 | */ | 21 | */ | ||
22 | 22 | | |||
23 | #include "quickopenwidget.h" | 23 | #include "quickopenwidget.h" | ||
24 | #include <KParts/MainWindow> | | |||
25 | #include "debug.h" | 24 | #include "debug.h" | ||
26 | 25 | | |||
27 | #include "expandingtree/expandingdelegate.h" | 26 | #include "expandingtree/expandingdelegate.h" | ||
28 | #include "quickopenmodel.h" | 27 | #include "quickopenmodel.h" | ||
29 | 28 | | |||
30 | #include <icore.h> | 29 | #include <icore.h> | ||
31 | #include <iuicontroller.h> | 30 | #include <iuicontroller.h> | ||
32 | 31 | | |||
33 | #include <QDialog> | 32 | #include <QDialog> | ||
33 | #include <QIdentityProxyModel> | ||||
34 | #include <QMenuBar> | 34 | #include <QMenuBar> | ||
35 | #include <QKeyEvent> | 35 | #include <QKeyEvent> | ||
36 | #include <QScrollBar> | 36 | #include <QScrollBar> | ||
37 | 37 | | |||
38 | #include <KParts/MainWindow> | ||||
38 | #include <KTextEditor/CodeCompletionModel> | 39 | #include <KTextEditor/CodeCompletionModel> | ||
39 | 40 | | |||
40 | using namespace KDevelop; | 41 | using namespace KDevelop; | ||
41 | 42 | | |||
42 | class QuickOpenDelegate : public ExpandingDelegate { | 43 | class QuickOpenDelegate : public ExpandingDelegate { | ||
43 | Q_OBJECT | 44 | Q_OBJECT | ||
44 | public: | 45 | public: | ||
45 | explicit QuickOpenDelegate(ExpandingWidgetModel* model, QObject* parent = nullptr) : ExpandingDelegate(model, parent) { | 46 | explicit QuickOpenDelegate(ExpandingWidgetModel* model, QObject* parent = nullptr) : ExpandingDelegate(model, parent) { | ||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Line(s) | 144 | if(show) { | |||
144 | ui.okButton->show(); | 145 | ui.okButton->show(); | ||
145 | ui.cancelButton->show(); | 146 | ui.cancelButton->show(); | ||
146 | }else{ | 147 | }else{ | ||
147 | ui.okButton->hide(); | 148 | ui.okButton->hide(); | ||
148 | ui.cancelButton->hide(); | 149 | ui.cancelButton->hide(); | ||
149 | } | 150 | } | ||
150 | } | 151 | } | ||
151 | 152 | | |||
153 | bool QuickOpenWidget::sortingEnabled() const | ||||
154 | { | ||||
155 | return m_sortingEnabled; | ||||
156 | } | ||||
157 | | ||||
158 | void QuickOpenWidget::setSortingEnabled(bool enabled) | ||||
159 | { | ||||
160 | m_sortingEnabled = enabled; | ||||
161 | } | ||||
162 | | ||||
152 | void QuickOpenWidget::updateTimerInterval(bool cheapFilterChange) | 163 | void QuickOpenWidget::updateTimerInterval(bool cheapFilterChange) | ||
153 | { | 164 | { | ||
154 | const int MAX_ITEMS = 10000; | 165 | const int MAX_ITEMS = 10000; | ||
155 | if ( cheapFilterChange && m_model->rowCount(QModelIndex()) < MAX_ITEMS ) { | 166 | if ( cheapFilterChange && m_model->rowCount(QModelIndex()) < MAX_ITEMS ) { | ||
156 | // cheap change and there are currently just a few items, | 167 | // cheap change and there are currently just a few items, | ||
157 | // so apply filter instantly | 168 | // so apply filter instantly | ||
158 | m_filterTimer.setInterval(0); | 169 | m_filterTimer.setInterval(0); | ||
159 | } else if ( m_model->unfilteredRowCount() < MAX_ITEMS ) { | 170 | } else if ( m_model->unfilteredRowCount() < MAX_ITEMS ) { | ||
Show All 30 Lines | 197 | { | |||
190 | }else{ | 201 | }else{ | ||
191 | ui.searchLine->hide(); | 202 | ui.searchLine->hide(); | ||
192 | ui.searchLabel->hide(); | 203 | ui.searchLabel->hide(); | ||
193 | } | 204 | } | ||
194 | } | 205 | } | ||
195 | 206 | | |||
196 | void QuickOpenWidget::prepareShow() | 207 | void QuickOpenWidget::prepareShow() | ||
197 | { | 208 | { | ||
198 | ui.list->setModel( nullptr ); | 209 | ui.list->setModel(nullptr); | ||
199 | ui.list->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); | 210 | ui.list->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); | ||
200 | m_model->setTreeView( ui.list ); | 211 | m_model->setTreeView(ui.list); | ||
201 | ui.list->setModel( m_model ); | 212 | | ||
213 | // set up proxy filter | ||||
214 | delete m_proxy; | ||||
215 | m_proxy = nullptr; | ||||
216 | | ||||
217 | if (sortingEnabled()) { | ||||
218 | auto sortFilterProxyModel = new QSortFilterProxyModel(this); | ||||
219 | sortFilterProxyModel->setDynamicSortFilter(true); | ||||
220 | m_proxy = sortFilterProxyModel; | ||||
221 | } else { | ||||
222 | m_proxy = new QIdentityProxyModel(this); | ||||
223 | } | ||||
224 | m_proxy->setSourceModel(m_model); | ||||
225 | if (sortingEnabled()) { | ||||
226 | m_proxy->sort(1); | ||||
227 | } | ||||
228 | ui.list->setModel(m_proxy); | ||||
202 | 229 | | |||
203 | m_filterTimer.stop(); | 230 | m_filterTimer.stop(); | ||
204 | m_filter = QString(); | 231 | m_filter = QString(); | ||
205 | 232 | | |||
206 | if (!m_preselectedText.isEmpty()) | 233 | if (!m_preselectedText.isEmpty()) | ||
207 | { | 234 | { | ||
208 | ui.searchLine->setText(m_preselectedText); | 235 | ui.searchLine->setText(m_preselectedText); | ||
209 | ui.searchLine->selectAll(); | 236 | ui.searchLine->selectAll(); | ||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Line(s) | 329 | { | |||
306 | m_filterTimer.start(); | 333 | m_filterTimer.start(); | ||
307 | } | 334 | } | ||
308 | 335 | | |||
309 | void QuickOpenWidget::applyFilter() | 336 | void QuickOpenWidget::applyFilter() | ||
310 | { | 337 | { | ||
311 | m_model->textChanged( m_filter ); | 338 | m_model->textChanged( m_filter ); | ||
312 | 339 | | |||
313 | QModelIndex currentIndex = m_model->index(0, 0, QModelIndex()); | 340 | QModelIndex currentIndex = m_model->index(0, 0, QModelIndex()); | ||
314 | ui.list->selectionModel()->setCurrentIndex( currentIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows | QItemSelectionModel::Current ); | 341 | | ||
342 | ui.list->selectionModel()->setCurrentIndex( m_proxy->mapFromSource( currentIndex ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows | QItemSelectionModel::Current ); | ||||
315 | 343 | | |||
316 | callRowSelected(); | 344 | callRowSelected(); | ||
317 | } | 345 | } | ||
318 | 346 | | |||
319 | void QuickOpenWidget::callRowSelected() { | 347 | void QuickOpenWidget::callRowSelected() { | ||
320 | QModelIndex currentIndex = ui.list->selectionModel()->currentIndex(); | 348 | const QModelIndex currentIndex = ui.list->currentIndex(); | ||
321 | if( currentIndex.isValid() ) | 349 | if( currentIndex.isValid() ) | ||
322 | m_model->rowSelected( currentIndex ); | 350 | m_model->rowSelected(m_proxy->mapToSource(currentIndex)); | ||
323 | else | 351 | else | ||
324 | qCDebug(PLUGIN_QUICKOPEN) << "current index is not valid"; | 352 | qCDebug(PLUGIN_QUICKOPEN) << "current index is not valid"; | ||
325 | } | 353 | } | ||
326 | 354 | | |||
327 | void QuickOpenWidget::accept() { | 355 | void QuickOpenWidget::accept() { | ||
328 | QString filterText = ui.searchLine->text(); | 356 | QString filterText = ui.searchLine->text(); | ||
329 | m_model->execute( ui.list->currentIndex(), filterText ); | 357 | m_model->execute( m_proxy->mapToSource( ui.list->currentIndex() ), filterText ); | ||
330 | } | 358 | } | ||
331 | 359 | | |||
332 | void QuickOpenWidget::doubleClicked ( const QModelIndex & index ) { | 360 | void QuickOpenWidget::doubleClicked ( const QModelIndex & index ) { | ||
333 | // crash guard: https://bugs.kde.org/show_bug.cgi?id=297178 | 361 | // crash guard: https://bugs.kde.org/show_bug.cgi?id=297178 | ||
334 | ui.list->setCurrentIndex(index); | 362 | ui.list->setCurrentIndex(index); | ||
335 | QMetaObject::invokeMethod(this, "accept", Qt::QueuedConnection); | 363 | QMetaObject::invokeMethod(this, "accept", Qt::QueuedConnection); | ||
336 | QMetaObject::invokeMethod(this, "ready", Qt::QueuedConnection); | 364 | QMetaObject::invokeMethod(this, "ready", Qt::QueuedConnection); | ||
337 | } | 365 | } | ||
Show All 11 Lines | |||||
349 | bool QuickOpenWidget::eventFilter ( QObject * watched, QEvent * event ) | 377 | bool QuickOpenWidget::eventFilter ( QObject * watched, QEvent * event ) | ||
350 | { | 378 | { | ||
351 | QKeyEvent *keyEvent = dynamic_cast<QKeyEvent*>(event); | 379 | QKeyEvent *keyEvent = dynamic_cast<QKeyEvent*>(event); | ||
352 | 380 | | |||
353 | if( event->type() == QEvent::KeyRelease ) { | 381 | if( event->type() == QEvent::KeyRelease ) { | ||
354 | if(keyEvent->key() == Qt::Key_Alt) { | 382 | if(keyEvent->key() == Qt::Key_Alt) { | ||
355 | if((m_expandedTemporary && m_altDownTime.msecsTo( QTime::currentTime() ) > 300) || (!m_expandedTemporary && m_altDownTime.msecsTo( QTime::currentTime() ) < 300 && m_hadNoCommandSinceAlt)) { | 383 | if((m_expandedTemporary && m_altDownTime.msecsTo( QTime::currentTime() ) > 300) || (!m_expandedTemporary && m_altDownTime.msecsTo( QTime::currentTime() ) < 300 && m_hadNoCommandSinceAlt)) { | ||
356 | //Unexpand the item | 384 | //Unexpand the item | ||
357 | QModelIndex row = ui.list->selectionModel()->currentIndex(); | 385 | QModelIndex row = m_proxy->mapToSource(ui.list->selectionModel()->currentIndex()); | ||
358 | if( row.isValid() ) { | 386 | if( row.isValid() ) { | ||
359 | row = row.sibling( row.row(), 0 ); | 387 | row = row.sibling( row.row(), 0 ); | ||
360 | if(m_model->isExpanded( row )) | 388 | if(m_model->isExpanded( row )) | ||
361 | m_model->setExpanded( row, false ); | 389 | m_model->setExpanded( row, false ); | ||
362 | } | 390 | } | ||
363 | } | 391 | } | ||
364 | m_expandedTemporary = false; | 392 | m_expandedTemporary = false; | ||
365 | } | 393 | } | ||
366 | } | 394 | } | ||
367 | 395 | | |||
368 | if( event->type() == QEvent::KeyPress ) { | 396 | if( event->type() == QEvent::KeyPress ) { | ||
369 | m_hadNoCommandSinceAlt = false; | 397 | m_hadNoCommandSinceAlt = false; | ||
370 | if(keyEvent->key() == Qt::Key_Alt) { | 398 | if(keyEvent->key() == Qt::Key_Alt) { | ||
371 | avoidMenuAltFocus(); | 399 | avoidMenuAltFocus(); | ||
372 | m_hadNoCommandSinceAlt = true; | 400 | m_hadNoCommandSinceAlt = true; | ||
373 | //Expand | 401 | //Expand | ||
374 | QModelIndex row = ui.list->selectionModel()->currentIndex(); | 402 | QModelIndex row = m_proxy->mapToSource(ui.list->selectionModel()->currentIndex()); | ||
375 | if( row.isValid() ) { | 403 | if( row.isValid() ) { | ||
376 | row = row.sibling( row.row(), 0 ); | 404 | row = row.sibling( row.row(), 0 ); | ||
377 | m_altDownTime = QTime::currentTime(); | 405 | m_altDownTime = QTime::currentTime(); | ||
378 | if(!m_model->isExpanded( row )) { | 406 | if(!m_model->isExpanded( row )) { | ||
379 | m_expandedTemporary = true; | 407 | m_expandedTemporary = true; | ||
380 | m_model->setExpanded( row, true ); | 408 | m_model->setExpanded( row, true ); | ||
381 | } | 409 | } | ||
382 | } | 410 | } | ||
Show All 15 Lines | 423 | if ( keyEvent->modifiers() == Qt::ShiftModifier ) { | |||
398 | QCoreApplication::sendEvent(ui.list, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Up, Qt::NoModifier)); | 426 | QCoreApplication::sendEvent(ui.list, new QKeyEvent(QEvent::KeyRelease, Qt::Key_Up, Qt::NoModifier)); | ||
399 | return true; | 427 | return true; | ||
400 | } | 428 | } | ||
401 | break; | 429 | break; | ||
402 | case Qt::Key_Down: | 430 | case Qt::Key_Down: | ||
403 | case Qt::Key_Up: | 431 | case Qt::Key_Up: | ||
404 | { | 432 | { | ||
405 | if( keyEvent->modifiers() == Qt::AltModifier ) { | 433 | if( keyEvent->modifiers() == Qt::AltModifier ) { | ||
406 | QWidget* w = m_model->expandingWidget(ui.list->selectionModel()->currentIndex()); | 434 | const QModelIndex index = m_proxy->mapToSource(ui.list->currentIndex()); | ||
435 | QWidget* w = m_model->expandingWidget(index); | ||||
407 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | 436 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | ||
408 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | 437 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | ||
409 | if( keyEvent->key() == Qt::Key_Down ) | 438 | if( keyEvent->key() == Qt::Key_Down ) | ||
410 | interface->down(); | 439 | interface->down(); | ||
411 | else | 440 | else | ||
412 | interface->up(); | 441 | interface->up(); | ||
413 | return true; | 442 | return true; | ||
414 | } | 443 | } | ||
415 | return false; | 444 | return false; | ||
416 | } | 445 | } | ||
417 | } | 446 | } | ||
418 | case Qt::Key_PageUp: | 447 | case Qt::Key_PageUp: | ||
419 | case Qt::Key_PageDown: | 448 | case Qt::Key_PageDown: | ||
420 | if(watched == ui.list ) | 449 | if(watched == ui.list ) | ||
421 | return false; | 450 | return false; | ||
422 | QApplication::sendEvent( ui.list, event ); | 451 | QApplication::sendEvent( ui.list, event ); | ||
423 | //callRowSelected(); | 452 | //callRowSelected(); | ||
424 | return true; | 453 | return true; | ||
425 | 454 | | |||
426 | case Qt::Key_Left: { | 455 | case Qt::Key_Left: { | ||
427 | //Expand/unexpand | 456 | //Expand/unexpand | ||
428 | if( keyEvent->modifiers() == Qt::AltModifier ) { | 457 | if( keyEvent->modifiers() == Qt::AltModifier ) { | ||
429 | //Eventually Send action to the widget | 458 | //Eventually Send action to the widget | ||
430 | QWidget* w = m_model->expandingWidget(ui.list->selectionModel()->currentIndex()); | 459 | const QModelIndex index = m_proxy->mapToSource(ui.list->currentIndex()); | ||
460 | QWidget* w = m_model->expandingWidget(index); | ||||
431 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | 461 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | ||
432 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | 462 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | ||
433 | interface->previous(); | 463 | interface->previous(); | ||
434 | return true; | 464 | return true; | ||
435 | } | 465 | } | ||
436 | } else { | 466 | } else { | ||
437 | QModelIndex row = ui.list->selectionModel()->currentIndex(); | 467 | QModelIndex row = m_proxy->mapToSource(ui.list->currentIndex()); | ||
438 | if( row.isValid() ) { | 468 | if( row.isValid() ) { | ||
439 | row = row.sibling( row.row(), 0 ); | 469 | row = row.sibling( row.row(), 0 ); | ||
440 | 470 | | |||
441 | if( m_model->isExpanded( row ) ) { | 471 | if( m_model->isExpanded( row ) ) { | ||
442 | m_model->setExpanded( row, false ); | 472 | m_model->setExpanded( row, false ); | ||
443 | return true; | 473 | return true; | ||
444 | } | 474 | } | ||
445 | } | 475 | } | ||
446 | } | 476 | } | ||
447 | return false; | 477 | return false; | ||
448 | } | 478 | } | ||
449 | case Qt::Key_Right: { | 479 | case Qt::Key_Right: { | ||
450 | //Expand/unexpand | 480 | //Expand/unexpand | ||
451 | if( keyEvent->modifiers() == Qt::AltModifier ) { | 481 | if( keyEvent->modifiers() == Qt::AltModifier ) { | ||
452 | //Eventually Send action to the widget | 482 | //Eventually Send action to the widget | ||
453 | QWidget* w = m_model->expandingWidget(ui.list->selectionModel()->currentIndex()); | 483 | const QModelIndex index = m_proxy->mapToSource(ui.list->currentIndex()); | ||
484 | QWidget* w = m_model->expandingWidget(index); | ||||
454 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | 485 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | ||
455 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | 486 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | ||
456 | interface->next(); | 487 | interface->next(); | ||
457 | return true; | 488 | return true; | ||
458 | } | 489 | } | ||
459 | } else { | 490 | } else { | ||
460 | QModelIndex row = ui.list->selectionModel()->currentIndex(); | 491 | QModelIndex row = m_proxy->mapToSource(ui.list->selectionModel()->currentIndex()); | ||
461 | if( row.isValid() ) { | 492 | if( row.isValid() ) { | ||
462 | row = row.sibling( row.row(), 0 ); | 493 | row = row.sibling( row.row(), 0 ); | ||
463 | 494 | | |||
464 | if( !m_model->isExpanded( row ) ) { | 495 | if( !m_model->isExpanded( row ) ) { | ||
465 | m_model->setExpanded( row, true ); | 496 | m_model->setExpanded( row, true ); | ||
466 | return true; | 497 | return true; | ||
467 | } | 498 | } | ||
468 | } | 499 | } | ||
469 | } | 500 | } | ||
470 | return false; | 501 | return false; | ||
471 | } | 502 | } | ||
472 | case Qt::Key_Return: | 503 | case Qt::Key_Return: | ||
473 | case Qt::Key_Enter: { | 504 | case Qt::Key_Enter: { | ||
474 | if (m_filterTimer.isActive()) { | 505 | if (m_filterTimer.isActive()) { | ||
475 | m_filterTimer.stop(); | 506 | m_filterTimer.stop(); | ||
476 | applyFilter(); | 507 | applyFilter(); | ||
477 | } | 508 | } | ||
478 | if( keyEvent->modifiers() == Qt::AltModifier ) { | 509 | if( keyEvent->modifiers() == Qt::AltModifier ) { | ||
479 | //Eventually Send action to the widget | 510 | //Eventually Send action to the widget | ||
480 | QWidget* w = m_model->expandingWidget(ui.list->selectionModel()->currentIndex()); | 511 | const QModelIndex index = m_proxy->mapToSource(ui.list->currentIndex()); | ||
512 | QWidget* w = m_model->expandingWidget(index); | ||||
481 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | 513 | if( KDevelop::QuickOpenEmbeddedWidgetInterface* interface = | ||
482 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | 514 | dynamic_cast<KDevelop::QuickOpenEmbeddedWidgetInterface*>( w ) ){ | ||
483 | interface->accept(); | 515 | interface->accept(); | ||
484 | return true; | 516 | return true; | ||
485 | } | 517 | } | ||
486 | } else { | 518 | } else { | ||
487 | QString filterText = ui.searchLine->text(); | 519 | QString filterText = ui.searchLine->text(); | ||
488 | 520 | | |||
489 | //Safety: Track whether this object is deleted. When execute() is called, a dialog may be opened, | 521 | //Safety: Track whether this object is deleted. When execute() is called, a dialog may be opened, | ||
490 | //which kills the quickopen widget. | 522 | //which kills the quickopen widget. | ||
491 | QPointer<QObject> stillExists(this); | 523 | QPointer<QObject> stillExists(this); | ||
492 | 524 | | |||
493 | if( m_model->execute( ui.list->currentIndex(), filterText ) ) { | 525 | if( m_model->execute( m_proxy->mapToSource( ui.list->currentIndex() ), filterText ) ) { | ||
494 | 526 | | |||
495 | if(!stillExists) | 527 | if(!stillExists) | ||
496 | return true; | 528 | return true; | ||
497 | 529 | | |||
498 | if(!(keyEvent->modifiers() & Qt::ShiftModifier)) | 530 | if(!(keyEvent->modifiers() & Qt::ShiftModifier)) | ||
499 | emit ready(); | 531 | emit ready(); | ||
500 | } else { | 532 | } else { | ||
501 | //Maybe the filter-text was changed: | 533 | //Maybe the filter-text was changed: | ||
Show All 14 Lines |