//============================================================================
// Copyright 2009-2020 ECMWF.
// This software is licensed under the terms of the Apache Licence version 2.0
// which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
// In applying this licence, ECMWF does not waive the privileges and immunities
// granted to it by virtue of its status as an intergovernmental organisation
// nor does it submit to any jurisdiction.
//============================================================================

#include "TableNodeView.hpp"

#include <QtGlobal>
#include <QComboBox>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QMenu>
#include <QMessageBox>
#include <QMouseEvent>
#include <QPainter>
#include <QScrollBar>
#include <QShortcut>
#include <QStyle>
#include <QToolButton>

#include "ActionHandler.hpp"
#include "AddModelColumnDialog.hpp"
#include "FilterWidget.hpp"
#include "IconProvider.hpp"
#include "TableNodeSortModel.hpp"
#include "PropertyMapper.hpp"
#include "TableNodeModel.hpp"
#include "TableNodeViewDelegate.hpp"
#include "UiLog.hpp"
#include "VFilter.hpp"
#include "VNode.hpp"
#include "VSettings.hpp"

#define _UI_TABLENODEVIEW_DEBUG

TableNodeView::TableNodeView(TableNodeSortModel* model,NodeFilterDef* filterDef,QWidget* parent) :
     QTreeView(parent),
     NodeViewBase(filterDef),
     model_(model),
	 needItemsLayout_(false),
     prop_(nullptr),
     setCurrentIsRunning_(false),
     setCurrentAfterUpdateIsRunning_(false),
     autoScrollToSelection_(true)
{
    setObjectName("view");
    setProperty("style","nodeView");
	setProperty("view","table");

	setRootIsDecorated(false);

    //We enable sorting but do not want to perform it immediately
    setSortingEnabledNoExec(true);

    //setSortingEnabled(false);
    //sortByColumn(-1,Qt::AscendingOrder);

	setAllColumnsShowFocus(true);
	setUniformRowHeights(true);
	setMouseTracking(true);
	setSelectionMode(QAbstractItemView::ExtendedSelection);

	//!!!!We need to do it because:
	//The background colour between the views left border and the nodes cannot be
	//controlled by delegates or stylesheets. It always takes the QPalette::Highlight
	//colour from the palette. Here we set this to transparent so that Qt could leave
    //this area empty and we fill it appropriately in our delegate.
	QPalette pal=palette();
	pal.setColor(QPalette::Highlight,QColor(128,128,128,0));
	setPalette(pal);

	//Context menu
	setContextMenuPolicy(Qt::CustomContextMenu);

	connect(this, SIGNAL(customContextMenuRequested(const QPoint &)),
		                this, SLOT(slotContextMenu(const QPoint &)));

	//Selection
	connect(this,SIGNAL(doubleClicked(const QModelIndex&)),
			this,SLOT(slotDoubleClickItem(const QModelIndex)));

    actionHandler_=new ActionHandler(this,this);

	//expandAll();

	//Header
	header_=new TableNodeHeader(this);

	setHeader(header_);

	//Set header ContextMenuPolicy
	header_->setContextMenuPolicy(Qt::CustomContextMenu);

	connect(header_,SIGNAL(customContextMenuRequested(const QPoint &)),
                this, SLOT(slotHeaderContextMenu(const QPoint &)));

	connect(header_,SIGNAL(customButtonClicked(QString,QPoint)),
	        this,SIGNAL(headerButtonClicked(QString,QPoint)));

	//for(int i=0; i < model_->columnCount(QModelIndex())-1; i++)
	//  	resizeColumnToContents(i);

	/*connect(header(),SIGNAL(sectionMoved(int,int,int)),
                this, SLOT(slotMessageTreeColumnMoved(int,int,int)));*/

	QTreeView::setModel(model_);

    //Create delegate to the view
    auto *delegate=new TableNodeViewDelegate(this);
    setItemDelegate(delegate);

	connect(delegate,SIGNAL(sizeHintChangedGlobal()),
			this,SLOT(slotSizeHintChangedGlobal()));

    //Properties
	std::vector<std::string> propVec;
	propVec.emplace_back("view.table.background");
	prop_=new PropertyMapper(propVec,this);

	//Initialise bg
	adjustBackground(prop_->find("view.table.background")->value().value<QColor>());

    header_->setSortIndicatorShown(true);
}

TableNodeView::~TableNodeView()
{
    delete prop_;
}

void TableNodeView::setModel(TableNodeSortModel *model)
{
	model_= model;

	//Set the model.
	QTreeView::setModel(model_);
}

QWidget* TableNodeView::realWidget()
{
	return this;
}

QObject* TableNodeView::realObject()
{
    return this;
}

//Enable sorting without actually performing it!!!
void TableNodeView::setSortingEnabledNoExec(bool b)
{
    if(b)
    {
        model_->setSkipSort(true);
        setSortingEnabled(true);
        model_->setSkipSort(false);
    }
    else
    {
        setSortingEnabled(false);
    }
}

//Collects the selected list of indexes
QModelIndexList TableNodeView::selectedList()
{
    QModelIndexList lst;
    Q_FOREACH(QModelIndex idx,selectedIndexes())
        if(idx.column() == 0)
            lst << idx;
    return lst;
}


// reimplement virtual function from QTreeView - called when the selection is changed
void TableNodeView::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
{
	QModelIndexList lst=selectedIndexes();
    if(lst.count() > 0 && !setCurrentAfterUpdateIsRunning_)
	{
		VInfo_ptr info=model_->nodeInfo(lst.front());
		if(info && !info->isEmpty())
		{
#ifdef _UI_TABLENODEVIEW_DEBUG
            UiLog().dbg() << "TableNodeView::selectionChanged --> emit=" << info->path();
#endif
			Q_EMIT selectionChanged(info);
		}
	}
	QTreeView::selectionChanged(selected, deselected);

    //The model has to know about the selection in order to manage the
    //nodes that are forced to be shown
    model_->selectionChanged(lst);
}

VInfo_ptr TableNodeView::currentSelection()
{
	QModelIndexList lst=selectedIndexes();
	if(lst.count() > 0)
	{
		return model_->nodeInfo(lst.front());
	}
	return VInfo_ptr();
}

//Sets the current selection to the given VInfo item.
// called:
//  -from outside of the view when the selection is broadcast from another view
//  -from within the view after a data update
void TableNodeView::setCurrentSelection(VInfo_ptr info)
{
    //While the current is being selected we do not allow
    //another setCurrent call go through
    if(setCurrentIsRunning_)
        return;

    setCurrentIsRunning_=true;
    QModelIndex idx=model_->infoToIndex(info);
    if(idx.isValid())
    {
#ifdef _UI_TABLENODEVIEW_DEBUG
        if(info)
            UiLog().dbg() << "TableNodeView::setCurrentSelection --> " <<  info->path();
#endif
        setCurrentIndex(idx);
    }
    setCurrentIsRunning_=false;
}

void TableNodeView::setCurrentSelectionAfterUpdate(VInfo_ptr info)
{
    //While the current is being selected we do not allow
    //another setCurrent call go through
    if(setCurrentAfterUpdateIsRunning_)
        return;

    setCurrentAfterUpdateIsRunning_=true;
    setCurrentSelection(info);
    setCurrentAfterUpdateIsRunning_=false;
}

void TableNodeView::slotUpdateBegin()
{
    lastSelection_=currentSelection();
}

void TableNodeView::slotUpdateEnd()
{
    if(lastSelection_)
    {
        lastSelection_->regainData();
        if(lastSelection_->hasData())
        {
            bool autoScr = hasAutoScroll();
            if (autoScr != autoScrollToSelection_)
            {
                setAutoScroll(autoScrollToSelection_);
            }

            setCurrentSelectionAfterUpdate(lastSelection_);

            if (autoScr != autoScrollToSelection_)
            {
                setAutoScroll(autoScr);
            }

        }

        lastSelection_.reset();
    }
}

void TableNodeView::slotSelectionAutoScrollChanged(bool st)
{
    autoScrollToSelection_ = st;
}

void TableNodeView::slotDoubleClickItem(const QModelIndex&)
{
}

void TableNodeView::slotContextMenu(const QPoint &position)
{
	QModelIndexList lst=selectedList();
	//QModelIndex index=indexAt(position);
	QPoint scrollOffset(horizontalScrollBar()->value(),verticalScrollBar()->value());

	handleContextMenu(indexAt(position),lst,mapToGlobal(position),position+scrollOffset,this);
}


void TableNodeView::handleContextMenu(QModelIndex indexClicked,QModelIndexList indexLst,QPoint globalPos,QPoint widgetPos,QWidget *widget)
{
	//Node actions
	  	if(indexClicked.isValid() && indexClicked.column() == 0)   //indexLst[0].isValid() && indexLst[0].column() == 0)
		{
            UiLog().dbg()  << "context menu " << indexClicked;

	  		std::vector<VInfo_ptr> nodeLst;
			for(int i=0; i < indexLst.count(); i++)
			{
				VInfo_ptr info=model_->nodeInfo(indexLst[i]);
				if(!info->isEmpty())
					nodeLst.push_back(info);
			}

			actionHandler_->contextMenu(nodeLst,globalPos);
		}

		//Desktop actions
		else
		{
		}
}


void TableNodeView::slotCommandShortcut()
{
    if (auto* sc = static_cast<QShortcut*>(QObject::sender())) {
        QModelIndexList indexLst=selectedList();
        std::vector<VInfo_ptr> nodeLst;
        for(int i=0; i < indexLst.count(); i++)
        {
            VInfo_ptr info=model_->nodeInfo(indexLst[i]);
            if(info && !info->isEmpty())
                nodeLst.push_back(info);
        }
        actionHandler_->runCommand(nodeLst, sc->property("id").toInt());
    }
}

void TableNodeView::slotViewCommand(VInfo_ptr info,QString cmd)
{
}

void TableNodeView::rerender()
{
	if(needItemsLayout_)
	{
		doItemsLayout();
		needItemsLayout_=false;
	}
	else
	{
		viewport()->update();
	}
}

void TableNodeView::slotRerender()
{
	rerender();
}

void TableNodeView::slotSizeHintChangedGlobal()
{
	needItemsLayout_=true;
}

void TableNodeView::adjustBackground(QColor col)
{
	if(col.isValid())
	{
		QString sh="QTreeView { background : " + col.name() + ";}";
		setStyleSheet(sh);
	}
}

void TableNodeView::notifyChange(VProperty* p)
{
	if(p->path() == "view.table.background")
	{
		adjustBackground(p->value().value<QColor>());
	}
}

//=========================================
// Header
//=========================================

void TableNodeView::collectVariableNames(std::set<std::string>& vars)
{
    Q_ASSERT(model_);

    //collect the list of avialable variables using the selected node
    //or if it is not valid the first row in the table
    QModelIndex idx=currentIndex();
    if(!idx.isValid())
    {
        idx=model_->index(0,0);
    }

    if(idx.isValid())
    {
        VInfo_ptr info=model_->nodeInfo(idx);
        if(info)
        {
            if(VNode* vn=info->node())
            {
                vn->collectInheritedVariableNames(vars);
            }
        }
    }
}


void TableNodeView::slotAddVariableColumn()
{
    Q_ASSERT(model_);

    std::set<std::string> vars;
    collectVariableNames(vars);

    AddModelColumnDialog d(this);
    d.init(model_->columns(),vars);
    d.exec();
}

void TableNodeView::changeVariableColumn(QString varName)
{
    Q_ASSERT(model_);

    std::set<std::string> vars;
    collectVariableNames(vars);

    ChangeModelColumnDialog d(this);
    d.init(model_->columns(),vars,varName);
    d.setColumn(varName);
    d.exec();
}

void TableNodeView::slotHeaderContextMenu(const QPoint &position)
{
    int section=header_->logicalIndexAt(position);
	if(section< 0 || section >= header_->count())
		return;

    int visCnt=0;
    for(int i=0; i <header_->count(); i++)
    {
        if(!header_->isSectionHidden(i))
            visCnt++;
    }

	QList<QAction*> lst;
	auto *menu=new QMenu(this);
	QAction *ac;

    //Show/hide current columns
    QString name=header_->model()->headerData(section,Qt::Horizontal).toString();
    ac=new QAction(menu);
    ac->setData("show_current");
    bool vis=!header_->isSectionHidden(section);
    ac->setText(((!vis)?"Show column \'":"Hide column \'")  + name + "\'");
    if(vis && visCnt <=1)
    {
        ac->setEnabled(false);
    }
    menu->addAction(ac);

    menu->addSeparator();

    //Add special menu for variable columns
    bool varColumn=header_->model()->headerData(section,Qt::Horizontal,AbstractNodeModel::VariableRole).toBool();
    QString varName;

    if(varColumn)
    {
        varName=header_->model()->headerData(section,Qt::Horizontal).toString();

        ac=new QAction(menu);
        ac->setText(tr("Change column \'") + varName + "\'");
        ac->setData("change");
        menu->addAction(ac);

        ac=new QAction(menu);
        ac->setText(tr("Remove column \'") + varName + "\'");
        ac->setIcon(QPixmap(":viewer/remove.svg"));
        ac->setData("remove");
        menu->addAction(ac);

        menu->addSeparator();
    }

    //Submenu to control the visibility of other columns
    QMenu *visMenu=menu->addMenu("Show/hide other columns");
	for(int i=0; i <header_->count(); i++)
	{
        if(i != section)
        {
            name=header_->model()->headerData(i,Qt::Horizontal).toString();
            ac=new QAction(visMenu);
            ac->setText(name);
            ac->setCheckable(true);
            ac->setData(i);

            bool vis=!header_->isSectionHidden(i);
            ac->setChecked(vis);

            if(vis && visCnt <=1)
            {
                ac->setEnabled(false);
            }

            visMenu->addAction(ac);
        }
	}

    //Show the context menu and check selected action
	ac=menu->exec(header_->mapToGlobal(position));
    if(ac && ac->isEnabled())
	{
        if(ac->data().toString() == "change")
        {
            changeVariableColumn(varName);
        }
        else if(ac->data().toString() == "remove")
        {
            delete menu;
            if(QMessageBox::question(nullptr,tr("Confirm: remove column"),
                            tr("Are you sure that you want to remove column <b>") + varName + "</b>?",
                            QMessageBox::Ok | QMessageBox::Cancel,QMessageBox::Cancel) == QMessageBox::Ok)
            {
                model_->removeColumn(varName);
            }
            return;
        }
        else if(ac->data().toString() == "show_current")
        {
            header_->setSectionHidden(section,!header_->isSectionHidden(section));
        }
        else if(ac->isCheckable())
        {
            int i=ac->data().toInt();
            header_->setSectionHidden(i,!ac->isChecked());
        }                  
	}
    delete menu;
}

void TableNodeView::readSettings(VSettings* vs)
{
    vs->beginGroup("column");

    std::vector<std::string> orderVec;
    std::vector<int> visVec, wVec;

    vs->get("order",orderVec);
    vs->get("visible",visVec);
    vs->get("width",wVec);

    int sortColumn = vs->get<int>("sortColumn",0);
    int sortOrder = vs->get<int>("sortOrder",0);

    vs->endGroup();

    if(orderVec.size() != visVec.size() || orderVec.size() != wVec.size())
        return;

    for(size_t i=0; i < orderVec.size(); i++)
    {
        std::string id=orderVec[i];
        for(int j=0; j < model_->columnCount(QModelIndex()); j++)
        {
            if(model_->headerData(j,Qt::Horizontal,Qt::UserRole).toString().toStdString() == id)
            {
                if(visVec[i] == 0)
                    header()->setSectionHidden(j,true);               

                else if(wVec[i] > 0)
                    setColumnWidth(j,wVec[i]);

                break;
            }
        }
    }

    if(header_->count() > 0)
    {
        int visCnt=0;
        for(int i=0; i < header_->count(); i++)
            if(!header_->isSectionHidden(i))
                visCnt++;

        if(visCnt==0)
            header()->setSectionHidden(0,false);
    }

    sortByColumn(sortColumn, (sortOrder==0)?Qt::AscendingOrder:Qt::DescendingOrder);
}

void TableNodeView::writeSettings(VSettings* vs)
{
    vs->beginGroup("column");

    std::vector<std::string> orderVec;
    std::vector<int> visVec, wVec;
    for(int i=0; i < model_->columnCount(QModelIndex()); i++)
    {
        std::string id=model_->headerData(i,Qt::Horizontal,Qt::UserRole).toString().toStdString();
        orderVec.push_back(id);
        visVec.push_back((header()->isSectionHidden(i))?0:1);
        wVec.push_back(columnWidth(i));
    }

    vs->put("order",orderVec);
    vs->put("visible",visVec);
    vs->put("width",wVec);
    vs->put("sortColumn",header_->sortIndicatorSection());
    vs->put("sortOrder",header_->sortIndicatorOrder());

    vs->endGroup();
}

//=========================================
// TableNodeHeader
//=========================================

TableNodeHeader::TableNodeHeader(QWidget *parent) : QHeaderView(Qt::Horizontal, parent)
{
	setStretchLastSection(true);

	connect(this, SIGNAL(sectionResized(int, int, int)),
    		 this, SLOT(slotSectionResized(int)));

    int pixId=IconProvider::add(":viewer/filter_decor.svg","filter_decor");

    customPix_=IconProvider::pixmap(pixId,10);


     //connect(this, SIGNAL(sectionMoved(int, int, int)), this,
     //        SLOT(handleSectionMoved(int, int, int)));

     //setMovable(true);
}

void TableNodeHeader::showEvent(QShowEvent *e)
{
  /*  for(int i=0;i<count();i++)
    {


       if(1)
       {
    	   widgets_[i]->setGeometry(sectionViewportPosition(i),0,
                                sectionSize(i),height());
    	   widgets_[i]->show();
       }
    }
    */

    QHeaderView::showEvent(e);
}

void TableNodeHeader::slotSectionResized(int i)
{
    /*for (int j=visualIndex(i);j<count();j++)
    {
        int logical = logicalIndex(j);

        if(combo_[logical])
        {
        	combo_[logical]->setGeometry(sectionViewportPosition(logical), height()/2,
                                   sectionSize(logical) - 16, height());
        }
   }*/
}

QSize TableNodeHeader::sizeHint() const
{
	return QHeaderView::sizeHint();

	QSize s = size();
    //s.setHeight(headerSections[0]->minimumSizeHint().height() + 35);
    //s.setHeight(2*35);
    return s;
}

void TableNodeHeader::setModel(QAbstractItemModel *model)
{
	if(model)
	{
		for(int i=0; i< model->columnCount(); i++)
		{
			QString id=model->headerData(i,Qt::Horizontal,Qt::UserRole).toString();
			if(id == "status")
				customButton_.insert(i,TableNodeHeaderButton(id));
		}
	}
	QHeaderView::setModel(model);
}

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


	/*QPixmap customPix(":viewer/filter_decor.svg");
    QRect cbRect(0,0,12,12);
	cbRect.moveCenter(QPoint(rect.right()-16-6,rect.center().y()));
	customButton_[logicalIndex].setRect(cbRect);
	painter->drawPixmap(cbRect,pix);*/

	if (!rect.isValid())
		return;

	 QStyleOptionHeader opt;
	 initStyleOption(&opt);
	 QStyle::State state = QStyle::State_None;
	 if(isEnabled())
	    state |= QStyle::State_Enabled;
	 if(window()->isActiveWindow())
	    state |= QStyle::State_Active;

	bool clickable;

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
	clickable=sectionsClickable();
#else
	clickable=isClickable();
#endif

	 if(clickable)
	 {
		 /*if (logicalIndex == d->hover)
	            state |= QStyle::State_MouseOver;
	        if (logicalIndex == d->pressed)
	            state |= QStyle::State_Sunken;
	        else if (d->highlightSelected) {
	            if (d->sectionIntersectsSelection(logicalIndex))
	                state |= QStyle::State_On;
	            if (d->isSectionSelected(logicalIndex))
	                state |= QStyle::State_Sunken;
	        }*/

	    }

	// if(isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
	//        opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
	//                            ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;

	 // setup the style options structure
	 //QVariant textAlignment = model->headerData(logicalIndex, d->orientation,
	 //                                                 Qt::TextAlignmentRole);
	 opt.rect = rect;
	 opt.section = logicalIndex;
	 opt.state |= state;
	 //opt.textAlignment = Qt::Alignment(textAlignment.isValid()
	 //                                     ? Qt::Alignment(textAlignment.toInt())
	 //                                     : d->defaultAlignment);

	 //opt.text = model()->headerData(logicalIndex, Qt::Horizontal),
	 //                                    Qt::DisplayRole).toString();

	 QVariant foregroundBrush;
	 if (foregroundBrush.canConvert<QBrush>())
	     opt.palette.setBrush(QPalette::ButtonText, qvariant_cast<QBrush>(foregroundBrush));

	 QPointF oldBO = painter->brushOrigin();
	 QVariant backgroundBrush;
	 if (backgroundBrush.canConvert<QBrush>())
	 {
	        opt.palette.setBrush(QPalette::Button, qvariant_cast<QBrush>(backgroundBrush));
	        opt.palette.setBrush(QPalette::Window, qvariant_cast<QBrush>(backgroundBrush));
	        painter->setBrushOrigin(opt.rect.topLeft());
	 }

	// the section position
	int visual = visualIndex(logicalIndex);
	assert(visual != -1);

	if (count() == 1)
		opt.position = QStyleOptionHeader::OnlyOneSection;
	else if (visual == 0)
		opt.position = QStyleOptionHeader::Beginning;
    else if (visual == count() - 1)
	    opt.position = QStyleOptionHeader::End;
	else
	    opt.position = QStyleOptionHeader::Middle;

	opt.orientation = Qt::Horizontal;

	// the selected position
	/*bool previousSelected = d->isSectionSelected(logicalIndex(visual - 1));
	    bool nextSelected =  d->isSectionSelected(logicalIndex(visual + 1));
	    if (previousSelected && nextSelected)
	        opt.selectedPosition = QStyleOptionHeader::NextAndPreviousAreSelected;
	    else if (previousSelected)
	        opt.selectedPosition = QStyleOptionHeader::PreviousIsSelected;
	    else if (nextSelected)
	        opt.selectedPosition = QStyleOptionHeader::NextIsSelected;
	    else
	        opt.selectedPosition = QStyleOptionHeader::NotAdjacent;
	*/

	// draw the section
	style()->drawControl(QStyle::CE_Header, &opt, painter, this);
	painter->setBrushOrigin(oldBO);

	painter->restore();


	int rightPos=rect.right();
	if(isSortIndicatorShown() && sortIndicatorSection() == logicalIndex)
		opt.sortIndicator = (sortIndicatorOrder() == Qt::AscendingOrder)
                            ? QStyleOptionHeader::SortDown : QStyleOptionHeader::SortUp;

    if (opt.sortIndicator != QStyleOptionHeader::None)
    {
        QStyleOptionHeader subopt = opt;
        subopt.rect = style()->subElementRect(QStyle::SE_HeaderArrow, &opt, this);
        rightPos=subopt.rect.left();
           style()->drawPrimitive(QStyle::PE_IndicatorHeaderArrow, &subopt, painter, this);
    }


	QMap<int,TableNodeHeaderButton>::iterator it=customButton_.find(logicalIndex);
	if(it != customButton_.end())
	{
		//Custom button
		QStyleOptionButton optButton;

		//visPbOpt.text="Visualise";
		optButton.state = QStyle::State_AutoRaise ; //QStyle::State_Active | QStyle::State_Enabled;
		//optButton.icon=customIcon_;
		//optButton.iconSize=QSize(12,12);

		int buttonWidth=customPix_.width();
		int buttonHeight=buttonWidth;
		optButton.rect = QRect(rightPos-4-buttonWidth,(rect.height()-buttonWidth)/2,
								   buttonWidth,buttonHeight);

		painter->drawPixmap(optButton.rect,customPix_);

		rightPos=optButton.rect.left();
		it.value().setRect(optButton.rect);
	}

    //Text is left aligned, a decoration icon might be added to left just before the text
	QString text=model()->headerData(logicalIndex,Qt::Horizontal).toString();
	QRect textRect=rect;
    textRect.setRight(rightPos-5);
    textRect.adjust(2,0,0,0);

    //Draw icon to the left of the text
    QVariant pixVa=model()->headerData(logicalIndex,Qt::Horizontal,Qt::DecorationRole);
    if(pixVa.type() == QVariant::Pixmap)
    {
        QPixmap pix=pixVa.value<QPixmap>();
        int pixH=qMin(pix.height(),rect.height()-2);

        QFont f;
        QFontMetrics fm(f);
        int textLeft=textRect.x();
        QRect pixRect=QRect(rect.x()+3,rect.center().y()-pixH/2,
                            pix.width(),pix.height());
        if(pixRect.x()+pixRect.width() + fm.width(text) + 4 < textRect.x() + textRect.width())
        {
            painter->drawPixmap(pixRect,pix);
            textRect.setX(pixRect.x()+pixRect.width() + 3);
        }
    }

    painter->drawText(textRect,Qt::AlignLeft | Qt::AlignVCenter,text);

	//style()->drawControl(QStyle::CE_PushButton, &optButton,painter,this);
}

void TableNodeHeader::mousePressEvent(QMouseEvent *event)
{
	QMap<int,TableNodeHeaderButton>::const_iterator it = customButton_.constBegin();
	while(it != customButton_.constEnd())
	{
		if(it.value().rect_.contains(event->pos()))
		{
            UiLog().dbg() << "header " << it.key() << " clicked";
			Q_EMIT customButtonClicked(it.value().id(),event->globalPos());
		}
	     ++it;
	 }

	QHeaderView::mousePressEvent(event);
}

/*void TableNodeHeader::mouseMoveEvent(QMouseEvent *event)
{
	int prevIndex=hoverIndex_;
	QMap<int,TableNodeHeaderButton>::const_iterator it = customButton_.constBegin();
	while(it != customButton_.constEnd())
	{
		if(it.value().rect_.contains(event->pos()))
		{
			hoverIndex_=it.key();
			if(hoveIndex != prevIndex)
			{
				rerender;
			}
		}
	    ++it;
	}

	if(preIndex !=-1)
	{

	}
	hoverIndex_=-1;
}*/

