Files

149 lines
5.6 KiB
C++
Raw Permalink Normal View History

2026-05-24 23:21:33 +02:00
#include "filtertableheader.h"
#include "filtertableheader.h"
#include <QApplication>
#include <QTableView>
#include <QScrollBar>
#include "utils/filterlineedit.h"
FilterTableHeader::FilterTableHeader(QTableView* parent) :
QHeaderView(Qt::Horizontal, parent)
{
// Activate the click signals to allow sorting
setSectionsClickable(true);
// But use our own indicators allowing multi-column sorting
setSortIndicatorShown(false);
// Make sure to not automatically resize the columns according to the contents
setSectionResizeMode(QHeaderView::Interactive);
// Highlight column headers of selected cells to emulate spreadsheet behaviour
setHighlightSections(true);
// Do some connects: Basically just resize and reposition the input widgets whenever anything changes
connect(this, &FilterTableHeader::sectionResized, this, &FilterTableHeader::adjustPositions);
connect(this, &FilterTableHeader::sectionClicked, this, &FilterTableHeader::adjustPositions);
connect(parent->horizontalScrollBar(), &QScrollBar::valueChanged, this, &FilterTableHeader::adjustPositions);
connect(parent->verticalScrollBar(), &QScrollBar::valueChanged, this, &FilterTableHeader::adjustPositions);
// Set custom context menu handling
setContextMenuPolicy(Qt::CustomContextMenu);
}
void FilterTableHeader::generateFilters(size_t number, size_t number_of_hidden_filters)
{
// Delete all the current filter widgets
qDeleteAll(filterWidgets);
filterWidgets.clear();
// And generate a bunch of new ones
for(size_t i=0; i < number; ++i)
{
FilterLineEdit* l = new FilterLineEdit(this, &filterWidgets, i);
l->setVisible(i >= number_of_hidden_filters);
// Set as focus proxy the first non-row-id visible filter-line.
if(i!=0 && l->isVisible() && !focusProxy())
setFocusProxy(l);
connect(l, &FilterLineEdit::delayedTextChanged, this, &FilterTableHeader::inputChanged);
connect(l, &FilterLineEdit::filterFocused, this, [this](){emit filterFocused();});
connect(l, &FilterLineEdit::addFilterAsCondFormat, this, &FilterTableHeader::addFilterAsCondFormat);
connect(l, &FilterLineEdit::clearAllCondFormats, this, &FilterTableHeader::clearAllCondFormats);
connect(l, &FilterLineEdit::editCondFormats, this, &FilterTableHeader::editCondFormats);
filterWidgets.push_back(l);
}
// Position them correctly
updateGeometries();
}
QSize FilterTableHeader::sizeHint() const
{
// For the size hint just take the value of the standard implementation and add the height of a input widget to it if necessary
QSize s = QHeaderView::sizeHint();
if(filterWidgets.size())
s.setHeight(s.height() + filterWidgets.at(0)->sizeHint().height() + 4); // The 4 adds just adds some extra space
return s;
}
void FilterTableHeader::updateGeometries()
{
// If there are any input widgets add a viewport margin to the header to generate some empty space for them which is not affected by scrolling
if(filterWidgets.size())
setViewportMargins(0, 0, 0, filterWidgets.at(0)->sizeHint().height());
else
setViewportMargins(0, 0, 0, 0);
// Now just call the parent implementation and reposition the input widgets
QHeaderView::updateGeometries();
adjustPositions();
}
void FilterTableHeader::adjustPositions()
{
// The two adds some extra space between the header label and the input widget
const int y = QHeaderView::sizeHint().height() + 2;
// Loop through all widgets
for(int i=0;i < static_cast<int>(filterWidgets.size()); ++i)
{
// Get the current widget, move it and resize it
QWidget* w = filterWidgets.at(static_cast<size_t>(i));
if (QApplication::layoutDirection() == Qt::RightToLeft)
w->move(width() - (sectionPosition(i) + sectionSize(i) - offset()), y);
else
w->move(sectionPosition(i) - offset(), y);
w->resize(sectionSize(i), w->sizeHint().height());
}
}
void FilterTableHeader::inputChanged(const QString& new_value)
{
adjustPositions();
// Just get the column number and the new value and send them to anybody interested in filter changes
emit filterChanged(sender()->property("column").toUInt(), new_value);
}
void FilterTableHeader::addFilterAsCondFormat(const QString& filter)
{
// Just get the column number and the new value and send them to anybody interested in new conditional formatting
emit addCondFormat(sender()->property("column").toUInt(), filter);
}
void FilterTableHeader::clearAllCondFormats()
{
// Just get the column number and send it to anybody responsible or interested in clearing conditional formatting
emit allCondFormatsCleared(sender()->property("column").toUInt());
}
void FilterTableHeader::editCondFormats()
{
// Just get the column number and the new value and send them to anybody interested in editing conditional formatting
emit condFormatsEdited(sender()->property("column").toUInt());
}
void FilterTableHeader::clearFilters()
{
for(FilterLineEdit* filterLineEdit : filterWidgets)
filterLineEdit->clear();
}
void FilterTableHeader::setFilter(size_t column, const QString& value)
{
if(column < filterWidgets.size())
filterWidgets.at(column)->setText(value);
}
QString FilterTableHeader::filterValue(size_t column) const
{
return filterWidgets[column]->text();
}
void FilterTableHeader::setFocusColumn(size_t column)
{
if(column < filterWidgets.size())
filterWidgets.at(column)->setFocus();
}