Буквально на днях вышел QtCreator 2.5.0, и в нем появился плагин TODO. Но этот плагин поддерживает комментарии вида: <KEYWORD>: <some text>, а я везде использую doxygen комментарии: @<KEYWORD> <SOME_TEXT>. Поэтому я решил доработать плагин, так чтобы он мог поддерживать комментарии обоих видов.
Подготовка
Итак, первым делом, я клонировал официальный репозиторий проекта, настроил окружение (QtCreator-2.5.0 требует для сборки Qt не ниже версии 4.7.4, поэтому пришлось собрать еще и Qt, выбрал версию 4.8.1).
Реализация
Добавление нового функционала
Собственно, код самого плагина очень прост и понятен. Основной класс, который содержит в себе информацию о ключевых словах — Keyword
. Для того чтобы мы могли определять тип ключевого слова, вводим новую сущность:
enum KeywordStyle {
DefaultKeywordStyle,
DoxygenKeywordStyle
};
И добавляем в класс Keyword
новое поле style
и новый метод QString searchingText() const;
. Этот метод возвращает строку, по которой ищется ключевое слово, вот его реализация:
QString Keyword::searchingText() const
{
if (style == DefaultKeywordStyle)
return name + QLatin1Char(':');
else {
Q_ASSERT(style == DoxygenKeywordStyle && "keywordStyle is not properly configured");
return QLatin1Char('@') + name.toLower();
}
}
Также добавляем в метод equals
соответствующее сравнение полей
style
.
Использование нового поля
Теперь, нам надо заменить использование поля name
на новый метод
searchingText
. Это необходимо сделать в классе
LineParser
в трех методах:
findKeywordEntryCandidates
- этот метод используется для формирования списка позиций ключевых слов, которые находятся в строке комментария. С помощью
searchingText
осуществляется поиск указанного ключевого слова
keywordEntriesFromCandidates
- данный метод формирует список пар {KEYWORD, TEXT}. Здесь
searchingText
используется для определения длины ключевого слова.
todoItemsFromKeywordEntries
- этот метод формирует список записей, который мы видим в окне To-Do. Здесь метод
searchingText
используется для формирования строки, которая будет отображена пользователю
findKeywordEntryCandidates
- этот метод используется для формирования списка позиций ключевых слов, которые находятся в строке комментария. С помощью
searchingText
осуществляется поиск указанного ключевого слова
keywordEntriesFromCandidates
- данный метод формирует список пар {KEYWORD, TEXT}. Здесь
searchingText
используется для определения длины ключевого слова.
todoItemsFromKeywordEntries
- этот метод формирует список записей, который мы видим в окне To-Do. Здесь метод
searchingText
используется для формирования строки, которая будет отображена пользователю
Поддержка конфигурации
Теперь плагин уже умеет осуществлять поиск и формирование списка TODO на основе информации о ключевых словах. Теперь надо доработать механизм создания, сохранения и редактирования ключевых слов.
Для этого, сначала, поправим реализацию класса Settings
. В данном классе мы поправим методы
load
save
setDefault
.
Метод load
осуществляет восстановление информации о ключевых словах из конфигурации. Так как конфигурация может быть в старом формате, то по умолчанию мы должны ставить тип ключевого слова
DefaultKeywordStyle
. Собственно, сама доработка этого метода довольно тривиальна, добавилось всего две строки:
const QString styleKey = QLatin1String("style");
//...
keyword.style = static_cast<KeywordStyle>(settings->value(styleKey, DefaultKeywordStyle).toInt());
.
Аналогичным образом обновился метод save
:
const QString styleKey = QLatin1String("style");
//...
settings->setValue(styleKey, keyword.style);
Метод setDefault используется для восстановления значений по умолчанию:
void Settings::setDefault()
{
scanningScope = ScanningScopeCurrentFile;
keywords.clear();
setDefaultKeywordStyle();
setDoxygenKeywordStyle();
}
void Settings::setDefaultKeywordStyle()
{
Keyword keyword;
keyword.name = QLatin1String("TODO");
keyword.iconResource = QLatin1String(Constants::ICON_WARNING);
keyword.color = QColor(QLatin1String(Constants::COLOR_TODO_BG));
keyword.style = DefaultKeywordStyle;
keywords.append(keyword);
//... Добавляются остальные ключевые слова
}
void Settings::setDoxygenKeywordStyle()
{
Keyword keyword;
keyword.name = QLatin1String("todo");
keyword.iconResource = QLatin1String(Constants::ICON_WARNING);
keyword.color = QColor(QLatin1String(Constants::COLOR_TODO_BG));
keyword.style = DoxygenKeywordStyle;
keywords.append(keyword);
//... Добавляются остальные ключевые слова
}
Поддержка UI
Ну и напоследок осталось реализовать поддержку нового поля в GUI. Для этого я добавил в ui файл check box, для того чтобы можно было определять тип ключевого слова
Теперь осталось в реализации KeywordDialog
поправить работу с новым полем
style
и новым check box. В конструкторе класса добавляем код для включения/ выключения checkbox:
if (keyword.style == DoxygenKeywordStyle)
ui->doxygenStyleCheckBox->setCheckState(Qt::Checked);
else
ui->doxygenStyleCheckBox->setCheckState(Qt::Unchecked);
В методе генерации Keyword
из
ui
тоже добавляем соответствующий код:
result.style = (ui->doxygenStyleCheckBox->checkState() == Qt::Checked)
? DoxygenKeywordStyle
: DefaultKeywordStyle;
Также, необходимо поправить класс OptionsDialog
, так как объекты класса
Keyword
преобразуются в объекты класса
QListWidgetItem
. Для этого я выделил такие преобразования в отдельные методы:
void OptionsDialog::itemFromKeyword(const Keyword &keyword, QListWidgetItem *item)
{
item->setIcon(QIcon(keyword.iconResource));
item->setText(keyword.name);
item->setData(Constants::IconResourceRole, keyword.iconResource);
item->setData(Constants::KeywordStyleRole, keyword.style);
item->setBackgroundColor(keyword.color);
}
Keyword OptionsDialog::keywordFromItem(const QListWidgetItem *item)
{
Keyword keyword;
keyword.name = item->text();
keyword.iconResource = item->data(Constants::IconResourceRole).toString();
keyword.color = item->backgroundColor();
keyword.style = static_cast<KeywordStyle>(item->data(Constants::KeywordStyleRole).toInt());
return keyword;
}
И заменил в коде все преобразования на вызовы этих методов.
Результат
Вот как это выглядит у меня:
Также создал заявку, приложил патч, который реализует описанную функциональность.
В принципе, можно также добавить поддержку обратного слэша в DoxygenKeywordStyle, так как в документации к Doxygen сказано:
All commands in the documentation start with a backslash () or an at-sign (@)
Автор: prograholic