diff --git a/libs/ui/forms/wdgpaintopsettings.ui b/libs/ui/forms/wdgpaintopsettings.ui
index ce8e23366f..3eedff072b 100644
--- a/libs/ui/forms/wdgpaintopsettings.ui
+++ b/libs/ui/forms/wdgpaintopsettings.ui
@@ -1,750 +1,765 @@
WdgPaintOpSettings
0
0
- 1313
+ 1250
436
+
+
+ 0
+ 0
+
+
Brush Editor
-
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
-
-
0
0
Presets
-
-
0
0
Engine:
-
0
0
-
0
0
-
0
0
0
120
1677215
1677215
-
-
22
22
-
Qt::Horizontal
5
- 10
+ 5
-
0
0
0
0
22
22
false
false
-
0
-
6
-
0
0
30
30
30
30
QFrame::Box
QFrame::Sunken
true
-
0
0
10
75
true
current brush
-
0
0
30
30
30
30
true
-
0
0
26
26
26
- 26
+ 16777215
-
+
+
+ 0
+ 0
+
+
- 180
+ 10
0
-
0
0
16777215
- 28
+ 16777215
Save
-
0
0
16777215
- 28
+ 16777215
Cancel
-
Qt::Horizontal
- 148
- 56
+ 5
+ 5
-
0
0
26
26
QFrame::NoFrame
QFrame::Plain
-
-
+
0
0
Current Brush Engine
-
...
-
7
-
0
0
- 600
- 80
+ 0
+ 0
600
80
false
Qt::DefaultContextMenu
QFrame::StyledPanel
QFrame::Raised
0
Qt::ScrollBarAlwaysOff
Qt::ScrollBarAlwaysOff
true
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
QPainter::Antialiasing|QPainter::HighQualityAntialiasing|QPainter::SmoothPixmapTransform
QGraphicsView::AnchorViewCenter
-
0
4
100
0
QFrame::NoFrame
QFrame::Plain
0
-
5
5
0
5
5
-
-
-
+
0
0
60
0
-
Qt::Horizontal
+
+ QSizePolicy::Minimum
+
- 40
- 20
+ 5
+ 5
-
8
-
-
+
0
0
16777215
28
Overwrite Brush
-
-
+
0
0
16777215
28
Save New Brush Preset...
-
false
5
5
5
5
5
-
-
Scratchpad
-
QFrame::NoFrame
QFrame::Plain
0
0
0
0
0
0
-
0
0
250
0
-
-
Fill area with brush preset icon
-
Fill area with current image
-
Fill area with gradient
-
Fill area with background color
-
Reset area to white
KisScratchPad
QWidget
1
KisPresetLivePreviewView
QGraphicsView
kis_preset_live_preview_view.h
1
KisPresetSelectorStrip
QWidget
kis_preset_selector_strip.h
1
KisLodAvailabilityWidget
QWidget
kis_lod_availability_widget.h
1
diff --git a/libs/ui/kis_paintop_settings_widget.cpp b/libs/ui/kis_paintop_settings_widget.cpp
index 067f5f26fe..893d9b51f4 100644
--- a/libs/ui/kis_paintop_settings_widget.cpp
+++ b/libs/ui/kis_paintop_settings_widget.cpp
@@ -1,257 +1,264 @@
/* This file is part of the KDE project
* Copyright (C) Boudewijn Rempt , (C) 2008
* Copyright (C) Silvio Heinrich , (C) 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "kis_paintop_settings_widget.h"
#include "kis_paintop_option.h"
#include "kis_paintop_options_model.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
struct KisPaintOpSettingsWidget::Private
{
QList paintOpOptions;
KisCategorizedListView* optionsList;
KisPaintOpOptionListModel* model;
QStackedWidget* optionsStack;
QScrollArea* optionsStackScrollableArea;
};
KisPaintOpSettingsWidget::KisPaintOpSettingsWidget(QWidget * parent)
: KisPaintOpConfigWidget(parent)
, m_d(new Private())
{
setObjectName("KisPaintOpPresetsWidget");
m_d->model = new KisPaintOpOptionListModel(this);
m_d->optionsList = new KisCategorizedListView(this);
m_d->optionsList->setModel(m_d->model);
m_d->optionsList->setItemDelegate(new KisCategorizedItemDelegate(m_d->optionsList));
m_d->optionsList->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
m_d->optionsList->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- QSizePolicy policy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+ QSizePolicy policy = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_d->optionsList->setSizePolicy(policy);
m_d->optionsList->setMinimumWidth(140); // this should be just big enough to show all of the setting names
m_d->optionsStack = new QStackedWidget(this);
- policy = QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+ policy = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
m_d->optionsStack->setSizePolicy(policy);
-
// put settings in a scrollable area in case they get too long
m_d->optionsStackScrollableArea = new QScrollArea(this);
m_d->optionsStackScrollableArea->setWidgetResizable(true);
m_d->optionsStackScrollableArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
m_d->optionsStackScrollableArea->setWidget(m_d->optionsStack);
+ policy = QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ m_d->optionsStackScrollableArea->setSizePolicy(policy);
+
+
+ // TODO: This area seems to not be collapsing right, so manually set width for now
+ m_d->optionsStack->setMaximumWidth(330);
+ m_d->optionsStackScrollableArea->setMaximumWidth(350);
+
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(m_d->optionsList);
layout->addWidget(m_d->optionsStackScrollableArea);
layout->setStretch(0, 0);
layout->setStretch(1, 1);
m_saveLockedOption = false;
connect(m_d->optionsList, SIGNAL(activated(const QModelIndex&)), this, SLOT(changePage(const QModelIndex&)));
connect(m_d->optionsList, SIGNAL(clicked(QModelIndex)), this, SLOT(changePage(const QModelIndex&)));
connect(m_d->optionsList, SIGNAL(rightClickedMenuDropSettingsTriggered()), this, SLOT(slotLockPropertiesDrop()));
connect(m_d->optionsList, SIGNAL(rightClickedMenuSaveSettingsTriggered()), this, SLOT(slotLockPropertiesSave()));
connect(m_d->optionsList, SIGNAL(sigEntryChecked(QModelIndex)), this, SLOT(slotEntryChecked(QModelIndex)));
connect (m_d->optionsList, SIGNAL(lockAreaTriggered(QModelIndex)), this, SLOT(lockProperties(const QModelIndex&)));
}
KisPaintOpSettingsWidget::~KisPaintOpSettingsWidget()
{
qDeleteAll(m_d->paintOpOptions);
delete m_d;
}
void KisPaintOpSettingsWidget::addPaintOpOption(KisPaintOpOption *option, const QString &label)
{
addPaintOpOption(option, label, option->category());
}
void KisPaintOpSettingsWidget::addPaintOpOption(KisPaintOpOption *option, const QString &label, KisPaintOpOption::PaintopCategory category)
{
if (!option->configurationPage()) return;
m_d->model->addPaintOpOption(option, m_d->optionsStack->count(), label, category);
connect(option, SIGNAL(sigSettingChanged()), SIGNAL(sigConfigurationItemChanged()));
m_d->optionsStack->addWidget(option->configurationPage());
m_d->paintOpOptions << option;
}
void KisPaintOpSettingsWidget::setConfiguration(const KisPropertiesConfigurationSP config)
{
Q_ASSERT(!config->getString("paintop").isEmpty());
KisLockedPropertiesProxySP propertiesProxy = KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(config);
int indexcount = 0;
Q_FOREACH (KisPaintOpOption* option, m_d->paintOpOptions) {
option->startReadOptionSetting(propertiesProxy);
if (KisLockedPropertiesServer::instance()->propertiesFromLocked()) {
option->setLocked(true);
}
else {
option->setLocked(false);
}
KisLockedPropertiesServer::instance()->setPropertiesFromLocked(false);
KisOptionInfo info;
info.option = option;
info.index = indexcount;
m_d->model->categoriesMapper()->itemFromRow(m_d->model->indexOf(info).row())->setLocked(option->isLocked());
m_d->model->categoriesMapper()->itemFromRow(m_d->model->indexOf(info).row())->setLockable(true);
m_d->model->signalDataChanged(m_d->model->indexOf(info));
indexcount++;
}
}
void KisPaintOpSettingsWidget::writeConfiguration(KisPropertiesConfigurationSP config) const
{
KisLockedPropertiesProxySP propertiesProxy = KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(config);
Q_FOREACH (const KisPaintOpOption* option, m_d->paintOpOptions) {
option->startWriteOptionSetting(propertiesProxy);
}
}
KisPaintopLodLimitations KisPaintOpSettingsWidget::lodLimitations() const
{
KisPaintopLodLimitations l;
Q_FOREACH (const KisPaintOpOption* option, m_d->paintOpOptions) {
if (option->isCheckable() && !option->isChecked()) continue;
option->lodLimitations(&l);
}
return l;
}
void KisPaintOpSettingsWidget::setImage(KisImageWSP image)
{
Q_FOREACH (KisPaintOpOption* option, m_d->paintOpOptions) {
option->setImage(image);
}
}
void KisPaintOpSettingsWidget::setNode(KisNodeWSP node)
{
Q_FOREACH (KisPaintOpOption* option, m_d->paintOpOptions) {
option->setNode(node);
}
}
void KisPaintOpSettingsWidget::changePage(const QModelIndex& index)
{
KisOptionInfo info;
QPalette palette;
palette.setColor(QPalette::Base, QColor(255,200,200));
palette.setColor(QPalette::Text, Qt::black);
if(m_d->model->entryAt(info, index)) {
m_d->optionsStack->setCurrentIndex(info.index);
// disable the widget if a setting area is not active and not being used
if (info.option->isCheckable() ) {
m_d->optionsStack->setEnabled(info.option->isChecked());
} else {
m_d->optionsStack->setEnabled(true); // option is not checkable, so always enable
}
}
notifyPageChanged();
}
void KisPaintOpSettingsWidget::notifyPageChanged()
{
}
void KisPaintOpSettingsWidget::lockProperties(const QModelIndex& index)
{
KisOptionInfo info;
if (m_d->model->entryAt(info, index)) {
m_d->optionsList->setCurrentIndex(index);
KisPropertiesConfigurationSP p = new KisPropertiesConfiguration();
info.option->startWriteOptionSetting(p);
if (!info.option->isLocked()){
KisLockedPropertiesServer::instance()->addToLockedProperties(p);
info.option->setLocked(true);
m_d->model->categoriesMapper()->itemFromRow(index.row())->setLocked(true);
}
else {
KisLockedPropertiesServer::instance()->removeFromLockedProperties(p);
info.option->setLocked(false);
m_d->model->categoriesMapper()->itemFromRow(index.row())->setLocked(false);
if (m_saveLockedOption){
emit sigSaveLockedConfig(p);
}
else {
emit sigDropLockedConfig(p);
}
m_saveLockedOption = false;
}
m_d->model->signalDataChanged(index);
}
}
void KisPaintOpSettingsWidget::slotLockPropertiesDrop()
{
m_saveLockedOption = false;
lockProperties(m_d->optionsList->currentIndex());
}
void KisPaintOpSettingsWidget::slotLockPropertiesSave()
{
m_saveLockedOption = true;
lockProperties(m_d->optionsList->currentIndex());
}
void KisPaintOpSettingsWidget::slotEntryChecked(const QModelIndex &index)
{
Q_UNUSED(index);
emit sigConfigurationItemChanged();
}
diff --git a/libs/ui/widgets/kis_paintop_presets_popup.cpp b/libs/ui/widgets/kis_paintop_presets_popup.cpp
index 56df009371..57a0332315 100644
--- a/libs/ui/widgets/kis_paintop_presets_popup.cpp
+++ b/libs/ui/widgets/kis_paintop_presets_popup.cpp
@@ -1,845 +1,844 @@
/* This file is part of the KDE project
* Copyright (C) 2008 Boudewijn Rempt
* Copyright (C) 2010 Lukáš Tvrdý
* Copyright (C) 2011 Silvio Heinrich
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "widgets/kis_paintop_presets_popup.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_config.h"
#include "KisResourceServerProvider.h"
#include "kis_lod_availability_widget.h"
#include "kis_signal_auto_connection.h"
#include
// ones from brush engine selector
#include
#include
struct KisPaintOpPresetsPopup::Private
{
public:
Ui_WdgPaintOpSettings uiWdgPaintOpPresetSettings;
QGridLayout *layout;
KisPaintOpConfigWidget *settingsWidget;
QFont smallFont;
KisCanvasResourceProvider *resourceProvider;
KisFavoriteResourceManager *favoriteResManager;
bool detached;
bool ignoreHideEvents;
bool isCreatingBrushFromScratch = false;
QSize minimumSettingsWidgetSize;
QRect detachedGeometry;
KisSignalAutoConnectionsStore widgetConnections;
};
KisPaintOpPresetsPopup::KisPaintOpPresetsPopup(KisCanvasResourceProvider * resourceProvider,
KisFavoriteResourceManager* favoriteResourceManager,
KisPresetSaveWidget* savePresetWidget,
QWidget * parent)
: QWidget(parent)
, m_d(new Private())
{
setObjectName("KisPaintOpPresetsPopup");
setFont(KoDockRegistry::dockFont());
KisConfig cfg(true);
current_paintOpId = "";
m_d->resourceProvider = resourceProvider;
m_d->favoriteResManager = favoriteResourceManager;
m_d->uiWdgPaintOpPresetSettings.setupUi(this);
m_d->layout = new QGridLayout(m_d->uiWdgPaintOpPresetSettings.frmOptionWidgetContainer);
m_d->layout->setSizeConstraint(QLayout::SetFixedSize);
m_d->uiWdgPaintOpPresetSettings.scratchPad->setupScratchPad(resourceProvider, Qt::white);
m_d->uiWdgPaintOpPresetSettings.scratchPad->setCutoutOverlayRect(QRect(25, 25, 200, 200));
m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setToolTip(i18n("The settings for this preset have changed from their default."));
m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setToolTip(i18n("Reload the brush preset"));
// brush configuration option menu.
// these options aren't tied to a brush preset, but affect how they behave, or how brushes behave in general
brushConfigurationMenu = new QMenu();
brushConfigurationMenu->setStyleSheet("margin: 6px");
brushConfigAction = brushConfigurationMenu->addAction(i18n("Show Scratchpad"));
brushConfigAction->setCheckable(true);
brushConfigAction->setChecked(cfg.scratchpadVisible());
connect(brushConfigAction, SIGNAL(toggled(bool)), this, SLOT(slotSwitchScratchpad(bool)));
brushConfigAction = brushConfigurationMenu->addAction(i18n("Show Brush Presets"));
brushConfigAction->setCheckable(true);
connect(brushConfigAction, SIGNAL(toggled(bool)), this, SLOT(slotSwitchShowPresets(bool)));
brushConfigAction->setChecked(false);
slotSwitchShowPresets(false);
brushConfigurationMenu->addSeparator(); // we are going from showing to confi. so add a separator
brushConfigAction = brushConfigurationMenu->addAction(i18n("Eraser Switch Size"));
connect(brushConfigAction, SIGNAL(toggled(bool)), this, SIGNAL(eraserBrushSizeToggled(bool)));
brushConfigAction->setCheckable(true);
brushConfigAction->setChecked(cfg.useEraserBrushSize());
eraserBrushSizeToggled(cfg.useEraserBrushSize());
brushConfigAction = brushConfigurationMenu->addAction(i18n("Eraser Switch Opacity"));
connect(brushConfigAction, SIGNAL(toggled(bool)),this, SIGNAL(eraserBrushOpacityToggled(bool)));
brushConfigAction->setCheckable(true);
brushConfigAction->setChecked(false);
eraserBrushOpacityToggled(cfg.useEraserBrushOpacity());
brushConfigAction = brushConfigurationMenu->addAction(i18n("Temporarily Save Brush Presets"));
connect(brushConfigAction, SIGNAL(toggled(bool)),this, SIGNAL(dirtyPresetToggled(bool)));
brushConfigAction->setCheckable(true);
brushConfigAction->setChecked(cfg.useDirtyPresets());
dirtyPresetToggled(cfg.useDirtyPresets());
brushConfigAction = brushConfigurationMenu->addAction(i18n("Rename Brush Preset"));
brushConfigAction->setCheckable(false);
connect (brushConfigAction, SIGNAL(triggered(bool)), this, SLOT(slotRenameBrushActivated()));
m_d->uiWdgPaintOpPresetSettings.configureBrushesToolButton->setMenu(brushConfigurationMenu);
m_d->uiWdgPaintOpPresetSettings.configureBrushesToolButton->setIcon(KisIconUtils::loadIcon("configure"));
m_d->uiWdgPaintOpPresetSettings.configureBrushesToolButton->setPopupMode(QToolButton::InstantPopup);
// creating a new preset from scratch. Part of the brush presets area
// the menu options will get filled up later when we are generating all available paintops
// in the filter drop-down
newPresetBrushEnginesMenu = new QMenu();
// overwrite existing preset and saving a new preset use the same dialog
saveDialog = savePresetWidget;
saveDialog->scratchPadSetup(resourceProvider);
saveDialog->setFavoriteResourceManager(m_d->favoriteResManager); // this is needed when saving the preset
saveDialog->hide();
// the area on the brush editor for renaming the brush. make sure edit fields are hidden by default
toggleBrushRenameUIActive(false);
// DETAIL and THUMBNAIL view changer
QMenu* menu = new QMenu(this);
menu->setStyleSheet("margin: 6px");
menu->addSection(i18n("Display"));
QActionGroup *actionGroup = new QActionGroup(this);
KisPresetChooser::ViewMode mode = (KisPresetChooser::ViewMode)KisConfig(true).presetChooserViewMode();
QAction* action = menu->addAction(KisIconUtils::loadIcon("view-preview"), i18n("Thumbnails"), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotThumbnailMode()));
action->setCheckable(true);
action->setChecked(mode == KisPresetChooser::THUMBNAIL);
action->setActionGroup(actionGroup);
action = menu->addAction(KisIconUtils::loadIcon("view-list-details"), i18n("Details"), m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotDetailMode()));
action->setCheckable(true);
action->setChecked(mode == KisPresetChooser::DETAIL);
action->setActionGroup(actionGroup);
// add horizontal slider for the icon size
QSlider* iconSizeSlider = new QSlider(this);
iconSizeSlider->setOrientation(Qt::Horizontal);
iconSizeSlider->setRange(30, 80);
iconSizeSlider->setValue(m_d->uiWdgPaintOpPresetSettings.presetWidget->iconSize());
iconSizeSlider->setMinimumHeight(20);
iconSizeSlider->setMinimumWidth(40);
iconSizeSlider->setTickInterval(10);
QWidgetAction *sliderAction= new QWidgetAction(this);
sliderAction->setDefaultWidget(iconSizeSlider);
menu->addSection(i18n("Icon Size"));
menu->addAction(sliderAction);
// configure the button and assign menu
m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setMenu(menu);
m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("view-list-details"));
m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setPopupMode(QToolButton::InstantPopup);
// loading preset from scratch option
m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setPopupMode(QToolButton::InstantPopup);
// show/hide buttons
slotSwitchScratchpad(cfg.scratchpadVisible());
// Connections
connect(m_d->uiWdgPaintOpPresetSettings.paintPresetIcon, SIGNAL(clicked()),
m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(paintPresetImage()));
connect(saveDialog, SIGNAL(resourceSelected(KoResource*)), this, SLOT(resourceSelected(KoResource*)));
connect (m_d->uiWdgPaintOpPresetSettings.cancelBrushNameUpdateButton, SIGNAL(clicked(bool)),
this, SLOT(slotRenameBrushDeactivated()));
connect(m_d->uiWdgPaintOpPresetSettings.updateBrushNameButton, SIGNAL(clicked(bool)),
this, SLOT(slotSaveRenameCurrentBrush()));
connect(m_d->uiWdgPaintOpPresetSettings.renameBrushNameTextField, SIGNAL(returnPressed()),
SLOT(slotSaveRenameCurrentBrush()));
connect(iconSizeSlider, SIGNAL(sliderMoved(int)),
m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotSetIconSize(int)));
connect(iconSizeSlider, SIGNAL(sliderReleased()),
m_d->uiWdgPaintOpPresetSettings.presetWidget, SLOT(slotSaveIconSize()));
connect(m_d->uiWdgPaintOpPresetSettings.eraseScratchPad, SIGNAL(clicked()),
m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillDefault()));
connect(m_d->uiWdgPaintOpPresetSettings.fillLayer, SIGNAL(clicked()),
m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillLayer()));
connect(m_d->uiWdgPaintOpPresetSettings.fillGradient, SIGNAL(clicked()),
m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillGradient()));
connect(m_d->uiWdgPaintOpPresetSettings.fillSolid, SIGNAL(clicked()),
m_d->uiWdgPaintOpPresetSettings.scratchPad, SLOT(fillBackground()));
m_d->settingsWidget = 0;
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
connect(m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton, SIGNAL(clicked()),
this, SLOT(slotSaveBrushPreset()));
connect(m_d->uiWdgPaintOpPresetSettings.saveNewBrushPresetButton, SIGNAL(clicked()),
this, SLOT(slotSaveNewBrushPreset()));
connect(m_d->uiWdgPaintOpPresetSettings.reloadPresetButton, SIGNAL(clicked()),
this, SIGNAL(reloadPresetClicked()));
// preset widget connections
connect(m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SIGNAL(resourceSelected(KoResource*)),
this, SIGNAL(signalResourceSelected(KoResource*)));
connect(m_d->uiWdgPaintOpPresetSettings.reloadPresetButton, SIGNAL(clicked()),
m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser, SLOT(updateViewSettings()));
connect(m_d->uiWdgPaintOpPresetSettings.reloadPresetButton, SIGNAL(clicked()), SLOT(slotUpdatePresetSettings()));
m_d->detached = false;
m_d->ignoreHideEvents = false;
m_d->minimumSettingsWidgetSize = QSize(0, 0);
m_d->detachedGeometry = QRect(100, 100, 0, 0);
m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->setCanvasResourceManager(resourceProvider->resourceManager());
connect(resourceProvider->resourceManager(),
SIGNAL(canvasResourceChanged(int,QVariant)),
SLOT(slotResourceChanged(int, QVariant)));
connect(m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability,
SIGNAL(sigUserChangedLodAvailability(bool)),
SLOT(slotLodAvailabilityChanged(bool)));
connect(m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability,
SIGNAL(sigUserChangedLodThreshold(qreal)),
SLOT(slotLodThresholdChanged(qreal)));
slotResourceChanged(KisCanvasResourceProvider::LodAvailability,
resourceProvider->resourceManager()->
resource(KisCanvasResourceProvider::LodAvailability));
slotResourceChanged(KisCanvasResourceProvider::LodSizeThreshold,
resourceProvider->resourceManager()->
resource(KisCanvasResourceProvider::LodSizeThreshold));
connect(m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(slotUpdatePaintOpFilter()));
connect(m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset, SIGNAL(clicked()), this, SLOT(slotBlackListCurrentPreset()));
updateThemedIcons();
// setup things like the scene construct images, layers, etc that is a one-time thing
m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->setup();
}
void KisPaintOpPresetsPopup::slotBlackListCurrentPreset()
{
KisPaintOpPresetResourceServer * rServer = KisResourceServerProvider::instance()->paintOpPresetServer();
KisPaintOpPresetSP curPreset = m_d->resourceProvider->currentPreset();
if (rServer->resourceByName(curPreset->name())) {
rServer->removeResourceAndBlacklist(curPreset);
}
}
void KisPaintOpPresetsPopup::slotRenameBrushActivated()
{
toggleBrushRenameUIActive(true);
}
void KisPaintOpPresetsPopup::slotRenameBrushDeactivated()
{
toggleBrushRenameUIActive(false);
}
void KisPaintOpPresetsPopup::toggleBrushRenameUIActive(bool isRenaming)
{
// This function doesn't really do anything except get the UI in a state to rename a brush preset
m_d->uiWdgPaintOpPresetSettings.renameBrushNameTextField->setVisible(isRenaming);
m_d->uiWdgPaintOpPresetSettings.updateBrushNameButton->setVisible(isRenaming);
m_d->uiWdgPaintOpPresetSettings.cancelBrushNameUpdateButton->setVisible(isRenaming);
// hide these below areas while renaming
m_d->uiWdgPaintOpPresetSettings.currentBrushNameLabel->setVisible(!isRenaming);
m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setEnabled(!isRenaming);
m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setVisible(!isRenaming);
m_d->uiWdgPaintOpPresetSettings.saveNewBrushPresetButton->setEnabled(!isRenaming);
m_d->uiWdgPaintOpPresetSettings.saveNewBrushPresetButton->setVisible(!isRenaming);
// if the presets area is shown, only then can you show/hide the load default brush
// need to think about weird state when you are in the middle of renaming a brush
// what happens if you try to change presets. maybe we should auto-hide (or disable)
// the presets area in this case
if (m_d->uiWdgPaintOpPresetSettings.presetWidget->isVisible()) {
m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setVisible(!isRenaming);
m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setVisible(!isRenaming);
}
}
void KisPaintOpPresetsPopup::slotSaveRenameCurrentBrush()
{
// if you are renaming a brush, that is different than updating the settings
// make sure we are in a clean state before renaming. This logic might change,
// but that is what we are going with for now
emit reloadPresetClicked();
m_d->favoriteResManager->setBlockUpdates(true);
// get a reference to the existing (and new) file name and path that we are working with
KisPaintOpPresetSP curPreset = m_d->resourceProvider->currentPreset();
if (!curPreset)
return;
KisPaintOpPresetResourceServer * rServer = KisResourceServerProvider::instance()->paintOpPresetServer();
QString saveLocation = rServer->saveLocation();
QString originalPresetName = curPreset->name();
QString renamedPresetName = m_d->uiWdgPaintOpPresetSettings.renameBrushNameTextField->text();
QString originalPresetPathAndFile = saveLocation + originalPresetName + curPreset->defaultFileExtension();
QString renamedPresetPathAndFile = saveLocation + renamedPresetName + curPreset->defaultFileExtension();
// create a new brush preset with the name specified and add to resource provider
KisPaintOpPresetSP newPreset = curPreset->clone();
newPreset->setFilename(renamedPresetPathAndFile); // this also contains the path
newPreset->setName(renamedPresetName);
newPreset->setImage(curPreset->image()); // use existing thumbnail (might not need to do this)
newPreset->setPresetDirty(false);
newPreset->setValid(true);
rServer->addResource(newPreset);
resourceSelected(newPreset.data()); // refresh and select our freshly renamed resource
// Now blacklist the original file
if (rServer->resourceByName(originalPresetName)) {
rServer->removeResourceAndBlacklist(curPreset);
}
m_d->favoriteResManager->setBlockUpdates(false);
toggleBrushRenameUIActive(false); // this returns the UI to its original state after saving
slotUpdatePresetSettings(); // update visibility of dirty preset and icon
}
void KisPaintOpPresetsPopup::slotResourceChanged(int key, const QVariant &value)
{
if (key == KisCanvasResourceProvider::LodAvailability) {
m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->slotUserChangedLodAvailability(value.toBool());
} else if (key == KisCanvasResourceProvider::LodSizeThreshold) {
m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->slotUserChangedLodThreshold(value.toDouble());
} else if (key == KisCanvasResourceProvider::Size) {
m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->slotUserChangedSize(value.toDouble());
}
}
void KisPaintOpPresetsPopup::slotLodAvailabilityChanged(bool value)
{
m_d->resourceProvider->resourceManager()->setResource(KisCanvasResourceProvider::LodAvailability, QVariant(value));
}
void KisPaintOpPresetsPopup::slotLodThresholdChanged(qreal value)
{
m_d->resourceProvider->resourceManager()->setResource(KisCanvasResourceProvider::LodSizeThreshold, QVariant(value));
}
KisPaintOpPresetsPopup::~KisPaintOpPresetsPopup()
{
if (m_d->settingsWidget) {
m_d->layout->removeWidget(m_d->settingsWidget);
m_d->settingsWidget->hide();
m_d->settingsWidget->setParent(0);
m_d->settingsWidget = 0;
}
delete m_d;
delete newPresetBrushEnginesMenu;
delete brushConfigurationMenu;
}
void KisPaintOpPresetsPopup::setPaintOpSettingsWidget(QWidget * widget)
{
if (m_d->settingsWidget) {
m_d->layout->removeWidget(m_d->settingsWidget);
m_d->uiWdgPaintOpPresetSettings.frmOptionWidgetContainer->updateGeometry();
}
+
m_d->layout->update();
updateGeometry();
m_d->widgetConnections.clear();
m_d->settingsWidget = 0;
if (widget) {
m_d->settingsWidget = dynamic_cast(widget);
KIS_ASSERT_RECOVER_RETURN(m_d->settingsWidget);
KisConfig cfg(true);
if (m_d->settingsWidget->supportScratchBox() && cfg.scratchpadVisible()) {
slotSwitchScratchpad(true);
} else {
slotSwitchScratchpad(false);
}
m_d->widgetConnections.addConnection(m_d->settingsWidget, SIGNAL(sigConfigurationItemChanged()),
this, SLOT(slotUpdateLodAvailability()));
widget->setFont(m_d->smallFont);
-
QSize hint = widget->sizeHint();
m_d->minimumSettingsWidgetSize = QSize(qMax(hint.width(), m_d->minimumSettingsWidgetSize.width()),
qMax(hint.height(), m_d->minimumSettingsWidgetSize.height()));
widget->setMinimumSize(m_d->minimumSettingsWidgetSize);
/**/
// manually control the brush settings size for now to help see what is taking up the most space
//widget->setMaximumHeight(640);
//widget->setMaximumWidth(600);
-
m_d->layout->addWidget(widget);
// hook up connections that will monitor if our preset is dirty or not. Show a notification if it is
if (m_d->resourceProvider && m_d->resourceProvider->currentPreset() ) {
KisPaintOpPresetSP preset = m_d->resourceProvider->currentPreset();
m_d->widgetConnections.addConnection(preset->updateProxy(), SIGNAL(sigSettingsChanged()),
this, SLOT(slotUpdatePresetSettings()));
}
m_d->layout->update();
widget->show();
}
slotUpdateLodAvailability();
}
void KisPaintOpPresetsPopup::slotUpdateLodAvailability()
{
if (!m_d->settingsWidget) return;
KisPaintopLodLimitations l = m_d->settingsWidget->lodLimitations();
m_d->uiWdgPaintOpPresetSettings.wdgLodAvailability->setLimitations(l);
}
QImage KisPaintOpPresetsPopup::cutOutOverlay()
{
return m_d->uiWdgPaintOpPresetSettings.scratchPad->cutoutOverlay();
}
void KisPaintOpPresetsPopup::contextMenuEvent(QContextMenuEvent *e)
{
Q_UNUSED(e);
}
void KisPaintOpPresetsPopup::switchDetached(bool show)
{
if (parentWidget()) {
m_d->detached = !m_d->detached;
if (m_d->detached) {
m_d->ignoreHideEvents = true;
if (show) {
parentWidget()->show();
}
m_d->ignoreHideEvents = false;
}
else {
parentWidget()->hide();
}
KisConfig cfg(false);
cfg.setPaintopPopupDetached(m_d->detached);
}
}
void KisPaintOpPresetsPopup::setCreatingBrushFromScratch(bool enabled)
{
m_d->isCreatingBrushFromScratch = enabled;
}
void KisPaintOpPresetsPopup::resourceSelected(KoResource* resource)
{
// this gets called every time the brush editor window is opened
// TODO: this gets called multiple times whenever the preset is changed in the presets area
// the connections probably need to be thought about with this a bit more to keep things in sync
m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->setCurrentResource(resource);
// find the display name of the brush engine and append it to the selected preset display
QString currentBrushEngineName;
QPixmap currentBrushEngineIcon = QPixmap(26, 26);
currentBrushEngineIcon.fill(Qt::transparent);
for(int i=0; i < sortedBrushEnginesList.length(); i++) {
if (sortedBrushEnginesList.at(i).id == currentPaintOpId() ) {
currentBrushEngineName = sortedBrushEnginesList.at(i).name;
currentBrushEngineIcon = sortedBrushEnginesList.at(i).icon.pixmap(26, 26);
}
}
// brush names have underscores as part of the file name (to help with building). We don't really need underscores
// when viewing the names, so replace them with spaces
QString formattedBrushName = resource->name().replace("_", " ");
m_d->uiWdgPaintOpPresetSettings.currentBrushNameLabel->setText(formattedBrushName);
m_d->uiWdgPaintOpPresetSettings.currentBrushEngineLabel->setText(i18nc("%1 is the name of a brush engine", "%1 Engine", currentBrushEngineName));
m_d->uiWdgPaintOpPresetSettings.currentBrushEngineIcon->setPixmap(currentBrushEngineIcon);
m_d->uiWdgPaintOpPresetSettings.renameBrushNameTextField->setText(resource->name()); // use file name
// get the preset image and pop it into the thumbnail area on the top of the brush editor
m_d->uiWdgPaintOpPresetSettings.presetThumbnailicon->setPixmap(QPixmap::fromImage(resource->image().scaled(55, 55, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
toggleBrushRenameUIActive(false); // reset the UI state of renaming a brush if we are changing brush presets
slotUpdatePresetSettings(); // check to see if the dirty preset icon needs to be shown
}
bool variantLessThan(const KisPaintOpInfo v1, const KisPaintOpInfo v2)
{
return v1.priority < v2.priority;
}
void KisPaintOpPresetsPopup::setPaintOpList(const QList< KisPaintOpFactory* >& list)
{
m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->clear(); // reset combobox list just in case
// create a new list so we can sort it and populate the brush engine combo box
sortedBrushEnginesList.clear(); // just in case this function is called again, don't keep adding to the list
for(int i=0; i < list.length(); i++) {
KisPaintOpInfo paintOpInfo;
paintOpInfo.id = list.at(i)->id();
paintOpInfo.name = list.at(i)->name();
paintOpInfo.icon = list.at(i)->icon();
paintOpInfo.priority = list.at(i)->priority();
sortedBrushEnginesList.append(paintOpInfo);
}
std::stable_sort(sortedBrushEnginesList.begin(), sortedBrushEnginesList.end(), variantLessThan );
// add an "All" option at the front to show all presets
QPixmap emptyPixmap = QPixmap(22,22);
emptyPixmap.fill(Qt::transparent);
// if we create a new brush from scratch, we need a full list of paintops to choose from
// we don't want "All", so populate the list before that is added
newPresetBrushEnginesMenu->actions().clear(); // clean out list in case we run this again
newBrushEngineOptions.clear();
for (int j = 0; j < sortedBrushEnginesList.length(); j++) {
KisAction * newEngineAction = static_cast( newPresetBrushEnginesMenu->addAction(sortedBrushEnginesList[j].name));
newEngineAction->setObjectName(sortedBrushEnginesList[j].id); // we need the ID for changing the paintop when action triggered
newEngineAction->setIcon(sortedBrushEnginesList[j].icon);
newBrushEngineOptions.append(newEngineAction);
connect(newEngineAction, SIGNAL(triggered()), this, SLOT(slotCreateNewBrushPresetEngine()));
}
m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setMenu(newPresetBrushEnginesMenu);
// fill the list into the brush combo box
sortedBrushEnginesList.push_front(KisPaintOpInfo(QString("all_options"), i18n("All"), QString(""), QIcon(emptyPixmap), 0 ));
for (int m = 0; m < sortedBrushEnginesList.length(); m++) {
m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->addItem(sortedBrushEnginesList[m].icon, sortedBrushEnginesList[m].name, QVariant(sortedBrushEnginesList[m].id));
}
}
void KisPaintOpPresetsPopup::setCurrentPaintOpId(const QString& paintOpId)
{
current_paintOpId = paintOpId;
}
QString KisPaintOpPresetsPopup::currentPaintOpId() {
return current_paintOpId;
}
void KisPaintOpPresetsPopup::setPresetImage(const QImage& image)
{
m_d->uiWdgPaintOpPresetSettings.scratchPad->setPresetImage(image);
saveDialog->brushPresetThumbnailWidget->setPresetImage(image);
}
void KisPaintOpPresetsPopup::hideEvent(QHideEvent *event)
{
if (m_d->ignoreHideEvents) {
return;
}
if (m_d->detached) {
m_d->detachedGeometry = window()->geometry();
}
QWidget::hideEvent(event);
}
void KisPaintOpPresetsPopup::showEvent(QShowEvent *)
{
if (m_d->detached) {
window()->setGeometry(m_d->detachedGeometry);
}
emit brushEditorShown();
}
void KisPaintOpPresetsPopup::resizeEvent(QResizeEvent* event)
{
QWidget::resizeEvent(event);
if (parentWidget()) {
// Make sure resizing doesn't push this widget out of the screen
QRect screenRect = QApplication::desktop()->availableGeometry(this);
QRect newPositionRect = kisEnsureInRect(parentWidget()->geometry(), screenRect);
parentWidget()->setGeometry(newPositionRect);
}
}
bool KisPaintOpPresetsPopup::detached() const
{
return m_d->detached;
}
void KisPaintOpPresetsPopup::slotSwitchScratchpad(bool visible)
{
// hide all the internal controls except the toggle button
/*
m_d->uiWdgPaintOpPresetSettings.scratchPad->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.paintPresetIcon->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.fillGradient->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.fillLayer->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.fillSolid->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.scratchpadSidebarLabel->setVisible(visible);
*/
m_d->uiWdgPaintOpPresetSettings.scratchpadControls->setVisible(visible);
KisConfig cfg(false);
cfg.setScratchpadVisible(visible);
}
void KisPaintOpPresetsPopup::slotSwitchShowEditor(bool visible) {
// m_d->uiWdgPaintOpPresetSettings.brushEditorSettingsControls->setVisible(visible);
}
void KisPaintOpPresetsPopup::slotSwitchShowPresets(bool visible) {
/*
m_d->uiWdgPaintOpPresetSettings.presetWidget->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.engineFilterLabel->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.presetsSidebarLabel->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setVisible(visible);
m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setVisible(visible);
*/
m_d->uiWdgPaintOpPresetSettings.presetsContainer->setVisible(visible);
}
void KisPaintOpPresetsPopup::slotUpdatePaintOpFilter() {
QVariant userData = m_d->uiWdgPaintOpPresetSettings.brushEgineComboBox->currentData(); // grab paintOpID from data
QString filterPaintOpId = userData.toString();
if (filterPaintOpId == "all_options") {
filterPaintOpId = "";
}
m_d->uiWdgPaintOpPresetSettings.presetWidget->setPresetFilter(filterPaintOpId);
}
void KisPaintOpPresetsPopup::slotSaveBrushPreset() {
// here we are assuming that people want to keep their existing preset icon. We will just update the
// settings and save a new copy with the same name.
// there is a dialog with save options, but we don't need to show it in this situation
saveDialog->useNewBrushDialog(false); // this mostly just makes sure we keep the existing brush preset name when saving
saveDialog->loadExistingThumbnail(); // This makes sure we use the existing preset icon when updating the existing brush preset
saveDialog->savePreset();
// refresh the view settings so the brush doesn't appear dirty
slotUpdatePresetSettings();
}
void KisPaintOpPresetsPopup::slotSaveNewBrushPreset() {
saveDialog->useNewBrushDialog(true);
saveDialog->saveScratchPadThumbnailArea(m_d->uiWdgPaintOpPresetSettings.scratchPad->cutoutOverlay());
saveDialog->showDialog();
}
void KisPaintOpPresetsPopup::slotCreateNewBrushPresetEngine()
{
emit createPresetFromScratch(sender()->objectName());
}
void KisPaintOpPresetsPopup::updateViewSettings()
{
m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->updateViewSettings();
}
void KisPaintOpPresetsPopup::currentPresetChanged(KisPaintOpPresetSP preset)
{
if (preset) {
m_d->uiWdgPaintOpPresetSettings.presetWidget->smallPresetChooser->setCurrentResource(preset.data());
setCurrentPaintOpId(preset->paintOp().id());
}
}
void KisPaintOpPresetsPopup::updateThemedIcons()
{
m_d->uiWdgPaintOpPresetSettings.paintPresetIcon->setIcon(KisIconUtils::loadIcon("krita_tool_freehand"));
m_d->uiWdgPaintOpPresetSettings.fillLayer->setIcon(KisIconUtils::loadIcon("document-new"));
m_d->uiWdgPaintOpPresetSettings.fillLayer->hide();
m_d->uiWdgPaintOpPresetSettings.fillGradient->setIcon(KisIconUtils::loadIcon("krita_tool_gradient"));
m_d->uiWdgPaintOpPresetSettings.fillSolid->setIcon(KisIconUtils::loadIcon("krita_tool_color_fill"));
m_d->uiWdgPaintOpPresetSettings.eraseScratchPad->setIcon(KisIconUtils::loadIcon("edit-delete"));
m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setIcon(KisIconUtils::loadIcon("addlayer"));
m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setIcon(KisIconUtils::loadIcon("deletelayer"));
m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setIcon(KisIconUtils::loadIcon("updateColorize")); // refresh icon
m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setIcon(KisIconUtils::loadIcon("warning"));
m_d->uiWdgPaintOpPresetSettings.newPresetEngineButton->setIcon(KisIconUtils::loadIcon("addlayer"));
m_d->uiWdgPaintOpPresetSettings.bnBlacklistPreset->setIcon(KisIconUtils::loadIcon("deletelayer"));
m_d->uiWdgPaintOpPresetSettings.presetChangeViewToolButton->setIcon(KisIconUtils::loadIcon("configure"));
m_d->uiWdgPaintOpPresetSettings.configureBrushesToolButton->setIcon(KisIconUtils::loadIcon("configure"));
}
void KisPaintOpPresetsPopup::slotUpdatePresetSettings()
{
if (!m_d->resourceProvider) {
return;
}
if (!m_d->resourceProvider->currentPreset()) {
return;
}
// hide options on UI if we are creating a brush preset from scratch to prevent confusion
if (m_d->isCreatingBrushFromScratch) {
m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setVisible(false);
m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(false);
m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setVisible(false);
} else {
bool isPresetDirty = m_d->resourceProvider->currentPreset()->isPresetDirty();
// don't need to reload or overwrite a clean preset
m_d->uiWdgPaintOpPresetSettings.dirtyPresetIndicatorButton->setVisible(isPresetDirty);
m_d->uiWdgPaintOpPresetSettings.reloadPresetButton->setVisible(isPresetDirty);
m_d->uiWdgPaintOpPresetSettings.saveBrushPresetButton->setEnabled(isPresetDirty);
}
// update live preview area in here...
// don't update the live preview if the widget is not visible.
if (m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->isVisible()) {
m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->setCurrentPreset(m_d->resourceProvider->currentPreset());
m_d->uiWdgPaintOpPresetSettings.liveBrushPreviewView->updateStroke();
}
}
diff --git a/libs/ui/widgets/kis_preset_live_preview_view.cpp b/libs/ui/widgets/kis_preset_live_preview_view.cpp
index 2189a7c8a8..f84b85a41c 100644
--- a/libs/ui/widgets/kis_preset_live_preview_view.cpp
+++ b/libs/ui/widgets/kis_preset_live_preview_view.cpp
@@ -1,333 +1,332 @@
/*
* Copyright (c) 2017 Scott Petrovic
*
* 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
#include
#include
#include "kis_paintop_settings.h"
#include
#include
#include
KisPresetLivePreviewView::KisPresetLivePreviewView(QWidget *parent): QGraphicsView(parent)
{
}
KisPresetLivePreviewView::~KisPresetLivePreviewView()
{
delete m_noPreviewText;
delete m_brushPreviewScene;
}
void KisPresetLivePreviewView::setup()
{
// initializing to 0 helps check later if they actually have something in them
m_noPreviewText = 0;
m_sceneImageItem = 0;
setHorizontalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
setVerticalScrollBarPolicy ( Qt::ScrollBarAlwaysOff );
// layer image needs to be big enough to get an entire stroke of data
m_canvasSize.setWidth(this->width());
m_canvasSize.setHeight(this->height());
m_canvasCenterPoint.setX(m_canvasSize.width()*0.5);
m_canvasCenterPoint.setY(m_canvasSize.height()*0.5);
m_colorSpace = KoColorSpaceRegistry::instance()->rgb8();
m_image = new KisImage(0, m_canvasSize.width(), m_canvasSize.height(), m_colorSpace, "stroke sample image");
m_layer = new KisPaintLayer(m_image, "livePreviewStrokeSample", OPACITY_OPAQUE_U8, m_colorSpace);
// set scene for the view
m_brushPreviewScene = new QGraphicsScene();
setScene(m_brushPreviewScene);
}
void KisPresetLivePreviewView::setCurrentPreset(KisPaintOpPresetSP preset)
{
+ setup();
m_currentPreset = preset;
}
void KisPresetLivePreviewView::updateStroke()
{
paintBackground();
// do not paint a stroke if we are any of these engines (they have some issue currently)
if (m_currentPreset->paintOp().id() == "roundmarker" ||
m_currentPreset->paintOp().id() == "experimentbrush" ||
m_currentPreset->paintOp().id() == "duplicate") {
return;
}
setupAndPaintStroke();
// crop the layer so a brush stroke won't go outside of the area
m_layer->paintDevice()->crop(0,0, m_layer->image()->width(), m_layer->image()->height());
QImage m_temp_image;
m_temp_image = m_layer->paintDevice()->convertToQImage(0);
// only add the object once...then just update the pixmap so we can move the preview around
if (!m_sceneImageItem) {
m_sceneImageItem = m_brushPreviewScene->addPixmap(QPixmap::fromImage(m_temp_image));
} else {
m_sceneImageItem->setPixmap(QPixmap::fromImage(m_temp_image));
}
}
-
-
void KisPresetLivePreviewView::paintBackground()
{
// clean up "no preview" text object if it exists. we will add it later if we need it
if (m_noPreviewText) {
this->scene()->removeItem(m_noPreviewText);
m_noPreviewText = 0;
}
if (m_currentPreset->paintOp().id() == "colorsmudge" ||
m_currentPreset->paintOp().id() == "deformbrush" ||
m_currentPreset->paintOp().id() == "filter") {
// easier to see deformations and smudging with alternating stripes in the background
// paint the whole background with alternating stripes
// filter engine may or may not show things depending on the filter...but it is better than nothing
int grayStrips = 20;
for (int i=0; i < grayStrips; i++ ) {
float sectionPercent = 1.0 / (float)grayStrips;
bool isAlternating = i % 2;
KoColor fillColor(m_layer->paintDevice()->colorSpace());
if (isAlternating) {
fillColor.fromQColor(QColor(80,80,80));
} else {
fillColor.fromQColor(QColor(140,140,140));
}
const QRect fillRect(m_layer->image()->width()*sectionPercent*i,
0,
m_layer->image()->width()*(sectionPercent*i +sectionPercent),
m_layer->image()->height());
m_layer->paintDevice()->fill(fillRect, fillColor);
}
m_paintColor = KoColor(Qt::white, m_colorSpace);
}
else if (m_currentPreset->paintOp().id() == "roundmarker" ||
m_currentPreset->paintOp().id() == "experimentbrush" ||
m_currentPreset->paintOp().id() == "duplicate" ) {
// cases where we will not show a preview for now
// roundbrush (quick) -- this isn't showing anything, disable showing preview
// experimentbrush -- this creates artifacts that carry over to other previews and messes up their display
// duplicate (clone) brush doesn't have a preview as it doesn't show anything)
if(m_sceneImageItem) {
this->scene()->removeItem(m_sceneImageItem);
m_sceneImageItem = 0;
}
QFont font;
font.setPixelSize(14);
font.setBold(false);
m_noPreviewText = this->scene()->addText(i18n("No Preview for this engine"),font);
m_noPreviewText->setPos(50, this->height()/4);
return;
}
else {
// fill with gray first to clear out what existed from previous preview
m_layer->paintDevice()->fill(m_image->bounds(), KoColor(palette().color(QPalette::Background) , m_colorSpace));
m_paintColor = KoColor(palette().color(QPalette::Text), m_colorSpace);
}
}
void KisPresetLivePreviewView::setupAndPaintStroke()
{
// limit the brush stroke size. larger brush strokes just don't look good and are CPU intensive
// we are making a proxy preset and setting it to the painter...otherwise setting the brush size of the original preset
// will fire off signals that make this run in an infinite loop
qreal originalPresetSize = m_currentPreset->settings()->paintOpSize();
qreal previewSize = qBound(3.0, m_currentPreset->settings()->paintOpSize(), 70.0 ); // constrain live preview brush size
//Except for the sketchbrush where it determine sthe history.
if (m_currentPreset->paintOp().id() == "sketchbrush" ||
m_currentPreset->paintOp().id() == "spraybrush") {
previewSize = qMax(3.0, m_currentPreset->settings()->paintOpSize());
}
KisPaintOpPresetSP proxy_preset = m_currentPreset->clone();
KisPaintOpSettingsSP settings = proxy_preset->settings();
proxy_preset->settings()->setPaintOpSize(previewSize);
int maxTextureSize = 200;
int textureOffsetX = settings->getInt("Texture/Pattern/MaximumOffsetX")*2;
int textureOffsetY = settings->getInt("Texture/Pattern/MaximumOffsetY")*2;
double textureScale = settings->getDouble("Texture/Pattern/Scale");
if ( textureOffsetX*textureScale> maxTextureSize || textureOffsetY*textureScale > maxTextureSize) {
int maxSize = qMax(textureOffsetX, textureOffsetY);
double result = qreal(maxTextureSize) / maxSize;
settings->setProperty("Texture/Pattern/Scale", result);
}
if (m_currentPreset->paintOp().id() == "spraybrush") {
QDomElement element;
QDomDocument d;
QString brushDefinition = settings->getString("brush_definition");
if (!brushDefinition.isEmpty()) {
d.setContent(brushDefinition, false);
element = d.firstChildElement("Brush");
KisBrushSP brush = KisBrush::fromXML(element);
qreal width = brush->image().width();
qreal scale = brush->scale();
qreal diameterToBrushRatio = 1.0;
qreal diameter = settings->getInt("Spray/diameter");
//hack, 1000 being the maximum possible brushsize.
if (brush->filename().endsWith(".svg")) {
diameterToBrushRatio = diameter/(1000.0*scale);
scale = 25.0 / 1000.0;
} else {
if (width * scale > 25.0) {
diameterToBrushRatio = diameter / (width * scale);
scale = 25.0 / width;
}
}
settings->setProperty("Spray/diameter", int(25.0 * diameterToBrushRatio));
brush->setScale(scale);
d.clear();
element = d.createElement("Brush");
brush->toXML(d, element);
d.appendChild(element);
settings->setProperty("brush_definition", d.toString());
}
}
proxy_preset->setSettings(settings);
KisResourcesSnapshotSP resources =
new KisResourcesSnapshot(m_image,
m_layer);
resources->setBrush(proxy_preset);
resources->setFGColorOverride(m_paintColor);
KisFreehandStrokeInfo *strokeInfo = new KisFreehandStrokeInfo();
KisStrokeStrategy *stroke =
new FreehandStrokeStrategy(resources, strokeInfo, kundo2_noi18n("temp_stroke"));
KisStrokeId strokeId = m_image->startStroke(stroke);
//m_brushPreviewPainter->setPaintOpPreset(proxy_preset, m_layer, m_image);
// paint the stroke. The sketchbrush gets a different shape than the others to show how it works
if (m_currentPreset->paintOp().id() == "sketchbrush"
|| m_currentPreset->paintOp().id() == "curvebrush"
|| m_currentPreset->paintOp().id() == "particlebrush") {
qreal startX = m_canvasCenterPoint.x() - (this->width()*0.4);
qreal endX = m_canvasCenterPoint.x() + (this->width()*0.4);
qreal middle = m_canvasCenterPoint.y();
KisPaintInformation pointOne;
pointOne.setPressure(0.0);
pointOne.setPos(QPointF(startX, middle));
KisPaintInformation pointTwo;
pointTwo.setPressure(0.0);
pointTwo.setPos(QPointF(startX, middle));
int repeats = 8;
for (int i = 0; i < repeats; i++) {
pointOne.setPos(pointTwo.pos());
pointOne.setPressure(pointTwo.pressure());
pointTwo.setPressure((1.0/repeats)*(i+1));
qreal xPos = ((1.0/repeats) * (i+1) * (endX-startX) )+startX;
pointTwo.setPos(QPointF(xPos, middle));
qreal offset = (this->height()/(repeats*1.5))*(i+1);
qreal handleY = middle + offset;
if (i%2 == 0) {
handleY = middle - offset;
}
m_image->addJob(strokeId,
new FreehandStrokeStrategy::Data(0,
pointOne,
QPointF(pointOne.pos().x(),
handleY),
QPointF(pointTwo.pos().x(),
handleY),
pointTwo));
m_image->addJob(strokeId, new FreehandStrokeStrategy::UpdateData(true));
}
} else {
// paint an S curve
m_curvePointPI1.setPos(QPointF(m_canvasCenterPoint.x() - (this->width()*0.45),
m_canvasCenterPoint.y() + (this->height()*0.2)));
m_curvePointPI1.setPressure(0.0);
m_curvePointPI2.setPos(QPointF(m_canvasCenterPoint.x() + (this->width()*0.4),
m_canvasCenterPoint.y() - (this->height()*0.2) ));
m_curvePointPI2.setPressure(1.0);
m_image->addJob(strokeId,
new FreehandStrokeStrategy::Data(0,
m_curvePointPI1,
QPointF(m_canvasCenterPoint.x(),
m_canvasCenterPoint.y()-this->height()),
QPointF(m_canvasCenterPoint.x(),
m_canvasCenterPoint.y()+this->height()),
m_curvePointPI2));
m_image->addJob(strokeId, new FreehandStrokeStrategy::UpdateData(true));
}
m_image->endStroke(strokeId);
m_image->waitForDone();
// even though the brush is cloned, the proxy_preset still has some connection to the original preset which will mess brush sizing
// we need to return brush size to normal.The normal brush sends out a lot of extra signals, so keeping the proxy for now
proxy_preset->settings()->setPaintOpSize(originalPresetSize);
}
diff --git a/plugins/paintops/libpaintop/forms/wdgautobrush.ui b/plugins/paintops/libpaintop/forms/wdgautobrush.ui
index af280d6cdc..d8306a174f 100644
--- a/plugins/paintops/libpaintop/forms/wdgautobrush.ui
+++ b/plugins/paintops/libpaintop/forms/wdgautobrush.ui
@@ -1,402 +1,402 @@
KisWdgAutoBrush
0
0
- 317
- 447
+ 269
+ 393
0
0
-
-
- 110
- 110
+ 70
+ 70
- 110
- 110
+ 70
+ 70
-
-
0
0
Mask Type:
-
Qt::ClickFocus
-
Circle
-
Square
-
0
0
Shape:
-
-
The border of the brush will be smoothed to avoid aliasing
Anti-alias
-
-
- 200
+ 0
0
-
Angle:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
Diameter:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
Ratio:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
0
0
0
0
1
-
0
0
1024
1024
Fade
4
-
-
Horizontal:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
-
Vertical:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
0
0
80
0
Softness:
Qt::AlignHCenter|Qt::AlignTop
-
0
0
0
0
10000
10000
-
Qt::Horizontal
- 40
- 20
+ 5
+ 5
-
Randomness:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
Spikes:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
- 200
+ 0
0
-
-
-
-
Density:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
Spacing:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
Qt::Vertical
- 20
- 40
+ 5
+ 5
KisDoubleSliderSpinBox
QWidget
1
- KisCurveWidget
+ KisSpacingSelectionWidget
QWidget
- widgets/kis_curve_widget.h
+ kis_spacing_selection_widget.h
1
- KisSliderSpinBox
+ KisCurveWidget
QWidget
-
+ widgets/kis_curve_widget.h
1
- KisSpacingSelectionWidget
+ KisSliderSpinBox
QWidget
- kis_spacing_selection_widget.h
+
1
KoAspectButton
QWidget
1
diff --git a/plugins/paintops/libpaintop/forms/wdgpredefinedbrushchooser.ui b/plugins/paintops/libpaintop/forms/wdgpredefinedbrushchooser.ui
index ebec3ed49e..d19271f4d2 100644
--- a/plugins/paintops/libpaintop/forms/wdgpredefinedbrushchooser.ui
+++ b/plugins/paintops/libpaintop/forms/wdgpredefinedbrushchooser.ui
@@ -1,241 +1,243 @@
WdgPredefinedBrushChooser
0
0
- 327
+ 348
267
-
-
- 11
+ 10
+ 50
false
+ false
false
false
Current Brush Tip
0
-
0
0
Reset
-
9
Brush Details
0
-
-
+
0
QLayout::SetDefaultConstraint
0
0
0
0
-
4
20
-
0
0
Import
-
0
0
Stamp
-
0
0
Clipboard
-
0
0
-
Qt::Horizontal
- 40
+ 5
20
-
0
0
-
0
0
-
0
0
-
Use Color as Mask
-
Preserve Brush Preset Settings
true
-
Qt::Vertical
- 20
- 40
+ 5
+ 5
KisDoubleSliderSpinBox
QWidget
1
KisSpacingSelectionWidget
QWidget
kis_spacing_selection_widget.h
1
diff --git a/plugins/paintops/libpaintop/forms/wdgtextbrush.ui b/plugins/paintops/libpaintop/forms/wdgtextbrush.ui
index 9a8e91a6dd..11d6fefd33 100644
--- a/plugins/paintops/libpaintop/forms/wdgtextbrush.ui
+++ b/plugins/paintops/libpaintop/forms/wdgtextbrush.ui
@@ -1,208 +1,205 @@
KisWdgTextBrush
0
0
- 381
+ 265
182
-
-
0
0
Font:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
10
5
-
0
0
- 180
+ 50
30
16777
40
QFrame::Box
QFrame::Plain
1
--
true
10
-
0
0
...
-
10
-
Text:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
0
0
0
0
50
false
false
false
false
The Quick Brown Fox Jumps Over The Lazy Dog
-
0
0
Spacing:
Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
-
-
0
0
use only one letter at a time
Pipe mode
-
Qt::Vertical
QSizePolicy::Expanding
- 30
- 21
+ 5
+ 5
- horizontalLayoutWidget
- horizontalLayoutWidget
spacer2
- gridLayoutWidget
KisDoubleSliderSpinBox
QWidget
1
diff --git a/plugins/paintops/libpaintop/kis_brush_chooser.cpp b/plugins/paintops/libpaintop/kis_brush_chooser.cpp
index 9480eff6bb..bea93265dd 100644
--- a/plugins/paintops/libpaintop/kis_brush_chooser.cpp
+++ b/plugins/paintops/libpaintop/kis_brush_chooser.cpp
@@ -1,432 +1,432 @@
/*
* Copyright (c) 2004 Adrian Page
* Copyright (c) 2009 Sven Langkamp
* Copyright (c) 2010 Cyrille Berger
* Copyright (c) 2010 Lukáš Tvrdý
* Copyright (C) 2011 Srikanth Tiyyagura
*
* 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_brush_chooser.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_brush_server.h"
#include "widgets/kis_slider_spin_box.h"
#include "widgets/kis_multipliers_double_slider_spinbox.h"
#include "kis_spacing_selection_widget.h"
#include "kis_signals_blocker.h"
#include "kis_imagepipe_brush.h"
#include "kis_custom_brush_widget.h"
#include "kis_clipboard_brush_widget.h"
#include
#include "kis_global.h"
#include "kis_gbr_brush.h"
#include "kis_debug.h"
#include "kis_image.h"
/// The resource item delegate for rendering the resource preview
class KisBrushDelegate : public QAbstractItemDelegate
{
public:
KisBrushDelegate(QObject * parent = 0) : QAbstractItemDelegate(parent) {}
~KisBrushDelegate() override {}
/// reimplemented
void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const override;
/// reimplemented
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex &) const override {
return option.decorationSize;
}
};
void KisBrushDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
if (! index.isValid())
return;
KisBrush *brush = static_cast(index.internalPointer());
QRect itemRect = option.rect;
QImage thumbnail = brush->image();
if (thumbnail.height() > itemRect.height() || thumbnail.width() > itemRect.width()) {
thumbnail = thumbnail.scaled(itemRect.size() , Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
painter->save();
int dx = (itemRect.width() - thumbnail.width()) / 2;
int dy = (itemRect.height() - thumbnail.height()) / 2;
painter->drawImage(itemRect.x() + dx, itemRect.y() + dy, thumbnail);
if (option.state & QStyle::State_Selected) {
painter->setPen(QPen(option.palette.highlight(), 2.0));
painter->drawRect(option.rect);
painter->setCompositionMode(QPainter::CompositionMode_HardLight);
painter->setOpacity(0.65);
painter->fillRect(option.rect, option.palette.highlight());
}
painter->restore();
}
KisPredefinedBrushChooser::KisPredefinedBrushChooser(QWidget *parent, const char *name)
: QWidget(parent),
m_stampBrushWidget(0),
m_clipboardBrushWidget(0)
{
setObjectName(name);
setupUi(this);
brushSizeSpinBox->setRange(0, KSharedConfig::openConfig()->group("").readEntry("maximumBrushSize", 1000), 2);
brushSizeSpinBox->setValue(5);
brushSizeSpinBox->setExponentRatio(3.0);
brushSizeSpinBox->setPrefix(i18n("Size: "));
brushSizeSpinBox->setSuffix(i18n(" px"));
brushSizeSpinBox->setExponentRatio(3.0);
QObject::connect(brushSizeSpinBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetItemSize(qreal)));
brushRotationSpinBox->setRange(0, 360, 0);
brushRotationSpinBox->setValue(0);
brushRotationSpinBox->setPrefix(i18n("Rotation: "));
brushRotationSpinBox->setSuffix(QChar(Qt::Key_degree));
QObject::connect(brushRotationSpinBox, SIGNAL(valueChanged(qreal)), this, SLOT(slotSetItemRotation(qreal)));
brushSpacingSelectionWidget->setSpacing(true, 1.0);
connect(brushSpacingSelectionWidget, SIGNAL(sigSpacingChanged()), SLOT(slotSpacingChanged()));
QObject::connect(useColorAsMaskCheckbox, SIGNAL(toggled(bool)), this, SLOT(slotSetItemUseColorAsMask(bool)));
KisBrushResourceServer* rServer = KisBrushServer::instance()->brushServer();
QSharedPointer adapter(new KisBrushResourceServerAdapter(rServer));
m_itemChooser = new KoResourceItemChooser(adapter, this);
m_itemChooser->setObjectName("brush_selector");
m_itemChooser->showTaggingBar(true);
m_itemChooser->setColumnCount(10);
m_itemChooser->setRowHeight(30);
m_itemChooser->setItemDelegate(new KisBrushDelegate(this));
m_itemChooser->setCurrentItem(0, 0);
m_itemChooser->setSynced(true);
m_itemChooser->setMinimumWidth(100);
- m_itemChooser->setMinimumHeight(150);
+ m_itemChooser->setMinimumHeight(50);
m_itemChooser->showButtons(false); // turn the import and delete buttons since we want control over them
KisConfig cfg(true);
m_itemChooser->configureKineticScrolling(cfg.kineticScrollingGesture(),
cfg.kineticScrollingSensitivity(),
cfg.kineticScrollingScrollbar());
addPresetButton->setIcon(KisIconUtils::loadIcon("list-add"));
deleteBrushTipButton->setIcon(KisIconUtils::loadIcon("trash-empty"));
connect(addPresetButton, SIGNAL(clicked(bool)), this, SLOT(slotImportNewBrushResource()));
connect(deleteBrushTipButton, SIGNAL(clicked(bool)), this, SLOT(slotDeleteBrushResource()));
presetsLayout->addWidget(m_itemChooser);
connect(m_itemChooser, SIGNAL(resourceSelected(KoResource *)), this, SLOT(updateBrushTip(KoResource *)));
stampButton->setIcon(KisIconUtils::loadIcon("list-add"));
stampButton->setToolTip(i18n("Creates a brush tip from the current image selection."
"\n If no selection is present the whole image will be used."));
clipboardButton->setIcon(KisIconUtils::loadIcon("list-add"));
clipboardButton->setToolTip(i18n("Creates a brush tip from the image in the clipboard."));
connect(stampButton, SIGNAL(clicked()), this, SLOT(slotOpenStampBrush()));
connect(clipboardButton, SIGNAL(clicked()), SLOT(slotOpenClipboardBrush()));
QGridLayout *spacingLayout = new QGridLayout();
spacingLayout->setObjectName("spacing grid layout");
resetBrushButton->setIcon(KisIconUtils::loadIcon("view-refresh"));
resetBrushButton->setToolTip(i18n("Reloads Spacing from file\nSets Scale to 1.0\nSets Rotation to 0.0"));
connect(resetBrushButton, SIGNAL(clicked()), SLOT(slotResetBrush()));
updateBrushTip(m_itemChooser->currentResource());
}
KisPredefinedBrushChooser::~KisPredefinedBrushChooser()
{
}
void KisPredefinedBrushChooser::setBrush(KisBrushSP brush)
{
/**
* Warning: since the brushes are always cloned after loading from XML or
* fetching from the server, we cannot just ask for that brush explicitly.
* Instead, we should search for the brush with the same filename and/or name
* and load it. Please take it into account that after selecting the brush
* explicitly in the chooser, m_itemChooser->currentResource() might be
* **not** the same as the value in m_brush.
*
* Ideally, if the resource is not found on the server, we should add it, but
* it might lead to a set of weird consequences. So for now we just
* select nothing.
*/
KisBrushResourceServer* server = KisBrushServer::instance()->brushServer();
KoResource *resource = server->resourceByFilename(brush->shortFilename()).data();
if (!resource) {
resource = server->resourceByName(brush->name()).data();
}
if (!resource) {
resource = brush.data();
}
m_itemChooser->setCurrentResource(resource);
updateBrushTip(brush.data(), true);
}
void KisPredefinedBrushChooser::slotResetBrush()
{
/**
* The slot also resets the brush on the server
*
* TODO: technically, after we refactored all the brushes to be forked,
* we can just re-update the brush from the server without reloading.
* But it needs testing.
*/
KisBrush *brush = dynamic_cast(m_itemChooser->currentResource());
if (brush) {
brush->load();
brush->setScale(1.0);
brush->setAngle(0.0);
updateBrushTip(brush);
emit sigBrushChanged();
}
}
void KisPredefinedBrushChooser::slotSetItemSize(qreal sizeValue)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(m_brush);
if (m_brush) {
int brushWidth = m_brush->width();
m_brush->setScale(sizeValue / qreal(brushWidth));
emit sigBrushChanged();
}
}
void KisPredefinedBrushChooser::slotSetItemRotation(qreal rotationValue)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(m_brush);
if (m_brush) {
m_brush->setAngle(rotationValue / 180.0 * M_PI);
emit sigBrushChanged();
}
}
void KisPredefinedBrushChooser::slotSpacingChanged()
{
KIS_SAFE_ASSERT_RECOVER_RETURN(m_brush);
if (m_brush) {
m_brush->setSpacing(brushSpacingSelectionWidget->spacing());
m_brush->setAutoSpacing(brushSpacingSelectionWidget->autoSpacingActive(), brushSpacingSelectionWidget->autoSpacingCoeff());
emit sigBrushChanged();
}
}
void KisPredefinedBrushChooser::slotSetItemUseColorAsMask(bool useColorAsMask)
{
KIS_SAFE_ASSERT_RECOVER_RETURN(m_brush);
KisGbrBrush *brush = dynamic_cast(m_brush.data());
if (brush) {
brush->setUseColorAsMask(useColorAsMask);
emit sigBrushChanged();
}
}
void KisPredefinedBrushChooser::slotOpenStampBrush()
{
if(!m_stampBrushWidget) {
m_stampBrushWidget = new KisCustomBrushWidget(this, i18n("Stamp"), m_image);
m_stampBrushWidget->setModal(false);
connect(m_stampBrushWidget, SIGNAL(sigNewPredefinedBrush(KoResource *)),
SLOT(slotNewPredefinedBrush(KoResource *)));
}
QDialog::DialogCode result = (QDialog::DialogCode)m_stampBrushWidget->exec();
if(result) {
updateBrushTip(m_itemChooser->currentResource());
}
}
void KisPredefinedBrushChooser::slotOpenClipboardBrush()
{
if(!m_clipboardBrushWidget) {
m_clipboardBrushWidget = new KisClipboardBrushWidget(this, i18n("Clipboard"), m_image);
m_clipboardBrushWidget->setModal(true);
connect(m_clipboardBrushWidget, SIGNAL(sigNewPredefinedBrush(KoResource *)),
SLOT(slotNewPredefinedBrush(KoResource *)));
}
QDialog::DialogCode result = (QDialog::DialogCode)m_clipboardBrushWidget->exec();
if(result) {
updateBrushTip(m_itemChooser->currentResource());
}
}
void KisPredefinedBrushChooser::updateBrushTip(KoResource * resource, bool isChangingBrushPresets)
{
QString animatedBrushTipSelectionMode; // incremental, random, etc
{
KisBrush* brush = dynamic_cast(resource);
m_brush = brush ? brush->clone() : 0;
}
if (m_brush) {
brushTipNameLabel->setText(i18n(m_brush->name().toUtf8().data()));
QString brushTypeString = "";
if (m_brush->brushType() == INVALID) {
brushTypeString = i18n("Invalid");
} else if (m_brush->brushType() == MASK) {
brushTypeString = i18n("Mask");
} else if (m_brush->brushType() == IMAGE) {
brushTypeString = i18n("GBR");
} else if (m_brush->brushType() == PIPE_MASK ) {
brushTypeString = i18n("Animated Mask"); // GIH brush
// cast to GIH brush and grab parasite name
//m_brush
KisImagePipeBrush* pipeBrush = dynamic_cast(resource);
animatedBrushTipSelectionMode = pipeBrush->parasiteSelection();
} else if (m_brush->brushType() == PIPE_IMAGE ) {
brushTypeString = i18n("Animated Image");
}
QString brushDetailsText = QString("%1 (%2 x %3) %4")
.arg(brushTypeString)
.arg(m_brush->width())
.arg(m_brush->height())
.arg(animatedBrushTipSelectionMode);
brushDetailsLabel->setText(brushDetailsText);
// keep the current preset's tip settings if we are preserving it
// this will set the brush's model data to keep what it currently has for size, spacing, etc.
if (preserveBrushPresetSettings->isChecked() && !isChangingBrushPresets) {
m_brush->setAutoSpacing(brushSpacingSelectionWidget->autoSpacingActive(), brushSpacingSelectionWidget->autoSpacingCoeff());
m_brush->setAngle(brushRotationSpinBox->value() * M_PI / 180);
m_brush->setSpacing(brushSpacingSelectionWidget->spacing());
m_brush->setUserEffectiveSize(brushSizeSpinBox->value());
}
brushSpacingSelectionWidget->setSpacing(m_brush->autoSpacingActive(),
m_brush->autoSpacingActive() ?
m_brush->autoSpacingCoeff() : m_brush->spacing());
brushRotationSpinBox->setValue(m_brush->angle() * 180 / M_PI);
brushSizeSpinBox->setValue(m_brush->width() * m_brush->scale());
// useColorAsMask support is only in gimp brush so far
KisGbrBrush *gimpBrush = dynamic_cast(m_brush.data());
if (gimpBrush) {
useColorAsMaskCheckbox->setChecked(gimpBrush->useColorAsMask());
}
useColorAsMaskCheckbox->setEnabled(m_brush->hasColor() && gimpBrush);
emit sigBrushChanged();
}
}
void KisPredefinedBrushChooser::slotNewPredefinedBrush(KoResource *resource)
{
m_itemChooser->setCurrentResource(resource);
updateBrushTip(resource);
}
void KisPredefinedBrushChooser::setBrushSize(qreal xPixels, qreal yPixels)
{
Q_UNUSED(yPixels);
qreal oldWidth = m_brush->width() * m_brush->scale();
qreal newWidth = oldWidth + xPixels;
newWidth = qMax(newWidth, qreal(0.1));
brushSizeSpinBox->setValue(newWidth);
}
void KisPredefinedBrushChooser::setImage(KisImageWSP image)
{
m_image = image;
}
void KisPredefinedBrushChooser::slotImportNewBrushResource() {
m_itemChooser->slotButtonClicked(KoResourceItemChooser::Button_Import);
}
void KisPredefinedBrushChooser::slotDeleteBrushResource() {
m_itemChooser->slotButtonClicked(KoResourceItemChooser::Button_Remove);
}
#include "moc_kis_brush_chooser.cpp"
diff --git a/plugins/paintops/libpaintop/kis_brush_selection_widget.cpp b/plugins/paintops/libpaintop/kis_brush_selection_widget.cpp
index 5a97862527..f679712184 100644
--- a/plugins/paintops/libpaintop/kis_brush_selection_widget.cpp
+++ b/plugins/paintops/libpaintop/kis_brush_selection_widget.cpp
@@ -1,362 +1,357 @@
/*
* Copyright (c) 2008 Boudewijn Rempt
* Copyright (c) 2014 Mohit Goyal
*
* 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_brush_selection_widget.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "kis_brush.h"
#include "kis_auto_brush.h"
#include "kis_imagepipe_brush.h"
#include "kis_brush_chooser.h"
#include "kis_auto_brush_widget.h"
#include "kis_custom_brush_widget.h"
#include "kis_clipboard_brush_widget.h"
#include "kis_text_brush_chooser.h"
KisBrushSelectionWidget::KisBrushSelectionWidget(QWidget * parent)
: QWidget(parent), m_currentBrushWidget(0)
{
uiWdgBrushChooser.setupUi(this);
m_buttonGroup = new QButtonGroup(this);
m_buttonGroup->setExclusive(true);
m_layout = new QGridLayout(uiWdgBrushChooser.settingsFrame);
m_autoBrushWidget = new KisAutoBrushWidget(this, "autobrush");
connect(m_autoBrushWidget, SIGNAL(sigBrushChanged()), SIGNAL(sigBrushChanged()));
addChooser(i18n("Auto"), m_autoBrushWidget, AUTOBRUSH, KoGroupButton::GroupLeft);
m_predefinedBrushWidget = new KisPredefinedBrushChooser(this);
connect(m_predefinedBrushWidget, SIGNAL(sigBrushChanged()), SIGNAL(sigBrushChanged()));
addChooser(i18n("Predefined"), m_predefinedBrushWidget, PREDEFINEDBRUSH, KoGroupButton::GroupCenter);
m_textBrushWidget = new KisTextBrushChooser(this, "textbrush", i18n("Text"));
connect(m_textBrushWidget, SIGNAL(sigBrushChanged()), SIGNAL(sigBrushChanged()));
addChooser(i18n("Text"), m_textBrushWidget, TEXTBRUSH, KoGroupButton::GroupRight);
connect(m_buttonGroup, SIGNAL(buttonClicked(int)), this, SLOT(buttonClicked(int)));
- Q_FOREACH (QWidget * widget, m_chooserMap.values()) {
- m_mininmumSize = m_mininmumSize.expandedTo(widget->sizeHint());
- }
-
setCurrentWidget(m_autoBrushWidget);
uiWdgBrushChooser.sizeToStartFromSpinBox->setPrefix(i18n("Starting Brush Size: "));
uiWdgBrushChooser.sizeToStartFromSpinBox->setSuffix(i18n(" px"));
uiWdgBrushChooser.deltaValueSpinBox->setPrefix(i18n("Delta: "));
uiWdgBrushChooser.deltaValueSpinBox->setSuffix(i18n(" px"));
uiWdgBrushChooser.sliderPrecision->setRange(1, 5);
uiWdgBrushChooser.sliderPrecision->setSingleStep(1);
uiWdgBrushChooser.sliderPrecision->setPageStep(1);
connect(uiWdgBrushChooser.sliderPrecision, SIGNAL(valueChanged(int)), SLOT(precisionChanged(int)));
connect(uiWdgBrushChooser.autoPrecisionCheckBox, SIGNAL(stateChanged(int)), SLOT(setAutoPrecisionEnabled(int)));
connect(uiWdgBrushChooser.deltaValueSpinBox, SIGNAL(valueChanged(int)), SLOT(setDeltaValue(int)));
connect(uiWdgBrushChooser.sizeToStartFromSpinBox, SIGNAL(valueChanged(int)), SLOT(setSizeToStartFrom(int)));
uiWdgBrushChooser.sliderPrecision->setValue(4);
setPrecisionEnabled(false);
uiWdgBrushChooser.deltaValueSpinBox->setVisible(false);
uiWdgBrushChooser.sizeToStartFromSpinBox->setVisible(false);
uiWdgBrushChooser.lblPrecisionValue->setVisible(false);
uiWdgBrushChooser.sizeToStartFromSpinBox->setToolTip(i18n("Use to set the size from which the Automatic Precision Setting should begin. \nThe Precision will remain 5 before this value."));
uiWdgBrushChooser.deltaValueSpinBox->setToolTip(i18n("Use to set the interval at which the Automatic Precision will change. \nThe Precision will decrease as brush size increases."));
m_presetIsValid = true;
}
KisBrushSelectionWidget::~KisBrushSelectionWidget()
{
}
KisBrushSP KisBrushSelectionWidget::brush() const
{
KisBrushSP theBrush;
switch (m_buttonGroup->checkedId()) {
case AUTOBRUSH:
theBrush = m_autoBrushWidget->brush();
break;
case PREDEFINEDBRUSH:
theBrush = m_predefinedBrushWidget->brush();
break;
case TEXTBRUSH:
theBrush = m_textBrushWidget->brush();
break;
default:
;
}
// Fallback to auto brush if no brush selected
// Can happen if there is no predefined brush found
if (!theBrush)
theBrush = m_autoBrushWidget->brush();
return theBrush;
}
void KisBrushSelectionWidget::setAutoBrush(bool on)
{
m_buttonGroup->button(AUTOBRUSH)->setVisible(on);
}
void KisBrushSelectionWidget::setPredefinedBrushes(bool on)
{
m_buttonGroup->button(PREDEFINEDBRUSH)->setVisible(on);
}
void KisBrushSelectionWidget::setCustomBrush(bool on)
{
m_buttonGroup->button(CUSTOMBRUSH)->setVisible(on);
}
void KisBrushSelectionWidget::setClipboardBrush(bool on)
{
m_buttonGroup->button(CLIPBOARDBRUSH)->setVisible(on);
}
void KisBrushSelectionWidget::setTextBrush(bool on)
{
m_buttonGroup->button(TEXTBRUSH)->setVisible(on);
}
void KisBrushSelectionWidget::setImage(KisImageWSP image)
{
m_predefinedBrushWidget->setImage(image);
}
void KisBrushSelectionWidget::setCurrentBrush(KisBrushSP brush)
{
if (!brush) {
return;
}
// XXX: clever code have brush plugins know their configuration
// pane, so we don't have to have this if statement and
// have an extensible set of brush types
if (dynamic_cast(brush.data())) {
setCurrentWidget(m_autoBrushWidget);
m_autoBrushWidget->setBrush(brush);
}
else if (dynamic_cast(brush.data())) {
setCurrentWidget(m_textBrushWidget);
m_textBrushWidget->setBrush(brush);
}
else {
setCurrentWidget(m_predefinedBrushWidget);
m_predefinedBrushWidget->setBrush(brush);
}
}
void KisBrushSelectionWidget::buttonClicked(int id)
{
setCurrentWidget(m_chooserMap[id]);
emit sigBrushChanged();
}
void KisBrushSelectionWidget::precisionChanged(int value)
{
QString toolTip;
switch (value) {
case 1:
toolTip =
i18n("Precision Level 1 (fastest)\n"
"Subpixel precision: disabled\n"
"Brush size precision: 5%\n"
"\n"
"Optimal for very big brushes");
break;
case 2:
toolTip =
i18n("Precision Level 2\n"
"Subpixel precision: disabled\n"
"Brush size precision: 1%\n"
"\n"
"Optimal for big brushes");
break;
case 3:
toolTip =
i18n("Precision Level 3\n"
"Subpixel precision: disabled\n"
"Brush size precision: exact");
break;
case 4:
toolTip =
i18n("Precision Level 4 (optimal)\n"
"Subpixel precision: 50%\n"
"Brush size precision: exact\n"
"\n"
"Gives up to 50% better performance in comparison to Level 5");
break;
case 5:
toolTip =
i18n("Precision Level 5 (best quality)\n"
"Subpixel precision: exact\n"
"Brush size precision: exact\n"
"\n"
"The slowest performance. Best quality.");
break;
}
uiWdgBrushChooser.sliderPrecision->blockSignals(true);
uiWdgBrushChooser.sliderPrecision->setValue(value);
uiWdgBrushChooser.sliderPrecision->blockSignals(false);
uiWdgBrushChooser.sliderPrecision->setToolTip(toolTip);
m_precisionOption.setPrecisionLevel(value);
emit sigPrecisionChanged();
}
void KisBrushSelectionWidget::writeOptionSetting(KisPropertiesConfigurationSP settings) const
{
m_precisionOption.writeOptionSetting(settings);
}
void KisBrushSelectionWidget::readOptionSetting(const KisPropertiesConfigurationSP setting)
{
m_precisionOption.readOptionSetting(setting);
uiWdgBrushChooser.sliderPrecision->setValue(m_precisionOption.precisionLevel());
uiWdgBrushChooser.autoPrecisionCheckBox->setChecked(m_precisionOption.autoPrecisionEnabled());
uiWdgBrushChooser.deltaValueSpinBox ->setValue(m_precisionOption.deltaValue());
uiWdgBrushChooser.sizeToStartFromSpinBox ->setValue(m_precisionOption.sizeToStartFrom());
}
void KisBrushSelectionWidget::setPrecisionEnabled(bool value)
{
uiWdgBrushChooser.sliderPrecision->setVisible(value);
}
void KisBrushSelectionWidget::hideOptions(const QStringList &options)
{
Q_FOREACH(const QString &option, options) {
QStringList l = option.split("/");
if (l.count() != 2) {
continue;
}
QObject *o = 0;
if (l[0] == "KisAutoBrushWidget") {
o = m_autoBrushWidget->findChild(l[1]);
}
else if (l[0] == "KisBrushChooser") {
o = m_predefinedBrushWidget->findChild(l[1]);
}
else if (l[0] == "KisTextBrushChooser") {
o = m_textBrushWidget->findChild(l[1]);
}
else {
qWarning() << "KisBrushSelectionWidget: Invalid option given to disable:" << option;
}
if (o) {
QWidget *w = qobject_cast(o);
if (w) {
w->setVisible(false);
}
o = 0;
}
}
}
void KisBrushSelectionWidget::setCurrentWidget(QWidget* widget)
{
if (widget == m_currentBrushWidget) return;
if (m_currentBrushWidget) {
m_layout->removeWidget(m_currentBrushWidget);
m_currentBrushWidget->setParent(this);
m_currentBrushWidget->hide();
}
- widget->setMinimumSize(m_mininmumSize);
m_currentBrushWidget = widget;
m_layout->addWidget(widget);
m_currentBrushWidget->show();
m_buttonGroup->button(m_chooserMap.key(widget))->setChecked(true);
m_presetIsValid = (m_buttonGroup->checkedId() != CUSTOMBRUSH);
}
void KisBrushSelectionWidget::addChooser(const QString& text, QWidget* widget, int id, KoGroupButton::GroupPosition pos)
{
KoGroupButton * button = new KoGroupButton(this);
button->setGroupPosition(pos);
button->setText(text);
button->setAutoRaise(false);
button->setCheckable(true);
uiWdgBrushChooser.brushChooserButtonLayout->addWidget(button);
m_buttonGroup->addButton(button, id);
m_chooserMap[m_buttonGroup->id(button)] = widget;
widget->hide();
}
void KisBrushSelectionWidget::setAutoPrecisionEnabled(int value)
{
m_precisionOption.setAutoPrecisionEnabled(value);
if(m_precisionOption.autoPrecisionEnabled())
{
m_precisionOption.setAutoPrecision(brush()->width());
setPrecisionEnabled(false);
precisionChanged(m_precisionOption.precisionLevel());
uiWdgBrushChooser.deltaValueSpinBox->setVisible(true);
uiWdgBrushChooser.sizeToStartFromSpinBox->setVisible(true);
uiWdgBrushChooser.lblPrecisionValue->setVisible(true);
uiWdgBrushChooser.lblPrecisionValue->setText("Precision:"+QString::number(m_precisionOption.precisionLevel()));
}
else
{
setPrecisionEnabled(true);
uiWdgBrushChooser.deltaValueSpinBox->setVisible(false);
uiWdgBrushChooser.sizeToStartFromSpinBox->setVisible(false);
uiWdgBrushChooser.lblPrecisionValue->setVisible(false);
}
emit sigPrecisionChanged();
}
void KisBrushSelectionWidget::setSizeToStartFrom(int value)
{
m_precisionOption.setSizeToStartFrom((double)value);
emit sigPrecisionChanged();
}
void KisBrushSelectionWidget::setDeltaValue(int value)
{
m_precisionOption.setDeltaValue((double)value);
emit sigPrecisionChanged();
}
#include "moc_kis_brush_selection_widget.cpp"
diff --git a/plugins/paintops/libpaintop/kis_brush_selection_widget.h b/plugins/paintops/libpaintop/kis_brush_selection_widget.h
index 840280903a..c8fb80cbb8 100644
--- a/plugins/paintops/libpaintop/kis_brush_selection_widget.h
+++ b/plugins/paintops/libpaintop/kis_brush_selection_widget.h
@@ -1,117 +1,116 @@
/*
* Copyright (c) 2008 Boudewijn Rempt
* Copyright (c) 2014 Mohit Goyal
*
* 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 KIS_BRUSH_SELECTION_WIDGET_H
#define KIS_BRUSH_SELECTION_WIDGET_H
#include
#include
#include
#include
#include "kis_precision_option.h"
#include "ui_wdgbrushchooser.h"
class KisAutoBrushWidget;
class KisPredefinedBrushChooser;
class KisTextBrushChooser;
class KisCustomBrushWidget;
class KisClipboardBrushWidget;
class KisBrush;
/**
* Compound widget that collects all the various brush selection widgets.
*/
class PAINTOP_EXPORT KisBrushSelectionWidget : public QWidget
{
Q_OBJECT
public:
KisBrushSelectionWidget(QWidget * parent = 0);
~KisBrushSelectionWidget() override;
KisBrushSP brush() const;
void setAutoBrush(bool on);
void setPredefinedBrushes(bool on);
void setCustomBrush(bool on);
void setClipboardBrush(bool on);
void setTextBrush(bool on);
void setImage(KisImageWSP image);
void setCurrentBrush(KisBrushSP brush);
bool presetIsValid() {
return m_presetIsValid;
}
void writeOptionSetting(KisPropertiesConfigurationSP settings) const;
void readOptionSetting(const KisPropertiesConfigurationSP setting);
void setPrecisionEnabled(bool value);
bool autoPrecisionEnabled();
void hideOptions(const QStringList &options);
Q_SIGNALS:
void sigBrushChanged();
void sigPrecisionChanged();
private Q_SLOTS:
void buttonClicked(int id);
void precisionChanged(int value);
void setAutoPrecisionEnabled(int value);
void setSizeToStartFrom(int value);
void setDeltaValue(int value);
private:
void setCurrentWidget(QWidget * widget);
void addChooser(const QString & text, QWidget * widget, int id, KoGroupButton::GroupPosition pos);
private:
enum Type {
AUTOBRUSH,
PREDEFINEDBRUSH,
CUSTOMBRUSH,
TEXTBRUSH,
CLIPBOARDBRUSH
};
bool m_presetIsValid;
Ui_WdgBrushChooser uiWdgBrushChooser;
QGridLayout * m_layout;
QWidget * m_currentBrushWidget;
QHash m_chooserMap;
QButtonGroup * m_buttonGroup;
- QSize m_mininmumSize;
KisAutoBrushWidget * m_autoBrushWidget;
KisPredefinedBrushChooser * m_predefinedBrushWidget;
KisTextBrushChooser * m_textBrushWidget;
KisPrecisionOption m_precisionOption;
};
#endif