InformationPositionSubTableView::InformationPositionSubTableView(QStringList& columnNameList,QList<PositionItem>& positionItemList,QWidget *parent) : m_ColumnNameList(columnNameList), m_PositionItemList(positionItemList),QTableView(parent)
{
    m_InformationPositionSubTableModel = new InformationPositionSubTableModel(columnNameList,positionItemList);
    this->setModel(m_InformationPositionSubTableModel);

    this->setMouseTracking(true);
    this->setFocusPolicy(Qt::NoFocus);
    this->setGridStyle(Qt::NoPen);
     this->setSelectionBehavior(QAbstractItemView::SelectItems);
    this->setSelectionMode(QAbstractItemView::SingleSelection);

    QHeaderView* headerView = new InformationPositionSubHeaderview(Qt::Horizontal,this);
    headerView->setSectionsClickable(true);
    this->setHorizontalHeader(headerView);
    this->horizontalHeader()->setStretchLastSection(true);
    this->verticalHeader()->setVisible(false);

    this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setContextMenuPolicy(Qt::CustomContextMenu);

    this->resizeColumnsToContents();
//    this->resizeRowsToContents();    //不能加上,否则做为QTreeWidget的子控件会多出一行的间隙;

    this->setFrameShape(QFrame::NoFrame);  //设置成无边框;

    this->horizontalHeader()->setStyleSheet("QHeaderView{background-color:gray;}");    //设置表头背景为灰色(这样也看起来扁平);
}

InformationPositionSubTableView::~InformationPositionSubTableView()
{

}

void InformationPositionSubTableView::mouseMoveEvent(QMouseEvent * event)
{
    QModelIndex index = indexAt(event->pos());
    if(index.isValid() && index.row()>=0)
    {
        this->setSelection(visualRect(index),QItemSelectionModel::SelectCurrent);
    }

}

========

InformationPositionSubTableModel::InformationPositionSubTableModel(QStringList& columnNameList,QList<PositionItem>& positionItemList,QObject *parent) : m_ColumnNameList(columnNameList),m_PositionItemList(positionItemList),QAbstractTableModel(parent)
{
    this->m_ColumnNameList = columnNameList;
}

InformationPositionSubTableModel::~InformationPositionSubTableModel()
{

}
QVariant InformationPositionSubTableModel::data(const QModelIndex & index, int role) const
{
    Q_UNUSED(index);
    if(!index.isValid())
        return QVariant();

    if(role==Qt::DisplayRole)
    {
        PositionItem item = m_PositionItemList[index.row()];
        int column = index.column();
        switch (column)
        {
        case 0:
            return item.GetAccountName();
        case 1:
            return item.GetBuyLot();
        case 2:
            return item.GetAvgBuyPrice();
        case 3:
            return item.GetSellLot();
        case 4:
            return item.GetAvgSellPrice();
        case 5:
            return item.GetNet();
        default:
            return item.GetFloatingMap()[headerData(column,Qt::Horizontal,Qt::DisplayRole).toString()];
        }
    }

    if(role==Qt::TextAlignmentRole)
    {
        return Qt::AlignCenter;
    }

    if(role==Qt::TextColorRole)
    {
        if(index.column()==3 || index.column()==5)
        {
            return QColor(Qt::red);
        }
        if(index.column()==1)
        {
            return QColor(Qt::green);
        }
    }

    return QVariant();
}
QVariant InformationPositionSubTableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role!=Qt::DisplayRole)
        return  QVariant();

    if(orientation == Qt::Horizontal)
    {
        return m_ColumnNameList[section];
    }

    return QVariant();
}
bool InformationPositionSubTableModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant & value, int role)
{
    if(role!=Qt::EditRole)
        return false;
    if(orientation == Qt::Horizontal && section >=7)
    {
        m_ColumnNameList.append(value.toString());
        emit headerDataChanged(orientation,section,section);
        return true;
    }
    return false;
}

int    InformationPositionSubTableModel::rowCount(const QModelIndex & parent) const
{
    int rows = m_PositionItemList.count();
    return rows;
}
int    InformationPositionSubTableModel::columnCount(const QModelIndex & parent) const
{
    return m_ColumnNameList.count();
}
bool InformationPositionSubTableModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
    Q_UNUSED(index);
    if (index.isValid() && role == Qt::DisplayRole)
    {
        int row = index.row();
        m_PositionItemList.replace(row, m_UpdatingItem);
        emit(dataChanged(index, index));
    }
    return true;
}
Qt::ItemFlags InformationPositionSubTableModel::flags(const QModelIndex & index) const
{
     Q_UNUSED(index);
    if (!index.isValid())
        return Qt::ItemIsEditable;

    return QAbstractTableModel::flags(index) | Qt::ItemIsEditable;
}

bool InformationPositionSubTableModel::insertRow(int position,const QModelIndex &index)
{
    Q_UNUSED(index);
    beginInsertRows(index, position, position);

    int count = m_UpdatingItem.GetFloatingMap().count();
    QMapIterator<QString,float> it(m_UpdatingItem.GetFloatingMap());
    while(it.hasNext())
    {
        it.next();
        this->AddHeaderSection(it.key());
    }

    m_PositionItemList.insert(position,m_UpdatingItem);
    endInsertRows();
    return true;
}
bool InformationPositionSubTableModel::removeRow(int position,const QModelIndex &index)
{
    Q_UNUSED(index);
    beginRemoveRows(index, position, position);
    m_PositionItemList.removeAt(position);
    endRemoveRows();
    return true;
}
void InformationPositionSubTableModel::AddHeaderSection(const QString& columnName)
{
    if(!m_ColumnNameList.contains(columnName))
    {
        setHeaderData(m_ColumnNameList.count(),Qt::Horizontal,Qt::EditRole);
        m_ColumnNameList.append(columnName);
    }
}

=====


InformationPositionSubHeaderview::InformationPositionSubHeaderview(Qt::Orientation orientation,QWidget* parent) : QHeaderView(orientation,parent)
{
    this->setSectionsClickable(false);
    this->m_IsHided = false;
}

InformationPositionSubHeaderview::~InformationPositionSubHeaderview()
{
}

void InformationPositionSubHeaderview::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
    painter->save();
    QHeaderView::paintSection(painter, rect, logicalIndex);
    painter->restore();

    if(logicalIndex==0 && m_IsHided==false)
    {
        painter->drawText(rect,Qt::AlignRight|Qt::AlignVCenter, "<<");
    }

    if(logicalIndex==1 && m_IsHided==true)
    {
        QRect leftRect = QRect(rect.x(),rect.y(),HIDEDCOLORBTNWIDTH,rect.height());
        painter->setBrush(QBrush(Qt::blue));
        painter->drawRect(leftRect);
    }

}

void InformationPositionSubHeaderview::mousePressEvent(QMouseEvent * event)
{
    if(event->button()==Qt::LeftButton)
    {
        QFontMetrics fm(this->font());
        int textWidth = fm.width("<<");

        int index = logicalIndexAt(event->pos());
        int xPos =event->pos().x();
        int xLeft = sectionPosition(index)+sectionSize(index);
        if(index==0 && m_IsHided==false && (xPos<xLeft-HIDEDCOLORBTNWIDTH && xPos>xLeft-textWidth) )
        {
            setSectionHidden(index,true);
            m_IsHided = true;
        }
        else if(index==1 && m_IsHided==true && xPos<=HIDEDCOLORBTNWIDTH)
        {
            setSectionHidden(index-1,false);
            m_IsHided = false;
        }
    }
    QHeaderView::mousePressEvent(event);
}

======

InformationPositionTreeView::InformationPositionTreeView(InformationPositionItem& infoItem,QWidget *parent) : QTreeWidget(parent)
{
    m_SubColumnNameList = infoItem.GetColumnNameList();
    m_SubColumnNameList.removeAt(0);
    m_SubColumnNameList.replace(0,"Account    ");//多出四个空格,是为"<<"腾出空间;

    this->Init();
    this->InitPositionItemListMap(infoItem);

    int columnNameCount = infoItem.GetColumnNameList().count();
    this->setHeaderLabels(infoItem.GetColumnNameList()); //增加标题;

    int count = m_InstrumentStringList.count();
    for(int i=0;i<count;i++)
    {
        QList<PositionItem>  positionItemList = m_PositionItemListMap[m_InstrumentStringList[i]];
        QStringList summaryList;
        summaryList << "" << (m_InstrumentStringList[i]) << QString("%0").arg(GetSumValue(positionItemList,"buy")) << QString("%0").arg(GetSumValue(positionItemList,"avgbuy")) << QString("%0").arg(GetSumValue(positionItemList,"sell")) << QString("%0").arg(GetSumValue(positionItemList,"avgsell")) << QString("%0").arg(GetSumValue(positionItemList,"net")) ;
        QTreeWidgetItem* node = new QTreeWidgetItem(summaryList);
        this->addTopLevelItem(node);

        InformationPositionSubTableView* subTableView = new InformationPositionSubTableView(m_SubColumnNameList,m_PositionItemListMap[m_InstrumentStringList[i]],this);
        QTreeWidgetItem* subItem = new QTreeWidgetItem;
        node->addChild(subItem);
        setFirstItemColumnSpanned(subItem,true);
        setItemWidget(subItem,0,subTableView);

        int rowHeight = subTableView->verticalHeader()->defaultSectionSize();
        node->setSizeHint(i,QSize(rowHeight,rowHeight));

/////////////--附注:
如果要让子tableview的宽度随着行数的变化而变化,却不会出现滚动条的话,应先将其滚动条关闭
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
然后在此treeWidget中,
    int subTableItemHeight= subTableView->rowHeight(0);
    int height = subTableItemHeight+subTableItemHeight*m_PositionItemListMap[m_PositionItemListMap.keys()[subIndex]].count();//算出子table的高度;
    subTableView->setMaximumHeight(height);
    subItem->setSizeHint(0,QSize(subTableView->size().width(),height));//改变树节点的宽度
//这样,子表就能动态变化而不会高度太大或太小。
如果动态变化后发现要出现大小 变化后才能正常显示,可能如下
topLevelItem(parentIndex)->setExpanded(false);
topLevelItem(parentIndex)->setExpanded(true);
即先收起子Treewidgetitem,然后再展开。这只是一种强制其更新的方法。
////////////////


        node->setIcon(0,QIcon(QPixmap("Fold.png")));
        m_IsFoldedList.append(true);

        int id = 0;
        while(id<columnNameCount)
            node->setTextAlignment(id++,Qt::AlignCenter);

    }
    connect(this,SIGNAL(itemClicked(QTreeWidgetItem*,int)),this,SLOT(ChangeIconSlot(QTreeWidgetItem*,int)));

}

InformationPositionTreeView::~InformationPositionTreeView()
{

}
void InformationPositionTreeView::mouseMoveEvent(QMouseEvent * event)
{
    QModelIndex index = indexAt(event->pos());
    if(index.isValid() && index.row()>=0)
    {
        this->setSelection(visualRect(index),QItemSelectionModel::SelectCurrent);
    }

}
void InformationPositionTreeView::ChangeIconSlot(QTreeWidgetItem * item, int column)
{
    QIcon icon;
    bool isNeedExpanded = true;
    if(column==0 && item->parent()==nullptr)
    {
        if(m_IsFoldedList[column])
        {
            icon = QIcon(QPixmap("UnFold.png"));
            isNeedExpanded = true;
        }
        else
        {
            icon = QIcon(QPixmap("Fold.png"));
            isNeedExpanded = false;
        }
        item->setIcon(column,icon);
        m_IsFoldedList.replace(column,!m_IsFoldedList[column]);
        item->setExpanded(isNeedExpanded);
    }
}
void InformationPositionTreeView::Init()
{
//    this->setMouseTracking(true);
    this->setFocusPolicy(Qt::NoFocus);
     this->setSelectionBehavior(QAbstractItemView::SelectRows);
    this->setSelectionMode(QAbstractItemView::SingleSelection);

    this->setEditTriggers(QAbstractItemView::NoEditTriggers);
    this->setContextMenuPolicy(Qt::CustomContextMenu);

    QHeaderView* headerView = new QHeaderView(Qt::Horizontal,this);
    this->setHeader(headerView);
    headerView->setStretchLastSection(true);
    headerView->setDefaultAlignment(Qt::AlignCenter);
    headerView->setSectionsClickable(true);
    headerView->setSectionResizeMode(QHeaderView::ResizeToContents);



    this->setStyleSheet("QTreeView::branch {image:none;}");
//    this->setRootIsDecorated(false);
//    this->setItemDelegateForColumn(0,);
}
void InformationPositionTreeView::InitPositionItemListMap(InformationPositionItem& infoItem)
{
    QList<PositionItem>  positionItemList = infoItem.GetPositionItemList();
    int count = positionItemList.count();
    for(int i=0;i<count;i++)
    {
        m_InstrumentStringList << positionItemList[i].GetInstrument();
    }

    m_InstrumentStringList.removeDuplicates();
    int keyCount = m_InstrumentStringList.count();
    for(int i=0;i<keyCount;i++)
    {
        QList<PositionItem> value;
        for(int j=0;j<count;j++)
        {
            if(positionItemList[j].GetInstrument()==m_InstrumentStringList[i])
                value.append(positionItemList[j]);
        }
        m_PositionItemListMap.insert(m_InstrumentStringList[i],value);
    }

}
float InformationPositionTreeView::GetSumValue(const QList<PositionItem>& positionItemList,const QString& itemName)
{
    float sum = 0.0;
    int count = positionItemList.count();
    //.....

    return 2.01;
}

======

InformationPositionTreeModel::InformationPositionTreeModel(InformationPositionItem& infoItem,QObject * parent):m_InformationPositionItem(infoItem),QAbstractItemModel(parent)
{

}

InformationPositionTreeModel::~InformationPositionTreeModel(void)
{
}

int InformationPositionTreeModel::rowCount(const QModelIndex &parent) const
{
    return m_InformationPositionItem.GetPositionItemList().count();
}
int InformationPositionTreeModel::columnCount(const QModelIndex &parent) const
{
    return m_InformationPositionItem.GetColumnNameList().count();
}
QVariant InformationPositionTreeModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();




    if(role==Qt::DisplayRole)
    {
        PositionItem item = m_InformationPositionItem.GetPositionItemList()[index.row()];
        switch (index.column())
        {
        case 0:
            return "";
        case 1:
            return item.GetInstrument();
        case 2:
            return item.GetBuyLot();
        case 3:
            return item.GetAvgBuyPrice();
        case 4:
            return item.GetSellLot();
        case 5:
            return item.GetAvgSellPrice();
        case 6:
            return item.GetNet();
        default:
            return item.GetFloatingMap()[headerData(index.column(),Qt::Horizontal,Qt::DisplayRole).toString()];;
        }
    }
    if(role==Qt::DecorationRole && index.column()==0)
    {
        return     QIcon(QPixmap("Fold.png"));
    }
    if(role==Qt::TextAlignmentRole)
    {
        Qt::AlignCenter;
    }
    return QVariant();
}
QVariant InformationPositionTreeModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        return m_InformationPositionItem.GetColumnNameList()[section];
    }
    return QVariant();
}
Qt::ItemFlags InformationPositionTreeModel::flags(const QModelIndex &index) const
{
   if (!index.isValid())
        return Qt::ItemIsSelectable;

   return QAbstractItemModel::flags(index) | Qt::ItemIsSelectable;
}
bool InformationPositionTreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if(!index.isValid())
        return false;
    return false;
}

QModelIndex    InformationPositionTreeModel::parent(const QModelIndex & index) const
{
    if(index.isValid())
        return index.parent();
    return QModelIndex();
}
QModelIndex    InformationPositionTreeModel::index(int row, int column, const QModelIndex & parent) const
{
    if(parent.isValid())
        return parent.child(row,column);
    return QModelIndex();
}