mosg
mosg

Reputation: 12391

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:

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!

Upvotes: 0

Views: 1735

Answers (1)

mosg
mosg

Reputation: 12391

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!

Upvotes: 1

Related Questions