Hi cataling
the problem of your code is that qt don't suport that you call gui operations from other thread that is not the qt main thread where Qt::eventLoop is runing,
the correct way to solve this proble is dispacth a custom event from the oder thread and intercept this even't in your widget class
to dispach a custom event yo main call static function QApplication::postEvent( QObject * receiver, QEvent * event ) Note: This function is thread-safe when Qt is built withthread support.
Example
Code:
// A custom event class
class ProgressEvent : public QCustomEvent
{
private:
int total;
int part;
public:
ProgressEvent(int total,int part);
int getTotal();
int getPart();
};
// A QObject class to install as eventFilter in widgets that's need intercept your customeEvent
//this EventFilter is instaled in a QWidget calling void installEventFilter ( const QObject * filterObj ) a passing this object as filterObject param
class ProgressEventFilter : public QObject
{
Q_OBJECT
public:
ProgressEventFilter(QObject* parent=0,const char* name=0);
protected:
bool eventFilter(QObject *o,QEvent *e);
};
// A Qthread class to invoque Ice methods from a diferent thread
class FileLoader : public QThread
{
private:
FilePrx target;
string path;
string action;
QObject* listener;
public:
FileLoader();
FileLoader(const FilePrx& target,const string& path,const string& action,QObject* listener=0);
bool Upload(const string& source);
bool Download(const string& target);
bool toString();
//QTrhead virtuals abstract
virtual void run();
};
FileLoader implementation
Code:
FileLoader::FileLoader()
{
}
FileLoader::FileLoader(const FilePrx& target,const string& path,const string& action,QObject* listener)
{
this->target=target;
this->path=path;
this->action=action;
this->listener=listener;
}
bool FileLoader::Upload(const string& filePath)
{
bool retval=false;
if(QFile::exists(filePath))
{
ifstream source(filePath.c_str(),ios::binary);
if(source)
{
/*Calculate the file size*/
long fileSize;
source.seekg(0,ios::end);
fileSize=source.tellg();
source.seekg(0,ios::beg);
cout <<"File size is: "<<fileSize<<endl;
int chunkSize=target->getChunkSize();
cout<<"chunkSize is: "<<chunkSize<<endl;
int totalChunks = fileSize/chunkSize;
cout<<"totalChunks: "<<totalChunks<<endl;
long chunk_pos=0;
while(!source.eof())
{
int currentProgress=source.tellg();
if(currentProgress!=-1)
{
//Creating Out custom Event
ProgressEvent* progress=new ProgressEvent(fileSize,currentProgress);
cout<<source.tellg()<<"/"<<fileSize<<endl;
//Thispathc the event to QApplication
QApplication::postEvent(listener,progress);
}
/*Creating a new chunk for add in to the file*/
ChunkPtr chunk=new ChunkI();
chunk->pos=chunk_pos;
chunk_pos++;
chunk->content.resize(chunkSize);
source.read(reinterpret_cast<char*>(&chunk->content[0]),chunk->content.size());
if((source.eof())&&(source.gcount()<chunkSize))
chunk->content.resize(source.gcount());
/*
upload the new chunk to target File
*/
target->addChunk(chunk);
msleep(20);
//emit progress(source.tellg(),fileSize);
}
ProgressEvent* progress=new ProgressEvent(fileSize,fileSize);
QApplication::postEvent(listener,progress);
cout<<"source file upload ok"<<endl;
}
source.close();
retval=true;
}
else
cout<<"File: "<<filePath<<" no Exist"<<endl;
return retval;
}
bool FileLoader::Download(const string& filePath)
{
cout<<"go to download file to target : "<< filePath<<endl;
bool retval=false;
QFile targetFile(filePath);
if(targetFile.open(IO_WriteOnly))
{
long chunks=target->countChunks();
long chunkSize=target->getChunkSize()*sizeof(Ice::Byte);
for(int cont=0;cont<chunks;cont++)
{
ChunkPrx chunk=target->readChunk(cont);
Bytes content=chunk->read();
targetFile.writeBlock(reinterpret_cast<char*>(&content[0]),content.size());
}
targetFile.close();
FileDownloaded* downloaded=new FileDownloaded(filePath);
QApplication::postEvent(listener,downloaded);
cout<<"File Downloaded OK"<<endl;
retval=true;
}
else
cout<<"error creating file: "<<filePath<<endl;
return retval;
}
bool FileLoader::toString()
{
QString str;
QTextStream ts( &str, IO_WriteOnly );
long chunks=target->countChunks();
for(int cont=0;cont<chunks;cont++)
{
ChunkPrx chunk=target->readChunk(cont);
Bytes content=chunk->read();
Bytes::const_iterator it_1;
for(it_1=content.begin();it_1!=content.end();it_1++)
{
char* slot=(char*)malloc(sizeof(Ice::Byte));
memcpy((void*)slot,(void*)(&(*it_1)),sizeof(Ice::Byte));
std::cout<<slot;
delete(slot);
}
std::cout<<endl;
}
return true;
}
void FileLoader::run()
{
if(target)
{
cout<<"FileLoader run action: "<<action<<" path: "<<path<<endl;
if(action=="download")
Download(path);
else if(action=="upload")
Upload(path);
else if(action=="toString")
toString();
}
}
A widget thas's install the customEventFilter
Code:
#include <FileUploaderView.h>
FileUploaderView::FileUploaderView(QWidget* parent,const char* name,string fileName)
:QWidget(parent,name)
{
qDebug("FileUploaderView constructor");
lblFileName=new QLabel(this,"lblFileName");
QString lblText=QString("Uploading %1").arg(fileName.c_str());
lblFileName->setText(lblText);
//Creating a custom event filter
ProgressEventFilter* eventFilter=new ProgressEventFilter(this);
progressBar=new QProgressBar(this,"progressBar");
//Instaling the event filter
progressBar->installEventFilter(eventFilter);
QVBoxLayout* mainLayout=new QVBoxLayout(this,2,2,"mainLayout");
mainLayout->addWidget(lblFileName);
mainLayout->addWidget(progressBar);
qDebug("FileUploaderView constructor");
}
QProgressBar* FileUploaderView::getProgressBar()
{
return progressBar;
}
the event and event filter implementation
Code:
#include <ProgressEvent.h>
ProgressEventFilter::ProgressEventFilter(QObject* parent,const char* name)
:QObject(parent,name)
{
}
bool ProgressEventFilter::eventFilter(QObject *o,QEvent *e )
{
if ( e->type() == 10001 )
{
// special processing for progress event
ProgressEvent* p =(ProgressEvent*)e;
qDebug( "Porgress %d of %d", p->getTotal(),p->getPart());
QProgressBar* bar=(QProgressBar*)o;
bar-> setProgress (p->getPart(),p->getTotal());
return TRUE; // eat event
}
else
{
// standard event processing
return FALSE;
}
}
ProgressEvent::ProgressEvent(int total,int part)
:QCustomEvent(10001)
{
this->total=total;
this->part=part;
}
int ProgressEvent::getTotal()
{
return total;
}
int ProgressEvent::getPart()
{
return part;
}
I hope this code help you