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. [SOLVED]Custom TreeView storing objects of different classes.

[SOLVED]Custom TreeView storing objects of different classes.

Scheduled Pinned Locked Moved General and Desktop
6 Posts 3 Posters 5.6k 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.
  • S Offline
    S Offline
    Sam
    wrote on last edited by
    #1

    Hello everyone ,
    I am new to Qt and i need some help regarding the implementation of a treeView with objects from different class.
    I have two classes named Employee and AccountDetails
    I am trying to store both the objects in a treview as QStandardItem and visually it should be represented with two different colors like:
    "CustomTreeView":http://imageshack.us/f/27/capturehze.png/

    While retriving the data from treeView i am filtering the information based on the child rows eg:
    @void MainWindow::on_treeView_clicked(const QModelIndex &index)
    {
    int indx =0;
    QStandardItem *item = model->itemFromIndex(index);
    if(item->hasChildren())
    return;

    QVariant variant = index.data(Qt::DisplayRole);
    
    if(index.row()==0)
    {
        Employee *empInfo = reinterpret_cast<Employee*>(variant.value<void*>());
        
        if(empInfo!=NULL)
        {   ui->txtId->setText(empInfo->getId());
            ui->txtFirstName->setText(empInfo->getFirstName());
            ui->txtLastName->setText(empInfo->getLastName());
            ui->txtCity->setText(empInfo->getCity());
        }
    
    }
    
    if(index.row()==1)
    {
        AccountDetails *accountInfo = reinterpret_cast<AccountDetails*>(variant.value<void*>());
      
        if(accountInfo!=NULL)
        {
            for(int i=0;i<bankList.size();++i)
            {
                if(accountInfo->getBankName()==bankList[i])
                {
                    indx = i;
                }
            }
            ui->cmbBank->setCurrentIndex(indx);
            ui->txtAccountNumber->setText(accountInfo->getAccountNumber());
            ui->txtBalance->setText(accountInfo->getBalance());
        }
    
    }
    

    }@

    Also i am using my own delegate subclassing from QStyledItemDelegate and in the paint method i am writing the following code to display the nodes in different colors :

    @void TreeViewDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
    {
    QStyledItemDelegate::paint(painter,option,index);

    QVariant variant = index.data(Qt::DisplayRole);
    Employee *empInfo = reinterpret_cast<Employee *>(variant.value<void*>());
    
    if(empInfo==NULL)
        return;
    
    if(index.row()==0)
    {
        painter->setPen(Qt::red);
        QString empDetails = QString("%1").arg(empInfo->getFirstName() + "-" + empInfo->getLastName() + "-" + empInfo->getCity());
        painter->drawText(option.rect,empDetails);
        return;
    }
    
    if(index.row()==1)
    {
        AccountDetails *accountInfo = reinterpret_cast<AccountDetails*>(variant.value<void*>());
        painter->setPen(Qt::green);
        QString accountDetails = QString("%1").arg(accountInfo->getBankName() + "-" + accountInfo->getAccountNumber() + "-" +accountInfo->getBalance());
        painter->drawText(option.rect,accountDetails);
    }
    

    }@

    Here the problem is that this approach is specific based in row number of the child items in the tree node.
    I need a solution where when i click on a node i should check whether selected item object is an instance of class Employee or AccountDetails.
    I tried the following code:
    @QObject object = dynamic_cast<QObject>variant.value<void*>();
    if(qobject_cast<Employee*>(object)!=NULL)
    {
    //do something

    }
    else if(qobject_cast<Employee*>(object)!=NULL)
    {
    //do something
    }
    @

    But it didn't work. Please help

    1 Reply Last reply
    0
    • N Offline
      N Offline
      Nosf
      wrote on last edited by
      #2

      If your Classes Employee & AccountDetails have been registered with qRegisterMetaType or Q_DECLARE_METATYPE

      You could just use (in your paint function)

      @
      if (index.data().canConvert<Employee*>())
      // QVariant is of type Employee*
      @

      You might possibly want to use "convert":http://qt-project.org/doc/qt-4.8/qvariant.html#convert as well to be sure your converting valid data

      1 Reply Last reply
      0
      • G Offline
        G Offline
        goetz
        wrote on last edited by
        #3

        Another solution could be to introduce a user type in the model and connect that with an enum describing the different types of nodes in your tree. For example like this:

        @
        enum NodeTypes { EmployeeNode, AccountDetailsNode };
        enum MyItemRoles { NodeTypeRole = UserRole + 1 };
        @

        then in the data() method of your model return one of the enum values for the NodeTypeRole. In the delegate query the type:

        @
        NodeTypes nodeType = static_cast<NodeTypes>(index.data(NodeTypeRole));

        if(nodeType == EmployeeNode) {
        // draw red
        Employee empInfo = reinterpret_cast<Employee >(variant.value<void>());
        } else if( nodeType == AccountDetailsNode) {
        // draw green
        AccountDetails accountInfo = reinterpret_cast<AccountDetails>(variant.value<void
        >());
        }
        @

        http://www.catb.org/~esr/faqs/smart-questions.html

        1 Reply Last reply
        0
        • S Offline
          S Offline
          Sam
          wrote on last edited by
          #4

          Nosf,
          I tried to register both classes with Q_DECLARE_METATYPE and qRegisterMetatype<Employee>("Employee");
          But while converting it with:

          @if(index.data().canConvert<Employee*>())@

          it always returns false, I also tried,

          @if(qVariantCanConvert<Employee>(variant)@

          this also returns false.

          Volker,
          I got the idea about what has to be implemented but the thing is that i am confused how to use the
          UserRole in my model. As of now I am using a QStandardItemModel. Also, i tried to subclass QStandardItemModel and override the data() function of MyModel.
          While storing the item i tried the following code:

          @QStandardItem itemEmployee = new QStandardItem();
          itemEmployee->setData(QVariant::fromValue<void
          >(m_Employee),EmployeeNode);
          itemId->appendRow(itemEmployee);

          QStandardItem *itemAccounts = new QStandardItem();
          itemAccounts->setData(QVariant::fromValue<void*>(m_Accounts),AccountDetailsNode);
          itemId->appendRow(itemAccounts);@
          

          I have searched for the same problem on net and got the same solution that are listed above but while implementing its not working.

          Please help.Thanks for your time :)

          1 Reply Last reply
          0
          • G Offline
            G Offline
            goetz
            wrote on last edited by
            #5

            You do not need to sublcass the standard item model. Just call data() and setData() with the UserRole. Everything else is handled by the model for you, i.e. it stores the value of the enum for you. You just need to call setData() with the UserRole at the time you populate the model.

            http://www.catb.org/~esr/faqs/smart-questions.html

            1 Reply Last reply
            0
            • S Offline
              S Offline
              Sam
              wrote on last edited by
              #6

              Volker,

              Thanks for you help and support, I tried with that approach but didnt get the result as when i cast the Qt::UserRole it returns 0. So i got other approach.
              I subclassed both classes Employee and AccountDetails from a Base class.

              Then I tried the following code and it works

              @QVariant variant = index.data(Qt::DisplayRole);
              Employee empInfo = dynamic_cast<Employee>((Base )variant.value<void>());
              AccountDetails accInfo = dynamic_cast<AccountDetails>((Base )variant.value<void>());

              if(empInfo!=NULL)
              {
              //paint red
              }
              if(accInfo!=NULL)
              {
              //paint green
              }
              @

              Thanks for your time :)

              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