/***************************************************************************

    source::worx xtree
    Copyright © 2024-2025 c.holzheuer
    christoph.holzheuer@gmail.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

***************************************************************************/

#include <QPainter>
#include <QTime>
#include <QHeaderView>

#include <xqtreetable.h>
#include <xqviewmodel.h>

#define DB_TIMESTAMP QTime::currentTime().toString(" -- HH:mm:ss.zzz")

//! standardkonstruktor

XQTreeTable::XQTreeTable(QWidget* parent)
    : QTreeView(parent)
{
  /*
  setDragEnabled(true);
  setAcceptDrops(true);
  setDragDropOverwriteMode(true);
  setDropIndicatorShown(false);
  */
  setHeaderHidden(true);
  setMouseTracking(true);
}


//! gibt die verbundene modelview zurück, cast auf 'model()'

XQViewModel* XQTreeTable::viewModel()
{
  return static_cast<XQViewModel*>(model());
}


//! shortcut: gibt das item für index zurück

XQItem& XQTreeTable::xqItemFromIndex(const QModelIndex& index )
{
  return viewModel()->xqItemFromIndex( index );
}


//! rows sichtbar/unsichtbar schalten, von 'fstRow' bis _einschliesslich_
//! 'lstRow'

void XQTreeTable::toggleRowsHidden( int fstRow, int lstRow )
{
  bool hidden = isRowHidden( fstRow, rootIndex() );
  for (int row = fstRow; row <= lstRow; ++row )
   setRowHidden( row, rootIndex(), !hidden );
}


//! override von 'currentChanged' (noch nicht implementiert)

void XQTreeTable::currentChanged(const QModelIndex& current, const QModelIndex& previous)
{

  QTreeView::currentChanged(current, previous);
  // edit comboboxes directly
  //XQItem& currentItem = xqItemFromIndex(current);
  // xx_fix!
  /*
  if (curreXQItem && curreXQItem->renderStyle() == XQItem::ComboBoxStyle )
  {
    QTreeView::edit(current);
  }
  */

}


//! ändert die breite eines header-feldes anhand der maus-position

void XQTreeTable::mouseResizeHeaderEntry(int xpos)
{
  // resize colummn: minimal vertical margin in pixels
  static const int s_MinimalMargin = 50;

  QRect itemRect = visualRect(_indexToResize);

  // new position different to item rect outer right position
  int newPos = xpos - itemRect.right();

  // current section size from header
  int column = _indexToResize.column();
  int sectionSize = columnWidth( column );
  int maxPos = s_MinimalMargin + xpos;

  // resize header and update view
  if (maxPos <= width())
  {
    header()->resizeSection(column, sectionSize + newPos);
  }
}


//! behandelt den mouse-drag zur grössenänderung der header-felder.

void XQTreeTable::mouseMoveEvent(QMouseEvent* event)
{
  // pixel Grenzwert zur Anzeige des Splitcursors
  static const int s_CatchOffset = 5;

  bool leftBtn = (event->buttons() & Qt::LeftButton);
  QPoint eventPos = event->pos();

  // splitcursor ist gesetzt
  bool splitCursor = (cursor().shape() == Qt::SplitHCursor);

  // sind wir schon am 'draggen'?
  if (_indexToResize.isValid() && splitCursor && leftBtn)
  {
    return mouseResizeHeaderEntry(eventPos.x());
  }

  // nein, nocht nicht
  QModelIndex idxFromPos = indexAt(eventPos);

  // mousepointer is inside a header section
  if ( xqItemFromIndex(idxFromPos).isHeaderStyle() )
  {
    QRect itemRect = visualRect(idxFromPos);

    int crX = itemRect.topRight().x() - s_CatchOffset;
    QRect catchRect = QRect(crX, itemRect.y(), s_CatchOffset, itemRect.height());
    if (catchRect.contains(eventPos))
    {
      return setCursor(QCursor(Qt::SplitHCursor));
    }
  }
  setCursor(QCursor(Qt::ArrowCursor));

  QTreeView::mouseMoveEvent(event);
}


//! speichert die start-position fürs header-resizing.

void XQTreeTable::mousePressEvent(QMouseEvent* event)
{

  // case #1:
  // Handle header resiszing

  QPoint pos = event->pos();
  QModelIndex index = indexAt(pos);
  // set index for resize column if cursor for split is active
  if (cursor().shape() == Qt::SplitHCursor)
  {
    _indexToResize = index;
  }
  QTreeView::mousePressEvent(event);
}


//! speichert die index-position fürs header-resizing.

void XQTreeTable::mouseReleaseEvent(QMouseEvent* event)
{
  // reset index for resize column
  _indexToResize = QModelIndex();
  setCursor(QCursor(Qt::ArrowCursor));
  QTreeView::mouseReleaseEvent(event);
}


//! zoom-in / zoom-out mit mausrad & ctrl

void XQTreeTable::wheelEvent(QWheelEvent* event)
{
  // Ctrl-key down?
  if (!event->modifiers().testFlag(Qt::ControlModifier))
    // default processing
    return QTreeView::wheelEvent(event);

  // current size
  int curSize = fontInfo().pointSize();
  // increase?
  if (event->angleDelta().y() > 0)
  {
    // "zoom in"
    curSize += (curSize < 40) ? (1) : (0);
  }
  else
  {
    // "zoom out"
    curSize -= (curSize > 8) ? (1) : (0);
  }
  // adjust size via stylesheet
  setStyleSheet(QString("font: %1pt;").arg(curSize));

}
