简体   繁体   中英

How to iteratively qobject_cast items from a QList

I was trying out the "echo plugin" from the qt examples and i changed somethings to try out and stumbled upon an error that i cant fix. here is the original Echo Window class

#include <QWidget>
#include "echointerface.h"
QT_BEGIN_NAMESPACE
class QString;
class QLineEdit;
class QLabel;
class QPushButton;
class QGridLayout;
QT_END_NAMESPACE

//! [0]
class EchoWindow : public QWidget
{
    Q_OBJECT

public:
    EchoWindow();

private slots:
    void sendEcho();

private:
    void createGUI();
    bool loadPlugin();

    EchoInterface *echoInterface;  ***********
    QLineEdit *lineEdit;
    QLabel *label;
    QPushButton *button;
    QGridLayout *layout;

};

what i changed is the the line i highlighted with the stars. i changed it into A Qlist like this

QList<EchoInterface *>echoInterfaces 

also changed the implementation of the function LoadPlugin() From this:-

bool EchoWindow::loadPlugin()
{
    QDir pluginsDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            echoInterface = qobject_cast<EchoInterface *>(plugin);
            if (echoInterface)
                return true;
        }
    }

    return false;
}

To this:-

    bool ModifyWindow::loadPlugin()
{
    QDir pluginsDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            foreach ( EchoInterface *a, echoInterfaces)
            {
               a = qobject_cast <EchoInterface *>(plugin);
            }
                if(!echoInterfaces.contains(NULL))
                    return true;
            }

        }
    return false;
}

and thanks in advance

If my guess is correct, you'd like to store a collection of interfaces and your question is about how to read it properly. I do understand that

assumption is the mother of all screw-ups

:) But let's not focus on the reason for doing this and just guess (again) that the EchoInterface is a base class for a variety of some available interfaces.

What's wrong in your code:

bool ModifyWindow::loadPlugin()
{
    QDir pluginsDir(qApp->applicationDirPath());
    pluginsDir.cd("plugins");
    foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        if (plugin) {
            foreach ( EchoInterface *a, echoInterfaces)
            {
               // this is pointless - only a tmp variable 'a' is modified for a while
               // just to be reset on the next iteration
               a = qobject_cast <EchoInterface *>(plugin);
            }
                if(!echoInterfaces.contains(NULL)) // use nullptr instead of NULL 
                    return true; // echoInterfaces is always empty, so it doesnt contain null
            }

        }
    return false;
}

The changes you're loking for:

bool EchoWindow::loadPlugin()
{
    QDir pluginsDir(QCoreApplication::applicationDirPath());
    pluginsDir.cd("plugins");
    const QStringList entries = pluginsDir.entryList(QDir::Files);
    for (const QString &fileName : entries) {
        QPluginLoader pluginLoader(pluginsDir.absoluteFilePath(fileName));
        QObject *plugin = pluginLoader.instance();
        // it's unnecessary to check if plugin == nullptr,
        // because in this case qobject_cast returns nullptr
        // and we go directly to pluginLoader.unload();
        if (EchoInterface * echoIface = qobject_cast<EchoInterface *>(plugin)) {
            echoInterfaces.append(echoIface); // populate the collection with a valid pointer
            continue; // to avoid the pluginLoader.unload() call which would destroy the echoIface
        }
        pluginLoader.unload();
    }

    // Since we ensured that the echoInterfaces can contain only valid pointers,
    // no additional checks are necessary — the fact that something is stored in the collection is enough
    return !echoInterfaces.isEmpty();

    // or
    // return echoInterfaces.size() > 0;
    // or even just
    // return echoInterfaces.size();
}

In case my assumptions were wrong, then we definitely need a more detailed question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM