How to use the threads to create the images thumbnail - c++

I'm use QTreeView to get the images path, then I'm use QListView to display the images that in specific path as thumbnail.
The problem in the period, create and display the thumbnail images.
The previous process, take a long time to done, depend on the number of images.
And for that reason I decided to use the threads, maybe helps to prevent the hung up which occur in application and increase the speed of create and display the thumbnail images.
void mainWidget::on_treeView_clicked(const QModelIndex &index){
filesModel->clear();
QFileSystemModel *sysModel = qobject_cast<QFileSystemModel*>(ui->treeView->model());
QDir dir(sysModel->filePath(ui->treeView->currentIndex()));
QFileInfoList filesList = dir.entryInfoList(QStringList() << "*.jpg" << "*.jpeg" << "*.tif" << "*.png" << "*.gif" << "*.bmp" ,QDir::Files);
int filesCount = filesList.size();
for(int i=0;i<filesCount;i++){
QPixmap originalImage(filesList[i].filePath());
if(!originalImage.isNull()){
QPixmap scaledImage = originalImage.scaled(150, 120);
filesModel->setItem(i, new QStandardItem(QIcon(scaledImage), filesList[i].baseName()));
}
}
}
How can I use threads with the previous code ?

I believe that a simple and correct approach is using QtConcurrent as the following:
Note: If you are using Qt 5 you will need to add QT += concurrent to the .pro file.
Header:
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
#include <QtConcurrent>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void UpdateItem(int, QImage);
private slots:
void on_treeView_clicked(const QModelIndex &);
void List(QFileInfoList filesList, QSize size);
void setThumbs(int index, QImage img);
private:
Ui::MainWindow *ui;
QFileSystemModel *model;
QStandardItemModel *filesmodel;
QFuture<void> thread;
bool running;
};
CPP file:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
QThreadPool::globalInstance()->setMaxThreadCount(1);
model = new QFileSystemModel(this);
model->setRootPath("\\");
filesmodel = new QStandardItemModel(this);
ui->treeView->setModel(model);
ui->listView->setModel(filesmodel);
connect(this, SIGNAL(UpdateItem(int,QImage)), SLOT(setThumbs(int,QImage)));
ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
running = false;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_treeView_clicked(const QModelIndex&)
{
filesmodel->clear();
running = false;
thread.waitForFinished();
QDir dir(model->filePath(ui->treeView->currentIndex()));
QFileInfoList filesList = dir.entryInfoList(QStringList() << "*.jpg" << "*.jpeg" << "*.tif" << "*.png" << "*.gif" << "*.bmp", QDir::Files);
int filesCount = filesList.size();
QPixmap placeholder = QPixmap(ui->listView->iconSize());
placeholder.fill(Qt::gray);
for (int i = 0; i < filesCount; i++)
filesmodel->setItem(i, new QStandardItem(QIcon(placeholder), filesList[i].baseName()));
running = true;
thread = QtConcurrent::run(this, &MainWindow::List, filesList, ui->listView->iconSize());
}
void MainWindow::List(QFileInfoList filesList, QSize size)
{
int filesCount = filesList.size();
for (int i = 0; running && i < filesCount; i++)
{
QImage originalImage(filesList[i].filePath());
if (!originalImage.isNull())
{
QImage scaledImage = originalImage.scaled(size);
if (!running) return;
emit UpdateItem(i, scaledImage);
}
}
}
void MainWindow::setThumbs(int index, QImage img)
{
QIcon icon = QIcon(QPixmap::fromImage(img));
QStandardItem *item = filesmodel->item(index);
filesmodel->setItem(index, new QStandardItem(icon, item->text()));
}

You don't have to use threads to keep your application responsive in this case. Use QCoreApplication::processEvents() in the loop to keep the application responsive. QCoreApplication::processEvents() will process all the events in the event queue of the thread which calls it.

This is an older thread, but still comes up in Google. Check out the answer to this related question. I found the use of QIdentityProxyModel to be a bit more elegant, as it allowed QFileSystemModel to be used as the list view's model.

Related

How to obtain the full path of a file (or multiple files) after drag/drop it from a folder to a QListWidget

I have a small problem: How do I obtain the full path of a file (or multiple files) after I drag/drop it on a QListWidget?
I prepared a small verifiable example where I implemented the drag and drop function. The ui is composed only by 1 QListWidget and a QTableView (not used yet).
Below the wrong result after I drag and drop 2 files from a /home folder
Below the desired result I am looking for after I drag and drop the files from a folder:
Yes, you already guessed it right. The reason is that I would want the user to be able to visualize all the time where those files came from after dragging/dropping from different folders.
Below the Minimal verifiable example. You can copy/past on your machine and it will work no problem:
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragLeaveEvent(QDragLeaveEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDragEnterEvent>
#include <QDragLeaveEvent>
#include <QDragMoveEvent>
#include <QDropEvent>
#include <QMimeData>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setAcceptDrops(true);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
event->accept();
}
void MainWindow::dragLeaveEvent(QDragLeaveEvent *event)
{
event->accept();
}
void MainWindow::dragMoveEvent(QDragMoveEvent *event)
{
event->accept();
}
void MainWindow::dropEvent(QDropEvent *event)
{
QString name;
QList<QUrl> urls;
QList<QUrl>::Iterator i;
urls = event->mimeData()->urls();
for(i = urls.begin(); i != urls.end(); ++i) {
name = i->fileName();
ui->listWidget->addItem(name);
}
}
Below is what I have done so far:
In an attempt to try to solve it by myself I consulted this source but it mainly describe how to promote the widget, which is not my case. Also I read this one which seems to be good but still does not work. Finally I studied this but is not exactly what I am looking for as it deals with QGraphicsView.
Finally I tried to implement the dropEvent(QDropEvent *event) a little bit differently as explained below, it is close but still does not work as I expect because the drop event will leave the files in the same row but this is wrong. Close, but wrong:
void MainWindow::dropEvent(QDropEvent *event)
{
const QMimeData *mimeData = event->mimeData();
QList<QUrl> urlList = mimeData->urls();
QString text;
for (int i = 0; i < urlList.size(); ++i)
text += urlList.at(i).path() + QLatin1Char('\n');
ui->listWidget->addItem(text);
}
As you can see this is also wrong because as soon as I drag/drop multiple files, they are seen as one single row in the QListWidget as highlighted in the row:
Thanks for any pointers to the solution.
As pointed out by #Fareanor, in order to get the path of a file (or multiple files) after dragging and dropping them into a QListWidget simply use QUrl::path() and you are good to go. Below the answer to the question:
void MainWindow::dropEvent(QDropEvent *event)
{
QString name;
QList<QUrl> urls;
QList<QUrl>::Iterator i;
urls = event->mimeData()->urls();
for(i = urls.begin(); i != urls.end(); ++i) {
name = i->path(); // <-- Correct way to get the full path
ui->listWidget->addItem(name);
}
}

How to drag the QLabel from one window to another in Qt?

I am learning Qt for fun. And I got a question:
How could I drag and drop the QLabel in Qt among two different windows?
Here is what I have so far:
As you can tell from the .gif(which does not want to become downloaded and visible here for some reasons, but if you click on the link to it, you can clearly see it) provided above right now there are two main problems:
I can not move the QLabel outside of the window (and hence am not able to register the drag and drop event).
The label is flashing for some reasons when I am moving it.
Here is the relevant part of the implementation from the .gif:
#ifndef DRAGGERP_H
#define DRAGGERP_H
#include <QLabel>
#include <QApplication>
#include <QMouseEvent>
#include <QPoint>
class DraggerP : public QLabel
{
QPoint offset;
QPoint startingPosition;
public:
DraggerP(QWidget* parent = nullptr) : QLabel(parent){ }
protected:
void enterEvent(QEvent* event) override
{
QApplication::setOverrideCursor(Qt::PointingHandCursor);
}
void leaveEvent(QEvent* event) override
{
QApplication::restoreOverrideCursor();
}
void mousePressEvent(QMouseEvent* event) override
{
startingPosition = pos();
offset = QPoint(
event->pos().x() - pos().x() + 0.5*width(),
event->pos().y() - pos().y() + 0.5*height()
);
}
void mouseMoveEvent(QMouseEvent* event) override
{
move(event->pos() + offset);
}
void mouseReleaseEvent(QMouseEvent* event) override
{
move(startingPosition);
}
};
#endif // DRAGGERP_H
This is the extension of the QLabel I am using to create the drag and drop effect.
I do not need the whole solution, at least an idea of how to accomplish this and what am I doing wrong here.
Here is a pretty good example and I used it as a starting point.
That strange movement that the QLabel suffers is because the position of the QLabel now depends on the layout, the job of the layout is to establish the position of the widgets depending on the policies you establish.
The solution is not to implement those actions in the QLabel but in the MainWindow as I show below:
#include <QApplication>
#include <QLabel>
#include <QMainWindow>
#include <QScrollArea>
#include <QVBoxLayout>
#include <QTime>
#include <QDrag>
#include <QMimeData>
#include <QMouseEvent>
class MainWindow: public QMainWindow {
QScrollArea scrollArea;
QWidget contentWidget;
QVBoxLayout lay;
public:
MainWindow(QWidget* parent=nullptr): QMainWindow(parent){
qsrand((uint) QTime::currentTime().msec());
setCentralWidget(&scrollArea);
scrollArea.setWidget(&contentWidget);
contentWidget.setLayout(&lay);
scrollArea.setWidgetResizable(true);
for(int i=0; i< 20; i++){
QLabel *label = new QLabel(QString("label %1").arg(i));
QPalette pal = label->palette();
pal.setColor(QPalette::Background, QColor(10 +qrand() % 240, 10 +qrand() % 240, 10 +qrand() % 240));
label->setAutoFillBackground(true);
label->setPalette(pal);
lay.addWidget(label);
}
setAcceptDrops(true);
}
protected:
void mousePressEvent(QMouseEvent *event){
QMainWindow::mousePressEvent(event);
QWidget *child = childAt(event->pos());
if(qobject_cast<QLabel *>(child))
createDrag(event->pos(), child);
}
void dropEvent(QDropEvent *event){
QByteArray byteArray = event->mimeData()->data("Label");
QWidget * widget = *reinterpret_cast<QWidget**>(byteArray.data());
QLabel * new_label = qobject_cast<QLabel *>(widget);
QWidget *current_children = childAt(event->pos());
QLabel * current_label = qobject_cast<QLabel*>(current_children);
int index = 0;
if(new_label){
if(current_label)
index = lay.indexOf(current_label);
else{
index = 0;
QLayoutItem *item = lay.itemAt(index);
while(item->widget()->pos().y() < event->pos().y() && item)
item = lay.itemAt(index++);
}
lay.insertWidget(index, new_label);
}
}
private:
void createDrag(const QPoint &pos, QWidget *widget){
if(widget == Q_NULLPTR)
return;
QByteArray byteArray(reinterpret_cast<char*>(&widget),sizeof(QWidget*));
QDrag *drag = new QDrag(this);
QMimeData * mimeData = new QMimeData;
mimeData->setData("Label",byteArray);
drag->setMimeData(mimeData);
QPoint globalPos = mapToGlobal(pos);
QPoint p = widget->mapFromGlobal(globalPos);
drag->setHotSpot(p);
drag->setPixmap(widget->grab());
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
protected:
void dragEnterEvent(QDragEnterEvent *event){
if(event->mimeData()->hasFormat("Label"))
event->acceptProposedAction();
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w1;
MainWindow w2;
w1.show();
w2.show();
return a.exec();
}

How to start and stop usb camera streaming using openCV by clicking a button and paint it into a custom widget on Qt?

I'm quite new on qt. I'm trying to create a tab on my ui that can give the option to count how many usb cameras are connected to computer and list then using OPENCV. After that, I want to select one of then and start streaming a video into a custom widget, using paintEvent. My main difficulties are: how to start and stop a streaming when a button is pressed. Below i'm posting my code.
mainwindow.h
//includes...
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void on_CheckCamerasButton_clicked();
void on_StartStreamingButton_clicked();
private:
Ui::MainWindow *ui;
cameraimage camera;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow(){
delete ui;
}
void MainWindow::on_StartStreamingButton_clicked(){
camera.startStreaming();
}
void MainWindow::on_CheckCamerasButton_clicked(){
camera.stopStreaming();
}
cameraimage.h
//includes...
class cameraimage : public QWidget
{
Q_OBJECT
public:
explicit cameraimage(QWidget *parent = nullptr);
private:
QPoint mPoint;
QTimer *timer;
cv::VideoCapture captureVideo;
public slots:
void paintEvent(QPaintEvent * event);
void startStreaming();
void stopStreaming();
};
#endif // CAMERAIMAGE_H
cameraimage.cpp
#include "cameraimage.h"
cameraimage::cameraimage(QWidget *parent) : QWidget(parent)
{
setMouseTracking(true);
}
void cameraimage::startStreaming(){
qDebug() << "Starting Streaming";
captureVideo.open(-1);
if (captureVideo.isOpened() == false){
qDebug() << "Camera can't open";
return;
}
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(1);
}
void cameraimage::stopStreaming(){
captureVideo.release();
timer->stop();
}
void cameraimage::paintEvent(QPaintEvent *){
cv::Mat tmpImage;
cv::Mat image;
captureVideo.read(tmpImage);
if (tmpImage.empty() == true){
qDebug() << "EMPTY!";
return;
}
cv::cvtColor(tmpImage, image, CV_BGR2RGB);
QImage img((const unsigned char*)(image.data), image.cols, image.rows, QImage::Format_RGB888);
QPixmap pixmap = QPixmap::fromImage(img);
QPainter painter(this);
float comprimento = 1.0*width()/pixmap.width();
float altura = 1.0*height()/pixmap.height();
float ratio = 0.;
if (comprimento<=altura)
ratio = comprimento;
else
ratio = altura;
QSize size = ratio*pixmap.size();
size.setHeight(size.height()-10);
QPoint p;
p.setX(0 + (width()-size.width())/2);
p.setY(5);
painter.drawPixmap(QRect(p, size), pixmap.scaled(size, Qt::KeepAspectRatio));
}
I've got the following output after clicked on StartStreamingButton on MainWindow:
Starting Streaming...
EMPTY!
EMPTY!
EMPTY!
...
Can someone help me please?
Best regards :D

QFileDialog that accepts a single file or a single directory

Is it possible to show a QFileDialog where the user can select a file or a directory, either one?
QFileDialog::getOpenFileName() accepts only files, while QFileDialog::getExistingDirectory() is directories-only, but I need to show a file dialog that can accept both a file or a directory (it makes sense for my program). QFileDialog::​Options didn't have anything promising.
QFileDialog currently does not support this. I think the main problem for you here is that the FileMode is not a Q_FLAGS and the values are not power of 2, either, and so, you cannot write this to solve this issue.
setFileMode(QFileDialog::Directory|QFileDialog::ExistingFiles)
To solve this, you would need quite a bit of fiddling, e.g.:
Override the open button click operation.
Get the "treeview" indices properly for both files and directories.
My attempt below demonstrates the former, but I did not really go as far as solving the second because that seems to involve some more fiddling with the selection model.
main.cpp
#include <QFileDialog>
#include <QApplication>
#include <QWidget>
#include <QTreeWidget>
#include <QPushButton>
#include <QStringList>
#include <QModelIndex>
#include <QDir>
#include <QDebug>
class FileDialog : public QFileDialog
{
Q_OBJECT
public:
explicit FileDialog(QWidget *parent = Q_NULLPTR)
: QFileDialog(parent)
{
setOption(QFileDialog::DontUseNativeDialog);
setFileMode(QFileDialog::Directory);
// setFileMode(QFileDialog::ExistingFiles);
for (auto *pushButton : findChildren<QPushButton*>()) {
qDebug() << pushButton->text();
if (pushButton->text() == "&Open" || pushButton->text() == "&Choose") {
openButton = pushButton;
break;
}
}
disconnect(openButton, SIGNAL(clicked(bool)));
connect(openButton, &QPushButton::clicked, this, &FileDialog::openClicked);
treeView = findChild<QTreeView*>();
}
QStringList selected() const
{
return selectedFilePaths;
}
public slots:
void openClicked()
{
selectedFilePaths.clear();
qDebug() << treeView->selectionModel()->selection();
for (const auto& modelIndex : treeView->selectionModel()->selectedIndexes()) {
qDebug() << modelIndex.column();
if (modelIndex.column() == 0)
selectedFilePaths.append(directory().absolutePath() + modelIndex.data().toString());
}
emit filesSelected(selectedFilePaths);
hide();
qDebug() << selectedFilePaths;
}
private:
QTreeView *treeView;
QPushButton *openButton;
QStringList selectedFilePaths;
};
#include "main.moc"
int main(int argc, char **argv)
{
QApplication application(argc, argv);
FileDialog fileDialog;
fileDialog.show();
return application.exec();
}
main.pro
TEMPLATE = app
TARGET = main
QT += widgets
CONFIG += c++11
SOURCES += main.cpp
Build and Run
qmake && make && ./main
Quite old question but I think I have a simpler solution than most for the lazy ones.
You can connect the signal currentChanged of QFileDialog with a function that dynamically changes the fileMode.
//header
class my_main_win:public QMainWindow
{
private:
QFileDialog file_dialog;
}
//constructor
my_main_win(QWidget * parent):QMainWindow(parent)
{
connect(&file_dialog,QFileDialog::currentChanged,this,[&](const QString & str)
{
QFileInfo info(str);
if(info.isFile())
file_dialog.setFileMode(QFileDialog::ExistingFile);
else if(info.isDir())
file_dialog.setFileMode(QFileDialog::Directory);
});
}
And then simply call file_dialog as you would.
if(file_dialog.exec()){
QStringList dir_names=file_dialog.selectedFiles():
}
What worked for me was to use:
file_dialog.setProxyModel(nullptr);
as suggested here, or
class FileFilterProxyModel : public QSortFilterProxyModel
{
protected:
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
{
QFileSystemModel* fileModel = qobject_cast<QFileSystemModel*>(sourceModel());
return (fileModel!=NULL && fileModel->isDir(sourceModel()->index(sourceRow, 0, sourceParent))) || QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
}
};
...
FileFilterProxyModel* proxyModel = new FileFilterProxyModel;
file_dialog.setProxyModel(proxyModel);
as suggested here, or
class FileDialog : public QFileDialog
{
Q_OBJECT
public:
explicit FileDialog(QWidget *parent = Q_NULLPTR)
: QFileDialog(parent)
{
m_btnOpen = NULL;
m_listView = NULL;
m_treeView = NULL;
m_selectedFiles.clear();
this->setOption(QFileDialog::DontUseNativeDialog, true);
this->setFileMode(QFileDialog::Directory);
QList<QPushButton*> btns = this->findChildren<QPushButton*>();
for (int i = 0; i < btns.size(); ++i) {
QString text = btns[i]->text();
if (text.toLower().contains("open") || text.toLower().contains("choose"))
{
m_btnOpen = btns[i];
break;
}
}
if (!m_btnOpen) return;
m_btnOpen->installEventFilter(this);
//connect(m_btnOpen, SIGNAL(changed()), this, SLOT(btnChanged()))
m_btnOpen->disconnect(SIGNAL(clicked()));
connect(m_btnOpen, SIGNAL(clicked()), this, SLOT(chooseClicked()));
m_listView = findChild<QListView*>("listView");
if (m_listView)
m_listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_treeView = findChild<QTreeView*>();
if (m_treeView)
m_treeView->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
QStringList selectedFiles()
{
return m_selectedFiles;
}
bool eventFilter( QObject* watched, QEvent* event )
{
QPushButton *btn = qobject_cast<QPushButton*>(watched);
if (btn)
{
if(event->type()==QEvent::EnabledChange) {
if (!btn->isEnabled())
btn->setEnabled(true);
}
}
return QWidget::eventFilter(watched, event);
}
public slots:
void chooseClicked()
{
QModelIndexList indexList = m_listView->selectionModel()->selectedIndexes();
foreach (QModelIndex index, indexList)
{
if (index.column()== 0)
m_selectedFiles.append(this->directory().absolutePath() + "/" + index.data().toString());
}
QDialog::accept();
}
private:
QListView *m_listView;
QTreeView *m_treeView;
QPushButton *m_btnOpen;
QStringList m_selectedFiles;
};
as suggested here. Credits for the original authors and me.
Connect to the currentChanged signal and then set the file mode to the currently selected item (directory or file). This is a Python3 implementation:
class GroupFileObjectDialog(QFileDialog):
def __init__(self, parent):
super().__init__(parent)
self.setOption(QFileDialog.DontUseNativeDialog)
self.setFileMode(QFileDialog.Directory)
self.currentChanged.connect(self._selected)
def _selected(self,name):
if os.path.isdir(name):
self.setFileMode(QFileDialog.Directory)
else:
self.setFileMode(QFileDialog.ExistingFile)
Tested on PyQt 5.14 running on linux / Ubuntu18.04.

Qt send data from form1 into form2 treeview component

I am pretty new to Qt, but I guess that I need to use signals and slots to send/receive data, at least in tutorials and other posts it's always like that.
This should be working:
Push Import button, select xls file -> right after we've selected it. We are running through the file and get the same sheet name and sheet table column headers for each sheet (then the user selects the column and all what that column contains; we are inserting into a database, etc)
I want to make a GUI application like this in my "excel-2-some-db" module:
I got two classes. First one - import_module:
import_module.h:
#ifndef IMPORTDB_MODULE_H
#define IMPORTDB_MODULE_H
#include <QtGui/QMainWindow>
#include <QAxObject>
#include <QAxWidget>
#include "ui_importdb_module.h"
#include "headers_selection.h"//select form
class importdb_module : public QMainWindow
{
Q_OBJECT
public:
importdb_module(QWidget *parent = 0, Qt::WFlags flags = 0);
~importdb_module();
//...
private:
Ui::importdb_moduleClass ui;
//...
headers_selection* select_form;
public slots:
void on_getExcelPath_clicked();
void on_pushButton1_clicked();
//signal we will send after read some sheets columns
signals:
void sendTreeViewData(QString &sheet_name, QStringList &sheet_headers);
};
#endif // IMPORTDB_MODULE_H
import_module.cpp
#include <QtGui>
#include <QApplication>
#include "importdb_module.h"
importdb_module::importdb_module(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
select_form = new headers_selection();
//to show form on click
connect(ui.pushButton1, SIGNAL(clicked()), select_form, SLOT(show()));
connect(this,
SIGNAL(sendTreeViewData(QString &sheet_name, QStringList &sheet_headers)),
select_form,
SLOT(recieveTreeViewData(QString &sheet_name, QStringList &sheet_headers)));
}
importdb_module::~importdb_module()
{
}
//....
//all file headers
void importdb_module::readSheetsHeaders(QAxObject* &_workbook, QAxObject* _worksheets, QAxObject* &_excel){
QAxObject* sheet_i;
int sheets_count = _worksheets->property("Count").toInt(); //get how much lists there, gonna choose one to import data
QString sheet_name;
QStringList sheet_headers;//sheet headers will store here
//sheets num starts from 1
for(int i=1; i<= sheets_count; i++){
sheet_i = _workbook->querySubObject("Worksheets(int)", i);//get teh list
sheet_name = sheet_i->property("Name").toString();//get teh name
//...
getTableHeaders(sheet_i, sheet_headers);
//says that we've send tree data into the form
emit sendTreeViewData(sheet_name, sheet_headers);
sheet_i->clear();
sheet_headers.clear();
}
delete sheet_i;
};
//...
headers_selection.h
#ifndef HEADERS_SELECTION_H
#define HEADERS_SELECTION_H
#include <QWidget>
#include "ui_headers_selection.h"
class headers_selection : public QWidget
{
Q_OBJECT
public:
headers_selection(QWidget *parent = 0);
~headers_selection();
private:
Ui::headers_selection ui;
public slots:
void recieveTreeViewData(QString &sheet_name, QStringList &sheet_headers);
};
#endif // HEADERS_SELECTION_H
headers_selection.cpp
#include "headers_selection.h"
headers_selection::headers_selection(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
QStandardItemModel *model = new QStandardItemModel;
}
headers_selection::~headers_selection()
{
}
void headers_selection::recieveTreeViewData(QString &sheet_name, QStringList &sheet_headers)
{
//just test
QStandardItemModel *model = new QStandardItemModel;
model->setColumnCount(1);
model->setRowCount(5);
model->setData(model->index(0, 0), "some data0");
model->setData(model->index(1, 0), "some data1");
model->setData(model->index(2, 0), "some data2");
model->setData(model->index(3, 0), "some data3");
model->setData(model->index(4, 0), "some data4");
ui.treeView->setModel(model);
}
And after I import .xls and opening treeview selection windows - it's empty!
So I got two possible problems here
maybe sendTreeViewData does not invoke recieveTreeViewData or maybe I do something wrong with tree view inside recieveTreeViewData method.
Could somebody help me to fix it, please?
UPDATE
Well, I made a little changes (thanks to thomas_b, his answer shown me the way) in code and now it works!
//impordb_module.h
signals:
void sendTreeViewData(QString &sheet_name, QStringList &sheet_headers);
//heaqders_selection.h
public slots:
void recieveTreeViewData(QString &sheet_name, QStringList &sheet_headers);
//heaqders_selection.cpp
void headers_selection::recieveTreeViewData(QString &sheet_name, QStringList &sheet_headers)
{
qDebug()<<sheet_name<<" gotcha! ";
}
//in impordb_module.cpp
importdb_module::importdb_module(QWidget *parent, Qt::WFlags flags): QMainWindow(parent, flags){
connect(this, SIGNAL(sendTreeViewData(QString &,QStringList &)), select_form, SLOT(recieveTreeViewData(QString &,QStringList &)));
}
//...
void importdb_module::readSheetsHeaders(QAxObject* &_workbook, QAxObject* _worksheets, QAxObject* &_excel){
//...
getTableHeaders(sheet_i, sheet_headers);
//says that we've send tree data into the form
emit sendTreeViewData(sheet_name, sheet_headers);
//...
};
Maybe your connection failed because of the parameter names in your connect statement. Try change it to:
connect(this, SIGNAL(sendTreeViewData(QString,QStringList)),
select_form, SLOT(recieveTreeViewData(QString,QStringList)));