Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Unsolved Using a custom model with QCompleter and QLineEdit

    General and Desktop
    2
    5
    1774
    Loading More Posts
    • 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.
    • T
      TheFlyingMooseMan last edited by

      Within my app I have been using a QSqlQueryModel. I want to replace this with my own model (inherited from QAbstractTableModel), as I want to add additional items to the model that drives QCompleter. I could do this in SQL, it'll be much slower. I also want to be able to remove/replace/add items to this model.
      I started with the following definition of my own model class. However, the completer does not show a dropdown box when text is entered in my QLineEdit:

      class SearchItemModel : public QAbstractTableModel
      {
          Q_OBJECT
      
      public:
          SearchItemModel();
      
          int rowCount(const QModelIndex &parent) const;
          Qt::ItemFlags flags(const QModelIndex &index) const { Q_UNUSED(index); return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemNeverHasChildren; }
          int columnCount(const QModelIndex &parent) const;
          QVariant data(const QModelIndex &index, int role) const;
      
      
      public slots:
          void populate();
      
      private:
          typedef struct Tuple
          {
              SBIDBase::sb_type itemType;
              int               songID;
              QString           songTitle;
              int 	          performerID;
              QString           performerName;
              int               albumID;
              QString           albumTitle;
              QString           display;
          } Tuple;
      
          QList<Tuple> _searchItems;
      
          void _init();
      };
      

      The completer is constructed as follows:

          QCompleter* c=new QCompleter();
          c->setModel(qtm);
          c->setCaseSensitivity(Qt::CaseInsensitive);
          c->setModelSorting(QCompleter::CaseSensitivelySortedModel);
          c->setFilterMode(Qt::MatchStartsWith);
          c->setCompletionMode(QCompleter::PopupCompletion);
          c->setCompletionColumn(0);
      

      This works perfectly with the QSqlQueryModel, but not as well with my own model class. Do I need any other method implemented in my model?

      Any hint or reply is greatly appreciated!

      Thanks,
      Roy

      raven-worx 1 Reply Last reply Reply Quote 0
      • raven-worx
        raven-worx Moderators @TheFlyingMooseMan last edited by

        @TheFlyingMooseMan
        you should rather show the implementation of your SearchItemModel class than the definition.

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply Reply Quote 1
        • T
          TheFlyingMooseMan last edited by

          Here it is:

          #include "SearchItemModel.h"
          
          #include "Context.h"
          #include "DataAccessLayer.h"
          
          SearchItemModel::SearchItemModel()
          {
          }
          
          int
          SearchItemModel::rowCount(const QModelIndex &parent) const
          {
              Q_UNUSED(parent);
              return _searchItems.count();
          }
          
          int
          SearchItemModel::columnCount(const QModelIndex &parent) const
          {
              Q_UNUSED(parent);
              return 3;
          }
          
          QVariant
          SearchItemModel::data(const QModelIndex &index, int role) const
          {
              Q_UNUSED(role);
              if(_searchItems.count()==0 || !index.isValid())
              {
                  return QVariant();
              }
          
              if(index.row()<_searchItems.count())
              {
                  Tuple t=_searchItems.at(index.row());
                  switch(index.column())
                  {
                  case 0:
                      return t.display;
                      break;
          
                  case 1:		// 	itemid
                      int itemID;
                      switch(t.itemType)
                      {
                          case SBIDBase::sb_type_song:
                              itemID=t.songID;
                              break;
          
                          case SBIDBase::sb_type_performer:
                              itemID=t.performerID;
                              break;
          
                          case SBIDBase::sb_type_album:
                              itemID=t.albumID;
                              break;
          
                          default:
                              itemID=-1;
                      }
                      return itemID;
                      break;
          
                  case 2:		//	itemtype
                      return t.itemType;
                      break;
                  }
              }
              return QVariant();
          }
          
          
          ///	Slots
          void
          SearchItemModel::populate()
          {
              QString query=QString
              (
                  "SELECT  "
                      "t.type, "
                      "t.song_id, "
                      "t.title, "
                      "t.artist_id, "
                      "t.name, "
                      "t.record_id, "
                      "t.title "
                  "FROM "
                      "table t "
              )
                  .arg(SBIDBase::sb_type_song)
                  .arg(SBIDBase::sb_type_album)
                  .arg(SBIDBase::sb_type_performer)
              ;
          
              DataAccessLayer* dal=Context::instance()->getDataAccessLayer();
              QSqlDatabase db=QSqlDatabase::database(dal->getConnectionName());
              dal->customize(query);
          
              QSqlQuery queryList(query,db);
              while(queryList.next())
              {
                  QString key;
                  QSqlRecord r=queryList.record();
                  struct Tuple t;
                  int i=0;
                  t.itemType=(SBIDBase::sb_type)queryList.value(i++).toInt();
                  t.songID=Common::parseIntFieldDB(&r,queryList.value(i++).toInt());
                  t.songTitle=queryList.value(i++).toString();
                  t.performerID=Common::parseIntFieldDB(&r,queryList.value(i++).toInt());
                  t.performerName=queryList.value(i++).toString();
                  t.albumID=Common::parseIntFieldDB(&r,queryList.value(i++).toInt());
                  t.albumTitle=queryList.value(i++).toString();
          
                  switch(t.itemType)
                  {
                  case SBIDBase::sb_type_song:
                      t.display=QString("%1 - song by %2").arg(t.songTitle).arg(t.performerName);
                      key=SBIDSong::createKey(t.songID);
                      break;
          
                  case SBIDBase::sb_type_album:
                      t.display=QString("%1 - album by %2").arg(t.albumTitle).arg(t.performerName);
                      key=SBIDAlbum::createKey(t.albumID);
                      break;
          
                  case SBIDBase::sb_type_performer:
                      t.display=QString("%1 - performer").arg(t.performerName);
                      key=SBIDPerformer::createKey(t.performerID);
                      break;
          
                  default:
                      qDebug() << SB_DEBUG_ERROR << "Should not come here";
                  }
                  _searchItems.append(t);
              }
              QModelIndex s=this->index(0,0);
              QModelIndex e=this->index(3,_searchItems.count());
              emit dataChanged(s,e);
          }
          

          As soon as a database connection has been established, an emit populate is issued to retrieve and populate the data structure. Please let me know if anything else is needed.

          raven-worx 1 Reply Last reply Reply Quote 0
          • raven-worx
            raven-worx Moderators @TheFlyingMooseMan last edited by raven-worx

            @TheFlyingMooseMan
            you need to call beginResetModel() and endResetModel() at the beginning/end of your populate() method to inform the view about new data.

            --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
            If you have a question please use the forum so others can benefit from the solution in the future

            1 Reply Last reply Reply Quote 2
            • T
              TheFlyingMooseMan last edited by

              Thanks for replying!

              I added the beginResetModel() and endResetModel() -- no go.
              The dropdown box still does not appear -- what does appear is a white bar, probably a fourth the size of the lineEdit widget. If a press a couple of characters and then the cursor down/up keys, I see some choices. But no dropdown box.
              On top of that, quitting the app results in a crash.
              I appreciate any additional hints or replies!

              Thanks,
              Roy

              1 Reply Last reply Reply Quote 0
              • First post
                Last post