Буквально на днях вышел QtCreator 2.5.0, и в нем появился плагин TODO. Но этот плагин поддерживает комментарии вида: <KEYWORD>: <some text>, а я везде использую doxygen комментарии: @<KEYWORD> <SOME_TEXT>. Поэтому я решил доработать плагин, так чтобы он мог поддерживать комментарии обоих видов.
Итак, первым делом, я клонировал официальный репозиторий проекта, настроил окружение (QtCreator-2.5.0 требует для сборки Qt не ниже версии 4.7.4, поэтому пришлось собрать еще и Qt, выбрал версию 4.8.1).
Собственно, код самого плагина очень прост и понятен. Основной класс, который содержит в себе информацию о ключевых словах —
И добавляем в класс
Также добавляем в метод
Теперь, нам надо заменить использование поля
Теперь плагин уже умеет осуществлять поиск и формирование списка TODO на основе информации о ключевых словах. Теперь надо доработать механизм создания, сохранения и редактирования ключевых слов.
Для этого, сначала, поправим реализацию класса
Метод
Аналогичным образом обновился метод
Метод setDefault используется для восстановления значений по умолчанию:
Ну и напоследок осталось реализовать поддержку нового поля в GUI. Для этого я добавил в ui файл check box, для того чтобы можно было определять тип ключевого слова
Теперь осталось в реализации
В методе генерации
Также, необходимо поправить класс
Вот как это выглядит у меня:
Также создал заявку, приложил патч, который реализует описанную функциональность.
В принципе, можно также добавить поддержку обратного слэша \ в DoxygenKeywordStyle, так как в документации к Doxygen сказано:
Подготовка
Итак, первым делом, я клонировал официальный репозиторий проекта, настроил окружение (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
используется для формирования строки, которая будет отображена пользователю
Поддержка конфигурации
Теперь плагин уже умеет осуществлять поиск и формирование списка TODO на основе информации о ключевых словах. Теперь надо доработать механизм создания, сохранения и редактирования ключевых слов.
Для этого, сначала, поправим реализацию класса
Settings
. В данном классе мы поправим методы loadsave
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 (@)