diff --git a/outputview/ioutputviewmodel.h b/outputview/ioutputviewmodel.h --- a/outputview/ioutputviewmodel.h +++ b/outputview/ioutputviewmodel.h @@ -38,6 +38,15 @@ virtual void activate( const QModelIndex& index ) = 0; /** + * Called when the user wants to see first item. For example, in makebuilder it would be + * first error spot. + * + * @return First model index that is to be highlighted and activated. + * Return invalid index if no appropriate item to highlight exists. + */ + virtual QModelIndex firstHighlightIndex() = 0; + + /** * Called when the user wants to see next item. For example, in makebuilder it would be * next error spot. In subversion plugin it would be the next conflicted item. * @@ -59,6 +68,15 @@ */ virtual QModelIndex previousHighlightIndex( const QModelIndex& currentIndex ) = 0; + /** + * Called when the user wants to see last item. For example, in makebuilder it would be + * last error spot. + * + * @return Last model index that is to be highlighted and activated. + * Return invalid index if no appropriate item to highlight exists. + */ + virtual QModelIndex lastHighlightIndex() = 0; + }; } diff --git a/outputview/outputmodel.h b/outputview/outputmodel.h --- a/outputview/outputmodel.h +++ b/outputview/outputmodel.h @@ -59,8 +59,10 @@ /// IOutputViewModel interfaces void activate( const QModelIndex& index ) override; + QModelIndex firstHighlightIndex() override; QModelIndex nextHighlightIndex( const QModelIndex ¤t ) override; QModelIndex previousHighlightIndex( const QModelIndex ¤t ) override; + QModelIndex lastHighlightIndex() override; /// QAbstractItemModel interfaces QVariant data( const QModelIndex&, int = Qt::DisplayRole ) const override; diff --git a/outputview/outputmodel.cpp b/outputview/outputmodel.cpp --- a/outputview/outputmodel.cpp +++ b/outputview/outputmodel.cpp @@ -307,6 +307,21 @@ } } +QModelIndex OutputModel::firstHighlightIndex() +{ + if( !d->m_errorItems.empty() ) { + return index( *d->m_errorItems.begin(), 0, QModelIndex() ); + } + + for( int row = 0; row < rowCount(); ++row ) { + if( d->m_filteredItems.at( row ).isActivatable ) { + return index( row, 0, QModelIndex() ); + } + } + + return QModelIndex(); +} + QModelIndex OutputModel::nextHighlightIndex( const QModelIndex ¤tIdx ) { int startrow = d->isValidIndex(currentIdx, rowCount()) ? currentIdx.row() + 1 : 0; @@ -364,6 +379,21 @@ return QModelIndex(); } +QModelIndex OutputModel::lastHighlightIndex() +{ + if( !d->m_errorItems.empty() ) { + return index( *d->m_errorItems.rbegin(), 0, QModelIndex() ); + } + + for( int row = rowCount()-1; row >=0; --row ) { + if( d->m_filteredItems.at( row ).isActivatable ) { + return index( row, 0, QModelIndex() ); + } + } + + return QModelIndex(); +} + void OutputModel::setFilteringStrategy(const OutputFilterStrategy& currentStrategy) { // TODO: Turn into factory, decouple from OutputModel diff --git a/plugins/standardoutputview/outputwidget.h b/plugins/standardoutputview/outputwidget.h --- a/plugins/standardoutputview/outputwidget.h +++ b/plugins/standardoutputview/outputwidget.h @@ -61,8 +61,10 @@ void changeDelegate( int id ); void closeActiveView(); void closeOtherViews(); + void selectFirstItem(); void selectNextItem() override; void selectPreviousItem() override; + void selectLastItem(); void activate(const QModelIndex&); void scrollToIndex( const QModelIndex& ); void setTitle(int outputId, const QString& title); @@ -79,11 +81,13 @@ void updateFilter(int index); private: - enum Direction { + enum SelectionMode { + Last, Next, - Previous + Previous, + First }; - void selectItem(Direction direction); + void selectItem(SelectionMode direction); QTreeView* createListView(int id); void setCurrentWidget( QTreeView* view ); diff --git a/plugins/standardoutputview/outputwidget.cpp b/plugins/standardoutputview/outputwidget.cpp --- a/plugins/standardoutputview/outputwidget.cpp +++ b/plugins/standardoutputview/outputwidget.cpp @@ -118,6 +118,10 @@ QAction* action; + action = new QAction(QIcon::fromTheme("go-first"), i18n("First Item"), this); + connect(action, &QAction::triggered, this, &OutputWidget::selectFirstItem); + addAction(action); + action = new QAction(QIcon::fromTheme("go-previous"), i18n("Previous Item"), this); connect(action, &QAction::triggered, this, &OutputWidget::selectPreviousItem); addAction(action); @@ -126,6 +130,10 @@ connect(action, &QAction::triggered, this, &OutputWidget::selectNextItem); addAction(action); + action = new QAction(QIcon::fromTheme("go-last"), i18n("Last Item"), this); + connect(action, &QAction::triggered, this, &OutputWidget::selectLastItem); + addAction(action); + QAction* selectAllAction = KStandardAction::selectAll(this, SLOT(selectAll()), this); selectAllAction->setShortcut(QKeySequence()); //FIXME: why does CTRL-A conflict with Katepart (while CTRL-Cbelow doesn't) ? selectAllAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); @@ -385,6 +393,11 @@ } } +void OutputWidget::selectFirstItem() +{ + selectItem(First); +} + void OutputWidget::selectNextItem() { selectItem(Next); @@ -395,7 +408,12 @@ selectItem(Previous); } -void OutputWidget::selectItem(Direction direction) +void OutputWidget::selectLastItem() +{ + selectItem(Last); +} + +void OutputWidget::selectItem(SelectionMode direction) { auto view = outputView(); auto iface = outputViewModel(); @@ -412,9 +430,21 @@ } } - const auto newIndex = direction == Previous - ? iface->previousHighlightIndex( index ) - : iface->nextHighlightIndex( index ); + QModelIndex newIndex; + switch (direction) { + case First: + newIndex = iface->firstHighlightIndex(); + break; + case Next: + newIndex = iface->nextHighlightIndex( index ); + break; + case Previous: + newIndex = iface->previousHighlightIndex( index ); + break; + case Last: + newIndex = iface->lastHighlightIndex(); + break; + } qCDebug(PLUGIN_STANDARDOUTPUTVIEW) << "old:" << index << "- new:" << newIndex; activateIndex(newIndex, view, iface);