QT CREATOR plug-in development: adding new navigator

The navigator is located on the left side of Qt Creator. Here we can view projects, files, bookmarks, and more. The side bar is a component in the navigator. Please note that in the screenshot below, the red box is the navigator, and the red short line marks the drop-down box for selecting the navigator. In addition, Qt Creator can divide the navigator into several parts, as shown in the figure, there is also an “Open File” panel under “Project”:

Qt Creator Navigator

In this section we will learn how to create a new navigator in Qt Creator.

Core::INavigationWidgetFactory

One of the core objects exposed by Qt Creator is Core::INavigationWidgetFactory. We can find its definition in plugins/corelib/inavigationwidgetfactory.h:

#ifndef INAVIGATIONWIDGET_H
#define INAVIGATIONWIDGET_H

#include <coreplugin/core_global.h>
#include <QtCore/QObject>
#include <QtCore/QList>

QT_BEGIN_NAMESPACE
class QToolButton;
class QKeySequence;
class QWidget;
QT_END_NAMESPACE

namespace Core {

struct NavigationView
{
    QWidget *widget;
    QList dockToolBarWidgets;
};

class CORE_EXPORT INavigationWidgetFactory : public QObject
{
    Q_OBJECT
public:
    INavigationWidgetFactory();
    virtual ~INavigationWidgetFactory();

    virtual QString displayName() const = 0;
    virtual int priority() const = 0;
    virtual QString id() const = 0;
    virtual QKeySequence activationSequence() const;
    virtual NavigationView createWidget() = 0;
    virtual void saveSettings(int position, QWidget *widget);
    virtual void restoreSettings(int position, QWidget *widget);
};

} // namespace Core

#endif // INAVIGATIONWIDGET_H

Plug-ins that need to provide a navigator must implement this interface. In addition to this, the plug-in must also expose the class that implements the interface (we have explored this issue in detail in a previous article.)

Prepare Side Bar component

In order to implement the navigator, first, we need to create a component for the navigator display. Now we plan to implement a navigation panel for FTP access. Therefore, we need to have an interface like this:

Qt Creator FTP SideBar UI

We use Qt Designer to design the interface, and the running effect is as follows:

FTP Explorer

The user enters the FTP address in the text input box and clicks the “Go” button. The FTP directory contents will be displayed in the QTreeView below. We’ll call this component FtpExplorerSideBar:

FTP Explorer Get

Note that when we open a node, the corresponding “Fetching” will appear, indicating that it is being obtained.

Implement FtpExplorerSideBar

FtpExplorerSideBar.h is declared as follows:

#ifndef FTPEXPLORERSIDEBAR_H
#define FTPEXPLORERSIDEBAR_H

#include <QWidget>

struct FtpExplorerSideBarData;

class QUrl;

namespace Ui {
    class FtpExplorerSideBar;
}

class FtpExplorerSideBar : public QWidget
{
    Q_OBJECT

public:
    explicit FtpExplorerSideBar(QWidget *parent = 0);
    ~FtpExplorerSideBar();

    void setUrl(const QUrl & url);
    QUrl url() const;

private slots:
    void on_goButton_clicked();

private:
    FtpExplorerSideBarData* d;
};

#endif // FTPEXPLORERSIDEBAR_H

Benefits of this article,You can receive Qt development learning materials package and technical videos for free, including (C++ language basics, introduction to Qt programming, QT signals and slots mechanism, QT interface development -Image drawing, QT network, QT database programming, QT project practice, QT embedded development, Quick module, etc.) ↓↓↓↓↓↓See below↓↓Click at the bottom of the articleto receive the fee↓↓

In the FtpExplorerSideBar.cpp file, the first is the definition of FtpExplorerSideBarData:

struct FtpExplorerSideBarData
{
    FtpDirModel* model;
    Ui::FtpExplorerSideBar ui;
};

Initialize the UI in the constructor, and then associate the view with the model:

FtpExplorerSideBar::FtpExplorerSideBar(QWidget *parent):
    QWidget(parent)
{
    d = new FtpExplorerSideBarData;
    d->ui.setupUi(this);
    d->model = new FtpDirModel(this);
    d->ui.ftpView->setModel(d->model);
}

Delete the d pointer in the destructor:

FtpExplorerSideBar::~FtpExplorerSideBar()
{
    delete d;
}

URL getters and setters set URL information:

void FtpExplorerSideBar::setUrl(const QUrl & url)
{
    d->model->setUrl(url);
}

QUrl FtpExplorerSideBar::url() const
{
    return d->model->url();
}

After clicking the “Go” button, the on_goButton_clicked() function is automatically called (this is an implicit signal-slot connection):

void FtpExplorerSideBar::on_goButton_clicked()
{
    QUrl url(d->ui.ftpPathEdit->text());
    d->model->setUrl(url);
}

Now, our FtpExplorerSideBar has been written.

Note that we created the FtpDirModel class as the model for QTreeView. This class implements the connection between the component and FTP and is one of the core classes, but its writing has far exceeded the purpose of writing this article. The complete code of FtpExplorerSideBar has been placed in the attachment at the end of the article. If there is anything you don’t understand or need to explain FtpDirModel, please leave a message later.

Implement INavigationWidgetFactory

Now, we start to implement the INavigationWidgetFactory interface. This class is declared as follows:

#ifndef FTPVIEWNAVIGATION_H
#define FTPVIEWNAVIGATION_H

#include <coreplugin/inavigationwidgetfactory.h>

class FtpViewNavigationWidgetFactory
      : public Core::INavigationWidgetFactory
{
public:
    FtpViewNavigationWidgetFactory() { }
    ~FtpViewNavigationWidgetFactory() { }
    Core::NavigationView createWidget();
    QString displayName() const;
    int priority() const;
    QString id() const;
};

#endif // FTPVIEWNAVIGATION_H

Note that in the previous section, we gave the declaration of Core::INavigationWidgetFactory. Core::INavigationWidgetFactory has four pure virtual functions, which we must implement in order:

The createWidget() function is used to return the Side Bar component, as we said in the previous section:

Core::NavigationView FtpViewNavigationWidgetFactory::createWidget()
{
    Core::NavigationView view;
    view.widget = new FtpExplorerSideBar;
    return view;
}

The displayName() function returns the name of the side bar. This name will be displayed in the Navigator drop-down box:

QString FtpViewNavigationWidgetFactory::displayName() const
{
    return "Ftp View";
}

priority() and id() are used to return component priority and ID. Here we only give a default implementation:

int FtpViewNavigationWidgetFactory::priority() const
{
    return 0;
}

QString FtpViewNavigationWidgetFactory::id() const
{
    return "Ftp View";
}

Implement plug-in

We have implemented many plug-ins before. We are also familiar with the plug-in model. Therefore, here we only give the implementation of the initialize() function in the plug-in class:

bool FtpViewNavigationPlugin::initialize(const QStringList & amp; args, QString *errMsg)
{
    Q_UNUSED(args);
    Q_UNUSED(errMsg);

    addAutoReleasedObject(new FtpViewNavigationWidgetFactory);

    return true;
}

Note that in the initialize() function, we create an instance of the INavigationWidgetFactory implementation and then add it to the object pool. Once an object is added to the object pool, ExtensionSystem::PluginManager emits the objectAdded() signal; this signal is listened by the Qt Creator core. Once the core gets this signal, it adds it to the navigator panel using the implementation of the INavigationWidgetFactory interface we provided.

Finally, let’s test our plugin:

Qt Creator FTP View Navigation

Note that we have now embedded the previously independent FtpExplorerSideBar into the navigator.

Saving and restoring sidebar state

Return to the INavigationWidgetFactory code we gave in the previous section. We find two of these functions:

virtual void saveSettings(int position, QWidget *widget);
virtual void restoreSettings(int position, QWidget *widget);
  • The saveSettings() function is used to save component settings. The second parameter is the pointer to the component. The saving location is returned by Core::ICore::settings();
  • The restoreSettings() function is used to restore component settings.

Next, we add this functionality to FtpViewNavigationWidgetFactory:

void FtpViewNavigationWidgetFactory::saveSettings(int position, QWidget *widget)
{
    FtpExplorerSideBar* ftpExp = qobject_cast(widget);
    if(!ftpExp)
        return;
    QSettings *settings = Core::ICore::instance()->settings();
    settings->setValue("FtpView.URL", ftpExp->url().toString());
}

void FtpViewNavigationWidgetFactory::restoreSettings(int position, QWidget *widget)
{
    FtpExplorerSideBar* ftpExp = qobject_cast(widget);
    if(!ftpExp)
        return;
    QSettings *settings = Core::ICore::instance()->settings();
    QString urlStr = settings->value("FtpView.URL").toString();
    ftpExp->setUrl( QUrl(urlStr) );
}

By overriding these two functions, we save the FTP Path to settings, and the last entered value can be read when it is opened for the second time.

Benefits of this article,You can receive Qt development learning materials package and technical videos for free, including (C++ language basics, introduction to Qt programming, QT signals and slots mechanism, QT interface development -Image drawing, QT network, QT database programming, QT project practice, QT embedded development, Quick module, etc.) ↓↓↓↓↓↓See below↓↓Click at the bottom of the articleto receive the fee↓↓