3

Well, hi all. I've got a question. I have a QTableWidget where I need put images from directory and retrieve name of image that was in selected cell. How can it automatically generate number of rows and columns depending of number of files in directory? I can add image to table by hand but it's not that i want to do. I suppose it's must be something with

QDir dir("images/");
QFileInfoList dirContent = dir.entryInfoList(QStringList()<< "*.png", QDir::Files | 
QDir::NoDotAndDotDot);

But still can't figure how can I do this.

Jablonski
  • 18,083
  • 2
  • 46
  • 47
Azraith Sherkhan
  • 131
  • 2
  • 11

2 Answers2

3

There are two approaches.

Non-recursive

main.cpp

#include <QDir>
#include <QFileInfo>
#include <QTableWidget>
#include <QPixmap>
#include <QApplication>

int main(int argc, char **argv)
{
    QApplication application(argc, argv);
    QTableWidget tableWidget(100, 5);
    QDir dir("images/");
    for (const auto& fileInfo : dir.entryInfoList(QStringList{"*.png"}, QDir::Files | QDir::NoDotAndDotDot))
    {
        static int row = 0, column = 0;
        QTableWidgetItem *newItem = new QTableWidgetItem(QObject::tr("%1").arg((row+1)*(column+1)));
        newItem->setData(Qt::DecorationRole, QPixmap(fileInfo.absoluteFilePath()));
        tableWidget.setItem(row, column, newItem);
        if (column == tableWidget.columnCount()) {
            column = 0;
            row++;
        }
    }
    tableWidget.show();
    return application.exec();
}

main.pro

TEMPLATE = app
TARGET = main
QT += widgets
CONFIG += c++11
SOURCES += main.cpp

Build and Run

qmake && make && ./main

Recursive

main.cpp

#include <QDir>
#include <QDirIterator>
#include <QFileInfo>
#include <QTableWidget>
#include <QPixmap>
#include <QApplication>

int main(int argc, char **argv)
{
    QApplication application(argc, argv);
    QTableWidget tableWidget(100, 5);
    QDir dir("images/");
    dir.setFilter(QDir::NoDotAndDotDot| QDir::Files);
    QDirIterator it(dir, QDirIterator::Subdirectories);
    while (it.hasNext()) {
        static int row = 0, column = 0;
        it.next();
        QFileInfo Info = it.fileInfo();
        QString path = Info.absolutePath();
        if(Info.isFile() && path.endsWith(".png")) {
            QTableWidgetItem *newItem = new QTableWidgetItem(QObject::tr("%1").arg((row+1)*(column+1)));
            newItem->setData(Qt::DecorationRole, QPixmap(path));
            tableWidget.setItem(row, column, newItem);
            if (column == tableWidget.columnCount()) {
                column = 0;
                row++;
            }
        }
    }
    tableWidget.show();
    return application.exec();
}

main.pro

TEMPLATE = app
TARGET = main
QT += widgets
CONFIG += c++11
SOURCES += main.cpp

Build and Run

qmake && make && ./main
László Papp
  • 51,870
  • 39
  • 111
  • 135
  • `int index = 0;` I told in my comment about that(additional variable), maybe I'm wrong but I just don't like it, so I chose for loop. – Jablonski Dec 16 '14 at 17:38
  • @lpapp, thank you for your answer. I've searched about enabling C++11 features in VS2010 (working there for some reasons) and google said that c++11 enabled by default but not fully supported. Is there another way to do it? – Azraith Sherkhan Dec 16 '14 at 19:01
  • @AzraithSherkhan: replace constexpr with const and `QStringList{"*.png"}` with your initial `QStringList()<< "*.png"`. But I would suggest to update your Visual Studio in the future as life is easier in general with C++11 or even C++14. – László Papp Dec 16 '14 at 19:03
  • Q_FOREACH is not a problem, although it is usually used in headers, not source. – László Papp Dec 16 '14 at 19:17
  • @AzraithSherkhan: do you have the "images" folder beside your executable file or somewhere else? If you wish I can write you a full program later demonstrating it, but I thought this could be enough. – László Papp Dec 16 '14 at 19:20
  • @lpapp: I've try to update IDE asap. Strange, it's show empty tableWidget. I've put breakpoints and after `foreach (QFileInfo fileInfo, dir.entryInfoList(QStringList() <<"*.png", QDir::Files | QDir::NoDotAndDotDot))` After some manipulations it does run but also it gives Unhanded Exception here ` ui.tableWidget->item(row++, column++)->setData(Qt::DecorationRole, QPixmap(fileInfo.absoluteFilePath()));` – Azraith Sherkhan Dec 16 '14 at 19:25
  • @AzraithSherkhan: `ui->tableWidget->item(row+, column++)` is a typo in my post, it should be row, not row+. – László Papp Dec 16 '14 at 19:27
  • 1
    @AzraithSherkhan Maybe your tableWidget just not ready for this? Did you set row and column count? (write `ui->tableWidget->setColumnCount(5);` `ui->tableWidget->setRowCount(dirContent.size());` form my answer)? If no, try to write it before `while()` or before `foreach` – Jablonski Dec 16 '14 at 19:33
  • I've changed it but it still give Unhanded Exception error to me. After modification in this way `QTableWidgetItem* img = new QTableWidgetItem; img->setData(Qt::DecorationRole, QPixmap(fileInfo.absoluteFilePath()).scaled(64,64));` it's run, but table is still clear. – Azraith Sherkhan Dec 16 '14 at 19:33
  • @Chernobyl: Yes, that was it! Thank you guys. I've combined both answers and it does work. Last question, does my item store filename? I mean when i chose cell in table widget can i get it directly from cell? – Azraith Sherkhan Dec 16 '14 at 19:47
  • @AzraithSherkhan No, it stores pixmap, if you want store filename, you can set it to Qt::UserRole+1 with setData method and get this info with data() method. It is solution from top of my head, I can't said that it is the best approach. – Jablonski Dec 16 '14 at 20:00
  • @AzraithSherkhan: I have just compilation tested my approaches and they do build with C++11. They may need fine-tuning for runtime, but the concept ought to work. – László Papp Dec 16 '14 at 20:21
2

QFileInfoList is just a QList<QFileInfo>, so you can easily get size of this list. Use something like this:

QDir dir("G:/2");
QFileInfoList dirContent = dir.entryInfoList(QStringList()<< "*.png", QDir::Files |
QDir::NoDotAndDotDot);

ui->tableWidget->setColumnCount(1);
ui->tableWidget->setRowCount(dirContent.size());

for(int i=0; i < dirContent.size(); i++)
{
    qDebug() << dirContent.at(i).absoluteFilePath();
    ui->tableWidget->item(i,0)->setData(Qt::DecorationRole, QPixmap(dirContent.at(i).absoluteFilePath()));
}

Also you can scale your image with scale() method and use:

ui->tableWidget->resizeRowsToContents();
Jablonski
  • 18,083
  • 2
  • 46
  • 47