Search code examples
qtqt4qtreeview

Need example about nodes in QAbstractItemModel for QTreeView?


Problem: I'm looking example about creating model ( based on QAbstractItemModel ) to QTreeView, but can't find sane codes. Qt examples are based on QStandardModel, which is not very useful and complex, Internet examples are based on python?! codes... Other information can't gave me the right directions to go. So, here is what I have:

  • std::map

    typedef std::map< CompanyData, std::vector< ContractorData >, LessData< CompanyData > > Companies;

Here it's data example (CompanyName + ContractorsNames):

[Microsoft]*
   [Bill Gates]
   [Steve Balmer]
   [...]
[Apple]*
   [Steve Jobs - R.I.P.]
   [Wozniak]
[OtherStuff]*
...

where * means - expandable item (parent)

And all that I need it to create QTreeView with this data above!

Can any one help?

Many thanks!


Solution

  • So, as no posts was done here, I post here my own solution (also used text filtering):

    void ContractorsFilter::onCustomFilterChanged( const QString& text )
    {
         try
         {
              struct MatchFilter
              {
                   // data
                   QString        filter_;
                   Companies&     filtered_recipients_;
    
                   // methods
                   MatchFilter( const QString& _filter, Companies& _recipients )
                        : filter_( _filter )
                        , filtered_recipients_( _recipients )
                   {
                        filtered_recipients_.clear();
                   }
    
                   void operator()( const Companies::value_type& val ) const
                   {
                        bool isFound = false;
                        std::vector< ContractorData >::const_iterator con_i( val.second.begin() ), con_e( val.second.end() );
                        for( ; con_i != con_e; ++con_i )
                        {
                             const QString contractorName = (*con_i).name;
                             if( contractorName.contains( filter_, Qt::CaseInsensitive ) )
                             {
                                  filtered_recipients_[ val.first ].push_back( (*con_i) );
                                  isFound = true;
                             }
                        }
    
                        const QString companyName = val.first.name;
                        if( companyName.contains( filter_, Qt::CaseInsensitive ) )
                        {
                             filtered_recipients_[ val.first ].push_back( ContractorData() );
                        }
                   }
              };
    
              struct FillView
              {
                   // data
                   QFont     boldFont;
                   QBrush    whiteBrush;
    
                   QStandardItemModel* model_;
    
                   // methods
                   FillView( QStandardItemModel* model )
                        : model_( model )
                   {
                        model_->clear();
                   }
    
                   void operator ()( const Companies::value_type& val ) const
                   {
                        struct AppendContractors 
                        {
                             // data
                             QStandardItem* parent_;
    
                             // methods
                             AppendContractors( QStandardItem* _parent = 0 )
                                  : parent_( _parent )
                             {}
    
                             bool isEmpty( const ContractorData& contractor ) const
                             {
                                  return contractor.id.isEmpty();
                             }
    
                             void operator()( const std::vector< ContractorData >::value_type& contractor ) const
                             {
                                  if( !isEmpty( contractor ) )
                                  {
                                       QStandardItem *item = 0;
    
                                       QList< QStandardItem* > line;
                                       line << ( item = new QStandardItem( QIcon( ACCOUNT_ITEM_ICON ), contractor.name ) );
                                       item->setSizeHint( QSize( 0, 25 ) );
    
                                       parent_->appendRow( line );
                                  }
                             }
                        };
    
                        QStandardItem *parentItem = model_->invisibleRootItem();
    
                        // добавляем новую компанию + контрагента
                        QList< QStandardItem* > line;
                        line << ( parentItem = new QStandardItem( QIcon( COMPANY_ITEM_ICON ), val.first.name ) );
                        parentItem->setSizeHint( QSize( 0, 25 ) );
    
                        model_->appendRow( line );
    
                        std::for_each( val.second.begin(), val.second.end(), AppendContractors( parentItem ) );
                   }
              };
    
              // удаляем символ(ы), которые не фильтруются
              // формируется новая таблица, которая и будет использоваться моделью для отображения
              std::for_each( data_.begin(), data_.end(),
                   MatchFilter( text, filter_data_ ) );
    
              // вывод отфильтрованных контрагентов
              std::for_each( filter_data_.begin(), filter_data_.end(),
                   FillView( model_ ) );
    
              ui_.treeView->expandAll();
         }
         catch( const std::exception& e )
         {
              Core::errLog( "ContractorsFilter::onCustomFilterChanged", e.what() );
              throw;
         }
    }
    

    PS: type Companies is a

    typedef std::map< CompanyData, ContractorsData, LessData< CompanyData > > Companies;
    

    where CompanyData, ContractorsData are simple structures...

    Have a nice day!