Get Image FileList from FTP server



  • Hi,
    I am trying to build a Menu for FTP FileList to my android and iOS mobile.
    I am using widgets code.
    Of course, somebody use QFtp, but I use QNetworkAccessManager .

    below code is to link my FileList.txt which contain all the file path:

    QNetworkAccessManager *manager= new QNetworkAccessManager(this);
    QUrl url("ftp://XXXXXXXXXX/OOOOOOO/FileList.txt");
    url.setUserName("QQ");
    url.setPassword("123");
    url.setPort(21);
    QNetworkRequest request(url);
    manager->get(request);
    connect(manager, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(replyFinished(QNetworkReply*)));
    

    Then, I build my file list after get the fillets.txt

    BindLV(){
    ........
    QStringList fileList=slFileName;
    for (int i=0; i<fileList.count(); i++)
    {
        item = new QStandardItem();
    
        QString tmpFilePaht=fileList[i];
        QStringList sltmpFileName(tmpFilePaht.split("/"));
        QIcon icon=GetListIcon(tmpFilePaht);
        item->setData(icon,ListviewDelegate::IconRole);
        item->setData(tmpFilePaht,ListviewDelegate::headerTextRole);
    }
    

    }

    below is my jpg icon in the cell:

    QIcon diaCloudFileList::GetListIcon(QString strFilePath){
    QIcon icon=QIcon(":/Icon/Resources/Icon/ZhsFile.png");
    QNetworkAccessManager *manager= new QNetworkAccessManager(this);
    
    QUrl url("ftp://sXXXXX/QQQQQQQQQQ"+strFilePath+".jpg");
    url.setUserName("AAAA");
    url.setPassword("123");
    url.setPort(21);
    QNetworkRequest request(url);
    
    manager->get(request);
    
    connect(manager, SIGNAL(finished(QNetworkReply*)),
          this, SLOT(replyIcon(QNetworkReply*)));//**I want to get my icon here and return this icon**
    return icon;
    }
    

    But it just slot the signal in the GetListIcon method.
    I want to get icon in the GetListIcon method and return this icon,
    then I can put this icon to my FileList...

    What should I do ?


  • Moderators

    @mkdh If you are receiving the data in replyIcon then you can just use QPixmap or QImage to construct the actual image from that data using loadFromData method.
    Something like:

    void MyClass::replyIcon(QNetworkReply* reply) {
           QByteArray data = reply->readAll();
           QPixmap pix;
           pix.loadFromData(data); //pix now contains the image
    }
    


  • @p3c0
    Thanks for your reply.
    But this is not the question I want to ask. ^____^
    my question is:
    I want to get icon in the GetListIcon method and return this icon,
    then I can put this icon to my FileList...

    When I trace the process in Qt, its process flow look like:
    --->start BindLV()
    --->i=0--->GetListIcon(tmpFilePaht)---->set signal,slot and trigger this event //yet finished
    --->i=1--->GetListIcon(tmpFilePaht)---->set signal,slot and trigger this event//yet finished
    --->i=2--->GetListIcon(tmpFilePaht)---->set signal,slot and trigger this event//yet finished
    ........
    --->end BindLV()
    --->replyIcon(QNetworkReply*) for i=2 // finished here
    --->replyIcon(QNetworkReply*) for i=0 // finished here
    --->replyIcon(QNetworkReply*) for i=1 // finished here
    ...

    Now, I find a solution,
    active slot replyFinished(QNetworkReply*) //get filelist
    --->setlsIcon()//get iconList //set signal and slot for each file and trigger those event.
    --->BindLV()
    when filelist.count()==iconList.count() in the slot replyIcon(QNetworkReply *reply)
    //I modify this method. I bind ListView with fileList and iconList.

    But I must waiting till all file has been download.......it is a long time.

    Dose any one has other ideas? or suggestion?


  • Moderators

    @mkdh Do you mean that you want to wait till the complete image is downloaded ? Since QNetworkAccessManager is asynchronous you will need to implement your own event loop and quit it when finished. For eg. in your function

    QIcon diaCloudFileList::GetListIcon(QString strFilePath){
       QNetworkAccessManager *manager= new QNetworkAccessManager(this);
       ...
       QNetworkRequest request(url);
       QNetworkReply *reply = manager->get(request);
       QEventLoop loop;
       connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
       loop.exec();
       //Then usual stuff
       QByteArray data = reply->readAll();
       QPixmap pix;
       pix.loadFromData(data);
       return QIcon(pix);
    }
    

    Did I get it right ?



  • @p3c0
    It is work. ^^!



  • @p3c0

    The total time for loading all those images would be need waste some waiting time.
    Is it possible to make my process more quickly? (multi thread or...)

    QIcon diaCloudFileList::GetListIcon(QString strFilePath){
       icon=QIcon(":/Icon/Resources/Icon/ZhsFile.png");
    
    QNetworkAccessManager *manager= new QNetworkAccessManager(this);
    QUrl url("ftp://xxx@xx.xx.xx.xx/xx"+strFilePath+".jpg");
    url.setUserName("xx");
    url.setPassword("xxx");
    url.setPort(21);
    QNetworkRequest request(url);
    QNetworkReply* reply=manager->get(request);
    QEventLoop eventloop;
    connect(reply,SIGNAL(finished()),&eventloop,SLOT(quit()));
    eventloop.exec();
    QByteArray data = reply->readAll();
    QPixmap pix;
    pix.loadFromData(data);
    icon=QIcon(pix);
    return icon;
    }


  • @p3c0
    PS:
    I find the method which I mention yesterday is more fast.


  • Moderators

    @mkdh Which method ?



  • @p3c0

    void diaCloudFileList::replyFinished(QNetworkReply *reply){
        QByteArray bytes=reply->readAll();
        QString str="";
        for(int i=0;i<bytes.size();i++){
            str+=bytes.at(i);
        }
        //show each line
        QStringList input_rows(str.split(QRegExp("\n|\r\n|\r")));
        slFileName=input_rows;
        reply->close();
        BindLV_Asynchronous();
        reply->close();
        setlsIcon();
    }
    void diaCloudFileList::BindLV_Asynchronous(){
        init_styleditemdelegate_cell *listdelegate;
        model = new QStandardItemModel(this);
        ui->lvwFile->setModel(model);
        listdelegate = new init_styleditemdelegate_cell();
        ui->lvwFile->setItemDelegate(listdelegate);
        QStandardItem *item ;//= new QStandardItem();
        QDir dir=QDir::rootPath();
        QString myPath;
    
        myPath=gData->strFileFolder;
        dir.cd(gData->strFileFolder);
        dir.setNameFilters(QStringList()<<"*.xxx");
    
        qDebug() << "Scanning: " << dir.path();
    
        QStringList fileList=slFileName;
        for (int i=0; i<fileList.count(); i++)
        {
            item = new QStandardItem();
    
            QString tmpFilePaht=fileList[i];
            QStringList sltmpFileName(tmpFilePaht.split("/"));
            //        ui->lblWaiting->setText(strWait+QString::number(i+1)+"/"+QString::number(this->slFileName.count()));//"Please wait.. Process Loading...""
    
            icon=QIcon(":/Icon/Resources/Icon/xxxFile.png");
            item->setData(icon,init_styleditemdelegate_cell::IconRole);
            item->setData(tmpFilePaht,init_styleditemdelegate_cell::headerTextRole);
            item->setData(sltmpFileName[sltmpFileName.count()-1]+".zhs",init_styleditemdelegate_cell::subHeaderTextrole);
            item->setEditable(false);
            model->appendRow(item);
        }
        //    if(model->rowCount()>0){
        //        ui->lvwFile->setCurrentIndex(model->indexFromItem(model->item(0,0)));
        //        connect(btnOK, SIGNAL(onClicked()), this, SLOT(on_btnOK_clicked()));
        //    }
        ShowIni();
        //    ui->lblWaiting->setVisible(false);
    }
    void diaCloudFileList::setlsIcon(){
        icon=QIcon(":/Icon/Resources/Icon/xxxFile.png");
        for (int i=0; i<slFileName.count(); i++)
        {
            QString tmpFilePaht=slFileName[i];
            QNetworkAccessManager *manager= new QNetworkAccessManager(this);
            QUrl url("ftp://xxxx@xx.xx.xx.xx/xx"+tmpFilePaht+".jpg");
            url.setUserName("xxx");
            url.setPassword("xxx");
            url.setPort(21);
            QNetworkRequest request(url);
    
            QNetworkReply* reply=manager->get(request);
            reply->setProperty("idx", i);
            connect(manager, SIGNAL(finished(QNetworkReply*)),
                    this, SLOT(replyIcon(QNetworkReply*)));
        }
    }
    
    void diaCloudFileList::replyIcon(QNetworkReply *reply){
        ui->lblWaiting->setText("replyIcon"+QString::number(this->lsIcon.count())+"/"+QString::number(this->slFileName.count()));//"Please wait.. Process Loading...""
    
        QByteArray bytes=reply->readAll();
        QImage image=QImage::fromData(bytes);
    
        QPixmap sidebar_project_icon_Pixmap = sidebar_project_icon_Pixmap.fromImage(image);
        icon = sidebar_project_icon_Pixmap;
        this->lsIcon.push_back(icon);
        int i = reply->property("idx").toInt();
        this->lsIdx.push_back(i);
        ui->lblWaiting->setText("Please wait.. Process Loading..."+QString::number(this->lsIcon.count())+"/"+QString::number(this->slFileName.count()));//"Please wait.. Process Loading...""
        QModelIndex index = ui->lvwFile->model()->index(i,0);
        ui->lvwFile->model()->setData(index,icon,init_styleditemdelegate_cell::IconRole);
        if(this->lsIcon.count()==this->slFileName.count()){
            ui->lblWaiting->setVisible(false);
            ui->lblWaiting->setText("Please wait.. Process Loading...");
            if(model->rowCount()>0){
                ui->lvwFile->setCurrentIndex(model->indexFromItem(model->item(0,0)));
                connect(btnOK, SIGNAL(onClicked()), this, SLOT(on_btnOK_clicked()));
            }
        }
        //    if(this->lsIcon.count()==this->slFileName.count()){
        //        QList<QIcon> tmpList=this->lsIcon;
        //        for(int k=0;k<this->lsIcon.count();k++){
        //            int curIdx=this->lsIdx[k];
        //            this->lsIcon[curIdx]=tmpList[k];
        //        }
        //        BindLV();
        //        ui->lblWaiting->setVisible(false);
        //        ui->lblWaiting->setText("Please wait.. Process Loading...");
        //    }
    }
    


  • @p3c0
    that is my code.
    Do you have any suggestion for my code to improve?


  • Moderators

    @mkdh It's good that you switched back to async way :)
    Hmm I find some places that can be improved:

    • In replyIcon you are converting data to QImage and again back to QPixmap. I see you have never used image in that function. It would be better to convert it directly to QPixmap.
    • In setlsIcon you have a for loop where you create those many QNetworkAccessManager objects but never delete it. That would cause a lots of memory leak. Sure you have passed this but those wont be deleted until parent gets deleted. Better to handle it in app's runtime. Same for init_styleditemdelegate_cell and others if any.
    • In replyFinished you are concatenating bytes to str and then again splitting it. Wont directly split be possible ?


  • @p3c0
    Thanks. ^_____^


  • Moderators

    @mkdh You're Welcome :) Also please surround your code with ``` (3 backticks) while posting it here. It looks more nicer. I have now added those in your previous post. Happy Coding ...



Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.