Initial commit for TODO Plugin

Change-Id: I8f12017be5dc65b1244df369880e3b4851af4b2e
Reviewed-by: Eike Ziller <eike.ziller@nokia.com>
This commit is contained in:
Vasiliy Sorokin
2012-02-14 22:43:26 +04:00
committed by Eike Ziller
parent fe62330c9f
commit edb3094fa3
22 changed files with 1529 additions and 0 deletions

7
src/plugins/todo/INSTALL Normal file
View File

@@ -0,0 +1,7 @@
Installation.
1. Download QtCreator sources.
2. Build QtCreator from sources or download and install binary.
3. Change todoplugin.pro, You need QTC_BUILD_DIR set to your path to qtcreator binary and set QTC_SOURCE_DIR your path to qtcreator source
4. Build plugin:
qmake
make

View File

@@ -0,0 +1,20 @@
Copyright (c) 2010, Vasiliy Sorokin
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the vsorokin nor the names of its contributors may be used to endorse or
promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -0,0 +1,42 @@
#include "addkeyworddialog.h"
#include "ui_addkeyworddialog.h"
#include <QColorDialog>
AddKeywordDialog::AddKeywordDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::AddKeywordDialog)
{
ui->setupUi(this);
this->ui->listWidget->setViewMode(QListWidget::IconMode);
this->ui->listWidget->addItem(new QListWidgetItem(QIcon(":/info"), "information"));
this->ui->listWidget->addItem(new QListWidgetItem(QIcon(":/warning"), "warning"));
this->ui->listWidget->addItem(new QListWidgetItem(QIcon(":/error"), "error"));
connect(this->ui->pushButton, SIGNAL(clicked()), this, SLOT(chooseColor()));
}
AddKeywordDialog::~AddKeywordDialog()
{
delete ui;
}
QString AddKeywordDialog::keywordName()
{
return this->ui->lineEdit->text();
}
QColor AddKeywordDialog::keywordColor()
{
return QColor(this->ui->colorEdit->text());
}
QIcon AddKeywordDialog::keywordIcon()
{
return this->ui->listWidget->currentItem()->icon();
}
void AddKeywordDialog::chooseColor()
{
QColorDialog *dialog = new QColorDialog(QColor(this->ui->colorEdit->text()),this);
this->ui->colorEdit->setText(dialog->getColor().name());
}

View File

@@ -0,0 +1,28 @@
#ifndef ADDKEYWORDDIALOG_H
#define ADDKEYWORDDIALOG_H
#include <QDialog>
namespace Ui {
class AddKeywordDialog;
}
class AddKeywordDialog : public QDialog
{
Q_OBJECT
public:
explicit AddKeywordDialog(QWidget *parent = 0);
~AddKeywordDialog();
QString keywordName();
QColor keywordColor();
QIcon keywordIcon();
public slots:
void chooseColor();
private:
Ui::AddKeywordDialog *ui;
};
#endif // ADDKEYWORDDIALOG_H

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddKeywordDialog</class>
<widget class="QDialog" name="AddKeywordDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>379</width>
<height>225</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Icons</string>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="listWidget"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Color</string>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="2" column="0">
<widget class="QLineEdit" name="colorEdit">
<property name="inputMask">
<string>\#HHHHHH; </string>
</property>
<property name="text">
<string>#000000</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="pushButton">
<property name="text">
<string>Choose</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Keyword</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="lineEdit"/>
</item>
</layout>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>AddKeywordDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>AddKeywordDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

8
src/plugins/todo/icons.qrc Executable file
View File

@@ -0,0 +1,8 @@
<RCC>
<qresource prefix="/">
<file alias="error">images/error.png</file>
<file alias="info">images/info.png</file>
<file alias="warning">images/warning.png</file>
<file alias="todo">images/todo.png</file>
</qresource>
</RCC>

BIN
src/plugins/todo/images/error.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 640 B

BIN
src/plugins/todo/images/info.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 856 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 511 B

View File

@@ -0,0 +1,26 @@
#include "keyword.h"
Keyword::Keyword()
{
}
Keyword::Keyword(QString name_, QIcon icon_, QColor warningColor_) :
name(name_), icon(icon_), warningColor(warningColor_)
{
}
QDataStream &operator<<(QDataStream &out, const Keyword &myObj)
{
out << myObj.name;
out << myObj.icon;
out << myObj.warningColor;
return out;
}
QDataStream &operator>>(QDataStream &in, Keyword &myObj)
{
in >> myObj.name;
in >> myObj.icon;
in >> myObj.warningColor;
return in;
}

View File

@@ -0,0 +1,29 @@
#ifndef KEYWORD_H
#define KEYWORD_H
#include <QIcon>
#include <QColor>
#include <QString>
#include <QList>
#include <QMetaType>
class Keyword
{
public:
Keyword();
Keyword(QString name_, QIcon icon_, QColor warningColor_);
QString name;
QIcon icon;
QColor warningColor;
};
typedef QList<Keyword> KeywordsList;
QDataStream &operator<<(QDataStream &out, const Keyword &myObj);
QDataStream &operator>>(QDataStream &in, Keyword &myObj);
Q_DECLARE_METATYPE(KeywordsList)
Q_DECLARE_METATYPE(Keyword)
#endif // KEYWORD_H

View File

@@ -0,0 +1,138 @@
#include "settingsdialog.h"
#include "ui_settingsdialog.h"
#include "addkeyworddialog.h"
SettingsDialog::SettingsDialog(QWidget *parent) :
QWidget(parent),
ui(new Ui::SettingsDialog)
{
ui->setupUi(this);
connect(this->ui->addButton, SIGNAL(clicked()), this, SLOT(addButtonClicked()));
connect(this->ui->removeButton, SIGNAL(clicked()), this, SLOT(removeButtonClicked()));
connect(this->ui->resetButton, SIGNAL(clicked()), this, SLOT(resetButtonClicked()));
connect(this->ui->buildIssuesRadioButton, SIGNAL(toggled(bool)), this, SIGNAL(settingsChanged()));
connect(this->ui->todoOutputRadioButton, SIGNAL(toggled(bool)), this, SIGNAL(settingsChanged()));
connect(this->ui->projectRadioButton, SIGNAL(toggled(bool)), this, SIGNAL(settingsChanged()));
connect(this->ui->currentFileRadioButton, SIGNAL(toggled(bool)), this, SIGNAL(settingsChanged()));
}
SettingsDialog::~SettingsDialog()
{
delete ui;
}
void SettingsDialog::setProjectRadioButtonEnabled(bool what)
{
this->ui->projectRadioButton->setChecked(what);
}
void SettingsDialog::setCurrentFileRadioButtonEnabled(bool what)
{
this->ui->currentFileRadioButton->setChecked(what);
}
void SettingsDialog::setBuildIssuesRadioButtonEnabled(bool what)
{
this->ui->buildIssuesRadioButton->setChecked(what);
}
void SettingsDialog::setTodoOutputRadioButtonEnabled(bool what)
{
this->ui->todoOutputRadioButton->setChecked(what);
}
void SettingsDialog::addToKeywordsList(Keyword keyword)
{
QListWidgetItem *item = new QListWidgetItem(keyword.icon, keyword.name);
item->setBackgroundColor(keyword.warningColor);
this->ui->keywordsList->addItem(item);
}
void SettingsDialog::setKeywordsList(KeywordsList list)
{
if (!list.count())
{
resetButtonClicked();
}
else
{
for (int i = 0; i < list.count(); ++i)
{
addToKeywordsList(list.at(i));
}
}
}
bool SettingsDialog::projectRadioButtonEnabled()
{
return this->ui->projectRadioButton->isChecked();
}
bool SettingsDialog::currentFileRadioButtonEnabled()
{
return this->ui->currentFileRadioButton->isChecked();
}
bool SettingsDialog::buildIssuesRadioButtonEnabled()
{
return this->ui->buildIssuesRadioButton->isChecked();
}
bool SettingsDialog::todoOutputRadioButtonEnabled()
{
return this->ui->todoOutputRadioButton->isChecked();
}
KeywordsList SettingsDialog::keywordsList()
{
KeywordsList list;
for (int i = 0; i < this->ui->keywordsList->count(); ++i)
{
Keyword keyword;
keyword.name = this->ui->keywordsList->item(i)->text();
keyword.icon = this->ui->keywordsList->item(i)->icon();
keyword.warningColor = this->ui->keywordsList->item(i)->backgroundColor();
list.append(keyword);
}
return list;
}
void SettingsDialog::clearKeywordsList()
{
this->ui->keywordsList->clear();
}
void SettingsDialog::addButtonClicked()
{
Keyword keyword;
AddKeywordDialog *addKeywordDialog = new AddKeywordDialog(this);
if (addKeywordDialog->exec() == QDialog::Accepted)
{
keyword.name = addKeywordDialog->keywordName();
keyword.icon = addKeywordDialog->keywordIcon();
keyword.warningColor = addKeywordDialog->keywordColor();
addToKeywordsList(keyword);
emit settingsChanged();
}
}
void SettingsDialog::removeButtonClicked()
{
this->ui->keywordsList->takeItem(this->ui->keywordsList->currentRow());
emit settingsChanged();
}
void SettingsDialog::resetButtonClicked()
{
clearKeywordsList();
addToKeywordsList(Keyword("TODO", QIcon(":/warning"), QColor("#BFFFC8")));
addToKeywordsList(Keyword("NOTE", QIcon(":/info"), QColor("#E2DFFF")));
addToKeywordsList(Keyword("FIXME", QIcon(":/error"), QColor("#FFBFBF")));
addToKeywordsList(Keyword("BUG", QIcon(":/error"), QColor("#FFDFDF")));
addToKeywordsList(Keyword("HACK", QIcon(":/info"), QColor("#FFFFAA")));
emit settingsChanged();
}

View File

@@ -0,0 +1,45 @@
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include <QWidget>
#include "keyword.h"
namespace Ui {
class SettingsDialog;
}
class SettingsDialog : public QWidget
{
Q_OBJECT
public:
explicit SettingsDialog(QWidget *parent = 0);
~SettingsDialog();
void setProjectRadioButtonEnabled(bool what);
void setCurrentFileRadioButtonEnabled(bool what);
void setBuildIssuesRadioButtonEnabled(bool what);
void setTodoOutputRadioButtonEnabled(bool what);
void addToKeywordsList(Keyword);
void setKeywordsList(KeywordsList);
bool projectRadioButtonEnabled();
bool currentFileRadioButtonEnabled();
bool buildIssuesRadioButtonEnabled();
bool todoOutputRadioButtonEnabled();
KeywordsList keywordsList();
signals:
void settingsChanged();
private slots:
void clearKeywordsList();
void addButtonClicked();
void removeButtonClicked();
void resetButtonClicked();
private:
Ui::SettingsDialog *ui;
};
#endif // SETTINGSDIALOG_H

View File

@@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SettingsDialog</class>
<widget class="QWidget" name="SettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>740</width>
<height>423</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6"/>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QListWidget" name="keywordsList"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QPushButton" name="addButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="removeButton">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="resetButton">
<property name="text">
<string>Reset</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="projectGroupBox">
<property name="title">
<string>View options</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="QRadioButton" name="currentFileRadioButton">
<property name="text">
<string>From current opened file</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="projectRadioButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>From projects</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="paneGroupBox">
<property name="title">
<string>Pane options</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QRadioButton" name="todoOutputRadioButton">
<property name="text">
<string>Show in &quot;TODO Output&quot;</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="buildIssuesRadioButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>Show in &quot;Build Issues&quot;</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Icons and Colors show on
TODO Output pane only</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -0,0 +1,118 @@
#include "settingspage.h"
#include <coreplugin/icore.h>
#include <QList>
#include <QMessageBox>
SettingsPage::SettingsPage(KeywordsList keywords, int projectOptions, int paneOptions, QObject *parent) : IOptionsPage(parent)
{
this->keywords = keywords;
this->projectOptions = projectOptions;
this->paneOptions = paneOptions;
}
SettingsPage::~SettingsPage()
{
delete dialog;
}
QString SettingsPage::id() const
{
return "TodoSettings";
}
QString SettingsPage::trName() const
{
return tr("TODO Plugin");
}
QString SettingsPage::category() const
{
return "TODO";
}
QString SettingsPage::trCategory() const
{
return tr("TODO");
}
QString SettingsPage::displayName() const
{
return trName();
}
QString SettingsPage::displayCategory() const
{
return trCategory();
}
QIcon SettingsPage::categoryIcon() const
{
return QIcon(":/todo");
}
QWidget *SettingsPage::createPage(QWidget *parent)
{
settingsStatus = false;
dialog = new SettingsDialog(parent);
dialog->setKeywordsList(keywords);
switch (projectOptions)
{
case 0:
dialog->setProjectRadioButtonEnabled(false);
dialog->setCurrentFileRadioButtonEnabled(true);
break;
case 1:
default:
dialog->setProjectRadioButtonEnabled(true);
dialog->setCurrentFileRadioButtonEnabled(false);
break;
}
switch (paneOptions)
{
case 0:
dialog->setBuildIssuesRadioButtonEnabled(false);
dialog->setTodoOutputRadioButtonEnabled(true);
break;
case 1:
default:
dialog->setBuildIssuesRadioButtonEnabled(true);
dialog->setTodoOutputRadioButtonEnabled(false);
break;
}
connect(dialog, SIGNAL(settingsChanged()), this, SLOT(settingsChanged()));
return dialog;
}
void SettingsPage::apply()
{
if (settingsStatus)
{
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup("TODOPlugin");
projectOptions = dialog->currentFileRadioButtonEnabled() ? 0 : 1;
paneOptions = dialog->todoOutputRadioButtonEnabled() ? 0 : 1;
keywords = dialog->keywordsList();
settings->setValue("project_options", projectOptions);
settings->setValue("pane_options", paneOptions);
settings->setValue("keywords", qVariantFromValue(keywords));
settings->endGroup();
settings->sync();
QMessageBox::information(dialog, tr("Information"), tr("The TODO plugin settings change will take effect after a restart of Qt Creator."));
settingsStatus = false;
}
}
void SettingsPage::finish()
{
//apply();
}
void SettingsPage::settingsChanged()
{
settingsStatus = true;
}

View File

@@ -0,0 +1,39 @@
#ifndef SETTINGSPAGE_H
#define SETTINGSPAGE_H
#include <QIcon>
#include <coreplugin/dialogs/ioptionspage.h>
#include "settingsdialog.h"
class SettingsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
SettingsPage(KeywordsList keywords = KeywordsList(), int projectOptions = 0, int paneOptions = 0, QObject *parent = 0);
~SettingsPage();
QString id() const;
QString trName() const;
QString category() const;
QString trCategory() const;
QString displayName() const;
QIcon categoryIcon() const;
QString displayCategory() const;
QWidget *createPage(QWidget *parent);
void apply();
void finish();
public slots:
void settingsChanged();
private:
SettingsDialog *dialog;
bool settingsStatus;
int projectOptions;
int paneOptions;
KeywordsList keywords;
};
#endif // SETTINGSPAGE_H

View File

@@ -0,0 +1,174 @@
/*
*
* TODO plugin - Add pane with list all TODO, FIXME, etc. comments.
*
* Copyright (C) 2010 VasiliySorokin
*
* Authors: Vasiliy Sorokin <sorokin.vasiliy@gmail.com>
*
* This file is part of TODO plugin for QtCreator.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of the vsorokin nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "todooutputpane.h"
#include <QListWidgetItem>
#include <QRegExp>
#include <QIcon>
// TODO: make fix
// NOTE: make note
// HACK: make hack
// BUG: make bug
TodoOutputPane::TodoOutputPane(QObject *parent) : IOutputPane(parent)
{
todoList = new QListWidget();
todoList->setFlow(QListView::TopToBottom);
todoList->setFrameStyle(QFrame::NoFrame);
lastCurrentRow = 0;
}
TodoOutputPane::~TodoOutputPane()
{
delete todoList;
}
void TodoOutputPane::addItem(const QString &text, const QString &file, const int rowNumber, const QIcon &icon, const QColor &color)
{
QListWidgetItem *newItem = new QListWidgetItem();
newItem->setBackgroundColor(color);
newItem->setIcon(icon);
newItem->setData(Qt::UserRole + 1, file);
newItem->setData(Qt::UserRole + 2, rowNumber);
newItem->setToolTip(file + ":" + QString::number(rowNumber));
newItem->setText(file.right(file.size() - file.lastIndexOf("/") - 1) + ":" + QString::number(rowNumber) + ": " + text);
todoList->addItem(newItem);
}
QListWidget *TodoOutputPane::getTodoList() const
{
return todoList;
}
QWidget *TodoOutputPane::outputWidget(QWidget */*parent*/)
{
return todoList;
}
QList<QWidget*> TodoOutputPane::toolBarWidgets() const
{
return QList<QWidget*>();
}
QString TodoOutputPane::name() const
{
return tr("TODO Output");
}
QString TodoOutputPane::displayName() const
{
return name();
}
int TodoOutputPane::priorityInStatusBar() const
{
return 1;
}
void TodoOutputPane::clearContents()
{
todoList->clear();
}
void TodoOutputPane::clearContents(QString filename)
{
int i = 0;
lastCurrentRow = 0;
while (i < todoList->count())
{
if (!filename.compare(todoList->item(i)->data(Qt::UserRole + 1).toString()))
{
if (lastCurrentRow == 0)
lastCurrentRow = todoList->currentRow();
todoList->takeItem(i);
}
else
{
++i;
}
}
}
void TodoOutputPane::visibilityChanged(bool visible)
{
todoList->setVisible(visible);
}
void TodoOutputPane::setFocus()
{
todoList->setFocus();
}
bool TodoOutputPane::hasFocus()
{
return todoList->hasFocus();
}
bool TodoOutputPane::canFocus()
{
return true;
}
bool TodoOutputPane::canNavigate()
{
return todoList->count() > 1;
}
bool TodoOutputPane::canNext()
{
return todoList->currentRow() < todoList->count() && todoList->count() > 1;
}
bool TodoOutputPane::canPrevious()
{
return todoList->currentRow() > 0 && todoList->count() > 1;
}
void TodoOutputPane::goToNext()
{
todoList->setCurrentRow(todoList->currentRow() + 1);
}
void TodoOutputPane::goToPrev()
{
todoList->setCurrentRow(todoList->currentRow() - 1);
}
void TodoOutputPane::sort()
{
todoList->sortItems(Qt::AscendingOrder);
if (todoList->count() > 0)
todoList->setCurrentRow(lastCurrentRow < todoList->count() ? lastCurrentRow : todoList->count() - 1);
}

View File

@@ -0,0 +1,76 @@
/*
*
* TODO plugin - Add pane with list all TODO, FIXME, etc. comments.
*
* Copyright (C) 2010 VasiliySorokin
*
* Authors: Vasiliy Sorokin <sorokin.vasiliy@gmail.com>
*
* This file is part of TODO plugin for QtCreator.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of the vsorokin nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TODOOUTPUTPANE_H
#define TODOOUTPUTPANE_H
#include "keyword.h"
#include <coreplugin/ioutputpane.h>
#include <QObject>
#include <QListWidget>
class TodoOutputPane : public Core::IOutputPane
{
public:
TodoOutputPane(QObject *parent);
~TodoOutputPane();
QWidget *outputWidget(QWidget *parent);
QList<QWidget*> toolBarWidgets() const;
QString name() const;
QString displayName() const;
int priorityInStatusBar() const;
void clearContents();
void clearContents(QString filename);
void visibilityChanged(bool visible);
void setFocus();
bool hasFocus();
bool canFocus();
bool canNavigate();
bool canNext();
bool canPrevious();
void goToNext();
void goToPrev();
void sort();
void addItem(const QString &text, const QString &file, const int rowNumber, const QIcon &icon, const QColor &color);
QListWidget *getTodoList() const;
private:
QListWidget *todoList;
int lastCurrentRow;
};
#endif // TODOOUTPUTPANE_H

376
src/plugins/todo/todoplugin.cpp Executable file
View File

@@ -0,0 +1,376 @@
/*
*
* TODO plugin - Add pane with list all TODO, FIXME, etc. comments.
*
* Copyright (C) 2010 VasiliySorokin
*
* Authors: Vasiliy Sorokin <sorokin.vasiliy@gmail.com>
*
* This file is part of TODO plugin for QtCreator.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of the vsorokin nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "todoplugin.h"
#include <QtPlugin>
#include <QStringList>
#include <QtConcurrentRun>
#include <coreplugin/icore.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <qtconcurrent/runextensions.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/itexteditor.h>
#include <coreplugin/ifile.h>
#include <extensionsystem/pluginmanager.h>
#include <QKeySequence>
#include <QAction>
#include <QFile>
#include <QFileInfo>
#include <QDataStream>
#include <QSettings>
#include <QMessageBox>
#include <QTextCodec>
#include <coreplugin/progressmanager/progressmanager.h>
#include <coreplugin/progressmanager/futureprogress.h>
TodoPlugin::TodoPlugin()
{
qRegisterMetaTypeStreamOperators<Keyword>("Keyword");
qRegisterMetaTypeStreamOperators<KeywordsList>("KeywordsList");
currentProject = 0;
inReading = false;
readSettings();
}
TodoPlugin::~TodoPlugin()
{
// Do notning
}
void TodoPlugin::readSettings()
{
QSettings *settings = Core::ICore::instance()->settings();
settings->beginGroup("TODOPlugin");
projectOptions = settings->value("project_options", 0).toInt();
paneOptions = settings->value("pane_options", 0).toInt();
KeywordsList defaultKeywords;
defaultKeywords.append(Keyword("TODO", QIcon(":/warning"), QColor("#BFFFC8")));
defaultKeywords.append(Keyword("NOTE", QIcon(":/info"), QColor("#E2DFFF")));
defaultKeywords.append(Keyword("FIXME", QIcon(":/error"), QColor("#FFBFBF")));
defaultKeywords.append(Keyword("BUG", QIcon(":/error"), QColor("#FFDFDF")));
defaultKeywords.append(Keyword("HACK", QIcon(":/info"), QColor("#FFFFAA")));
keywords = settings->value("keywords", qVariantFromValue(defaultKeywords)).value<KeywordsList>();
settings->endGroup();
}
bool TodoPlugin::initialize(const QStringList& args, QString *errMsg)
{
Q_UNUSED(args);
Q_UNUSED(errMsg);
patternString = generatePatternString();
settingsPage = new SettingsPage(keywords, projectOptions, paneOptions, this);
if (paneOptions == 0)
{
outPane = new TodoOutputPane(this);
addAutoReleasedObject(outPane);
connect(outPane->getTodoList(), SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(gotoToRowInFile(QListWidgetItem*)));
connect(outPane->getTodoList(), SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(gotoToRowInFile(QListWidgetItem*)));
}
else
{
ExtensionSystem::PluginManager* pluginManager = ExtensionSystem::PluginManager::instance();
taskHub = pluginManager->getObject<ProjectExplorer::TaskHub>();
if (!taskHub)
{
paneOptions = 1;
outPane = new TodoOutputPane(this);
addAutoReleasedObject(outPane);
connect(outPane->getTodoList(), SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(gotoToRowInFile(QListWidgetItem*)));
connect(outPane->getTodoList(), SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(gotoToRowInFile(QListWidgetItem*)));
QMessageBox::warning((QWidget *)Core::ICore::instance()->mainWindow(), tr("TODO plugin"), tr("Task window object not found.\nWork in TODO Output pane."));
}
else
{
taskHub->addCategory("todoplugin", tr("TODOs comments"));
}
}
addAutoReleasedObject(settingsPage);
connect(Core::EditorManager::instance(), SIGNAL(currentEditorChanged(Core::IEditor*)), this, SLOT(currentEditorChanged(Core::IEditor*)));
if (projectOptions != 0)
{
connect(ProjectExplorer::ProjectExplorerPlugin::instance(), SIGNAL(currentProjectChanged(ProjectExplorer::Project*)), this, SLOT(projectChanged(ProjectExplorer::Project *)));
}
return true;
}
void TodoPlugin::extensionsInitialized()
{
// Do nothing
}
void TodoPlugin::shutdown()
{
// Do nothing
}
void TodoPlugin::showPane()
{
if (paneOptions == 0)
{
outPane->visibilityChanged(true);
outPane->setFocus();
}
}
void TodoPlugin::gotoToRowInFile(QListWidgetItem *item)
{
int row = item->data(Qt::UserRole + 2).toInt();
QString file = item->data(Qt::UserRole + 1).toString();
if (QFileInfo(file).exists())
{
Core::IEditor *editor = Core::EditorManager::instance()->openEditor(file);
editor->gotoLine(row);
}
}
void TodoPlugin::currentEditorChanged(Core::IEditor *editor)
{
if (inReading)
return;
if (projectOptions == 0)
{
if (paneOptions == 0)
{
outPane->clearContents();
}
else
{
taskHub->clearTasks("todoplugin");
}
}
if (!editor)
{
return;
}
connect(editor->file(), SIGNAL(changed()), this, SLOT(fileChanged()));
QString fileName = editor->file()->fileName();
if (projectOptions == 0)
readFile(fileName);
}
void TodoPlugin::removeFromLocalTasks(QString filename)
{
for (int i = 0; i < tasks.count(); ++i)
{
if (!tasks.at(i).file.compare(filename))
{
tasks.removeAt(i);
}
}
}
void TodoPlugin::addLocalTaskToTaskWindow()
{
for (int i = 0; i < tasks.count(); ++i)
{
taskHub->addTask(tasks.at(i));
}
}
void TodoPlugin::fileChanged()
{
Core::IFile *file = (Core::IFile *)sender();
if (file)
{
if (projectOptions == 0)
{
if (paneOptions == 0)
{
outPane->clearContents();
}
else
{
taskHub->clearTasks("todoplugin");
}
}
else
{
if (paneOptions == 0)
{
outPane->clearContents(file->fileName());
}
else
{
taskHub->clearTasks("todoplugin");
removeFromLocalTasks(file->fileName());
}
}
readFile(file->fileName());
}
}
Keyword TodoPlugin::prepareOutputString(QString &text)
{
Keyword keyword;
for(int i = 0; i < keywords.count(); ++i)
{
QRegExp keywordExp("//\\s*" + keywords.at(i).name + "(:|\\s)", Qt::CaseInsensitive);
if (text.contains(keywordExp))
{
text = text.replace("\n", "");
text = text.replace("\r", "");
text = text.replace(keywordExp, keywords.at(i).name + ": ");
text = text.trimmed();
keyword = keywords.at(i);
break;
}
}
return keyword;
}
void TodoPlugin::readFile(QString fileName)
{
QFile file(fileName);
if (!file.open(QFile::ReadOnly | QFile::Text))
return;
int i = 1;
while (!file.atEnd())
{
QString currentLine = file.readLine();
if (currentLine.contains(QRegExp(patternString, Qt::CaseInsensitive)))
{
Keyword resultKeyword = prepareOutputString(currentLine);
QTextCodec *unicodeCodec = QTextCodec::codecForLocale();
currentLine = unicodeCodec->toUnicode(currentLine.toAscii());
if (paneOptions == 0)
{
outPane->addItem(currentLine, fileName, i, resultKeyword.icon, resultKeyword.warningColor);
if (!inReading)
outPane->sort();
}
else
{
ProjectExplorer::Task task(ProjectExplorer::Task::Unknown, currentLine, fileName, i, "todoplugin");
tasks.append(task);
}
}
++i;
}
if (paneOptions != 0 && !inReading)
{
qSort(tasks.begin(), tasks.end(), TodoPlugin::taskLessThan);
addLocalTaskToTaskWindow();
}
}
QString TodoPlugin::generatePatternString()
{
QString result = "";
if (keywords.count())
{
for (int i = 0; i < keywords.count() - 1; ++i)
{
result += "//\\s*" + keywords.at(i).name + "(:|\\s)|";
}
result += "//\\s*" + keywords.at(keywords.count() - 1).name + "(:|\\s)";
}
return result;
}
void TodoPlugin::projectChanged(ProjectExplorer::Project *project)
{
if (!project)
return;
if (inReading)
return;
currentProject = project;
if (paneOptions == 0)
{
outPane->clearContents();
}
else
{
taskHub->clearTasks("todoplugin");
}
inReading = true;
QFuture<void> result = QtConcurrent::run(&TodoPlugin::readCurrentProject, this);
Core::ICore::instance()->progressManager()->addTask(result, tr("Todoscan"), "Todo.Plugin.Scanning");
}
void TodoPlugin::readCurrentProject(QFutureInterface<void> &future, TodoPlugin *instance)
{
QStringList filesList = instance->currentProject->files(ProjectExplorer::Project::ExcludeGeneratedFiles);
future.setProgressRange(0, filesList.count()-1);
for (int i = 0; i < filesList.count(); ++i)
{
instance->readFile(filesList.at(i));
future.setProgressValue(i);
}
if (instance->paneOptions == 0)
{
instance->outPane->sort();
}
else
{
qSort(instance->tasks.begin(), instance->tasks.end(), TodoPlugin::taskLessThan);
instance->addLocalTaskToTaskWindow();
}
instance->inReading = false;
future.reportFinished();
}
bool TodoPlugin::taskLessThan(const ProjectExplorer::Task &t1, const ProjectExplorer::Task &t2)
{
if (!t1.file.right(t1.file.size() - t1.file.lastIndexOf("/") - 1).compare(t2.file.right(t2.file.size() - t2.file.lastIndexOf("/") - 1)))
{
if (t1.line < t2.line)
{
return true;
}
else
{
return false;
}
}
else
{
return t1.file.right(t1.file.size() - t1.file.lastIndexOf("/") - 1).compare(t2.file.right(t2.file.size() - t2.file.lastIndexOf("/") - 1)) < 0;
}
}
Q_EXPORT_PLUGIN(TodoPlugin)

91
src/plugins/todo/todoplugin.h Executable file
View File

@@ -0,0 +1,91 @@
/*
*
* TODO plugin - Add pane with list all TODO, FIXME, etc. comments.
*
* Copyright (C) 2010 VasiliySorokin
*
* Authors: Vasiliy Sorokin <sorokin.vasiliy@gmail.com>
*
* This file is part of TODO plugin for QtCreator.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* * Neither the name of the vsorokin nor the names of its contributors may be used to endorse or
* promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef TODOPLUGIN_H
#define TODOPLUGIN_H
#include <QFuture>
#include <QList>
#include <extensionsystem/iplugin.h>
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/task.h>
#include <projectexplorer/taskhub.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/project.h>
#include "todooutputpane.h"
#include "settingspage.h"
#include "keyword.h"
class TodoPlugin : public ExtensionSystem::IPlugin
{
Q_OBJECT
public:
TodoPlugin();
~TodoPlugin();
void extensionsInitialized();
bool initialize(const QStringList & arguments, QString * errorString);
void shutdown();
public slots:
void showPane();
void gotoToRowInFile(QListWidgetItem *);
void currentEditorChanged(Core::IEditor *editor);
void fileChanged();
void projectChanged(ProjectExplorer::Project *);
signals:
void updateFutureValue(int value);
void setFutureRange(int, int);
private:
void readFile(QString);
static void readCurrentProject(QFutureInterface<void> &future, TodoPlugin* instance);
void removeFromLocalTasks(QString filename);
void addLocalTaskToTaskWindow();
static bool taskLessThan(const ProjectExplorer::Task &t1, const ProjectExplorer::Task &t2);
Keyword prepareOutputString(QString &text);
QString generatePatternString();
void readSettings();
TodoOutputPane *outPane;
ProjectExplorer::TaskHub *taskHub;
SettingsPage *settingsPage;
QString patternString;
KeywordsList keywords;
int projectOptions;
int paneOptions;
ProjectExplorer::Project *currentProject;
QList<ProjectExplorer::Task> tasks;
bool inReading;
QFutureInterface<void> *progressObject;
};
#endif // TODOPLUGIN_H

46
src/plugins/todo/todoplugin.pro Executable file
View File

@@ -0,0 +1,46 @@
CONFIG += release
TEMPLATE = lib
TARGET = todo
PROVIDER = vsorokin
QTC_SOURCE_DIR = /home/vass/qt-creator
IDE_SOURCE_TREE = $$QTC_SOURCE_DIR
QTC_BUILD_DIR = /opt/qtcreator-2.1.81
DESTDIR = $$QTC_BUILD_DIR/lib/qtcreator/plugins/$$(PROVIDER)
IDE_BUILD_TREE = $$QTC_BUILD_DIR
LIBS += -L$$IDE_BUILD_TREE/lib/qtcreator/ \
-L$$IDE_BUILD_TREE/lib/qtcreator/plugins/Nokia
include( $$IDE_SOURCE_TREE/src/qtcreatorplugin.pri )
include( $$IDE_SOURCE_TREE/src/plugins/coreplugin/coreplugin.pri )
include( $$IDE_SOURCE_TREE/src/plugins/projectexplorer/projectexplorer.pri )
include( $$IDE_SOURCE_TREE/src/plugins/texteditor/texteditor.pri )
INCLUDEPATH += $$IDE_SOURCE_TREE/src \
$$IDE_SOURCE_TREE/src/plugins \
$$IDE_SOURCE_TREE/src/libs \
$$IDE_SOURCE_TREE/src/libs/extensionsystem
HEADERS += todoplugin.h \
todooutputpane.h \
settingsdialog.h \
settingspage.h \
addkeyworddialog.h \
keyword.h
SOURCES += todoplugin.cpp \
todooutputpane.cpp \
settingsdialog.cpp \
settingspage.cpp \
addkeyworddialog.cpp \
keyword.cpp
OTHER_FILES += todo.pluginspec
RESOURCES += \
icons.qrc
FORMS += \
settingsdialog.ui \
addkeyworddialog.ui