c++qtiterationqstringqlist

How to iterate through a QStringList


I'm trying to iterate through two different directories. The two directories are on the same root /.

void MainWindow::loadPlugins()
{
    pluginsDir = QDir(qApp -> applicationDirPath());

#if defined(Q_OS_WIN)
    if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
        pluginsDir.cdUp();
#elif defined(Q_OS_MAC)
    if (pluginsDir.dirName() == "MacOS") {
        pluginsDir.cdUp();
        pluginsDir.cdUp();
        pluginsDir.cdUp();
    }
#endif

    QStringList dirs;
    dirs << "plugins" << "core_plugs";

    QList<QObject *> loadedPlugs;

    for (int i = 0; i < dirs.size(); ++i)
    {
        cout << dirs.at(i).toLocal8Bit().constData() << endl;

        pluginsDir.cd(dirs.at(i).toLocal8Bit().constData());

        foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
            QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
            QObject *plugin = loader.instance();
            qDebug() << "NAME :: " << fileName;
            if (plugin && !(loadedPlugs . contains(plugin))) {
                loadedPlugs << plugin;
                dirs . removeAt(i);
            } else {
                continue;
            }
        }
    }
}

I'm only able to go into the first directory plugins in the list dirs << "plugins" << "core_plugs";. With a re-order dirs << "core_plugs" << "plugins";, the results are the same, and only the first directory, core_plugs is parsed.

Why am I getting this behavior, and how can I make it iterate through both directories.

UPDATE

void MainWindow::loadPlugins()
{
    pluginsDir = QDir(qApp -> applicationDirPath());

#if defined(Q_OS_WIN)
    if (pluginsDir.dirName().toLower() == "debug" || pluginsDir.dirName().toLower() == "release")
        pluginsDir.cdUp();
#elif defined(Q_OS_MAC)
    if (pluginsDir.dirName() == "MacOS") {
        pluginsDir.cdUp();
        pluginsDir.cdUp();
        pluginsDir.cdUp();
    }
#endif

    QStringList dirs;
    dirs << "plugins" << "core_plugs";

    QList<QObject *> loadedPlugs;

    for (int i = 0; i < dirs.size(); ++i)
    {
        pluginsDir.cd(dirs.at(i).toLocal8Bit().constData());

        foreach (QString fileName, pluginsDir.entryList(QDir::Files)) {
            QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
            QObject *plugin = loader.instance();
            if (plugin && !(loadedPlugs . contains(plugin))) {
                populateRevPlugins(plugin);
                loadedPlugs << plugin;
            }
        }
        qDebug() << pluginsDir . absolutePath();
        pluginsDir.cdUp();
        qDebug() << pluginsDir . absolutePath();
    }
}

Following Azeem's suggestion, I updated my attempt as shown above. I tried to cdUp(); after the foreach i.e:

foreach() {} pluginsDir.cdUp(); 

But, it doesn't get caught. It's too late there. Sooner than that and I get too few iterations. Could you please suggest how I can particularly go about it?

Thank you for the response!


Solution

  • Here is how you can iterate through a QStringList using C++11's range-based for loop:

    const QStringList list { "A", "B", "C" };
    
    for ( const auto& i : list )
    {
        qDebug() << i;
    }
    

    But, I believe that your problem is not the iteration. Your problem is that you are cding into a directory but not getting out of it i.e. cd("..") or cdUp().

    See QDir::cd() and QDir::cdUp() functions for more details.

    As you said that both these directories are in the same path, so after processing in the nested loop, you need to get back up to the root directory path to access the other directories at the same level.

    You can simply check the result of the QDir::cd() function whether it was successful or not. It is a Boolean function. But, in your case, the error handling is missing. With proper error handling, it should be like this:

    if ( dir.cd(path) )
    {
        // Do something here
    }
    

    You don't have to get the dirs.at(i).toLocal8Bit().constData() for the cd function. It takes a QString.

    Here is its signature:

    bool QDir::cd( const QString& dirName );
    

    You can also use QDirIterator for iterating a directory.


    Here is a complete working example.

    Directory structure:

    C:\Test
    -- A
    ---- a.txt
    -- B
    ---- b.txt
    

    Code:

    #include <QStringList>
    #include <QDebug>
    #include <QDir>
    
    int main()
    {
        const QString     root { "C:/Test" };
        const QStringList dirs { "A", "B" };
    
        QDir rootDir { root };
        qDebug() << "Root Path:" << rootDir.absolutePath();
        qDebug() << "Root List:" << rootDir.entryList( QDir::Dirs ) << '\n';
    
        for ( const auto& dir : dirs )
        {
            if ( rootDir.cd(dir) )
            {
                qDebug() << "Dir Path:" << rootDir.absolutePath();
                qDebug() << "Dir List:" << rootDir.entryList( QDir::Files ) << '\n';
            }
    
            rootDir.cdUp();
            qDebug() << "cding...";
            qDebug() << "Dir Path:" << rootDir.absolutePath() << '\n';
        }
    
        return 0;
    }
    

    Output:

    screenshot