📜 ⬆️ ⬇️

QtCreator TODO Plugin. Continuation

TODO Plugin

Some time ago I wrote about the plugin I developed that display a list of all the TODOs, FIXMEs, and so on comments in the current open document. Yesterday I released a new version of this plugin, in which there were quite a few changes, here are the key ones:

During the development, I managed to dig up a few interesting things that might come in handy for other plugin developers, and I’ll share it with the cat.



The first thing I needed was to find out how to create a custom tab in the QtCreator settings, it seemed pretty simple, all it took was to add a new class inherited from the Core :: IOptionsPage interface , its declaration looks like this:
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(); //       "Apply"  "OK" void finish(); //        - "OK"  "Cancel" public slots: void settingsChanged(); private: SettingsDialog *dialog; //   bool settingsStatus; //  ? int projectOptions; //   int paneOptions; //   KeywordsList keywords; //    }; 

The tab widget I created in the designer there’s nothing complicated about a standard QlistWidget, a few QRadioButton and a bunch of buttons (see the image).
The key here is the apply () method, which is where the settings are saved.
It looks like this:
 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; } } 

In general, nothing complicated, just to remind you that in order to be able to transfer your own data types to QVariant, for them you need to define the operators: << and >>, as well as register them in the MOC.

Build Issues Window


Strictly speaking, it is called TaskWindow and can serve as standard output for any messages. I decided to add the ability to display messages in this window on the strong advice of people from the Qt Developer Network community, which I also wrote about earlier. You can access this window as follows, you need to connect the following heading to the project:
 #include <projectexplorer/taskwindow.h> 

And get a pointer to the window:
 taskWindow = pluginManager->getObject<ProjectExplorer::TaskWindow>(); 

Everything. Now you can work with him, for this are the methods:
 void addCategory(const QString &categoryId, const QString &displayName); void addTask(const Task &task); void removeTask(const Task &task); void clearTasks(const QString &categoryId = QString()); 

Categories are needed to identify exactly our messages.
Task structure is simple and looks like this:
 struct PROJECTEXPLORER_EXPORT Task { enum TaskType { Unknown, Error, Warning }; Task() : type(Unknown), line(-1) { } Task(TaskType type_, const QString &description_, const QString &file_, int line_, const QString &category_) : type(type_), description(description_), file(file_), line(line_), category(category_) { } Task(const Task &source) : type(source.type), description(source.description), file(source.file), line(source.line), category(source.category), formats(source.formats) { } ~Task() { } TaskType type; QString description; QString file; int line; QString category; QList<QTextLayout::FormatRange> formats; }; 

Important: In the spec, you need to specify the dependence of the plugin on ProjectExplorer


progressbar To implement the progress bar, it took a bit of magic and nerves. In order for the scan not to slow down the rest of the project load, I put it in a separate thread:
  QFuture<void> result = QtConcurrent::run(&TodoPlugin::readCurrentProject, this); 

As it turned out, this beloved gray-green progress was specially tailored to work with a separate stream.

In order to work with it, you need to add the following headings:
 #include <coreplugin/progressmanager/progressmanager.h> #include <qtconcurrent/runextensions.h> 

Adding a new progress bar happens like this:
  Core::ICore::instance()->progressManager()->addTask(result, tr("Todoscan"), "Todo.Plugin.Scanning"); 

Work with it is done from the scan stream, this method:
 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); //    } // SKIPPED } 

What is the magic you ask? Notice, the function header and its call, two parameters are declared in the header, and only the second is passed in the call, the first is omitted. The first parameter is inserted there with the code from the second required header (qtconcurrent / runextensions.h). That's all the magic.


That's all for now, you can still download the plugin from here , distributed under the BSD license - experiment with the health. I will add that, under Windows it was not tested, due to the lack of on-line, I will be grateful for testing and bug reports.

Source: https://habr.com/ru/post/105085/

All Articles