diff --git a/libs/ui/widgets/kis_color_label_button.cpp b/libs/ui/widgets/kis_color_label_button.cpp index d31d856d63..7f97537e34 100644 --- a/libs/ui/widgets/kis_color_label_button.cpp +++ b/libs/ui/widgets/kis_color_label_button.cpp @@ -1,257 +1,261 @@ /* * Copyright (c) 2020 Eoin O'Neill * Copyright (c) 2020 Emmet O'Neill * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_color_label_button.h" #include #include #include #include "kis_global.h" #include "kis_debug.h" #include "krita_container_utils.h" struct KisColorLabelButton::Private { const QColor m_color; const uint m_sizeSquared; KisColorLabelButton::SelectionIndicationType selectionVis; Private(QColor color, uint sizeSquared) : m_color(color) , m_sizeSquared(sizeSquared) , selectionVis(KisColorLabelButton::FillIn) { } Private(const Private& rhs) : m_color(rhs.m_color) , m_sizeSquared(rhs.m_sizeSquared) { } }; KisColorLabelButton::KisColorLabelButton(QColor color, uint sizeSquared, QWidget *parent) : QAbstractButton(parent), m_d(new Private(color, sizeSquared)) { setCheckable(true); setChecked(true); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); } 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); QRect outlineRect = kisGrowRect(fillRect, -1); if (!isEnabled()) { fillRect -= QMargins(sizeHint().width() / 4, sizeHint().height() / 4, sizeHint().width() / 4, sizeHint().height() / 4); } else { fillRect = kisGrowRect(fillRect, -3); } fillRect.width(); if (m_d->m_color.alpha() > 0) { QColor fillColor = m_d->m_color; if ((!isChecked() || !isEnabled()) && (m_d->selectionVis == FillIn)) { fillColor.setAlpha(32); } QBrush brush = QBrush(fillColor); painter.fillRect(fillRect, brush); if ((isEnabled() && (m_d->selectionVis == FillIn)) || (isChecked() && (m_d->selectionVis == Outline))) { painter.setPen(QPen(m_d->m_color, 2)); painter.drawRect(outlineRect); } } 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() || !isEnabled()) { shade.setAlpha(64); } QPen pen = QPen(shade, 2); painter.setPen(pen); painter.drawLine(crossRect.topLeft(), crossRect.bottomRight()); painter.drawLine(crossRect.bottomLeft(), crossRect.topRight());*/ QColor white = QColor(255,255,255); QColor grey = QColor(200,200,200); QColor outlineColor = grey; if ((!isChecked() || !isEnabled()) && (m_d->selectionVis == FillIn)) { white.setAlpha(32); grey.setAlpha(32); } QBrush whiteBrush = QBrush(white); QBrush greyBrush = QBrush(grey); QRect upperLeftGrey = fillRect - QMargins(0, 0, fillRect.size().width() / 2, fillRect.size().height() /2); QRect lowerRightGrey = fillRect - QMargins(fillRect.size().width() / 2, fillRect.size().height() / 2, 0, 0); painter.fillRect(fillRect, whiteBrush); painter.fillRect(upperLeftGrey, greyBrush); painter.fillRect(lowerRightGrey, greyBrush); if ((isEnabled() && (m_d->selectionVis == FillIn)) || (isChecked() && (m_d->selectionVis == Outline))) { painter.setPen(QPen(outlineColor, 2)); painter.drawRect(outlineRect); } } } QSize KisColorLabelButton::sizeHint() const { return QSize(m_d->m_sizeSquared,m_d->m_sizeSquared); } void KisColorLabelButton::setSelectionVisType(KisColorLabelButton::SelectionIndicationType type) { m_d->selectionVis = type; } void KisColorLabelButton::nextCheckState() { KisColorLabelFilterGroup* colorLabelFilterGroup = dynamic_cast(group()); if (!colorLabelFilterGroup || (colorLabelFilterGroup->countCheckedViableButtons() > 1 || !isChecked())) { setChecked(!isChecked()); } else { setChecked(isChecked()); } } KisColorLabelFilterGroup::KisColorLabelFilterGroup(QObject *parent) : QButtonGroup(parent) { } KisColorLabelFilterGroup::~KisColorLabelFilterGroup() { } QList KisColorLabelFilterGroup::viableButtons() const { QList viableButtons; Q_FOREACH( int index, viableColorLabels ) { viableButtons.append(button(index)); } return viableButtons; } -void KisColorLabelFilterGroup::setViableLabels(QSet &labels) { +void KisColorLabelFilterGroup::setViableLabels(const QSet &labels) { setAllVisibility(false); disableAll(); QSet removed = viableColorLabels.subtract(labels); viableColorLabels = labels; if (viableColorLabels.count() > 1) { setAllVisibility(true); Q_FOREACH( int index, viableColorLabels) { if (button(index)) { button(index)->setEnabled(true); } } } Q_FOREACH( int index, removed ) { button(index)->setChecked(true); } } +void KisColorLabelFilterGroup::setViableLabels(const QList &viableLabels) { + setViableLabels(QSet::fromList(viableLabels)); +} + QSet KisColorLabelFilterGroup::getActiveLabels() const { QSet checkedLabels = QSet(); Q_FOREACH( int index, viableColorLabels ) { if (button(index)->isChecked()) { checkedLabels.insert(index); } } return checkedLabels.count() == viableColorLabels.count() ? QSet() : checkedLabels; } QList KisColorLabelFilterGroup::checkedViableButtons() const { QList checkedButtons = viableButtons(); KritaUtils::filterContainer(checkedButtons, [](QAbstractButton* btn){ return (btn->isChecked()); }); return checkedButtons; } int KisColorLabelFilterGroup::countCheckedViableButtons() const { return checkedViableButtons().count(); } int KisColorLabelFilterGroup::countViableButtons() const { return viableColorLabels.count(); } void KisColorLabelFilterGroup::reset() { Q_FOREACH( QAbstractButton* btn, viableButtons() ) { btn->setChecked(true); } } void KisColorLabelFilterGroup::disableAll() { Q_FOREACH( QAbstractButton* btn, buttons() ) { btn->setDisabled(true); } } void KisColorLabelFilterGroup::setAllVisibility(const bool vis) { Q_FOREACH( QAbstractButton* btn, buttons() ) { btn->setVisible(vis); } } diff --git a/libs/ui/widgets/kis_color_label_button.h b/libs/ui/widgets/kis_color_label_button.h index fc50131e18..5f4b6f9033 100644 --- a/libs/ui/widgets/kis_color_label_button.h +++ b/libs/ui/widgets/kis_color_label_button.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2020 Eoin O'Neill * Copyright (c) 2020 Emmet O'Neill * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KISCOLORLABELBUTTON_H #define KISCOLORLABELBUTTON_H #include #include #include #include "kritaui_export.h" class KRITAUI_EXPORT KisColorLabelButton : public QAbstractButton { Q_OBJECT public: enum SelectionIndicationType { FillIn, Outline }; KisColorLabelButton(QColor color, uint sizeSquared = 32, QWidget *parent = nullptr); ~KisColorLabelButton(); void paintEvent(QPaintEvent* event) override; QSize sizeHint() const override; void setSelectionVisType( SelectionIndicationType type ); virtual void nextCheckState() override; private: struct Private; const QScopedPointer m_d; }; class KRITAUI_EXPORT KisColorLabelFilterGroup : public QButtonGroup { Q_OBJECT public: KisColorLabelFilterGroup(QObject* parent); ~KisColorLabelFilterGroup(); QList viableButtons() const; - void setViableLabels(QSet &buttons); + void setViableLabels(const QSet &buttons); + void setViableLabels(const QList &viableLabels); QSet getActiveLabels() const; QList checkedViableButtons() const; int countCheckedViableButtons() const; int countViableButtons() const; void reset(); - + void setAllVisibility(const bool vis); private: void disableAll(); - void setAllVisibility(const bool vis); QSet viableColorLabels; }; #endif // KISCOLORLABELBUTTON_H diff --git a/libs/ui/widgets/kis_layer_filter_widget.cpp b/libs/ui/widgets/kis_layer_filter_widget.cpp index 8c29b0a17d..a66878ef22 100644 --- a/libs/ui/widgets/kis_layer_filter_widget.cpp +++ b/libs/ui/widgets/kis_layer_filter_widget.cpp @@ -1,299 +1,298 @@ /* * Copyright (c) 2020 Eoin O'Neill * Copyright (c) 2020 Emmet O'Neill * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_layer_filter_widget.h" #include #include #include #include #include #include #include #include #include #include #include "kis_debug.h" #include "kis_node.h" #include "kis_global.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); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); textFilter = new QLineEdit(this); textFilter->setPlaceholderText(i18n("Filter by name...")); textFilter->setMinimumWidth(192); textFilter->setMinimumHeight(32); textFilter->setClearButtonEnabled(true); connect(textFilter, SIGNAL(textChanged(QString)), this, SIGNAL(filteringOptionsChanged())); KisNodeViewColorScheme colorScheme; QWidget *buttonContainer = new QWidget(this); buttonContainer->setToolTip(i18n("Filter by color label...")); buttonEventFilter = new EventFilter(buttonContainer); { QHBoxLayout *subLayout = new QHBoxLayout(buttonContainer); buttonContainer->setLayout(subLayout); subLayout->setContentsMargins(0,0,0,0); //subLayout->setAlignment(Qt::AlignLeft); ENTER_FUNCTION() << ppVar(subLayout->alignment()); buttonGroup = new KisColorLabelFilterGroup(buttonContainer); buttonGroup->setExclusive(false); QVector colors = colorScheme.allColorLabels(); for (int id = 0; id < colors.count(); id++) { KisColorLabelButton* btn = new KisColorLabelButton(colors[id], 32, buttonContainer); buttonGroup->addButton(btn, id); btn->installEventFilter(buttonEventFilter); subLayout->addWidget(btn); } connect(buttonGroup, SIGNAL(buttonToggled(int,bool)), this, SIGNAL(filteringOptionsChanged())); } resetButton = new QPushButton(i18n("Reset Filters"), this); resetButton->setMinimumHeight(32); connect(resetButton, &QPushButton::clicked, [this](){ this->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); buttonGroup->setViableLabels(colorLabels); } bool KisLayerFilterWidget::isCurrentlyFiltering() const { const bool isFilteringText = !textFilter->text().isEmpty(); const bool isFilteringColors = buttonGroup->getActiveLabels().count() > 0; return isFilteringText || isFilteringColors; } QSet KisLayerFilterWidget::getActiveColors() const { QSet activeColors = buttonGroup->getActiveLabels(); return activeColors; } QString KisLayerFilterWidget::getTextFilter() const { return textFilter->text(); } int KisLayerFilterWidget::getDesiredMinimumWidth() const { return qMax(textFilter->minimumWidth(), buttonGroup->countViableButtons() * 32); } int KisLayerFilterWidget::getDesiredMinimumHeight() const { QList viableButtons = buttonGroup->viableButtons(); if (viableButtons.count() > 1) { return viableButtons[0]->sizeHint().height() + textFilter->minimumHeight() + resetButton->minimumHeight(); } else { return textFilter->minimumHeight() + resetButton->minimumHeight(); } } void KisLayerFilterWidget::reset() { textFilter->clear(); buttonGroup->reset(); filteringOptionsChanged(); } QSize KisLayerFilterWidget::sizeHint() const { return QSize(getDesiredMinimumWidth(), getDesiredMinimumHeight()); } void KisLayerFilterWidget::showEvent(QShowEvent *show) { QMenu *parentMenu = dynamic_cast(parentWidget()); if (parentMenu) { const int widthBefore = parentMenu->width(); const int rightEdgeThreshold = 5; //Fake resize event needs to be made to register change in widget menu size. //Not doing this will cause QMenu to not resize properly! resize(sizeHint()); adjustSize(); QResizeEvent event = QResizeEvent(sizeHint(), parentMenu->size()); parentMenu->resize(sizeHint()); parentMenu->adjustSize(); qApp->sendEvent(parentMenu, &event); QScreen *screen = QGuiApplication::screenAt(parentMenu->mapToGlobal(parentMenu->pos())); QRect screenGeometry = screen ? screen->geometry() : parentMenu->parentWidget()->window()->geometry(); const bool onRightEdge = (parentMenu->pos().x() + widthBefore + rightEdgeThreshold) > screenGeometry.width(); const int widthAfter = parentMenu->width(); if (onRightEdge) { if (widthAfter > widthBefore) { const QRect newGeo = kisEnsureInRect( parentMenu->geometry(), screenGeometry ); const int xShift = newGeo.x() - parentMenu->pos().x(); parentMenu->move(parentMenu->pos().x() + xShift, parentMenu->pos().y() + 0); } else { const int xShift = widthBefore - widthAfter; parentMenu->move(parentMenu->pos().x() + xShift, parentMenu->pos().y() + 0); } } } QWidget::showEvent(show); } -KisLayerFilterWidget::EventFilter::EventFilter(QWidget *buttonContainer, QObject* parent) : QObject(parent) +KisLayerFilterWidget::EventFilter::EventFilter(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); QAbstractButton* startingButton = static_cast(obj); //If we never left, toggle the original button. if( currentState == WaitingForDragLeave ) { if ( startingButton->group() && (mouseEvent->modifiers() & Qt::SHIFT)) { KisColorLabelFilterGroup* const group = static_cast(startingButton->group()); const QList viableCheckedButtons = group->checkedViableButtons(); const int buttonsEnabled = viableCheckedButtons.count(); const bool shouldChangeIsolation = (buttonsEnabled == 1) && (viableCheckedButtons.first() == startingButton); const bool shouldIsolate = (buttonsEnabled != 1) || !shouldChangeIsolation; Q_FOREACH(QAbstractButton* otherBtn, group->viableButtons()) { if (otherBtn == startingButton){ startingButton->setChecked(true); } else { otherBtn->setChecked(!shouldIsolate); } } } else { startingButton->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 QPoint upperLeft = QPoint(qMin(lastKnownMousePosition.x(), currentPosition.x()), qMin(lastKnownMousePosition.y(), currentPosition.y())); const QPoint lowerRight = QPoint(qMax(lastKnownMousePosition.x(), currentPosition.x()), qMax(lastKnownMousePosition.y(), currentPosition.y())); const QRect mouseMovement = QRect(upperLeft, lowerRight); 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 f4d60aa635..8d35b071fd 100644 --- a/libs/ui/widgets/kis_layer_filter_widget.h +++ b/libs/ui/widgets/kis_layer_filter_widget.h @@ -1,86 +1,83 @@ /* * Copyright (c) 2020 Eoin O'Neill * Copyright (c) 2020 Emmet O'Neill * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #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); + EventFilter(QObject *parent = nullptr); protected: bool eventFilter(QObject *obj, QEvent *event); void checkSlideOverNeighborButtons(QMouseEvent* mouseEvent, class QAbstractButton* startingButton); }; EventFilter *buttonEventFilter; class QLineEdit *textFilter; class KisColorLabelFilterGroup *buttonGroup; class QPushButton *resetButton; public: KisLayerFilterWidget(QWidget *parent = nullptr); static void scanUsedColorLabels(KisNodeSP node, QSet &colorLabels); void updateColorLabels(KisNodeSP root); bool isCurrentlyFiltering() const; QSet getActiveColors() const; QString getTextFilter() const; int getDesiredMinimumWidth() const; int getDesiredMinimumHeight() const; void reset(); QSize sizeHint() const override; /* Show Event has to be overridden to * correct for issues where QMenu isn't * correctly resizing. */ void showEvent(QShowEvent *show) override; Q_SIGNALS: void filteringOptionsChanged(); }; #endif // KISLAYERFILTERWIDGET_H diff --git a/plugins/dockers/animation/onion_skins_docker.cpp b/plugins/dockers/animation/onion_skins_docker.cpp index 309c68c67b..e0cb50c8b7 100644 --- a/plugins/dockers/animation/onion_skins_docker.cpp +++ b/plugins/dockers/animation/onion_skins_docker.cpp @@ -1,271 +1,231 @@ /* * Copyright (c) 2015 Jouni Pentikäinen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "onion_skins_docker.h" #include "ui_onion_skins_docker.h" #include #include #include #include "kis_icon_utils.h" #include "kis_image_config.h" #include "kis_onion_skin_compositor.h" #include "kis_signals_blocker.h" #include "kis_node_view_color_scheme.h" #include "KisViewManager.h" #include "kis_action_manager.h" #include "kis_action.h" #include #include "kis_equalizer_widget.h" +#include "kis_color_label_button.h" OnionSkinsDocker::OnionSkinsDocker(QWidget *parent) : QDockWidget(i18n("Onion Skins"), parent), ui(new Ui::OnionSkinsDocker), m_updatesCompressor(300, KisSignalCompressor::FIRST_ACTIVE), m_toggleOnionSkinsAction(0) { QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); KisImageConfig config(true); ui->setupUi(mainWidget); mainWidget->setContentsMargins(10, 10, 10, 10); ui->doubleTintFactor->setMinimum(0); ui->doubleTintFactor->setMaximum(100); ui->doubleTintFactor->setPrefix(i18n("Tint: ")); ui->doubleTintFactor->setSuffix(i18n("%")); ui->btnBackwardColor->setToolTip(i18n("Tint color for past frames")); ui->btnForwardColor->setToolTip(i18n("Tint color for future frames")); QVBoxLayout *layout = ui->slidersLayout; m_equalizerWidget = new KisEqualizerWidget(10, this); connect(m_equalizerWidget, SIGNAL(sigConfigChanged()), &m_updatesCompressor, SLOT(start())); layout->addWidget(m_equalizerWidget, 1); connect(ui->btnBackwardColor, SIGNAL(changed(KoColor)), &m_updatesCompressor, SLOT(start())); connect(ui->btnForwardColor, SIGNAL(changed(KoColor)), &m_updatesCompressor, SLOT(start())); connect(ui->doubleTintFactor, SIGNAL(valueChanged(qreal)), &m_updatesCompressor, SLOT(start())); connect(&m_updatesCompressor, SIGNAL(timeout()), SLOT(changed())); { const bool isShown = config.showAdditionalOnionSkinsSettings(); ui->btnShowHide->setChecked(isShown); connect(ui->btnShowHide, SIGNAL(toggled(bool)), SLOT(slotShowAdditionalSettings(bool))); slotShowAdditionalSettings(isShown); } - // create colored checkboxes for onion skin filtering - KisNodeViewColorScheme scm; - QPalette filterColorPalette; - QPixmap iconPixmap(10, 10); - - //iconPixmap.fill(scm.colorLabel(0)); - //ui->colorFilter0_checkbox->setIcon(iconPixmap); // default(no) color - - iconPixmap.fill(scm.colorLabel(1)); - ui->colorFilter1_checkbox->setIcon(QIcon(iconPixmap)); - - iconPixmap.fill(scm.colorLabel(2)); - ui->colorFilter2_checkbox->setIcon(QIcon(iconPixmap)); - - iconPixmap.fill(scm.colorLabel(3)); - ui->colorFilter3_checkbox->setIcon(QIcon(iconPixmap)); - - iconPixmap.fill(scm.colorLabel(4)); - ui->colorFilter4_checkbox->setIcon(QIcon(iconPixmap)); - - iconPixmap.fill(scm.colorLabel(5)); - ui->colorFilter5_checkbox->setIcon(QIcon(iconPixmap)); - - iconPixmap.fill(scm.colorLabel(6)); - ui->colorFilter6_checkbox->setIcon(QIcon(iconPixmap)); - - iconPixmap.fill(scm.colorLabel(7)); - ui->colorFilter7_checkbox->setIcon(QIcon(iconPixmap)); - - iconPixmap.fill(scm.colorLabel(8)); - ui->colorFilter8_checkbox->setIcon(QIcon(iconPixmap)); - - - // assign click events to color filters and group checkbox - connect(ui->colorFilter0_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter1_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter2_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter3_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter4_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter5_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter6_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter7_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilter8_checkbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); - connect(ui->colorFilterGroupbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); + { + KisNodeViewColorScheme scm; + m_filterButtonGroup = new KisColorLabelFilterGroup(this); + m_filterButtonGroup->setExclusive(false); + QWidget* filterButtonContainer = ui->colorFilterGroupbox; + QLayout* filterButtonLayout = ui->filterButtons; + QVector availableColors = scm.allColorLabels(); + QSet viableColors; + for (int i = 0; i < availableColors.count(); i++) { + KisColorLabelButton* colorLabelButton = new KisColorLabelButton(availableColors[i], 24, filterButtonContainer); + filterButtonLayout->addWidget(colorLabelButton); + m_filterButtonGroup->addButton(colorLabelButton, i); + viableColors << i; + } + + m_filterButtonGroup->setViableLabels(viableColors); + + connect(m_filterButtonGroup, SIGNAL(buttonToggled(int,bool)), this, SLOT(slotFilteredColorsChanged())); + connect(ui->colorFilterGroupbox, SIGNAL(toggled(bool)), this, SLOT(slotFilteredColorsChanged())); + } loadSettings(); KisOnionSkinCompositor::instance()->configChanged(); // this mostly hides the checkboxes since no filtering is done by default slotFilteredColorsChanged(); resize(sizeHint()); } OnionSkinsDocker::~OnionSkinsDocker() { delete ui; } void OnionSkinsDocker::setCanvas(KoCanvasBase *canvas) { Q_UNUSED(canvas); } void OnionSkinsDocker::unsetCanvas() { } void OnionSkinsDocker::setViewManager(KisViewManager *view) { KisActionManager *actionManager = view->actionManager(); m_toggleOnionSkinsAction = actionManager->createAction("toggle_onion_skin"); connect(m_toggleOnionSkinsAction, SIGNAL(triggered()), SLOT(slotToggleOnionSkins())); slotUpdateIcons(); connect(view->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateIcons())); } void OnionSkinsDocker::slotToggleOnionSkins() { m_equalizerWidget->toggleMasterSwitch(); } void OnionSkinsDocker::slotFilteredColorsChanged() { // what colors are selected to filter?? - QList selectedFilterColors; - - if (ui->colorFilter0_checkbox->isChecked()) selectedFilterColors << 0; - if (ui->colorFilter1_checkbox->isChecked()) selectedFilterColors << 1; - if (ui->colorFilter2_checkbox->isChecked()) selectedFilterColors << 2; - if (ui->colorFilter3_checkbox->isChecked()) selectedFilterColors << 3; - if (ui->colorFilter4_checkbox->isChecked()) selectedFilterColors << 4; - if (ui->colorFilter5_checkbox->isChecked()) selectedFilterColors << 5; - if (ui->colorFilter6_checkbox->isChecked()) selectedFilterColors << 6; - if (ui->colorFilter7_checkbox->isChecked()) selectedFilterColors << 7; - if (ui->colorFilter8_checkbox->isChecked()) selectedFilterColors << 8; + QSet selectedFilterColors = m_filterButtonGroup->getActiveLabels(); // show all colors if the filter is off and ignore the checkboxes if(ui->colorFilterGroupbox->isChecked() == false) { selectedFilterColors.clear(); selectedFilterColors << 0 << 1 << 2 << 3 << 4 << 5 << 6 << 7 << 8; // show everything } - ui->colorFilter0_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter1_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter2_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter3_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter4_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter5_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter6_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter7_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); - ui->colorFilter8_checkbox->setVisible(ui->colorFilterGroupbox->isChecked()); + m_filterButtonGroup->setAllVisibility(ui->colorFilterGroupbox->isChecked()); + ui->resetFilter->setVisible(ui->colorFilterGroupbox->isChecked()); // existing code - KisOnionSkinCompositor::instance()->setColorLabelFilter(selectedFilterColors); + KisOnionSkinCompositor::instance()->setColorLabelFilter(QList::fromSet(selectedFilterColors)); KisOnionSkinCompositor::instance()->configChanged(); } void OnionSkinsDocker::slotUpdateIcons() { if (m_toggleOnionSkinsAction) { m_toggleOnionSkinsAction->setIcon(KisIconUtils::loadIcon("onion_skin_options")); } } void OnionSkinsDocker::slotShowAdditionalSettings(bool value) { ui->lblPrevColor->setVisible(value); ui->lblNextColor->setVisible(value); ui->btnBackwardColor->setVisible(value); ui->btnForwardColor->setVisible(value); ui->doubleTintFactor->setVisible(value); QIcon icon = KisIconUtils::loadIcon(value ? "arrow-down" : "arrow-up"); ui->btnShowHide->setIcon(icon); KisImageConfig(false).setShowAdditionalOnionSkinsSettings(value); } void OnionSkinsDocker::changed() { KisImageConfig config(false); KisEqualizerWidget::EqualizerValues v = m_equalizerWidget->getValues(); config.setNumberOfOnionSkins(v.maxDistance); for (int i = -v.maxDistance; i <= v.maxDistance; i++) { config.setOnionSkinOpacity(i, v.value[i] * 255.0 / 100.0); config.setOnionSkinState(i, v.state[i]); } config.setOnionSkinTintFactor(ui->doubleTintFactor->value() * 255.0 / 100.0); config.setOnionSkinTintColorBackward(ui->btnBackwardColor->color().toQColor()); config.setOnionSkinTintColorForward(ui->btnForwardColor->color().toQColor()); KisOnionSkinCompositor::instance()->configChanged(); } void OnionSkinsDocker::loadSettings() { KisImageConfig config(true); KisSignalsBlocker b(ui->doubleTintFactor, ui->btnBackwardColor, ui->btnForwardColor, m_equalizerWidget); ui->doubleTintFactor->setValue(qRound(config.onionSkinTintFactor() * 100.0 / 255)); KoColor bcol(KoColorSpaceRegistry::instance()->rgb8()); bcol.fromQColor(config.onionSkinTintColorBackward()); ui->btnBackwardColor->setColor(bcol); bcol.fromQColor(config.onionSkinTintColorForward()); ui->btnForwardColor->setColor(bcol); KisEqualizerWidget::EqualizerValues v; v.maxDistance = 10; for (int i = -v.maxDistance; i <= v.maxDistance; i++) { v.value.insert(i, qRound(config.onionSkinOpacity(i) * 100.0 / 255.0)); v.state.insert(i, config.onionSkinState(i)); } m_equalizerWidget->setValues(v); } diff --git a/plugins/dockers/animation/onion_skins_docker.h b/plugins/dockers/animation/onion_skins_docker.h index 7d7785abc3..5c5c60cb5e 100644 --- a/plugins/dockers/animation/onion_skins_docker.h +++ b/plugins/dockers/animation/onion_skins_docker.h @@ -1,66 +1,68 @@ /* * Copyright (c) 2015 Jouni Pentikäinen * * 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef ONION_SKINS_DOCKER_H #define ONION_SKINS_DOCKER_H #include #include #include "kis_signal_compressor.h" class KisAction; namespace Ui { class OnionSkinsDocker; } class KisEqualizerWidget; class OnionSkinsDocker : public QDockWidget, public KisMainwindowObserver { Q_OBJECT public: explicit OnionSkinsDocker(QWidget *parent = 0); ~OnionSkinsDocker() override; QString observerName() override { return "OnionSkinsDocker"; } void setCanvas(KoCanvasBase *canvas) override; void unsetCanvas() override; void setViewManager(KisViewManager *kisview) override; private: Ui::OnionSkinsDocker *ui; KisSignalCompressor m_updatesCompressor; KisEqualizerWidget *m_equalizerWidget; KisAction *m_toggleOnionSkinsAction; + class KisColorLabelFilterGroup *m_filterButtonGroup; + private: void loadSettings(); private Q_SLOTS: void changed(); void slotShowAdditionalSettings(bool value); void slotUpdateIcons(); void slotToggleOnionSkins(); void slotFilteredColorsChanged(); }; #endif // ONION_SKINS_DOCKER_H diff --git a/plugins/dockers/animation/onion_skins_docker.ui b/plugins/dockers/animation/onion_skins_docker.ui index e16b4003d5..6adb25ea2a 100644 --- a/plugins/dockers/animation/onion_skins_docker.ui +++ b/plugins/dockers/animation/onion_skins_docker.ui @@ -1,258 +1,199 @@ OnionSkinsDocker 0 0 336 282 false Onion skin options 12 12 12 12 0 0 0 Filter Frames by Color true false 4 0 0 0 0 - - + + - 0 - 0 + 80 + 16777215 - None - - - - 16 - 16 - + Reset Filter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + 6 Qt::Horizontal + true false true 50 0 Previous frames Qt::Horizontal 13 13 Next frames KisDoubleSliderSpinBox QWidget
kis_slider_spin_box.h
1
KisColorButton QPushButton
kis_color_button.h