diff --git a/libs/ui/widgets/kis_color_label_button.cpp b/libs/ui/widgets/kis_color_label_button.cpp index 0ca3eb5d2e..1e47e781cb 100644 --- a/libs/ui/widgets/kis_color_label_button.cpp +++ b/libs/ui/widgets/kis_color_label_button.cpp @@ -1,104 +1,111 @@ #include "kis_color_label_button.h" #include #include #include #include "kis_global.h" #include "kis_debug.h" struct KisColorLabelButton::Private { QColor color; }; KisColorLabelButton::KisColorLabelButton(QColor color, QWidget *parent) : QAbstractButton(parent), m_d(new Private()) { setCheckable(true); setChecked(true); m_d->color = color; } KisColorLabelButton::~KisColorLabelButton() { } void KisColorLabelButton::paintEvent(QPaintEvent *event) { QWidget::paintEvent(event); QStylePainter painter(this); QStyleOption styleOption; styleOption.initFrom(this); if (isDown() || isChecked()){ styleOption.state |= QStyle::State_On; } // Draw fill.. QRect fillRect = kisGrowRect(rect(), -2); fillRect.width(); if (m_d->color.alpha() > 0) { QColor fillColor = m_d->color; if (!isChecked()) { fillColor.setAlpha(32); } painter.fillRect(fillRect, fillColor); } else { // draw an X for no color for the first item const int shortestEdge = std::min(fillRect.width(), fillRect.height()); const int longestEdge = std::max(fillRect.width(), fillRect.height()); bool horizontalIsShortest = (shortestEdge == fillRect.width()); QRect srcRect = horizontalIsShortest ? fillRect.adjusted(0, (longestEdge / 2) - (shortestEdge / 2), 0, (shortestEdge / 2) - (longestEdge / 2)) : fillRect.adjusted((longestEdge / 2) - (shortestEdge / 2), 0, (shortestEdge / 2) - (longestEdge / 2), 0); QRect crossRect = kisGrowRect(srcRect, -1); QColor shade = styleOption.palette.text().color(); if (!isChecked()) { shade.setAlpha(64); } painter.setPen(QPen(shade, 2)); painter.drawLine(crossRect.topLeft(), crossRect.bottomRight()); painter.drawLine(crossRect.bottomLeft(), crossRect.topRight()); } } QSize KisColorLabelButton::sizeHint() const { return QSize(16,32); } void KisColorLabelButton::nextCheckState() { KisColorLabelButtonGroup* colorLabelButtonGroup = dynamic_cast(group()); if (colorLabelButtonGroup && (colorLabelButtonGroup->viableButtonsChecked() > 1 || !isChecked())) { setChecked(!isChecked()); } else { setChecked(isChecked()); } } KisColorLabelButtonGroup::KisColorLabelButtonGroup(QObject *parent) : QButtonGroup(parent) { connect(this, SIGNAL(buttonToggled(QAbstractButton*,bool)), this, SLOT(slotRegisterButtonState(QAbstractButton*,bool))); } KisColorLabelButtonGroup::~KisColorLabelButtonGroup() { } int KisColorLabelButtonGroup::viableButtonsChecked() { int count = 0; Q_FOREACH( QAbstractButton* btn, buttons()) { count += (btn->isVisible() && btn->isChecked()) ? 1 : 0; } return count; } + +void KisColorLabelButtonGroup::reset() +{ + Q_FOREACH( QAbstractButton* btn, buttons()) { + btn->setChecked(true); + } +} diff --git a/libs/ui/widgets/kis_color_label_button.h b/libs/ui/widgets/kis_color_label_button.h index efc9ccf1bb..6914b4233f 100644 --- a/libs/ui/widgets/kis_color_label_button.h +++ b/libs/ui/widgets/kis_color_label_button.h @@ -1,39 +1,41 @@ #ifndef KISCOLORLABELBUTTON_H #define KISCOLORLABELBUTTON_H #include #include #include "kritaui_export.h" class KRITAUI_EXPORT KisColorLabelButton : public QAbstractButton { Q_OBJECT public: KisColorLabelButton(QColor color, QWidget *parent = nullptr); ~KisColorLabelButton(); void paintEvent(QPaintEvent* event) override; QSize sizeHint() const override; virtual void nextCheckState() override; Q_SIGNALS: void visibilityChanged(QAbstractButton* btn, bool isVisible); private: struct Private; const QScopedPointer m_d; }; class KRITAUI_EXPORT KisColorLabelButtonGroup : public QButtonGroup { Q_OBJECT public: KisColorLabelButtonGroup(QObject* parent); ~KisColorLabelButtonGroup(); int viableButtonsChecked(); + void reset(); + }; #endif // KISCOLORLABELBUTTON_H diff --git a/libs/ui/widgets/kis_layer_filter_widget.cpp b/libs/ui/widgets/kis_layer_filter_widget.cpp index 48282281cf..93067b137c 100644 --- a/libs/ui/widgets/kis_layer_filter_widget.cpp +++ b/libs/ui/widgets/kis_layer_filter_widget.cpp @@ -1,215 +1,225 @@ #include "kis_layer_filter_widget.h" #include #include #include #include #include #include +#include #include "kis_debug.h" #include "kis_node.h" #include "kis_color_label_button.h" #include "kis_color_label_selector_widget.h" #include "kis_node_view_color_scheme.h" KisLayerFilterWidget::KisLayerFilterWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *layout = new QVBoxLayout(this); setLayout(layout); textFilter = new QLineEdit(this); textFilter->setPlaceholderText("Filter by name..."); textFilter->setMinimumWidth(256); textFilter->setMinimumHeight(32); textFilter->setClearButtonEnabled(true); connect(textFilter, SIGNAL(textChanged(QString)), this, SIGNAL(filteringOptionsChanged())); KisNodeViewColorScheme colorScheme; QWidget *buttonContainer = new QWidget(this); + buttonContainer->setToolTip("Filter by color label..."); buttonEventFilter = new EventFilter(buttonContainer); { QHBoxLayout *subLayout = new QHBoxLayout(buttonContainer); buttonContainer->setLayout(subLayout); subLayout->setContentsMargins(0,0,0,0); - KisColorLabelButtonGroup *btnGroup = new KisColorLabelButtonGroup(buttonContainer); - btnGroup->setExclusive(false); + buttonGroup = new KisColorLabelButtonGroup(buttonContainer); + buttonGroup->setExclusive(false); foreach (const QColor &color, colorScheme.allColorLabels()) { KisColorLabelButton* btn = new KisColorLabelButton(color, buttonContainer); - btnGroup->addButton(btn); + buttonGroup->addButton(btn); btn->setVisible(false); btn->installEventFilter(buttonEventFilter); subLayout->addWidget(btn); colorLabelButtons.append(btn); } - connect(btnGroup, SIGNAL(buttonToggled(int,bool)), this, SIGNAL(filteringOptionsChanged())); + connect(buttonGroup, SIGNAL(buttonToggled(int,bool)), this, SIGNAL(filteringOptionsChanged())); } + QPushButton *resetButton = new QPushButton("Reset Filters", this); + connect(resetButton, &QPushButton::clicked, [this](){ + textFilter->clear(); + buttonGroup->reset(); + }); + + layout->addWidget(textFilter); layout->addWidget(buttonContainer); + layout->addWidget(resetButton); } void KisLayerFilterWidget::scanUsedColorLabels(KisNodeSP node, QSet &colorLabels) { if (node->parent()) { colorLabels.insert(node->colorLabelIndex()); } KisNodeSP child = node->firstChild(); while(child) { scanUsedColorLabels(child, colorLabels); child = child->nextSibling(); } } void KisLayerFilterWidget::updateColorLabels(KisNodeSP root) { QSet colorLabels; scanUsedColorLabels(root, colorLabels); if (colorLabels.size() > 1) { colorLabelButtons[0]->parentWidget()->setVisible(true); for (size_t index = 0; index < colorLabelButtons.size(); index++) { if (colorLabels.contains(index)) { colorLabelButtons[index]->setVisible(true); } else { colorLabelButtons[index]->setVisible(false); colorLabelButtons[index]->setChecked(true); } } } else { colorLabelButtons[0]->parentWidget()->setVisible(false); } } bool KisLayerFilterWidget::isCurrentlyFiltering() { const bool isFilteringText = !textFilter->text().isEmpty(); bool isFilteringColors = false; for (int index = 0; index < colorLabelButtons.size(); index++) { if (colorLabelButtons[index]->isVisible() && !colorLabelButtons[index]->isChecked()) { isFilteringColors = true; } } return isFilteringText || isFilteringColors; } QList KisLayerFilterWidget::getActiveColors() { QList activeColors; for (int index = 0; index < colorLabelButtons.size(); index++) { if (!colorLabelButtons[index]->isVisible() || colorLabelButtons[index]->isChecked()) { activeColors.append(index); } } return activeColors; } QString KisLayerFilterWidget::getTextFilter() { return textFilter->text(); } void KisLayerFilterWidget::reset() { textFilter->clear(); for (int index = 0; index < colorLabelButtons.size(); index++) { colorLabelButtons[index]->setChecked(true); } filteringOptionsChanged(); } KisLayerFilterWidget::EventFilter::EventFilter(QWidget *buttonContainer, QObject* parent) : QObject(parent) { m_buttonContainer = buttonContainer; lastKnownMousePosition = QPoint(0,0); currentState = Idle; } bool KisLayerFilterWidget::EventFilter::eventFilter(QObject *obj, QEvent *event) { if (event->type() == QEvent::MouseButtonPress) { QMouseEvent* mouseEvent = static_cast(event); currentState = WaitingForDragLeave; lastKnownMousePosition = mouseEvent->globalPos(); return true; } else if (event->type() == QEvent::MouseButtonRelease) { QMouseEvent* mouseEvent = static_cast(event); //If we never left, toggle the original button. if( currentState == WaitingForDragLeave ) { QAbstractButton* btn = static_cast(obj); btn->click(); } currentState = Idle; lastKnownMousePosition = mouseEvent->globalPos(); return true; } else if (event->type() == QEvent::MouseMove ) { if (currentState == WaitingForDragLeave) { QMouseEvent* mouseEvent = static_cast(event); QWidget* firstClicked = static_cast(obj); const QPointF localPosition = mouseEvent->localPos(); if (!firstClicked->rect().contains(localPosition.x(), localPosition.y())) { QAbstractButton* btn = static_cast(obj); btn->click(); checkSlideOverNeighborButtons(mouseEvent, btn); currentState = WaitingForDragEnter; } lastKnownMousePosition = mouseEvent->globalPos(); return true; } else if (currentState == WaitingForDragEnter) { QMouseEvent* mouseEvent = static_cast(event); QAbstractButton* startingButton = static_cast(obj); const QPoint currentPosition = mouseEvent->globalPos(); checkSlideOverNeighborButtons(mouseEvent, startingButton); lastKnownMousePosition = currentPosition; return true; } } return false; } void KisLayerFilterWidget::EventFilter::checkSlideOverNeighborButtons(QMouseEvent* mouseEvent, QAbstractButton* startingButton) { const QPoint currentPosition = mouseEvent->globalPos(); if (startingButton->group()) { QList allButtons = startingButton->group()->buttons(); Q_FOREACH(QAbstractButton* button, allButtons) { const QRect bounds = QRect(button->mapToGlobal(QPoint(0,0)), button->size()); const QRect mouseMovement = QRect(lastKnownMousePosition, currentPosition); if( bounds.intersects(mouseMovement) && !bounds.contains(lastKnownMousePosition)) { button->click(); } } } } diff --git a/libs/ui/widgets/kis_layer_filter_widget.h b/libs/ui/widgets/kis_layer_filter_widget.h index cc32b7e646..9b02b55953 100644 --- a/libs/ui/widgets/kis_layer_filter_widget.h +++ b/libs/ui/widgets/kis_layer_filter_widget.h @@ -1,58 +1,59 @@ #ifndef KISLAYERFILTERWIDGET_H #define KISLAYERFILTERWIDGET_H #include #include "kis_types.h" #include "kritaui_export.h" class KRITAUI_EXPORT KisLayerFilterWidget : public QWidget { Q_OBJECT private: class EventFilter : public QObject { private: QWidget* m_buttonContainer; enum State{ Idle, WaitingForDragLeave, //Waiting for mouse to exit first clicked while the mouse button is down. WaitingForDragEnter //Waiting for mouse to slide across buttons within the same button group. }; State currentState; QPoint lastKnownMousePosition; public: EventFilter(QWidget *buttonContainer, QObject *parent = nullptr); protected: bool eventFilter(QObject *obj, QEvent *event); void checkSlideOverNeighborButtons(QMouseEvent* mouseEvent, class QAbstractButton* startingButton); }; EventFilter *buttonEventFilter; class QLineEdit *textFilter; + class KisColorLabelButtonGroup *buttonGroup; QList colorLabelButtons; public: KisLayerFilterWidget(QWidget *parent = nullptr); static void scanUsedColorLabels(KisNodeSP node, QSet &colorLabels); void updateColorLabels(KisNodeSP root); bool isCurrentlyFiltering(); QList getActiveColors(); QString getTextFilter(); void reset(); Q_SIGNALS: void filteringOptionsChanged(); }; #endif // KISLAYERFILTERWIDGET_H