// SPDX-FileCopyrightText: Copyright (c) Kitware Inc.
// SPDX-FileCopyrightText: Copyright (c) Sandia Corporation
// SPDX-License-Identifier: BSD-3-Clause
#ifndef pqHeaderView_h
#define pqHeaderView_h

#include "pqWidgetsModule.h" // for exports
#include <QHeaderView>
#include <QPoint> // for QPoint
#include <QRect>  // for QRect

#include <utility> // for std::pair
#include <vector>  // for std::vector

/**
 * @class pqHeaderView
 * @brief pqHeaderView extends QHeaderView to add support for
 *        Qt::CheckStateRole.
 *
 * pqHeaderView extends QHeaderView to add support for getting and setting
 * Qt::CheckStateRole. The QAbstractItemModel connected to the view must support
 * getting/setting check state by providing appropriate implementations
 * for `QAbstractItemModel::setHeaderData` and `QAbstractItemModel::headerData`.
 *
 * This class is a reimplementation of pqCheckableHeaderView with improved
 * rendering as well as letting the model handle getting and setting of header
 * check state via the header-data API.
 *
 * Currently, pqHeaderView is only intended to be used for horizontal headers.
 * However, it should be fairly straight forward to support vertical headers, if
 * needed.
 */
class PQWIDGETS_EXPORT pqHeaderView : public QHeaderView
{
  Q_OBJECT
  typedef QHeaderView Superclass;
  Q_PROPERTY(bool showCustomIndicator READ isCustomIndicatorShown WRITE setCustomIndicatorShown);

public:
  pqHeaderView(Qt::Orientation orientation, QWidget* parent = nullptr);
  ~pqHeaderView() override;

  ///@{
  /**
   * For checkable section, this property controls if clicks on the entire
   * section should be treated as a request to toggle the check state or only
   * limit the click to the checkbox. Default is to limit to the checkbox, set
   * to true if you want the entire section respond to clicks as toggling the
   * check state.
   */
  void setToggleCheckStateOnSectionClick(bool val) { this->ToggleCheckStateOnSectionClick = val; }
  bool toggleCheckStateOnSectionClick() const { return this->ToggleCheckStateOnSectionClick; }
  ///@}

  ///@{
  /**
   * This property holds if a custom indicator is shown for sections. The custom
   * indicator can be used to popup a custom menu or filtering options, for
   * example. If enabled, all visible sections with non-empty header data get a
   * custom indicator rendered.
   *
   * By default, this property is `false`.
   */
  bool isCustomIndicatorShown() const { return this->CustomIndicatorShown; }
  void setCustomIndicatorShown(bool val);
  ///@}

  ///@{
  /**
   * When `showCustomIndicator` property is true, these are the icons
   * rendered. Icons are rendered in order from right to left i.e. first added
   * icon on the rightmost side and so on. The `role` is useful in
   * distinguishing user clicks when the `customIndicatorClicked` signal is
   * fired.
   */
  void addCustomIndicatorIcon(const QIcon& icon, const QString& role);
  void removeCustomIndicatorIcon(const QString& role);
  QIcon customIndicatorIcon(const QString& role) const;
  ///@}

  /**
   * For testing purposes only. Returns the position of the painted checkbox in
   * the most recent paint call. Note, currently we only support at most one
   * checkable section. We will need to change this API if we start
   * supporting multiple checkable sections.
   */
  QRect lastCheckRect() const { return this->CheckRect; }

Q_SIGNALS:
  void customIndicatorClicked(int section, const QPoint& pt, const QString& role);

protected:
  void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const override;
  void mousePressEvent(QMouseEvent* event) override;
  void mouseReleaseEvent(QMouseEvent* event) override;

private:
  Q_DISABLE_COPY(pqHeaderView);

  // return true if we handled the event.
  bool mouseClickEvent(QMouseEvent* event);

  bool ToggleCheckStateOnSectionClick;
  QPoint PressPosition;
  mutable QRect CheckRect;

  bool CustomIndicatorShown;

  // we keep as a vector since order of addition of icons is important.
  std::vector<std::pair<QIcon, QString>> CustomIndicatorIcons;
  mutable std::vector<std::pair<QRect, QString>> CustomIndicatorRects;
};

#endif
