Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Thoughts on how to implement FtpFileSystemModel

Thoughts on how to implement FtpFileSystemModel

Scheduled Pinned Locked Moved General and Desktop
8 Posts 2 Posters 2.1k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • I Offline
    I Offline
    i92guboj
    wrote on last edited by
    #1

    Hello.

    I've been a few days thinking about how to implement something like QFileSystemModel, but for Ftp.

    I have tried to hack something that inherits QFileSystem and has a private QFtp member, but I am getting nowhere (maybe I should just take some rest).

    I'd like to know some general hints on how an experienced Qt programmer would go about this. Do you think that a QFileSystemModel derivative can do this with a fair amount of work?

    Should I inherit QAbstractItemModel instead and implement my own from scratch? If so, I have a lot of learning to do before I can even think of that.

    My main concern now is that it's not too clear for me how QFileSystemModel populates whatever structure it uses internally. I have tried playing around with data() and setData(), using also a QSqlTableModel to store temporarily all the data from QFtp::list(). But I am getting nowhere. I also have reimplemented the setRootPath() method, but nothing seems to work.

    I have been looking around but haven't found anything about subclassing QFileSystemModel :(

    Thanks beforehand for any idea.

    PS: the ftp part works ok. I know how to handle that. But the data never reaches the model (let alone the view).

    1 Reply Last reply
    0
    • I Offline
      I Offline
      i92guboj
      wrote on last edited by
      #2

      After some more research, I think that migrating to QAbstractItemModel is a good idea. I am getting some results. Even if it doesn't work, at least, the model is correctly storing the values (or so it seems as per what qDebug() says.

      I am now using a QList<QTreeWidgetItem*>* as the storage engine. For no particular reason though.

      The FtpFileSystemModel class features a QFtp *ftp; member. It also has some member functions that are relevant:

      @ /* ftp member functions */

      int connectToHost(const QString& host, quint16 port = 21);
      int login(const QString& user = QString(), const QString& password = QString());
      QModelIndex setRootPath(const QString& newPath);@
      

      Those mimic the methods from QFtp with the same name. slot_command_finished(int,bool) monitors all the commands. Once a "cd" command finishes with success QFtp::list() is automatically started, which in turn activates a slot called slot_list_info(QUrlInfo), up to now, pretty much standard stuff.

      It's in slot_list_info() where all the magic should begin, I guess.

      Right now, I do this:

      @void FtpFileSystemModel::slot_list_info(QUrlInfo url_info)
      {

      QTreeWidgetItem *item = new QTreeWidgetItem;
      int row = remote_file_list->count();
      QModelIndex item_index = createIndex(row, 0);
      remote_file_list->append(item);
      
      QString file_name = url_info.name();
      QString file_size = QString::number(url_info.size());
      QString permissions = convert_perms_to_unix(url_info.permissions());
      QString file_type;
      QFileIconProvider icon_provider;
      if(url_info.isDir())
      {
          //item->setIcon(0, icon_provider.icon(QFileIconProvider::Folder));
          file_type = QString(tr("Folder"));
      }
      else if(url_info.isFile&#40;&#41;)
      {
          //item->setIcon(0, icon_provider.icon(QFileIconProvider::File));
          QString suffix = QFileInfo(url_info.name()).suffix();
          file_type = QString(tr("File"));
          if(!suffix.isEmpty())
          {
              file_type = suffix.append(" ").append(file_type);
          }
      }
      else if(url_info.isSymLink())
      {
          //item->setIcon(0, icon_provider.icon(QFileIconProvider::File));
          file_type = QString(tr("Symlink"));
      }
      
      setData(index(row, 0, QModelIndex()), file_name);
      setData(index(row, 1, QModelIndex()), file_size);
      setData(index(row, 2, QModelIndex()), file_type);
      setData(index(row, 3, QModelIndex()), permissions);
      

      }@

      And, setData() is:

      @bool FtpFileSystemModel::setData(const QModelIndex& index, const QVariant& value, int role)
      {
      Q_UNUSED(role);

      qDebug() << Q_FUNC_INFO << QString("inserting value '%1' into %2, %3")
                  .arg(value.toString()).arg(index.row()).arg(index.column());
      
      QTreeWidgetItem *item = remote_file_list->at(index.row());
      QString str = value.toString();
      
      item->setText(index.column(), str);
      emit dataChanged(index, index);
      
      return true;
      

      }@

      To be frank, I believe that the problem is in my understanding of the QModelIndex class. I had a hard time with that while learning the QtSql related classes.

      The output of that qDebug() clause in setData() seems to indicate that everything's fine.

      @void FtpFileSystemModel::slot_command_finished(int, bool) ".-4096-Folder-755"
      void FtpFileSystemModel::slot_command_finished(int, bool) "..-4096-Folder-555"
      void FtpFileSystemModel::slot_command_finished(int, bool) ".gitignore-174-gitignore File-755"
      void FtpFileSystemModel::slot_command_finished(int, bool) ".htaccess-5769-htaccess File-755"
      ........@
      but I have a similar one in data(), and that one seems not to agree...

      @QVariant FtpFileSystemModel::data(const QModelIndex& index, int role) const
      {
      qDebug() << Q_FUNC_INFO;
      // if(!index.isValid() || role != (Qt::DisplayRole|Qt::UserRole))
      // {
      // return QVariant();
      // }

      QTreeWidgetItem *item = remote_file_list->at(index.row());
      QString str = item->text(index.column());
      
      qDebug() << Q_FUNC_INFO << QString("reading value '%1' from %2, %3")
                  .arg(str).arg(index.row()).arg(index.column());
      
      return item->text(index.column());
      

      }@

      @virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const
      virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const "reading value '' from 0, 0"
      virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const
      virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const "reading value '' from 0, 1"
      virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const
      virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const "reading value '' from 0, 2"
      virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const
      virtual QVariant FtpFileSystemModel::data(const QModelIndex&, int) const "reading value '' from 0, 3" @

      The index() method is this, please, don't laugh at me :P

      @QModelIndex FtpFileSystemModel::index(const QString &path, int column) const
      {
      Q_UNUSED(column);

      for(int i = 0; i < remote_file_list->count(); i++)
      {
          int list_index = remote_file_list->indexOf(remote_file_list->at(i));
          QModelIndex index = createIndex(list_index, 0, list_index);
          if(index.data().toString() == path)
          {
              return createIndex(index.row(), index.column());
          }
      }
      return QModelIndex();
      

      }

      QModelIndex FtpFileSystemModel::index(int row, int column, const QModelIndex &parent) const
      {
      Q_UNUSED(parent);

      QModelIndex index = createIndex(row, column, row);
      return index;
      

      }@

      I really have no idea how a QAbstractItemModel tracks the indexes, where it stores them, nor even what kind of mysterious creatures they are. And, truly, I haven't the slightest clue what createIndex() is used for.

      The data is there, but for some reason, I can't get it back and it won't appear in my view.

      Thanks for reading.

      1 Reply Last reply
      0
      • I Offline
        I Offline
        i92guboj
        wrote on last edited by
        #3

        So, I have managed to get correct indexes to store the info using setData(). But for some reason, the indexes are incorrect when retrieving it using data().

        @QVariant FtpFileSystemModel::data(const QModelIndex& index, int role) const
        {
        if (!index.isValid() || role != (Qt::DisplayRole|Qt::UserRole))
        {
        return QVariant();
        }

        QTreeWidgetItem *item = remote_file_list->at(index.row());
        QString str = item->text(index.column());
        
        qDebug() << Q_FUNC_INFO << QString("reading value '%1' from %2, %3")
                    .arg(str).arg(index.row()).arg(index.column());
        
        return item->text(index.column());
        

        }

        bool FtpFileSystemModel::setData(const QModelIndex& index, const QVariant& value, int role)
        {
        Q_UNUSED(role);

        if(!index.isValid())
        {
            return false;
        }
        
        qDebug() << Q_FUNC_INFO << QString("inserting value '%1' into %2, %3")
                    .arg(value.toString()).arg(index.row()).arg(index.column());
        
        QTreeWidgetItem *item = remote_file_list->at(index.row());
        QString str = value.toString();
        
        item->setText(index.column(), str);
        emit dataChanged(index, index);
        
        return true;
        

        }

        QModelIndex FtpFileSystemModel::index(int row, int column, const QModelIndex &parent) const
        {
        if (!hasIndex(row, column, parent))
        {
        return QModelIndex();
        }

        QTreeWidgetItem *parent_item;
        
        if(!parent.isValid())
        {
            parent_item = root_item;
        }
        else
        {
            parent_item = static_cast<QTreeWidgetItem*>(parent.internalPointer());
        }
        
        //QTreeWidgetItem *child_item = parent_item->child(row);
        QTreeWidgetItem *child_item = remote_file_list->at(row);
        
        if(child_item)
        {
            return createIndex(row, column, child_item);
        }
        else
        {
            return QModelIndex();
        }
        

        }@

        The data() method always return an empty QVariant(). Hence, the view remains empty.

        I have debugged this step-by-step, and it seems that the data() method runs always after slot_list_info(). So, the data is already there. I have double checked it, by using a qDebug() in my slot_command_finished() and querying the model in a for loop. I can see that the data is there, and I am using the index to reach it.

        I have no idea, though, how QAbstractItemModel calls data() and how it uses index() to call it. So, I guess my problem is there. The index in data() is always invalid for some reason. I guess I might need to reimplement some other method, but for now I have no clue what.

        I'll post if I find anything. Thanks for reading :)

        1 Reply Last reply
        0
        • I Offline
          I Offline
          i92guboj
          wrote on last edited by
          #4

          Uggh!

          Shame on me. It turns out I had to emit a couple more signals at the right places.

          @ emit layoutAboutToBeChanged();
          remote_file_list->append(item);
          emit layoutChanged();@

          This is from slot_list_info(QUrlInfo), which is what takes the info from QFtp and puts it into the model structures.

          Finally, I can continue with this nonsense :lol:

          I will keep you informed.

          1 Reply Last reply
          0
          • D Offline
            D Offline
            danilomo
            wrote on last edited by
            #5

            Hello, OP.

            Did you finish this implementation?

            1 Reply Last reply
            0
            • D Offline
              D Offline
              danilomo
              wrote on last edited by
              #6

              Hello, OP.

              Did you finish this implementation?

              1 Reply Last reply
              0
              • I Offline
                I Offline
                i92guboj
                wrote on last edited by
                #7

                Sorry, but I had to put this one into pause for the time being. Real life distracted me with other issues and right now I have no time for development at all.

                1 Reply Last reply
                0
                • I Offline
                  I Offline
                  i92guboj
                  wrote on last edited by
                  #8

                  Sorry, but I had to put this one into pause for the time being. Real life distracted me with other issues and right now I have no time for development at all.

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved