How to iterate through a QStringList

Program-Me-Rev picture Program-Me-Rev · Jun 15, 2017 · Viewed 21.2k times · Source

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!

Answer

Azeem picture Azeem · Jun 15, 2017

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().

As you said that both these directories are in the same path i.e. root /. So, after the processing in the nested loop, you need to get back to the root path to access the other directory.

You can simply check the result of the cd function whether it was successful or not. It is a Boolean function. But, in your case, the error handling is missing. With the 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 );

Tip: You can also use QDirIterator for iterating a directory.


Below is a full working example.

I've followed this directory structure:

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

Code:

#include <QStringList>
#include <QDebug>
#include <QDir>
#include <cstdlib>

int main( void )
{
    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 EXIT_SUCCESS;
}

Output:

enter image description here