Commit 540ddcd5 authored by dt's avatar dt
Browse files

Add a next/prev shortcut (F6 for now) for outputpanes.

This one has some magic inside to always use the current outputpane.
This solves the issue that I don't want Search and Build Issues list to
have its own set of next/prev shortcuts. todo is a better definition of
next for the build issues and/or a way to restrict it only to errors.
parent 4e6e5408
......@@ -64,6 +64,12 @@ public:
// Wheter the outputpane can be focused at the moment.
// (E.g. the search result window doesn't want to be focussed if the are no results.)
virtual bool canFocus() = 0;
virtual bool canNavigate() = 0;
virtual bool canNext() = 0;
virtual bool canPrevious() = 0;
virtual void goToNext() = 0;
virtual void goToPrev() = 0;
public slots:
void popup()
{
......@@ -89,10 +95,16 @@ public slots:
emit togglePage(withFocusIfShown);
}
void navigateStateChanged()
{
emit navigateStateUpdate();
}
signals:
void showPage(bool withFocus);
void hidePage();
void togglePage(bool withFocusIfShown);
void navigateStateUpdate();
};
} // namespace Core
......
......@@ -89,3 +89,28 @@ int MessageOutputWindow::priorityInStatusBar() const
{
return -1;
}
bool MessageOutputWindow::canNext()
{
return false;
}
bool MessageOutputWindow::canPrevious()
{
return false;
}
void MessageOutputWindow::goToNext()
{
}
void MessageOutputWindow::goToPrev()
{
}
bool MessageOutputWindow::canNavigate()
{
return false;
}
......@@ -60,6 +60,12 @@ public:
bool hasFocus();
void setFocus();
virtual bool canNext();
virtual bool canPrevious();
virtual void goToNext();
virtual void goToPrev();
bool canNavigate();
private:
QTextEdit *m_widget;
};
......
......@@ -40,6 +40,8 @@
#include <extensionsystem/pluginmanager.h>
#include <QtCore/QDebug>
#include <QtGui/QAction>
#include <QtGui/QApplication>
#include <QtGui/QComboBox>
......@@ -159,6 +161,8 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) :
m_widgetComboBox(new QComboBox),
m_clearButton(new QToolButton),
m_closeButton(new QToolButton),
m_nextAction(0),
m_prevAction(0),
m_closeAction(0),
m_lastIndex(-1),
m_outputWidgetPane(new QStackedWidget),
......@@ -171,6 +175,18 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) :
m_clearButton->setToolTip(tr("Clear"));
connect(m_clearButton, SIGNAL(clicked()), this, SLOT(clearPage()));
m_nextAction = new QAction(this);
m_nextAction->setIcon(QIcon(":/core/images/next.png"));
m_nextAction->setProperty("type", QLatin1String("dockbutton"));
m_nextAction->setText(tr("Next Item"));
connect(m_nextAction, SIGNAL(triggered()), this, SLOT(slotNext()));
m_prevAction = new QAction(this);
m_prevAction->setIcon(QIcon(":/core/images/prev.png"));
m_prevAction->setProperty("type", QLatin1String("dockbutton"));
m_prevAction->setText(tr("Previous Item"));
connect(m_prevAction, SIGNAL(triggered()), this, SLOT(slotPrev()));
m_closeButton->setIcon(QIcon(":/core/images/closebutton.png"));
m_closeButton->setProperty("type", QLatin1String("dockbutton"));
connect(m_closeButton, SIGNAL(clicked()), this, SLOT(slotHide()));
......@@ -178,12 +194,13 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) :
QVBoxLayout *mainlayout = new QVBoxLayout;
mainlayout->setSpacing(0);
mainlayout->setMargin(0);
QToolBar *toolBar = new QToolBar;
toolBar->addWidget(m_widgetComboBox);
toolBar->addWidget(m_clearButton);
toolBar->addWidget(m_opToolBarWidgets);
m_closeAction = toolBar->addWidget(m_closeButton);
mainlayout->addWidget(toolBar);
m_toolBar = new QToolBar;
m_toolBar->addWidget(m_widgetComboBox);
m_toolBar->addWidget(m_clearButton);
m_opToolBarAction = m_toolBar->addWidget(m_opToolBarWidgets);
m_closeAction = m_toolBar->addWidget(m_closeButton);
mainlayout->addWidget(m_toolBar);
mainlayout->addWidget(m_outputWidgetPane, 10);
setLayout(mainlayout);
......@@ -195,6 +212,7 @@ OutputPaneManager::OutputPaneManager(QWidget *parent) :
#else
m_buttonsWidget->layout()->setSpacing(4);
#endif
}
OutputPaneManager::~OutputPaneManager()
......@@ -216,11 +234,32 @@ void OutputPaneManager::init()
{
ActionManager *am = Core::ICore::instance()->actionManager();
ActionContainer *mwindow = am->actionContainer(Constants::M_WINDOW);
QList<int> globalcontext;
globalcontext.append(Core::Constants::C_GLOBAL_ID);
// Window->Output Panes
ActionContainer *mpanes = am->createMenu(Constants::M_WINDOW_PANES);
mwindow->addMenu(mpanes, Constants::G_WINDOW_PANES);
mpanes->menu()->setTitle(tr("Output &Panes"));
mpanes->appendGroup("Coreplugin.OutputPane.ActionsGroup");
mpanes->appendGroup("Coreplugin.OutputPane.PanesGroup");
Core::Command *cmd;
cmd = am->registerAction(m_prevAction, "Coreplugin.OutputPane.previtem", globalcontext);
cmd->setDefaultKeySequence(QKeySequence("Shift+F6"));
m_toolBar->insertAction(m_opToolBarAction ,cmd->action());
mpanes->addAction(cmd, "Coreplugin.OutputPane.ActionsGroup");
cmd = am->registerAction(m_nextAction, "Coreplugin.OutputPane.nextitem", globalcontext);
m_toolBar->insertAction(m_opToolBarAction, cmd->action());
cmd->setDefaultKeySequence(QKeySequence("F6"));
mpanes->addAction(cmd, "Coreplugin.OutputPane.ActionsGroup");
QAction *sep = new QAction(this);
sep->setSeparator(true);
cmd = am->registerAction(sep, QLatin1String("Coreplugin.OutputPane.Sep"), globalcontext);
mpanes->addAction(cmd, "Coreplugin.OutputPane.ActionsGroup");
QList<IOutputPane*> panes = ExtensionSystem::PluginManager::instance()
->getObjects<IOutputPane>();
......@@ -241,6 +280,7 @@ void OutputPaneManager::init()
connect(outPane, SIGNAL(showPage(bool)), this, SLOT(showPage(bool)));
connect(outPane, SIGNAL(hidePage()), this, SLOT(slotHide()));
connect(outPane, SIGNAL(togglePage(bool)), this, SLOT(togglePage(bool)));
connect(outPane, SIGNAL(navigateStateUpdate()), this, SLOT(updateNavigateState()));
QWidget *toolButtonsContainer = new QWidget(m_opToolBarWidgets);
QHBoxLayout *toolButtonsLayout = new QHBoxLayout;
......@@ -265,7 +305,7 @@ void OutputPaneManager::init()
cmd->setDefaultKeySequence(QKeySequence(paneShortCut(Qt::ALT, shortcutNumber)));
#endif
}
mpanes->addAction(cmd);
mpanes->addAction(cmd, "Coreplugin.OutputPane.PanesGroup");
m_actions.insert(cmd->action(), idx);
// TODO priority -1
......@@ -343,6 +383,24 @@ void OutputPaneManager::updateToolTip()
}
}
void OutputPaneManager::slotNext()
{
int idx = m_widgetComboBox->itemData(m_widgetComboBox->currentIndex()).toInt();
ensurePageVisible(idx);
IOutputPane *out = m_pageMap.value(idx);
if (out->canNext())
out->goToNext();
}
void OutputPaneManager::slotPrev()
{
int idx = m_widgetComboBox->itemData(m_widgetComboBox->currentIndex()).toInt();
ensurePageVisible(idx);
IOutputPane *out = m_pageMap.value(idx);
if (out->canPrevious())
out->goToPrev();
}
void OutputPaneManager::slotHide()
{
if (OutputPanePlaceHolder::m_current) {
......@@ -384,6 +442,16 @@ void OutputPaneManager::ensurePageVisible(int idx)
}
}
void OutputPaneManager::updateNavigateState()
{
IOutputPane* pane = qobject_cast<IOutputPane*>(sender());
int idx = findIndexForPage(pane);
if (m_widgetComboBox->itemData(m_widgetComboBox->currentIndex()).toInt() == idx) {
m_prevAction->setEnabled(pane->canNavigate() && pane->canPrevious());
m_nextAction->setEnabled(pane->canNavigate() && pane->canNext());
}
}
// Slot connected to showPage signal of each page
void OutputPaneManager::showPage(bool focus)
{
......@@ -457,11 +525,17 @@ void OutputPaneManager::changePage()
}
int idx = m_widgetComboBox->itemData(m_widgetComboBox->currentIndex()).toInt();
if (m_lastIndex == idx)
return;
m_outputWidgetPane->setCurrentIndex(idx);
m_opToolBarWidgets->setCurrentIndex(idx);
m_pageMap.value(idx)->visibilityChanged(true);
m_pageMap.value(m_lastIndex)->visibilityChanged(false);
bool canNavigate = m_pageMap.value(idx)->canNavigate();
m_prevAction->setEnabled(canNavigate && m_pageMap.value(idx)->canPrevious());
m_nextAction->setEnabled(canNavigate && m_pageMap.value(idx)->canNext());
if (m_buttons.value(m_lastIndex))
m_buttons.value(m_lastIndex)->setChecked(false);
......
......@@ -39,6 +39,7 @@ QT_BEGIN_NAMESPACE
class QAction;
class QComboBox;
class QToolButton;
class QToolBar;
class QStackedWidget;
class QPushButton;
QT_END_NAMESPACE
......@@ -89,6 +90,8 @@ public:
public slots:
void slotHide();
void slotNext();
void slotPrev();
void shortcutTriggered();
protected:
......@@ -101,6 +104,7 @@ private slots:
void clearPage();
void updateToolTip();
void buttonTriggered();
void updateNavigateState();
private:
// the only class that is allowed to create and destroy
......@@ -118,13 +122,18 @@ private:
QComboBox *m_widgetComboBox;
QToolButton *m_clearButton;
QToolButton *m_closeButton;
QAction *m_nextAction;
QAction *m_prevAction;
QAction *m_closeAction;
QToolBar *m_toolBar;
QMap<int, Core::IOutputPane*> m_pageMap;
int m_lastIndex;
QStackedWidget *m_outputWidgetPane;
QStackedWidget *m_opToolBarWidgets;
QAction *m_opToolBarAction;
QWidget *m_buttonsWidget;
QMap<int, QPushButton *> m_buttons;
QMap<QAction *, int> m_actions;
......
......@@ -255,3 +255,61 @@ void SearchResultTreeModel::clear()
m_rootItem->clearChildren();
reset();
}
QModelIndex SearchResultTreeModel::next(const QModelIndex &idx) const
{
QModelIndex parent = idx.parent();
if (parent.isValid()) {
int row = idx.row();
if (row + 1 < rowCount(parent)) {
// Same parent
return index(row + 1, 0, parent);
} else {
// Next parent
int parentRow = parent.row();
QModelIndex nextParent;
if (parentRow + 1 < rowCount()) {
nextParent = index(parentRow + 1, 0);
} else {
// Wrap around
nextParent = index(0,0);
}
return nextParent.child(0, 0);
}
} else {
// We are on a top level item
return idx.child(0,0);
}
return QModelIndex();
}
QModelIndex SearchResultTreeModel::prev(const QModelIndex &idx) const
{
QModelIndex parent = idx.parent();
if (parent.isValid()) {
int row = idx.row();
if (row > 0) {
// Same parent
return index(row - 1, 0, parent);
} else {
// Prev parent
int parentRow = parent.row();
QModelIndex prevParent;
if (parentRow > 0 ) {
prevParent = index(parentRow - 1, 0);
} else {
// Wrap around
prevParent = index(rowCount() - 1, 0);
}
return prevParent.child(rowCount(prevParent) - 1, 0);
}
} else {
// We are on a top level item
int row = idx.row();
if (row > 0) {
QModelIndex prevParent = index(row - 1, 0);
return prevParent.child(rowCount(prevParent) ,0);
}
}
return QModelIndex();
}
......@@ -57,6 +57,9 @@ public:
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QModelIndex next(const QModelIndex &idx) const;
QModelIndex prev(const QModelIndex &idx) const;
signals:
void jumpToSearchResult(const QString &fileName, int lineNumber,
int searchTermStart, int searchTermLength);
......
......@@ -99,3 +99,8 @@ void SearchResultTreeView::keyPressEvent(QKeyEvent *e)
}
QTreeView::keyPressEvent(e);
}
SearchResultTreeModel *SearchResultTreeView::model() const
{
return m_model;
}
......@@ -48,6 +48,8 @@ public:
void setAutoExpandResults(bool expand);
void setTextEditorFont(const QFont &font);
SearchResultTreeModel *model() const;
signals:
void jumpToSearchResult(int index, const QString &fileName, int lineNumber,
int searchTermStart, int searchTermLength);
......@@ -56,8 +58,6 @@ public slots:
void clear();
void appendResultLine(int index, const QString &fileName, int lineNumber, const QString &lineText,
int searchTermStart, int searchTermLength);
private slots:
void emitJumpToSearchResult(const QModelIndex &index);
protected:
......
......@@ -35,6 +35,7 @@
#include <QtCore/QFile>
#include <QtCore/QTextStream>
#include <QtCore/QSettings>
#include <QtCore/QDebug>
#include <QtGui/QListWidget>
#include <QtGui/QToolButton>
......@@ -102,6 +103,7 @@ void SearchResultWindow::clearContents()
m_searchResultTreeView->clear();
qDeleteAll(m_items);
m_items.clear();
navigateStateChanged();
}
void SearchResultWindow::showNoMatchesFound()
......@@ -160,8 +162,8 @@ ResultWindowItem *SearchResultWindow::addResult(const QString &fileName, int lin
// We didn't have an item before, set the focus to the m_searchResultTreeView
m_searchResultTreeView->setFocus();
m_searchResultTreeView->selectionModel()->select(m_searchResultTreeView->model()->index(0, 0, QModelIndex()), QItemSelectionModel::Select);
emit navigateStateChanged();
}
return item;
}
......@@ -198,3 +200,39 @@ int SearchResultWindow::priorityInStatusBar() const
{
return 80;
}
bool SearchResultWindow::canNext()
{
return m_searchResultTreeView->model()->rowCount();
}
bool SearchResultWindow::canPrevious()
{
return m_searchResultTreeView->model()->rowCount();
}
void SearchResultWindow::goToNext()
{
if (!m_searchResultTreeView->model()->rowCount())
return;
QModelIndex idx = m_searchResultTreeView->model()->next(m_searchResultTreeView->currentIndex());
if (idx.isValid()) {
m_searchResultTreeView->setCurrentIndex(idx);
m_searchResultTreeView->emitJumpToSearchResult(idx);
}
}
void SearchResultWindow::goToPrev()
{
if (!m_searchResultTreeView->model()->rowCount())
return;
QModelIndex idx = m_searchResultTreeView->model()->prev(m_searchResultTreeView->currentIndex());
if (idx.isValid()) {
m_searchResultTreeView->setCurrentIndex(idx);
m_searchResultTreeView->emitJumpToSearchResult(idx);
}
}
bool SearchResultWindow::canNavigate()
{
return true;
}
......@@ -75,6 +75,12 @@ public:
bool canFocus();
void setFocus();
bool canNext();
bool canPrevious();
void goToNext();
void goToPrev();
bool canNavigate();
void setTextEditorFont(const QFont &font);
public slots:
......
......@@ -117,3 +117,27 @@ int GitOutputWindow::priorityInStatusBar() const
{
return -1;
}
bool GitOutputWindow::canNext()
{
return false;
}
bool GitOutputWindow::canPrevious()
{
return false;
}
void GitOutputWindow::goToNext()
{
}
void GitOutputWindow::goToPrev()
{
}
bool GitOutputWindow::canNavigate()
{
return false;
}
......@@ -59,6 +59,12 @@ public:
bool hasFocus();
void setFocus();
bool canNext();
bool canPrevious();
void goToNext();
void goToPrev();
bool canNavigate();
public slots:
void setText(const QString &text);
void append(const QString &text);
......
......@@ -159,3 +159,28 @@ int PerforceOutputWindow::priorityInStatusBar() const
{
return -1;
}
bool PerforceOutputWindow::canNext()
{
return false;
}
bool PerforceOutputWindow::canPrevious()
{
return false;
}
void PerforceOutputWindow::goToNext()
{
}
void PerforceOutputWindow::goToPrev()
{
}
bool PerforceOutputWindow::canNavigate()
{
return false;
}
......@@ -61,6 +61,12 @@ public:
bool hasFocus();
void setFocus();
bool canNext();
bool canPrevious();
void goToNext();
void goToPrev();
bool canNavigate();
public slots:
void append(const QString &txt, bool doPopup = false);
......
......@@ -93,3 +93,28 @@ int CompileOutputWindow::priorityInStatusBar() const
{
return 50;
}
bool CompileOutputWindow::canNext()
{
return false;
}
bool CompileOutputWindow::canPrevious()
{
return false;
}
void CompileOutputWindow::goToNext()
{
}
void CompileOutputWindow::goToPrev()
{
}
bool CompileOutputWindow::canNavigate()
{
return false;
}
......@@ -57,6 +57,12 @@ public:
bool hasFocus();
void setFocus();
bool canNext();
bool canPrevious();
void goToNext();
void goToPrev();
bool canNavigate();
private:
QPlainTextEdit *m_textEdit;
};
......
......@@ -305,6 +305,30 @@ RunControl* OutputPane::runControlForTab(int index) const
return m_outputWindows.key(qobject_cast<OutputWindow *>(m_tabWidget->widget(index)));
}
bool OutputPane::canNext()
{
return false;
}
bool OutputPane::canPrevious()
{