Как итеративно qobject_cast элементы из QList - PullRequest
0 голосов
/ 15 апреля 2020

Я пробовал «плагин эха» из примеров qt, и я кое-что изменил, чтобы попробовать, и наткнулся на ошибку, которую не могу исправить. Вот исходный класс Echo Window

#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;

};

, который я изменил, это линия, которую я выделил звездами. я изменил его в Qlist, как это

QList<EchoInterface *>echoInterfaces 

также изменил реализацию функции LoadPlugin () От этого: -

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;
}

На это: -

    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;
}

и заранее спасибо

1 Ответ

0 голосов
/ 15 апреля 2020

Если мои предположения верны, вы хотите сохранить коллекцию интерфейсов, и ваш вопрос о том, как правильно ее прочитать. Я понимаю, что предположение

является матерью всех ошибок

:) Но давайте не будем заострять внимание на причине этого и просто предположим (снова), что EchoInterface является базовым классом для множества доступных интерфейсов.

Что не так в вашем коде:

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;
}

Изменения, которые вы ищете:

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();
}

Если мои предположения были неверны, тогда нам определенно нужен более подробный вопрос.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...