QgsComposerTableColumn *QgsComposerTableColumn::clone()
{
  QgsComposerTableColumn *newColumn = new QgsComposerTableColumn;
  newColumn->setAttribute( mAttribute );
  newColumn->setHeading( mHeading );
  newColumn->setHAlignment( mHAlignment );
  newColumn->setVAlignment( mVAlignment );
  newColumn->setSortByRank( mSortByRank );
  newColumn->setSortOrder( mSortOrder );
  newColumn->setWidth( mWidth );
  return newColumn;
}
bool QgsComposerAttributeTableColumnModelV2::moveColumnInSortRank( QgsComposerTableColumn * column, ShiftDirection direction )
{
  if ( !mComposerTable || !column )
  {
    return false;
  }
  if (( direction == ShiftUp && column->sortByRank() <= 1 )
      || ( direction == ShiftDown && column->sortByRank() <= 0 ) )
  {
    //already at start/end of list or not being used for sort
    return false;
  }

  //find column before this one in sort order
  QList<QgsComposerTableColumn*> sortedColumns;
  QList<QgsComposerTableColumn*>::iterator columnIt = mComposerTable->columns()->begin();
  for ( ; columnIt != mComposerTable->columns()->end(); ++columnIt )
  {
    if (( *columnIt )->sortByRank() > 0 )
    {
      sortedColumns.append( *columnIt );
    }
  }
  qStableSort( sortedColumns.begin(), sortedColumns.end(), columnsBySortRank );
  int columnPos = sortedColumns.indexOf( column );

  if (( columnPos == 0 && direction == ShiftUp )
      || (( columnPos == sortedColumns.length() - 1 ) && direction == ShiftDown ) )
  {
    //column already at start/end
    return false;
  }

  QgsComposerTableColumn* swapColumn = direction == ShiftUp ?
                                       sortedColumns[ columnPos - 1]
                                       : sortedColumns[ columnPos + 1];
  QModelIndex idx = indexFromColumn( column );
  QModelIndex idxSwap = indexFromColumn( swapColumn );

  //now swap sort ranks
  int oldSortRank = column->sortByRank();
  column->setSortByRank( swapColumn->sortByRank() );
  emit dataChanged( idx, idx );

  swapColumn->setSortByRank( oldSortRank );
  emit dataChanged( idxSwap, idxSwap );

  return true;
}