QComboBox: элемент не отображается в поле LineEdit при выборе - PullRequest
0 голосов
/ 30 апреля 2019

У меня есть небольшая программа, я пытаюсь создать свое личное поле со списком, в котором есть несколько столбцов, например:

enter image description here

Ниже приведенконструктор моего поля со списком.

MyComboBox.h

#include <QComboBox>
#include <QTreeView>
#include "CompleterData.h"

class MyComboFor : public QComboBox
{      
public:
  MyComboBox( QWidget *p_parent = nullptr );
  CompleterData createTestData();

private:
  QTreeView *m_view = nullptr;
  CompleterSourceModel *m_sourceModel = nullptr;
};

MyComboBox.cpp

MyComboBox::MyComboBox( QWidget *p_parent ) : QComboBox( p_parent )
{
  setEditable( true );
  m_view = new QTreeView();
  m_sourceModel = new CompleterSourceModel( this );
  m_sourceModel->setCompleterData( createTestData() );      
  setModel( m_sourceModel );
  setCurrentText( "" );
  setView( m_view );
}

CompleterData MyComboBox::createTestData()
{
  CompleterData data;
  data.addData( CompleterDataRow( CompleterDataRow::Type::Header, { { "Last Used", {} } } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "PwC", {}}, {"Partner want Cash", {}} } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "CLASS", {}}, {"Come late and start sleeping", {}} } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::LastUsed, { { "DIET", {}}, {"Do I eat today?", {}} } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::SecondHeader, { { "Lorem Ipsum", {} } } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::Data, { { "FBI", {} }, { "Female Body Inspector", {} } } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::Data, { { "PIG", {} }, { "Pretty Insensitive Guy", {} } } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::Data, { { "SMILE", {} }, { "Showing Miracle In Little Effort", {} } } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::Data, { { "TEAM", {} }, { "Together Everyone Achieves More", {} } } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::Header, { { "Some Countries", {} } } ) );
  data.addData( CompleterDataRow( CompleterDataRow::Type::SecondHeader, { { "Some Cities", {} } } ) );
  data.setTitle( "Proposal List" );
  data.setHeaders( { "Abbreviation", "Meaning" } );
  return data;
}

Мои данныедля всплывающего окна имеет векторную структуру.В этом векторе каждый элемент представляет собой одну строку всплывающего окна.Каждый ряд состоит из его типа и текстов, которые будут показаны.Тексты обернуты в QPair (требование таково), а все пары обернуты в QList.

CompleterData.h

#include <QList>
#include <QPair>
#include <QVariant>
#include <QVector>

class CompleterDataRow
{
public:
  enum class Type
  {
     Header,
     SecondHeader,
     Data,
     LastUsed         
  };
  CompleterDataRow() = default;
  CompleterDataRow( const CompleterDataRow::Type p_rowType, const QList<QPair<QString, QVariant>> &p_rowData );
  void setType( const CompleterDataRow::Type p_type );
  CompleterDataRow::Type type() const;
  QList<QPair<QString, QVariant>> rowData() const;
  void setRowData( const QList<QPair<QString, QVariant>> &p_rowData );

private:
  QList<QPair<QString, QVariant>> m_rowData;
  Type m_type;
};

class CompleterData
{
public:
  CompleterData() = default;
  QVector<CompleterDataRow> data() const;
  void setData( const QVector<CompleterDataRow> &p_data );
  void addData( const CompleterDataRow &p_rowData );
  void removeData( int p_row );
  void setHeaders( const QStringList &p_headers );
  void setTitle( const QString &p_label );
  const QStringList &headers() const;
  const QString &title() const;

private:
  QVector<CompleterDataRow> m_completerData;
  QString m_title;
  QStringList m_headers;
};

CompleterData.cpp

#include "CompleterData.h"

CompleterDataRow::CompleterDataRow( const CompleterDataRow::Type p_rowType, const QList<QPair<QString, QVariant>> &p_rowData )
{
  m_type = p_rowType;
  m_rowData = p_rowData;
}

QList<QPair<QString, QVariant>> CompleterDataRow::rowData() const
{
  return m_rowData;
}

void CompleterDataRow::setRowData( const QList<QPair<QString, QVariant>> &p_rowData )
{
  m_rowData = p_rowData;
}

CompleterDataRow::Type CompleterDataRow::type() const
{
  return m_type;
}

void CompleterDataRow::setType( const Type p_type )
{
  m_type = p_type;
}

QVector<CompleterDataRow> CompleterData::data() const
{
  return m_completerData;
}

void CompleterData::addData( const CompleterDataRow &p_rowData )
{
  m_completerData.append( p_rowData );
}

void CompleterData::removeData( int p_row )
{
  m_completerData.remove( p_row );
}

void CompleterData::setData( const QVector<CompleterDataRow> &p_data )
{
  m_completerData = p_data;
}

void CompleterData::setTitle( const QString &p_title )
{
  m_title = p_title;
}

const QString &CompleterData::title() const
{
  return m_title;
}

void CompleterData::setHeaders( const QStringList &p_headers )
{
  m_headers = p_headers;
}

const QStringList &CompleterData::headers() const
{
  return m_headers;
}

И я использую QStandardItemModel в этом случае.Я переопределяю только некоторые функции QAbstractItemModel, как показано ниже.

CompleterSourceModel.h

#include <QStandardItemModel>
#include "CompleterData.h"

class CompleterSourceModel : public QStandardItemModel
{
public:
  CompleterSourceModel( QObject *p_parent = nullptr );
  CompleterSourceModel( const CompleterData &p_completerData, QObject *p_parent = nullptr );
  QVariant data( const QModelIndex &p_index, int p_role = Qt::DisplayRole ) const override;
  QVariant headerData( int p_section, Qt::Orientation p_orientation, int p_role = Qt::DisplayRole ) const override;
  Qt::ItemFlags flags( const QModelIndex &index ) const override;
  int rowCount( const QModelIndex &p_parent = QModelIndex() ) const override;
  int columnCount( const QModelIndex &p_parent = QModelIndex() ) const override;
  void setCompleterData( const CompleterData &p_completerData );

private:
  CompleterData m_completerData;
};

CompleterSourceModel.cpp

#include "CompleterSourceModel.h"

CompleterSourceModel::CompleterSourceModel( QObject *p_parent ) : QStandardItemModel( p_parent )
{
}

QVariant CompleterSourceModel::data( const QModelIndex &p_index, int p_role ) const
{
  if ( p_role == Qt::UserRole ) {
     if ( m_completerData.data().size() > p_index.row() ) {
        return QVariant( static_cast<int>( m_completerData.data().at( p_index.row() ).type() ) );
     }
  }
  else if ( p_role == Qt::DisplayRole ) {
     QList<QPair<QString, QVariant>> rowContent = m_completerData.data().at( p_index.row() ).rowData();
     CompleterDataRow::Type type = m_completerData.data().at( p_index.row() ).type();
     if ( type == CompleterDataRow::Type::Header || type == CompleterDataRow::Type::SecondHeader ) {
        if ( p_index.column() == 0 ) {
           return rowContent.first().first;
        }
     }
     else {
        if ( rowContent.size() > p_index.column() ) {
           return rowContent.at( p_index.column() ).first;
        }
     }
  }

  return {};
}

QVariant CompleterSourceModel::headerData( int p_section, Qt::Orientation p_orientation, int p_role ) const
{
  if ( p_role == Qt::DisplayRole && p_orientation == Qt::Horizontal ) {
     if ( m_completerData.headers().size() > p_section ) {
        return m_completerData.headers().at( p_section );
     }
  }

  return {};
}

Qt::ItemFlags CompleterSourceModel::flags( const QModelIndex &p_index ) const
{
  if ( !p_index.isValid() ) {
     return Qt::NoItemFlags;
  }

  CompleterDataRow::Type type = m_completerData.data().at( p_index.row() ).type();
  if ( type == CompleterDataRow::Type::Data || type == CompleterDataRow::Type::LastUsed ) {
     return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
  }
  return Qt::NoItemFlags;
}

int CompleterSourceModel::rowCount( const QModelIndex &p_parent ) const
{
  Q_UNUSED( p_parent );
  return m_completerData.data().size();
}

int CompleterSourceModel::columnCount( const QModelIndex &p_parent ) const
{
  Q_UNUSED( p_parent );
  return m_completerData.headers().size() + 1;
}

void CompleterSourceModel::setCompleterData( const CompleterData &p_completerData )
{
  m_completerData = p_completerData;
  setColumnCount( m_completerData.headers().size() + 1 );
  setRowCount( m_completerData.data().size() );
  for ( int row = 0; row < m_completerData.data().size(); row++ ) {
     if ( m_completerData.data().at( row ).type() == CompleterDataRow::Type::Header || m_completerData.data().at( row ).type() == CompleterDataRow::Type::SecondHeader ) {
        QString text = m_completerData.data().at( row ).rowData().at( 0 ).first;
        setData( index( row, 0 ), m_completerData.data().at( row ).rowData().at( 0 ).first );
     }
     else {
        for ( int col = 0; col < m_completerData.headers().size(); col++ ) {    
           QString text = m_completerData.data().at( row ).rowData().at( col ).first;
           setData( index( row, col ), m_completerData.data().at( row ).rowData().at( col ).first );
        }
     }
  }
}

При этой работе данные уже отображаются, как вы можете видеть выше.Но когда я нажимаю на 1 строку списка (отмеченная строка выше), слово «КОМАНДА» не записывается в поле LineEdit.Я не знаю, почему ???

Если я напишу в конструкторе моего поля со списком так:

QStandardItemModel *model = new QStandardItemModel( this );
model->setColumnCount( 1 );
model->setRowCount( 5 );
model->setData( model->index( 0, 0 ), "some data0" );
model->setData( model->index( 1, 0 ), "some data1" );
model->setData( model->index( 2, 0 ), "some data2" );
model->setData( model->index( 3, 0 ), "some data3" );
model->setData( model->index( 4, 0 ), "some data4" );
setModel( model );

, тогда все будет хорошо.Итак, я думаю, что у моей модели есть проблема, но я не знаю, где именно, потому что я не переопределяю все функции QAbstractItemModel?Пожалуйста, помогите мне!

...