Refactor TaskWindow to support different 'categories'

The category differs between e.g. TODO tasks, compiler errors/warnings,
qml syntax errrors ... Idea is that every plugin can manage it's
own virtual list of tasks.

Reviewed-by: dt
This commit is contained in:
Kai Koehne
2009-11-11 09:54:13 +01:00
parent 2d2d0b59c8
commit a475761384
10 changed files with 281 additions and 164 deletions

View File

@@ -86,6 +86,8 @@ BuildManager::BuildManager(ProjectExplorerPlugin *parent)
m_taskWindow = new TaskWindow; m_taskWindow = new TaskWindow;
pm->addObject(m_taskWindow); pm->addObject(m_taskWindow);
m_taskWindow->addCategory(Constants::TASK_CATEGORY_COMPILE, tr("Compile", "Category for compiler isses listened under 'Build Issues'"));
connect(m_taskWindow, SIGNAL(tasksChanged()), connect(m_taskWindow, SIGNAL(tasksChanged()),
this, SIGNAL(tasksChanged())); this, SIGNAL(tasksChanged()));
@@ -179,7 +181,7 @@ void BuildManager::toggleTaskWindow()
bool BuildManager::tasksAvailable() const bool BuildManager::tasksAvailable() const
{ {
return m_taskWindow->numberOfTasks() > 0; return m_taskWindow->taskCount() > 0;
} }
void BuildManager::gotoTaskWindow() void BuildManager::gotoTaskWindow()
@@ -221,7 +223,7 @@ void BuildManager::startBuildQueue()
void BuildManager::showBuildResults() void BuildManager::showBuildResults()
{ {
if (m_taskWindow->numberOfTasks() != 0) if (m_taskWindow->taskCount() != 0)
toggleTaskWindow(); toggleTaskWindow();
else else
toggleOutputWindow(); toggleOutputWindow();
@@ -230,7 +232,9 @@ void BuildManager::showBuildResults()
void BuildManager::addToTaskWindow(const QString &file, int type, int line, const QString &description) void BuildManager::addToTaskWindow(const QString &file, int type, int line, const QString &description)
{ {
m_taskWindow->addItem(BuildParserInterface::PatternType(type), description, file, line); TaskWindow::Task task(TaskWindow::TaskType(type), description, file, line,
Constants::TASK_CATEGORY_COMPILE);
m_taskWindow->addTask(task);
} }
void BuildManager::addToOutputWindow(const QString &string) void BuildManager::addToOutputWindow(const QString &string)

View File

@@ -42,10 +42,10 @@ namespace ProjectExplorer {
namespace Internal { namespace Internal {
class CompileOutputWindow; class CompileOutputWindow;
class TaskWindow;
class BuildProgressFuture; class BuildProgressFuture;
} }
class TaskWindow;
class BuildStep; class BuildStep;
class Project; class Project;
class ProjectExplorerPlugin; class ProjectExplorerPlugin;
@@ -109,7 +109,7 @@ private:
void decrementActiveBuildSteps(Project *pro); void decrementActiveBuildSteps(Project *pro);
Internal::CompileOutputWindow *m_outputWindow; Internal::CompileOutputWindow *m_outputWindow;
Internal::TaskWindow *m_taskWindow; TaskWindow *m_taskWindow;
QList<BuildStep *> m_buildQueue; QList<BuildStep *> m_buildQueue;
QStringList m_configurations; // the corresponding configuration to the m_buildQueue QStringList m_configurations; // the corresponding configuration to the m_buildQueue

View File

@@ -41,8 +41,6 @@ class PROJECTEXPLORER_EXPORT BuildParserInterface : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
enum PatternType { Unknown, Warning, Error };
virtual ~BuildParserInterface() {} virtual ~BuildParserInterface() {}
virtual QString name() const = 0; virtual QString name() const = 0;

View File

@@ -82,12 +82,12 @@ void BuildProgress::updateState()
{ {
if (!m_taskWindow) if (!m_taskWindow)
return; return;
int errors = m_taskWindow->numberOfErrors(); int errors = m_taskWindow->errorTaskCount();
bool haveErrors = (errors > 0); bool haveErrors = (errors > 0);
m_errorIcon->setEnabled(haveErrors); m_errorIcon->setEnabled(haveErrors);
m_errorLabel->setEnabled(haveErrors); m_errorLabel->setEnabled(haveErrors);
m_errorLabel->setText(QString("%1").arg(errors)); m_errorLabel->setText(QString("%1").arg(errors));
int warnings = m_taskWindow->numberOfTasks()-errors; int warnings = m_taskWindow->taskCount()-errors;
bool haveWarnings = (warnings > 0); bool haveWarnings = (warnings > 0);
m_warningIcon->setEnabled(haveWarnings); m_warningIcon->setEnabled(haveWarnings);
m_warningLabel->setEnabled(haveWarnings); m_warningLabel->setEnabled(haveWarnings);

View File

@@ -29,6 +29,7 @@
#include "gccparser.h" #include "gccparser.h"
#include "projectexplorerconstants.h" #include "projectexplorerconstants.h"
#include "taskwindow.h"
using namespace ProjectExplorer; using namespace ProjectExplorer;
@@ -72,17 +73,18 @@ void GccParser::stdError(const QString & line)
QString description = m_regExpLinker.cap(2); QString description = m_regExpLinker.cap(2);
emit addToTaskWindow( emit addToTaskWindow(
m_regExpLinker.cap(1), //filename m_regExpLinker.cap(1), //filename
ProjectExplorer::BuildParserInterface::Error, TaskWindow::Error,
-1, //linenumber -1, //linenumber
description); description);
//qDebug()<<"m_regExpLinker"<<m_regExpLinker.cap(2);
} else if (m_regExp.indexIn(lne) > -1) { } else if (m_regExp.indexIn(lne) > -1) {
ProjectExplorer::BuildParserInterface::PatternType type; TaskWindow::TaskType type;
if (m_regExp.cap(5) == "warning") if (m_regExp.cap(5) == "warning")
type = ProjectExplorer::BuildParserInterface::Warning; type = TaskWindow::Warning;
else if (m_regExp.cap(5) == "error") else if (m_regExp.cap(5) == "error")
type = ProjectExplorer::BuildParserInterface::Error; type = TaskWindow::Error;
else else
type = ProjectExplorer::BuildParserInterface::Unknown; type = TaskWindow::Unknown;
QString description = m_regExp.cap(6); QString description = m_regExp.cap(6);
@@ -94,7 +96,7 @@ void GccParser::stdError(const QString & line)
} else if (m_regExpIncluded.indexIn(lne) > -1) { } else if (m_regExpIncluded.indexIn(lne) > -1) {
emit addToTaskWindow( emit addToTaskWindow(
m_regExpIncluded.cap(1), //filename m_regExpIncluded.cap(1), //filename
ProjectExplorer::BuildParserInterface::Unknown, TaskWindow::Unknown,
m_regExpIncluded.cap(2).toInt(), //linenumber m_regExpIncluded.cap(2).toInt(), //linenumber
lne //description lne //description
); );

View File

@@ -79,12 +79,12 @@ void MsvcParser::stdOutput(const QString & line)
} }
} }
ProjectExplorer::BuildParserInterface::PatternType MsvcParser::toType(int number) TaskWindow::TaskType MsvcParser::toType(int number)
{ {
if (number == 0) if (number == 0)
return ProjectExplorer::BuildParserInterface::Unknown; return TaskWindow::Unknown;
else if (number > 4000 && number < 5000) else if (number > 4000 && number < 5000)
return ProjectExplorer::BuildParserInterface::Warning; return TaskWindow::Warning;
else else
return ProjectExplorer::BuildParserInterface::Error; return TaskWindow::Error;
} }

View File

@@ -31,6 +31,7 @@
#define MSVCPARSER_H #define MSVCPARSER_H
#include "buildparserinterface.h" #include "buildparserinterface.h"
#include "taskwindow.h"
#include <QtCore/QRegExp> #include <QtCore/QRegExp>
@@ -47,7 +48,7 @@ public:
virtual void stdOutput(const QString & line); virtual void stdOutput(const QString & line);
virtual void stdError(const QString & line); virtual void stdError(const QString & line);
private: private:
ProjectExplorer::BuildParserInterface::PatternType toType(int number); TaskWindow::TaskType toType(int number);
QRegExp m_compileRegExp; QRegExp m_compileRegExp;
QRegExp m_linkRegExp; QRegExp m_linkRegExp;
}; };

View File

@@ -189,6 +189,9 @@ const char * const BUILD_PARSER_ABLD_RVCT = "BuildParser.ABLD.Rvct";
const char * const PROJECTEXPLORER_CATEGORY = "ProjectExplorer"; const char * const PROJECTEXPLORER_CATEGORY = "ProjectExplorer";
const char * const PROJECTEXPLORER_PAGE = "ProjectExplorer.ProjectExplorer"; const char * const PROJECTEXPLORER_PAGE = "ProjectExplorer.ProjectExplorer";
// task categories
const char * const TASK_CATEGORY_COMPILE = "Task.Category.Compile";
} // namespace Constants } // namespace Constants
} // namespace ProjectExplorer } // namespace ProjectExplorer

View File

@@ -29,44 +29,69 @@
#include "taskwindow.h" #include "taskwindow.h"
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/actionmanager/actionmanager.h> #include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/coreconstants.h> #include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h> #include <coreplugin/icore.h>
#include <coreplugin/uniqueidmanager.h> #include <coreplugin/uniqueidmanager.h>
#include <extensionsystem/pluginmanager.h>
#include <texteditor/itexteditor.h>
#include <texteditor/basetexteditor.h> #include <texteditor/basetexteditor.h>
#include <projectexplorerconstants.h> #include <texteditor/itexteditor.h>
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtGui/QKeyEvent> #include <QtCore/QFileInfo>
#include <QtGui/QHeaderView>
#include <QtGui/QListView>
#include <QtGui/QPainter>
#include <QtCore/QAbstractItemModel>
#include <QtGui/QSortFilterProxyModel>
#include <QtGui/QApplication> #include <QtGui/QApplication>
#include <QtGui/QClipboard> #include <QtGui/QClipboard>
#include <QtGui/QFont> #include <QtGui/QKeyEvent>
#include <QtGui/QFontMetrics> #include <QtGui/QListView>
#include <QtGui/QTextLayout> #include <QtGui/QPainter>
#include <QtGui/QStyledItemDelegate>
#include <QtGui/QSortFilterProxyModel>
#include <QDebug> #include <QDebug>
using namespace ProjectExplorer::Internal; namespace ProjectExplorer {
namespace Internal {
// Internal Struct for TaskModel class TaskView : public QListView
struct TaskItem
{ {
QString description; public:
QString file; TaskView(QWidget *parent = 0);
int line; ~TaskView();
bool fileNotFound; void resizeEvent(QResizeEvent *e);
ProjectExplorer::BuildParserInterface::PatternType type; void keyPressEvent(QKeyEvent *e);
}; };
class ProjectExplorer::Internal::TaskModel : public QAbstractItemModel class TaskDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
TaskDelegate(QObject * parent = 0);
~TaskDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
// TaskView uses this method if the size of the taskview changes
void emitSizeHintChanged(const QModelIndex &index);
public slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
private:
void generateGradientPixmap(int width, int height, QColor color, bool selected) const;
};
class TaskWindowContext : public Core::IContext
{
public:
TaskWindowContext(QWidget *widget);
virtual QList<int> context() const;
virtual QWidget *widget();
private:
QWidget *m_taskList;
QList<int> m_context;
};
class TaskModel : public QAbstractItemModel
{ {
public: public:
// Model stuff // Model stuff
@@ -76,25 +101,34 @@ public:
int rowCount(const QModelIndex &parent = QModelIndex()) const; int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void clear();
void addTask(ProjectExplorer::BuildParserInterface::PatternType type, void addCategory(const QString &categoryId, const QString &categoryName);
const QString &description, const QString &file, int line);
QList<TaskWindow::Task> tasks(const QString &categoryId = QString()) const;
void addTask(const TaskWindow::Task &task);
void clearTasks(const QString &categoryId = QString());
int sizeOfFile(); int sizeOfFile();
int sizeOfLineNumber(); int sizeOfLineNumber();
void setFileNotFound(const QModelIndex &index, bool b); void setFileNotFound(const QModelIndex &index, bool b);
enum Roles { File = Qt::UserRole, Line, Description, FileNotFound, Type }; enum Roles { File = Qt::UserRole, Line, Description, FileNotFound, Type };
QIcon iconFor(ProjectExplorer::BuildParserInterface::PatternType type); QIcon iconFor(TaskWindow::TaskType type);
private: private:
QList<TaskItem> m_items; QHash<QString,QString> m_categories; // category id -> display name
QList<TaskWindow::Task> m_tasks; // all tasks (in order of insertion)
QMap<QString,QList<TaskWindow::Task> > m_tasksInCategory; // categoryId->tasks
QHash<QString,bool> m_fileNotFound;
int m_maxSizeOfFileName; int m_maxSizeOfFileName;
QIcon m_errorIcon; QIcon m_errorIcon;
QIcon m_warningIcon; QIcon m_warningIcon;
QIcon m_unspecifiedIcon; QIcon m_unspecifiedIcon;
}; };
class ProjectExplorer::Internal::TaskFilterModel : public QSortFilterProxyModel class TaskFilterModel : public QSortFilterProxyModel
{ {
public: public:
TaskFilterModel(TaskModel *sourceModel, QObject *parent = 0); TaskFilterModel(TaskModel *sourceModel, QObject *parent = 0);
@@ -120,6 +154,14 @@ private:
bool m_includeErrors; bool m_includeErrors;
}; };
} // Internal
} // ProjectExplorer
using namespace ProjectExplorer;
using namespace ProjectExplorer::Internal;
//// ////
// TaskView // TaskView
//// ////
@@ -164,17 +206,31 @@ TaskModel::TaskModel()
} }
void TaskModel::addTask(ProjectExplorer::BuildParserInterface::PatternType type, const QString &description, const QString &file, int line) void TaskModel::addCategory(const QString &categoryId, const QString &categoryName)
{ {
TaskItem task; Q_ASSERT(!categoryId.isEmpty());
task.description = description; m_categories.insert(categoryId, categoryName);
task.file = file; }
task.line = line;
task.type = type;
task.fileNotFound = false;
beginInsertRows(QModelIndex(), m_items.size(), m_items.size()); QList<TaskWindow::Task> TaskModel::tasks(const QString &categoryId) const
m_items.append(task); {
if (categoryId.isEmpty()) {
return m_tasks;
} else {
return m_tasksInCategory.value(categoryId);
}
}
void TaskModel::addTask(const TaskWindow::Task &task)
{
Q_ASSERT(m_categories.keys().contains(task.category));
QList<TaskWindow::Task> tasksInCategory = m_tasksInCategory.value(task.category);
tasksInCategory.append(task);
m_tasksInCategory.insert(task.category, tasksInCategory);
beginInsertRows(QModelIndex(), m_tasks.size(), m_tasks.size());
m_tasks.append(task);
endInsertRows(); endInsertRows();
QFont font; QFont font;
@@ -182,18 +238,48 @@ void TaskModel::addTask(ProjectExplorer::BuildParserInterface::PatternType type,
QString filename = task.file; QString filename = task.file;
int pos = filename.lastIndexOf("/"); int pos = filename.lastIndexOf("/");
if (pos != -1) if (pos != -1)
filename = file.mid(pos +1); filename = task.file.mid(pos +1);
m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.width(filename)); m_maxSizeOfFileName = qMax(m_maxSizeOfFileName, fm.width(filename));
} }
//
//void TaskModel::removeTask(const ITaskWindow::Task &task)
//{
// Q_ASSERT(m_tasks.contains(task));
// int index = m_tasks.indexOf(task);
// beginRemoveRows(QModelIndex(), index, index);
// m_tasks.removeAt(index);
// endRemoveRows();
//}
void TaskModel::clear() void TaskModel::clearTasks(const QString &categoryId)
{ {
if (m_items.isEmpty()) if (categoryId.isEmpty()) {
if (m_tasks.size() == 0)
return; return;
beginRemoveRows(QModelIndex(), 0, m_items.size() -1); beginRemoveRows(QModelIndex(), 0, m_tasks.size() -1);
m_items.clear(); m_tasks.clear();
m_tasksInCategory.clear();
endRemoveRows(); endRemoveRows();
m_maxSizeOfFileName = 0; m_maxSizeOfFileName = 0;
} else {
// TODO: Optimize this for consecutive rows
foreach (const TaskWindow::Task &task, m_tasksInCategory.value(categoryId)) {
int index = m_tasks.indexOf(task);
Q_ASSERT(index >= 0);
beginRemoveRows(QModelIndex(), index, index);
m_tasks.removeAt(index);
QList<TaskWindow::Task> tasksInCategory = m_tasksInCategory.value(categoryId);
tasksInCategory.removeOne(task);
m_tasksInCategory.insert(categoryId, tasksInCategory);
endRemoveRows();
}
// what to do with m_maxSizeOfFileName ?
}
} }
@@ -212,7 +298,7 @@ QModelIndex TaskModel::parent(const QModelIndex &child) const
int TaskModel::rowCount(const QModelIndex &parent) const int TaskModel::rowCount(const QModelIndex &parent) const
{ {
return parent.isValid() ? 0 : m_items.count(); return parent.isValid() ? 0 : m_tasks.count();
} }
int TaskModel::columnCount(const QModelIndex &parent) const int TaskModel::columnCount(const QModelIndex &parent) const
@@ -222,27 +308,27 @@ int TaskModel::columnCount(const QModelIndex &parent) const
QVariant TaskModel::data(const QModelIndex &index, int role) const QVariant TaskModel::data(const QModelIndex &index, int role) const
{ {
if (!index.isValid() || index.row() >= m_items.size() || index.column() != 0) if (!index.isValid() || index.row() >= m_tasks.size() || index.column() != 0)
return QVariant(); return QVariant();
if (role == TaskModel::File) if (role == TaskModel::File)
return m_items.at(index.row()).file; return m_tasks.at(index.row()).file;
else if (role == TaskModel::Line) else if (role == TaskModel::Line)
return m_items.at(index.row()).line; return m_tasks.at(index.row()).line;
else if (role == TaskModel::Description) else if (role == TaskModel::Description)
return m_items.at(index.row()).description; return m_tasks.at(index.row()).description;
else if (role == TaskModel::FileNotFound) else if (role == TaskModel::FileNotFound)
return m_items.at(index.row()).fileNotFound; return m_fileNotFound.value(m_tasks.at(index.row()).file);
else if (role == TaskModel::Type) else if (role == TaskModel::Type)
return (int)m_items.at(index.row()).type; return (int)m_tasks.at(index.row()).type;
return QVariant(); return QVariant();
} }
QIcon TaskModel::iconFor(ProjectExplorer::BuildParserInterface::PatternType type) QIcon TaskModel::iconFor(TaskWindow::TaskType type)
{ {
if (type == ProjectExplorer::BuildParserInterface::Error) if (type == TaskWindow::Error)
return m_errorIcon; return m_errorIcon;
else if (type == ProjectExplorer::BuildParserInterface::Warning) else if (type == TaskWindow::Warning)
return m_warningIcon; return m_warningIcon;
else else
return m_unspecifiedIcon; return m_unspecifiedIcon;
@@ -262,8 +348,8 @@ int TaskModel::sizeOfLineNumber()
void TaskModel::setFileNotFound(const QModelIndex &idx, bool b) void TaskModel::setFileNotFound(const QModelIndex &idx, bool b)
{ {
if (idx.isValid() && idx.row() < m_items.size()) { if (idx.isValid() && idx.row() < m_tasks.size()) {
m_items[idx.row()].fileNotFound = b; m_fileNotFound.insert(m_tasks[idx.row()].file, b);
emit dataChanged(idx, idx); emit dataChanged(idx, idx);
} }
} }
@@ -288,15 +374,15 @@ TaskModel *TaskFilterModel::taskModel() const
bool TaskFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const bool TaskFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{ {
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent); QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
ProjectExplorer::BuildParserInterface::PatternType type = ProjectExplorer::BuildParserInterface::PatternType(index.data(TaskModel::Type).toInt()); TaskWindow::TaskType type = TaskWindow::TaskType(index.data(TaskModel::Type).toInt());
switch (type) { switch (type) {
case ProjectExplorer::BuildParserInterface::Unknown: case TaskWindow::Unknown:
return m_includeUnknowns; return m_includeUnknowns;
case ProjectExplorer::BuildParserInterface::Warning: case TaskWindow::Warning:
return m_includeWarnings; return m_includeWarnings;
case ProjectExplorer::BuildParserInterface::Error: case TaskWindow::Error:
return m_includeErrors; return m_includeErrors;
} }
@@ -308,7 +394,7 @@ bool TaskFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceP
// TaskWindow // TaskWindow
///// /////
static QToolButton *createFilterButton(ProjectExplorer::BuildParserInterface::PatternType type, static QToolButton *createFilterButton(TaskWindow::TaskType type,
const QString &toolTip, TaskModel *model, const QString &toolTip, TaskModel *model,
QObject *receiver, const char *slot) QObject *receiver, const char *slot)
{ {
@@ -359,12 +445,11 @@ TaskWindow::TaskWindow()
connect(m_copyAction, SIGNAL(triggered()), SLOT(copy())); connect(m_copyAction, SIGNAL(triggered()), SLOT(copy()));
m_filterWarningsButton = createFilterButton(ProjectExplorer::BuildParserInterface::Warning, m_filterWarningsButton = createFilterButton(TaskWindow::Warning,
tr("Show Warnings"), m_model, tr("Show Warnings"), m_model,
this, SLOT(setShowWarnings(bool))); this, SLOT(setShowWarnings(bool)));
m_errorCount = 0; updateActions();
m_currentTask = -1;
} }
TaskWindow::~TaskWindow() TaskWindow::~TaskWindow()
@@ -386,12 +471,11 @@ QWidget *TaskWindow::outputWidget(QWidget *)
return m_listview; return m_listview;
} }
void TaskWindow::clearContents() void TaskWindow::clearTasks(const QString &categoryId)
{ {
m_errorCount = 0; m_model->clearTasks(categoryId);
m_currentTask = -1;
m_model->clear(); updateActions();
m_copyAction->setEnabled(false);
emit tasksChanged(); emit tasksChanged();
navigateStateChanged(); navigateStateChanged();
} }
@@ -400,15 +484,18 @@ void TaskWindow::visibilityChanged(bool /* b */)
{ {
} }
void TaskWindow::addItem(ProjectExplorer::BuildParserInterface::PatternType type, void TaskWindow::addCategory(const QString &categoryId, const QString &displayName)
const QString &description, const QString &file, int line)
{ {
m_model->addTask(type, description, file, line); Q_ASSERT(!categoryId.isEmpty());
if (type == ProjectExplorer::BuildParserInterface::Error) m_model->addCategory(categoryId, displayName);
++m_errorCount; }
m_copyAction->setEnabled(true);
void TaskWindow::addTask(const Task &task)
{
m_model->addTask(task);
updateActions();
emit tasksChanged(); emit tasksChanged();
if (m_model->rowCount() == 1)
navigateStateChanged(); navigateStateChanged();
} }
@@ -440,10 +527,10 @@ void TaskWindow::copy()
QString description = index.data(TaskModel::Description).toString(); QString description = index.data(TaskModel::Description).toString();
QString type; QString type;
switch (index.data(TaskModel::Type).toInt()) { switch (index.data(TaskModel::Type).toInt()) {
case ProjectExplorer::BuildParserInterface::Error: case TaskWindow::Error:
type = "error: "; type = "error: ";
break; break;
case ProjectExplorer::BuildParserInterface::Warning: case TaskWindow::Warning:
type = "warning: "; type = "warning: ";
break; break;
} }
@@ -457,14 +544,21 @@ void TaskWindow::setShowWarnings(bool show)
m_filter->setFilterIncludesUnknowns(show); // "Unknowns" are often associated with warnings m_filter->setFilterIncludesUnknowns(show); // "Unknowns" are often associated with warnings
} }
int TaskWindow::numberOfTasks() const int TaskWindow::taskCount(const QString &categoryId) const
{ {
return m_model->rowCount(QModelIndex()); return m_model->tasks(categoryId).count();
} }
int TaskWindow::numberOfErrors() const int TaskWindow::errorTaskCount(const QString &categoryId) const
{ {
return m_errorCount; int errorTaskCount = 0;
foreach (const Task &task, m_model->tasks(categoryId)) {
if (task.type == TaskWindow::Error)
++ errorTaskCount;
}
return errorTaskCount;
} }
int TaskWindow::priorityInStatusBar() const int TaskWindow::priorityInStatusBar() const
@@ -472,6 +566,11 @@ int TaskWindow::priorityInStatusBar() const
return 90; return 90;
} }
void TaskWindow::clearContents()
{
clearTasks();
}
bool TaskWindow::hasFocus() bool TaskWindow::hasFocus()
{ {
return m_listview->hasFocus(); return m_listview->hasFocus();
@@ -541,6 +640,11 @@ bool TaskWindow::canNavigate()
return true; return true;
} }
void TaskWindow::updateActions()
{
m_copyAction->setEnabled(m_model->tasks().count() > 0);
}
///// /////
// Delegate // Delegate
///// /////
@@ -636,7 +740,7 @@ void TaskDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
painter->setPen(textColor); painter->setPen(textColor);
TaskModel *model = static_cast<TaskFilterModel *>(view->model())->taskModel(); TaskModel *model = static_cast<TaskFilterModel *>(view->model())->taskModel();
ProjectExplorer::BuildParserInterface::PatternType type = ProjectExplorer::BuildParserInterface::PatternType(index.data(TaskModel::Type).toInt()); TaskWindow::TaskType type = TaskWindow::TaskType(index.data(TaskModel::Type).toInt());
QIcon icon = model->iconFor(type); QIcon icon = model->iconFor(type);
painter->drawPixmap(2, opt.rect.top() + 2, icon.pixmap(16, 16)); painter->drawPixmap(2, opt.rect.top() + 2, icon.pixmap(16, 16));
@@ -727,3 +831,22 @@ QWidget *TaskWindowContext::widget()
return m_taskList; return m_taskList;
} }
//
// functions
//
bool ProjectExplorer::operator==(const TaskWindow::Task &t1, const TaskWindow::Task &t2)
{
return t1.type == t2.type
&& t1.line == t2.line
&& t1.description == t2.description
&& t1.file == t2.file
&& t1.category == t2.category;
}
uint ProjectExplorer::qHash(const TaskWindow::Task &task)
{
return qHash(task.file) + task.line;
}
#include "taskwindow.moc"

View File

@@ -32,15 +32,15 @@
#include "buildparserinterface.h" #include "buildparserinterface.h"
#include <coreplugin/ioutputpane.h>
#include <coreplugin/icontext.h> #include <coreplugin/icontext.h>
#include <coreplugin/ioutputpane.h>
#include <QtGui/QTreeWidget> #include <QtCore/QModelIndex>
#include <QtGui/QStyledItemDelegate> #include <QtGui/QAction>
#include <QtGui/QListView>
#include <QtGui/QToolButton> #include <QtGui/QToolButton>
namespace ProjectExplorer { namespace ProjectExplorer {
namespace Internal { namespace Internal {
class TaskModel; class TaskModel;
@@ -48,7 +48,9 @@ class TaskFilterModel;
class TaskView; class TaskView;
class TaskWindowContext; class TaskWindowContext;
class TaskWindow : public Core::IOutputPane } // namespace Internal
class PROJECTEXPLORER_EXPORT TaskWindow : public Core::IOutputPane
{ {
Q_OBJECT Q_OBJECT
@@ -56,6 +58,35 @@ public:
TaskWindow(); TaskWindow();
~TaskWindow(); ~TaskWindow();
enum TaskType {
Unknown,
Error,
Warning
};
struct Task {
Task(TaskType type_, const QString &description_,
const QString &file_, int line_, const QString &category_) :
type(type_), description(description_), file(file_), line(line_), category(category_)
{ }
TaskType type;
QString description;
QString file;
int line;
QString category;
};
void addCategory(const QString &categoryId, const QString &displayName);
void addTask(const Task &task);
void clearTasks(const QString &categoryId = QString());
int taskCount(const QString &categoryId = QString()) const;
int errorTaskCount(const QString &categoryId = QString()) const;
// IOutputPane
QWidget *outputWidget(QWidget *); QWidget *outputWidget(QWidget *);
QList<QWidget*> toolBarWidgets() const; QList<QWidget*> toolBarWidgets() const;
@@ -64,21 +95,15 @@ public:
void clearContents(); void clearContents();
void visibilityChanged(bool visible); void visibilityChanged(bool visible);
void addItem(BuildParserInterface::PatternType type,
const QString &description, const QString &file, int line);
int numberOfTasks() const;
int numberOfErrors() const;
bool canFocus(); bool canFocus();
bool hasFocus(); bool hasFocus();
void setFocus(); void setFocus();
bool canNavigate();
bool canNext(); bool canNext();
bool canPrevious(); bool canPrevious();
void goToNext(); void goToNext();
void goToPrev(); void goToPrev();
bool canNavigate();
signals: signals:
void tasksChanged(); void tasksChanged();
@@ -89,59 +114,20 @@ private slots:
void setShowWarnings(bool); void setShowWarnings(bool);
private: private:
void updateActions();
int sizeHintForColumn(int column) const; int sizeHintForColumn(int column) const;
int m_errorCount; Internal::TaskModel *m_model;
int m_currentTask; Internal::TaskFilterModel *m_filter;
Internal::TaskView *m_listview;
TaskModel *m_model; Internal::TaskWindowContext *m_taskWindowContext;
TaskFilterModel *m_filter;
TaskView *m_listview;
TaskWindowContext *m_taskWindowContext;
QAction *m_copyAction; QAction *m_copyAction;
QToolButton *m_filterWarningsButton; QToolButton *m_filterWarningsButton;
}; };
class TaskView : public QListView bool operator==(const TaskWindow::Task &t1, const TaskWindow::Task &t2);
{ uint qHash(const TaskWindow::Task &task);
public:
TaskView(QWidget *parent = 0);
~TaskView();
void resizeEvent(QResizeEvent *e);
void keyPressEvent(QKeyEvent *e);
};
class TaskDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
TaskDelegate(QObject * parent = 0);
~TaskDelegate();
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
// TaskView uses this method if the size of the taskview changes
void emitSizeHintChanged(const QModelIndex &index);
public slots:
void currentChanged(const QModelIndex &current, const QModelIndex &previous);
private:
void generateGradientPixmap(int width, int height, QColor color, bool selected) const;
};
class TaskWindowContext : public Core::IContext
{
public:
TaskWindowContext(QWidget *widget);
virtual QList<int> context() const;
virtual QWidget *widget();
private:
QWidget *m_taskList;
QList<int> m_context;
};
} //namespace Internal
} //namespace ProjectExplorer } //namespace ProjectExplorer
#endif // TASKWINDOW_H #endif // TASKWINDOW_H