#include "FilterTableHeader.h" #include "FilterLineEdit.h" #include #include #include 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(filterWidgets.size()); ++i) { // Get the current widget, move it and resize it QWidget* w = filterWidgets.at(static_cast(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(); }