15

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!

Azeem
  • 11,148
  • 4
  • 27
  • 40
Program-Me-Rev
  • 6,184
  • 18
  • 58
  • 142
  • Why is it so late? And, what do you mean by "it doesn't get caught"? – Azeem Jun 15 '17 at 10:36
  • I'm unable to iterate into the second directory. The `pluginsDir.cdUp();` works, and the directory changes, but no iteration happens into the second directory. It seems like `cdUp` happens after the iteration is over. – Program-Me-Rev Jun 15 '17 at 10:47
  • 1
    Here's the stripped down version of your code: http://ideone.com/H3qY81 and it works fine! You need to check `cd` for error handling. – Azeem Jun 15 '17 at 11:10

1 Answers1

25

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

Azeem
  • 11,148
  • 4
  • 27
  • 40
  • Hi @Azeem. I'm trying to `cdUp();` after the foreach ie: `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. – Program-Me-Rev Jun 15 '17 at 09:40
  • 1
    @Program-Me-Rev: Hello! Can you update your code please? BTW, you don't need that `else { continue; }` at the end of the nested loop. It's going to reiterate when the `if` condition is not true and I believe that your intention is also the same. – Azeem Jun 15 '17 at 09:54
  • 1
    @Program-Me-Rev: You can simply create the fully qualified path while `cd`ing like this: `pluginsDir.cd( "/" + dir.at(i) );` That'll do it. And, you won't need that `cdUp()` after the loop. :) – Azeem Jun 15 '17 at 10:13
  • 1
    Thank so much @Azeem. I couldn't have figured this without your help. I can't be thankful enough. – Program-Me-Rev Jun 15 '17 at 11:16