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
Forum Updated to NodeBB v4.3 + New Features

Thoughts on how to implement FtpFileSystemModel

Scheduled Pinned Locked Moved General and Desktop
8 Posts 2 Posters 2.1k Views 1 Watching
  • 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 15 May 2014, 10:44 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 15 May 2014, 16:58 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 16 May 2014, 09:50 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 16 May 2014, 16:58 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 23 Feb 2015, 13:01 last edited by
            #5

            Hello, OP.

            Did you finish this implementation?

            1 Reply Last reply
            0
            • D Offline
              D Offline
              danilomo
              wrote on 23 Feb 2015, 13:01 last edited by
              #6

              Hello, OP.

              Did you finish this implementation?

              1 Reply Last reply
              0
              • I Offline
                I Offline
                i92guboj
                wrote on 24 Feb 2015, 13:28 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 24 Feb 2015, 13:28 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