diff --git a/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp b/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp index 0a4553176e..76ac20a7e3 100644 --- a/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp +++ b/krita/plugins/extensions/dockers/defaultdockers/kis_layer_box.cpp @@ -1,783 +1,789 @@ /* * kis_layer_box.cc - part of Krita aka Krayon aka KimageShop * * Copyright (c) 2002 Patrick Julien * Copyright (C) 2006 Gábor Lehel * Copyright (C) 2007 Thomas Zander * Copyright (C) 2007 Boudewijn Rempt * Copyright (c) 2011 José Luis Vergara * * 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_box.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 #include #include #include #include #include #include #include #include #include "kis_action.h" #include "kis_action_manager.h" #include "widgets/kis_cmb_composite.h" #include "widgets/kis_slider_spin_box.h" #include "KisViewManager.h" #include "kis_node_manager.h" #include "kis_node_model.h" #include "canvas/kis_canvas2.h" #include "KisDocument.h" #include "kis_dummies_facade_base.h" #include "kis_shape_controller.h" #include "kis_selection_mask.h" #include "kis_config.h" #include "KisView.h" #include "ui_wdglayerbox.h" class ButtonAction : public KisAction { public: ButtonAction(QAbstractButton* button, const KIcon& icon, const QString& text, QObject* parent) : KisAction(icon, text, parent) , m_button(button) { connect(m_button, SIGNAL(clicked()), this, SLOT(trigger())); } ButtonAction(QAbstractButton* button, QObject* parent) : KisAction(parent) , m_button(button) { connect(m_button, SIGNAL(clicked()), this, SLOT(trigger())); } virtual void setActionEnabled(bool enabled) { KisAction::setActionEnabled(enabled); m_button->setEnabled(enabled); } private: QAbstractButton* m_button; }; inline void KisLayerBox::connectActionToButton(KisViewManager* view, QAbstractButton *button, const QString &id) { Q_ASSERT(view); KisAction *action = view->actionManager()->actionByName(id); connect(button, SIGNAL(clicked()), action, SLOT(trigger())); connect(action, SIGNAL(sigEnableSlaves(bool)), button, SLOT(setEnabled(bool))); } inline void KisLayerBox::addActionToMenu(QMenu *menu, const QString &id) { Q_ASSERT(m_canvas); menu->addAction(m_canvas->viewManager()->actionManager()->actionByName(id)); } KisLayerBox::KisLayerBox() : QDockWidget(i18n("Layers")) , m_canvas(0) , m_wdgLayerBox(new Ui_WdgLayerBox) { + KisConfig cfg; + setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); QWidget* mainWidget = new QWidget(this); setWidget(mainWidget); m_opacityDelayTimer.setSingleShot(true); m_wdgLayerBox->setupUi(mainWidget); m_wdgLayerBox->listLayers->setDefaultDropAction(Qt::MoveAction); m_wdgLayerBox->listLayers->setSelectionMode(QAbstractItemView::ExtendedSelection); m_wdgLayerBox->listLayers->setVerticalScrollMode(QAbstractItemView::ScrollPerItem); m_wdgLayerBox->listLayers->setSelectionBehavior(QAbstractItemView::SelectRows); connect(m_wdgLayerBox->listLayers, SIGNAL(contextMenuRequested(const QPoint&, const QModelIndex&)), this, SLOT(slotContextMenuRequested(const QPoint&, const QModelIndex&))); connect(m_wdgLayerBox->listLayers, SIGNAL(collapsed(const QModelIndex&)), SLOT(slotCollapsed(const QModelIndex &))); connect(m_wdgLayerBox->listLayers, SIGNAL(expanded(const QModelIndex&)), SLOT(slotExpanded(const QModelIndex &))); connect(m_wdgLayerBox->listLayers, SIGNAL(selectionChanged(const QModelIndexList&)), SLOT(selectionChanged(const QModelIndexList&))); m_viewModeMenu = new KMenu(this); QActionGroup *group = new QActionGroup(this); QList actions; actions << m_viewModeMenu->addAction(themedIcon("view-list-text"), i18n("Minimal View"), this, SLOT(slotMinimalView())); actions << m_viewModeMenu->addAction(themedIcon("view-list-details"), i18n("Detailed View"), this, SLOT(slotDetailedView())); actions << m_viewModeMenu->addAction(themedIcon("view-preview"), i18n("Thumbnail View"), this, SLOT(slotThumbnailView())); for (int i = 0, n = actions.count(); i < n; ++i) { actions[i]->setCheckable(true); actions[i]->setActionGroup(group); } m_wdgLayerBox->bnAdd->setIcon(themedIcon("addlayer")); m_wdgLayerBox->bnViewMode->setMenu(m_viewModeMenu); m_wdgLayerBox->bnViewMode->setPopupMode(QToolButton::InstantPopup); m_wdgLayerBox->bnViewMode->setIcon(themedIcon("view-choose")); m_wdgLayerBox->bnViewMode->setText(i18n("View mode")); m_wdgLayerBox->bnDelete->setIcon(themedIcon("deletelayer")); m_wdgLayerBox->bnDelete->setIconSize(QSize(22, 22)); m_wdgLayerBox->bnRaise->setEnabled(false); m_wdgLayerBox->bnRaise->setIcon(themedIcon("arrowupblr")); m_wdgLayerBox->bnRaise->setIconSize(QSize(22, 22)); m_wdgLayerBox->bnLower->setEnabled(false); m_wdgLayerBox->bnLower->setIcon(themedIcon("arrowdown")); m_wdgLayerBox->bnLower->setIconSize(QSize(22, 22)); m_wdgLayerBox->bnLeft->setEnabled(true); m_wdgLayerBox->bnLeft->setIcon(themedIcon("removefromfolder")); m_wdgLayerBox->bnLeft->setIconSize(QSize(22, 22)); m_wdgLayerBox->bnRight->setEnabled(true); m_wdgLayerBox->bnRight->setIcon(themedIcon("addtofolder")); m_wdgLayerBox->bnRight->setIconSize(QSize(22, 22)); m_wdgLayerBox->bnProperties->setIcon(themedIcon("properties")); m_wdgLayerBox->bnProperties->setIconSize(QSize(22, 22)); m_wdgLayerBox->bnDuplicate->setIcon(themedIcon("duplicatelayer")); m_wdgLayerBox->bnDuplicate->setIconSize(QSize(22, 22)); m_removeAction = new ButtonAction(m_wdgLayerBox->bnDelete, themedIcon("deletelayer"), i18n("&Remove Layer"), this); m_removeAction->setActivationFlags(KisAction::ACTIVE_NODE); m_removeAction->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); m_removeAction->setObjectName("remove_layer"); connect(m_removeAction, SIGNAL(triggered()), this, SLOT(slotRmClicked())); m_actions.append(m_removeAction); KisAction* action = new ButtonAction(m_wdgLayerBox->bnLeft, this); action->setText(i18n("Move Layer Left")); action->setActivationFlags(KisAction::ACTIVE_NODE); action->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); action->setObjectName("move_layer_left"); connect(action, SIGNAL(triggered()), this, SLOT(slotLeftClicked())); m_actions.append(action); action = new ButtonAction(m_wdgLayerBox->bnRight, this); action->setText(i18n("Move Layer Right")); action->setActivationFlags(KisAction::ACTIVE_NODE); action->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); action->setObjectName("move_layer_right"); connect(action, SIGNAL(triggered()), this, SLOT(slotRightClicked())); m_actions.append(action); m_propertiesAction = new ButtonAction(m_wdgLayerBox->bnProperties, themedIcon("properties"), i18n("&Properties..."),this); m_propertiesAction->setActivationFlags(KisAction::ACTIVE_NODE); m_propertiesAction->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); m_propertiesAction->setObjectName("layer_properties"); connect(m_propertiesAction, SIGNAL(triggered()), this, SLOT(slotPropertiesClicked())); m_actions.append(m_propertiesAction); // NOTE: this is _not_ a mistake. The layerbox shows the layers in the reverse order connect(m_wdgLayerBox->bnRaise, SIGNAL(clicked()), SLOT(slotLowerClicked())); connect(m_wdgLayerBox->bnLower, SIGNAL(clicked()), SLOT(slotRaiseClicked())); // END NOTE + if (cfg.sliderLabels()) { + m_wdgLayerBox->opacityLabel->hide(); + m_wdgLayerBox->doubleOpacity->setPrefix(QString("%1: ").arg(i18n("Opacity"))); + } m_wdgLayerBox->doubleOpacity->setRange(0, 100, 0); m_wdgLayerBox->doubleOpacity->setSuffix("%"); connect(m_wdgLayerBox->doubleOpacity, SIGNAL(valueChanged(qreal)), SLOT(slotOpacitySliderMoved(qreal))); connect(&m_opacityDelayTimer, SIGNAL(timeout()), SLOT(slotOpacityChanged())); connect(m_wdgLayerBox->cmbComposite, SIGNAL(activated(int)), SLOT(slotCompositeOpChanged(int))); m_selectOpaque = new KisAction(i18n("&Select Opaque"), this); m_selectOpaque->setActivationFlags(KisAction::ACTIVE_LAYER); m_selectOpaque->setObjectName("select_opaque"); connect(m_selectOpaque, SIGNAL(triggered(bool)), this, SLOT(slotSelectOpaque())); m_actions.append(m_selectOpaque); m_newLayerMenu = new KMenu(this); m_wdgLayerBox->bnAdd->setMenu(m_newLayerMenu); m_wdgLayerBox->bnAdd->setPopupMode(QToolButton::MenuButtonPopup); m_nodeModel = new KisNodeModel(this); /** * Connect model updateUI() to enable/disable controls. * Note: nodeActivated() is connected separately in setImage(), because * it needs particular order of calls: first the connection to the * node manager should be called, then updateUI() */ connect(m_nodeModel, SIGNAL(rowsInserted(const QModelIndex&, int, int)), SLOT(updateUI())); connect(m_nodeModel, SIGNAL(rowsRemoved(const QModelIndex&, int, int)), SLOT(updateUI())); connect(m_nodeModel, SIGNAL(rowsMoved(const QModelIndex&, int, int, const QModelIndex&, int)), SLOT(updateUI())); connect(m_nodeModel, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), SLOT(updateUI())); connect(m_nodeModel, SIGNAL(modelReset()), SLOT(updateUI())); KisAction *showGlobalSelectionMask = new KisAction(i18n("&Show Global Selection Mask"), this); showGlobalSelectionMask->setObjectName("show-global-selection-mask"); showGlobalSelectionMask->setToolTip(i18nc("@info:tooltip", "Shows global selection as a usual selection mask in Layers docker")); showGlobalSelectionMask->setCheckable(true); connect(showGlobalSelectionMask, SIGNAL(triggered(bool)), SLOT(slotEditGlobalSelection(bool))); m_actions.append(showGlobalSelectionMask); - KisConfig cfg; showGlobalSelectionMask->setChecked(cfg.showGlobalSelection()); m_wdgLayerBox->listLayers->setModel(m_nodeModel); } KisLayerBox::~KisLayerBox() { delete m_wdgLayerBox; } void expandNodesRecursively(KisNodeSP root, QPointer nodeModel, KisDocumentSectionView *sectionView) { if (!root) return; if (nodeModel.isNull()) return; if (!sectionView) return; sectionView->blockSignals(true); KisNodeSP node = root->firstChild(); while (node) { QModelIndex idx = nodeModel->indexFromNode(node); if (idx.isValid()) { if (node->collapsed()) { sectionView->collapse(idx); } } if (node->childCount() > 0) { expandNodesRecursively(node, nodeModel, sectionView); } node = node->nextSibling(); } sectionView->blockSignals(false); } void KisLayerBox::setMainWindow(KisViewManager* kisview) { m_nodeManager = kisview->nodeManager(); foreach(KisAction *action, m_actions) { kisview->actionManager()-> addAction(action->objectName(), action); } connectActionToButton(kisview, m_wdgLayerBox->bnAdd, "add_new_paint_layer"); connectActionToButton(kisview, m_wdgLayerBox->bnDuplicate, "duplicatelayer"); } void KisLayerBox::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != 0); if (m_canvas) { m_canvas->disconnectCanvasObserver(this); m_nodeModel->setDummiesFacade(0, 0, 0); disconnect(m_image, 0, this, 0); disconnect(m_nodeManager, 0, this, 0); disconnect(m_nodeModel, 0, m_nodeManager, 0); disconnect(m_nodeModel, SIGNAL(nodeActivated(KisNodeSP)), this, SLOT(updateUI())); } m_canvas = dynamic_cast(canvas); if (m_canvas) { m_image = m_canvas->image(); connect(m_image, SIGNAL(sigImageUpdated(QRect)), SLOT(updateThumbnail())); KisDocument* doc = static_cast(m_canvas->imageView()->document()); KisShapeController *kritaShapeController = dynamic_cast(doc->shapeController()); KisDummiesFacadeBase *kritaDummiesFacade = static_cast(kritaShapeController); m_nodeModel->setDummiesFacade(kritaDummiesFacade, m_image, kritaShapeController); connect(m_image, SIGNAL(sigAboutToBeDeleted()), SLOT(notifyImageDeleted())); connect(m_image, SIGNAL(sigNodeCollapsedChanged()), SLOT(slotNodeCollapsedChanged())); // cold start if (m_nodeManager) { setCurrentNode(m_nodeManager->activeNode()); } else { setCurrentNode(m_canvas->imageView()->currentNode()); } // Connection KisNodeManager -> KisLayerBox connect(m_nodeManager, SIGNAL(sigUiNeedChangeActiveNode(KisNodeSP)), this, SLOT(setCurrentNode(KisNodeSP))); // Connection KisLayerBox -> KisNodeManager // The order of these connections is important! See comment in the ctor connect(m_nodeModel, SIGNAL(nodeActivated(KisNodeSP)), m_nodeManager, SLOT(slotUiActivatedNode(KisNodeSP))); connect(m_nodeModel, SIGNAL(nodeActivated(KisNodeSP)), SLOT(updateUI())); // Connection KisLayerBox -> KisNodeManager (isolate layer) connect(m_nodeModel, SIGNAL(toggleIsolateActiveNode()), m_nodeManager, SLOT(toggleIsolateActiveNode())); // Node manipulation methods are forwarded to the node manager connect(m_nodeModel, SIGNAL(requestAddNode(KisNodeSP, KisNodeSP, KisNodeSP)), m_nodeManager, SLOT(addNodeDirect(KisNodeSP, KisNodeSP, KisNodeSP))); connect(m_nodeModel, SIGNAL(requestMoveNode(KisNodeSP, KisNodeSP, KisNodeSP)), m_nodeManager, SLOT(moveNodeDirect(KisNodeSP, KisNodeSP, KisNodeSP))); m_wdgLayerBox->listLayers->expandAll(); expandNodesRecursively(m_image->rootLayer(), m_nodeModel, m_wdgLayerBox->listLayers); m_wdgLayerBox->listLayers->scrollTo(m_wdgLayerBox->listLayers->currentIndex()); addActionToMenu(m_newLayerMenu, "add_new_paint_layer"); addActionToMenu(m_newLayerMenu, "add_new_group_layer"); addActionToMenu(m_newLayerMenu, "add_new_clone_layer"); addActionToMenu(m_newLayerMenu, "add_new_shape_layer"); addActionToMenu(m_newLayerMenu, "add_new_adjustment_layer"); addActionToMenu(m_newLayerMenu, "add_new_fill_layer"); addActionToMenu(m_newLayerMenu, "add_new_file_layer"); m_newLayerMenu->addSeparator(); addActionToMenu(m_newLayerMenu, "add_new_transparency_mask"); addActionToMenu(m_newLayerMenu, "add_new_filter_mask"); addActionToMenu(m_newLayerMenu, "add_new_transform_mask"); addActionToMenu(m_newLayerMenu, "add_new_selection_mask"); } } void KisLayerBox::unsetCanvas() { setEnabled(false); if (m_canvas) { m_newLayerMenu->clear(); } setCanvas(0); m_nodeManager->setSelectedNodes(QList()); } void KisLayerBox::notifyImageDeleted() { setCanvas(0); m_nodeManager->setSelectedNodes(QList()); } void KisLayerBox::updateUI() { if (!m_canvas) return; if (!m_nodeManager) return; KisNodeSP activeNode = m_nodeManager->activeNode(); m_wdgLayerBox->bnRaise->setEnabled(activeNode && activeNode->isEditable(false) && (activeNode->nextSibling() || (activeNode->parent() && activeNode->parent() != m_image->root()))); m_wdgLayerBox->bnLower->setEnabled(activeNode && activeNode->isEditable(false) && (activeNode->prevSibling() || (activeNode->parent() && activeNode->parent() != m_image->root()))); m_wdgLayerBox->doubleOpacity->setEnabled(activeNode && activeNode->isEditable(false)); m_wdgLayerBox->cmbComposite->setEnabled(activeNode && activeNode->isEditable(false)); if (activeNode) { if (m_nodeManager->activePaintDevice()) { slotFillCompositeOps(m_nodeManager->activeColorSpace()); } else { slotFillCompositeOps(m_image->colorSpace()); } if (activeNode->inherits("KisMask")) { m_wdgLayerBox->cmbComposite->setEnabled(false); m_wdgLayerBox->doubleOpacity->setEnabled(false); } if (activeNode->inherits("KisLayer")) { m_wdgLayerBox->cmbComposite->setEnabled(true); m_wdgLayerBox->doubleOpacity->setEnabled(true); KisLayerSP l = qobject_cast(activeNode.data()); slotSetOpacity(l->opacity() * 100.0 / 255); const KoCompositeOp* compositeOp = l->compositeOp(); if (compositeOp) { slotSetCompositeOp(compositeOp); } else { m_wdgLayerBox->cmbComposite->setEnabled(false); } } } } /** * This method is callen *only* when non-GUI code requested the * change of the current node */ void KisLayerBox::setCurrentNode(KisNodeSP node) { QModelIndex index = node ? m_nodeModel->indexFromNode(node) : QModelIndex(); m_wdgLayerBox->listLayers->selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); updateUI(); } void KisLayerBox::slotSetCompositeOp(const KoCompositeOp* compositeOp) { KoID opId = KoCompositeOpRegistry::instance().getKoID(compositeOp->id()); m_wdgLayerBox->cmbComposite->blockSignals(true); m_wdgLayerBox->cmbComposite->selectCompositeOp(opId); m_wdgLayerBox->cmbComposite->blockSignals(false); } void KisLayerBox::slotFillCompositeOps(const KoColorSpace* colorSpace) { m_wdgLayerBox->cmbComposite->validate(colorSpace); } // range: 0-100 void KisLayerBox::slotSetOpacity(double opacity) { Q_ASSERT(opacity >= 0 && opacity <= 100); m_wdgLayerBox->doubleOpacity->blockSignals(true); m_wdgLayerBox->doubleOpacity->setValue(opacity); m_wdgLayerBox->doubleOpacity->blockSignals(false); } void KisLayerBox::slotContextMenuRequested(const QPoint &pos, const QModelIndex &index) { QMenu menu; if (index.isValid()) { menu.addAction(m_propertiesAction); menu.addSeparator(); menu.addAction(m_removeAction); addActionToMenu(&menu, "duplicatelayer"); addActionToMenu(&menu, "flatten_image"); addActionToMenu(&menu, "flatten_layer"); // TODO: missing icon "edit-merge" QAction* mergeLayerDown = menu.addAction(i18n("&Merge with Layer Below"), this, SLOT(slotMergeLayer())); if (!index.sibling(index.row() + 1, 0).isValid()) mergeLayerDown->setEnabled(false); menu.addSeparator(); QMenu *convertToMenu = menu.addMenu(i18n("&Convert")); addActionToMenu(convertToMenu, "convert_to_paint_layer"); addActionToMenu(convertToMenu, "convert_to_transparency_mask"); addActionToMenu(convertToMenu, "convert_to_filter_mask"); addActionToMenu(convertToMenu, "convert_to_transform_mask"); addActionToMenu(convertToMenu, "convert_to_selection_mask"); QMenu *splitAlphaMenu = menu.addMenu(i18n("S&plit Alpha")); addActionToMenu(splitAlphaMenu, "split_alpha_into_mask"); addActionToMenu(splitAlphaMenu, "split_alpha_write"); addActionToMenu(splitAlphaMenu, "split_alpha_save_merged"); addActionToMenu(&menu, "isolate_layer"); } menu.addSeparator(); addActionToMenu(&menu, "add_new_transparency_mask"); addActionToMenu(&menu, "add_new_filter_mask"); addActionToMenu(&menu, "add_new_transform_mask"); addActionToMenu(&menu, "add_new_selection_mask"); menu.addSeparator(); menu.addAction(m_selectOpaque); menu.exec(pos); } void KisLayerBox::slotMergeLayer() { if (!m_canvas) return; m_nodeManager->mergeLayerDown(); } void KisLayerBox::slotMinimalView() { m_wdgLayerBox->listLayers->setDisplayMode(KisDocumentSectionView::MinimalMode); } void KisLayerBox::slotDetailedView() { m_wdgLayerBox->listLayers->setDisplayMode(KisDocumentSectionView::DetailedMode); } void KisLayerBox::slotThumbnailView() { m_wdgLayerBox->listLayers->setDisplayMode(KisDocumentSectionView::ThumbnailMode); } void KisLayerBox::slotRmClicked() { if (!m_canvas) return; m_nodeManager->removeNode(); } void KisLayerBox::slotRaiseClicked() { if (!m_canvas) return; KisNodeSP node = m_nodeManager->activeNode(); KisNodeSP parent = node->parent(); KisNodeSP grandParent = parent->parent(); if (!m_nodeManager->activeNode()->prevSibling()) { if (!grandParent) return; if (!grandParent->parent() && node->inherits("KisMask")) return; m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent)); } else { m_nodeManager->raiseNode(); } } void KisLayerBox::slotLowerClicked() { if (!m_canvas) return; KisNodeSP node = m_nodeManager->activeNode(); KisNodeSP parent = node->parent(); KisNodeSP grandParent = parent->parent(); if (!m_nodeManager->activeNode()->nextSibling()) { if (!grandParent) return; if (!grandParent->parent() && node->inherits("KisMask")) return; m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent) + 1); } else { m_nodeManager->lowerNode(); } } void KisLayerBox::slotLeftClicked() { if (!m_canvas) return; foreach(KisNodeSP node, m_nodeManager->selectedNodes()) { KisNodeSP parent = node->parent(); KisNodeSP grandParent = parent->parent(); quint16 nodeIndex = parent->index(node); if (!grandParent) continue; if (!grandParent->parent() && node->inherits("KisMask")) continue; if (nodeIndex <= parent->childCount() / 2) { m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent)); } else { m_nodeManager->moveNodeAt(node, grandParent, grandParent->index(parent) + 1); } } } void KisLayerBox::slotRightClicked() { if (!m_canvas) return; foreach(KisNodeSP node, m_nodeManager->selectedNodes()) { KisNodeSP parent = m_nodeManager->activeNode()->parent(); KisNodeSP newParent; int nodeIndex = parent->index(node); int indexAbove = nodeIndex + 1; int indexBelow = nodeIndex - 1; if (parent->at(indexBelow) && parent->at(indexBelow)->allowAsChild(node)) { newParent = parent->at(indexBelow); m_nodeManager->moveNodeAt(node, newParent, newParent->childCount()); } else if (parent->at(indexAbove) && parent->at(indexAbove)->allowAsChild(node)) { newParent = parent->at(indexAbove); m_nodeManager->moveNodeAt(node, newParent, 0); } } } void KisLayerBox::slotPropertiesClicked() { if (!m_canvas) return; if (KisNodeSP active = m_nodeManager->activeNode()) { m_nodeManager->nodeProperties(active); } } void KisLayerBox::slotCompositeOpChanged(int index) { Q_UNUSED(index); if (!m_canvas) return; QString compositeOp = m_wdgLayerBox->cmbComposite->selectedCompositeOp().id(); m_nodeManager->nodeCompositeOpChanged(m_nodeManager->activeColorSpace()->compositeOp(compositeOp)); } void KisLayerBox::slotOpacityChanged() { if (!m_canvas) return; m_nodeManager->nodeOpacityChanged(m_newOpacity, true); } void KisLayerBox::slotOpacitySliderMoved(qreal opacity) { m_newOpacity = opacity; m_opacityDelayTimer.start(200); } void KisLayerBox::slotCollapsed(const QModelIndex &index) { KisNodeSP node = m_nodeModel->nodeFromIndex(index); if (node) { node->setCollapsed(true); } } void KisLayerBox::slotExpanded(const QModelIndex &index) { KisNodeSP node = m_nodeModel->nodeFromIndex(index); if (node) { node->setCollapsed(false); } } void KisLayerBox::slotSelectOpaque() { if (!m_canvas) return; QAction *action = m_canvas->viewManager()->actionManager()->actionByName("selectopaque"); if (action) { action->trigger(); } } void KisLayerBox::slotNodeCollapsedChanged() { m_wdgLayerBox->listLayers->expandAll(); expandNodesRecursively(m_image->rootLayer(), m_nodeModel, m_wdgLayerBox->listLayers); } inline bool isSelectionMask(KisNodeSP node) { return dynamic_cast(node.data()); } KisNodeSP KisLayerBox::findNonHidableNode(KisNodeSP startNode) { if (isSelectionMask(startNode) && startNode->parent() && !startNode->parent()->parent()) { KisNodeSP node = startNode->prevSibling(); while (node && isSelectionMask(node)) { node = node->prevSibling(); } if (!node) { node = startNode->nextSibling(); while (node && isSelectionMask(node)) { node = node->nextSibling(); } } if (!node) { node = m_image->root()->lastChild(); while (node && isSelectionMask(node)) { node = node->prevSibling(); } } KIS_ASSERT_RECOVER_NOOP(node && "cannot activate any node!"); startNode = node; } return startNode; } void KisLayerBox::slotEditGlobalSelection(bool showSelections) { KisNodeSP lastActiveNode = m_nodeManager->activeNode(); KisNodeSP activateNode = lastActiveNode; if (!showSelections) { activateNode = findNonHidableNode(activateNode); } m_nodeModel->setShowGlobalSelection(showSelections); if (showSelections) { KisNodeSP newMask = m_image->rootLayer()->selectionMask(); if (newMask) { activateNode = newMask; } } if (activateNode) { if (lastActiveNode != activateNode) { m_nodeManager->slotNonUiActivatedNode(activateNode); } else { setCurrentNode(lastActiveNode); } } } void KisLayerBox::selectionChanged(const QModelIndexList selection) { if (!m_nodeManager) return; if (selection.isEmpty() && m_nodeManager->activeNode()) { m_wdgLayerBox->listLayers->selectionModel()-> setCurrentIndex( m_nodeModel->indexFromNode(m_nodeManager->activeNode()), QItemSelectionModel::ClearAndSelect); return; } QList selectedNodes; foreach(const QModelIndex &idx, selection) { selectedNodes << m_nodeModel->nodeFromIndex(idx); } m_nodeManager->setSelectedNodes(selectedNodes); updateUI(); } void KisLayerBox::updateThumbnail() { m_wdgLayerBox->listLayers->updateNode(m_wdgLayerBox->listLayers->currentIndex()); } #include "kis_layer_box.moc" diff --git a/krita/ui/kis_config.cc b/krita/ui/kis_config.cc index 22339bec0f..65aedd0bca 100644 --- a/krita/ui/kis_config.cc +++ b/krita/ui/kis_config.cc @@ -1,1491 +1,1501 @@ /* * Copyright (c) 2002 Patrick Julien * * 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_config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas_resource_provider.h" #include "kis_global.h" #include "kis_config_notifier.h" #include #include namespace { const double IMAGE_DEFAULT_RESOLUTION = 100.0; // dpi const qint32 IMAGE_DEFAULT_WIDTH = 1600; const qint32 IMAGE_DEFAULT_HEIGHT = 1200; const enumCursorStyle DEFAULT_CURSOR_STYLE = CURSOR_STYLE_OUTLINE; const qint32 DEFAULT_MAX_TILES_MEM = 5000; static QMutex s_synchLocker; } KisConfig::KisConfig() : m_cfg(KGlobal::config()->group("")) { } KisConfig::~KisConfig() { s_synchLocker.lock(); m_cfg.sync(); s_synchLocker.unlock(); } bool KisConfig::disableTouchOnCanvas() const { return m_cfg.readEntry("disableTouchOnCanvas", false); } void KisConfig::setDisableTouchOnCanvas(bool value) const { m_cfg.writeEntry("disableTouchOnCanvas", value); } bool KisConfig::useProjections() const { return m_cfg.readEntry("useProjections", true); } void KisConfig::setUseProjections(bool useProj) const { m_cfg.writeEntry("useProjections", useProj); } bool KisConfig::undoEnabled() const { return m_cfg.readEntry("undoEnabled", true); } void KisConfig::setUndoEnabled(bool undo) const { m_cfg.writeEntry("undoEnabled", undo); } int KisConfig::undoStackLimit() const { return m_cfg.readEntry("undoStackLimit", 30); } void KisConfig::setUndoStackLimit(int limit) const { m_cfg.writeEntry("undoStackLimit", limit); } bool KisConfig::useCumulativeUndoRedo() { return m_cfg.readEntry("useCumulativeUndoRedo",false); } void KisConfig::setCumulativeUndoRedo(bool value) { m_cfg.writeEntry("useCumulativeUndoRedo", value); } double KisConfig::stackT1() { return m_cfg.readEntry("stackT1",5); } void KisConfig::setStackT1(int T1) { m_cfg.writeEntry("stackT1", T1); } double KisConfig::stackT2() { return m_cfg.readEntry("stackT2",1); } void KisConfig::setStackT2(int T2) { m_cfg.writeEntry("stackT2", T2); } int KisConfig::stackN() { return m_cfg.readEntry("stackN",5); } void KisConfig::setStackN(int N) { m_cfg.writeEntry("stackN", N); } qint32 KisConfig::defImageWidth() const { return m_cfg.readEntry("imageWidthDef", IMAGE_DEFAULT_WIDTH); } qint32 KisConfig::defImageHeight() const { return m_cfg.readEntry("imageHeightDef", IMAGE_DEFAULT_HEIGHT); } double KisConfig::defImageResolution() const { return m_cfg.readEntry("imageResolutionDef", IMAGE_DEFAULT_RESOLUTION) / 72.0; } QString KisConfig::defColorModel() const { return m_cfg.readEntry("colorModelDef", KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id()); } void KisConfig::defColorModel(const QString & model) const { m_cfg.writeEntry("colorModelDef", model); } QString KisConfig::defaultColorDepth() const { return m_cfg.readEntry("colorDepthDef", KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id()); } void KisConfig::setDefaultColorDepth(const QString & depth) const { m_cfg.writeEntry("colorDepthDef", depth); } QString KisConfig::defColorProfile() const { return m_cfg.readEntry("colorProfileDef", KoColorSpaceRegistry::instance()->rgb8()->profile()->name()); } void KisConfig::defColorProfile(const QString & profile) const { m_cfg.writeEntry("colorProfileDef", profile); } void KisConfig::defImageWidth(qint32 width) const { m_cfg.writeEntry("imageWidthDef", width); } void KisConfig::defImageHeight(qint32 height) const { m_cfg.writeEntry("imageHeightDef", height); } void KisConfig::defImageResolution(double res) const { m_cfg.writeEntry("imageResolutionDef", res*72.0); } bool KisConfig::defAutoFrameBreakEnabled() const { return m_cfg.readEntry("autoFrameBreakEnabled", false); } void KisConfig::defAutoFrameBreakEnabled(bool state) const { m_cfg.writeEntry("autoFrameBreakEnabled", state); } bool KisConfig::defOnionSkinningEnabled() const { return m_cfg.readEntry("onionSkinningEnabled", false); } void KisConfig::defOnionSkinningEnabled(bool state) const { m_cfg.writeEntry("onionSkinningEnabled", state); } int KisConfig::defFps() const { return m_cfg.readEntry("fps", 12); } void KisConfig::defFps(int value) const { m_cfg.writeEntry("fps", value); } int KisConfig::defLocalPlaybackRange() const { return m_cfg.readEntry("localPlaybackRange", 15); } void KisConfig::defLocalPlaybackRange(int value) const { m_cfg.writeEntry("localPlaybackRange", value); } bool KisConfig::defLoopingEnabled() const { return m_cfg.readEntry("loopingEnabled", true); } void KisConfig::defLoopingEnabled(bool state) const { m_cfg.writeEntry("loopingEnabled", state); } enumCursorStyle KisConfig::cursorStyle() const { return (enumCursorStyle) m_cfg.readEntry("cursorStyleDef", int(DEFAULT_CURSOR_STYLE)); } enumCursorStyle KisConfig::getDefaultCursorStyle() const { return DEFAULT_CURSOR_STYLE; } void KisConfig::setCursorStyle(enumCursorStyle style) const { m_cfg.writeEntry("cursorStyleDef", (int)style); } bool KisConfig::useDirtyPresets() const { return m_cfg.readEntry("useDirtyPresets",false); } void KisConfig::setUseDirtyPresets(bool value) { m_cfg.writeEntry("useDirtyPresets",value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::useEraserBrushSize() const { return m_cfg.readEntry("useEraserBrushSize",false); } void KisConfig::setUseEraserBrushSize(bool value) { m_cfg.writeEntry("useEraserBrushSize",value); KisConfigNotifier::instance()->notifyConfigChanged(); } QColor KisConfig::getMDIBackgroundColor() const { QColor col(77, 77, 77); return m_cfg.readEntry("mdiBackgroundColor", col); } void KisConfig::setMDIBackgroundColor(const QColor &v) const { m_cfg.writeEntry("mdiBackgroundColor", v); } QString KisConfig::getMDIBackgroundImage() const { return m_cfg.readEntry("mdiBackgroundImage", ""); } void KisConfig::setMDIBackgroundImage(const QString &filename) const { m_cfg.writeEntry("mdiBackgroundImage", filename); } QString KisConfig::monitorProfile(int screen) const { QString profile = m_cfg.readEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), ""); //qDebug() << "KisConfig::monitorProfile()" << profile; return profile; } QString KisConfig::monitorForScreen(int screen, const QString &defaultMonitor) const { return m_cfg.readEntry(QString("monitor_for_screen_%1").arg(screen), defaultMonitor); } void KisConfig::setMonitorForScreen(int screen, const QString& monitor) { m_cfg.writeEntry(QString("monitor_for_screen_%1").arg(screen), monitor); } void KisConfig::setMonitorProfile(int screen, const QString & monitorProfile, bool override) const { m_cfg.writeEntry("monitorProfile/OverrideX11", override); m_cfg.writeEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), monitorProfile); } const KoColorProfile *KisConfig::getScreenProfile(int screen) { KisConfig cfg; QString monitorId = cfg.monitorForScreen(screen, ""); if (monitorId.isEmpty()) { return 0; } QByteArray bytes = KisColorManager::instance()->displayProfile(monitorId); if (bytes.length() > 0) { const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(RGBAColorModelID.id(), Integer8BitsColorDepthID.id(), bytes); //qDebug() << "KisConfig::getScreenProfile for screen" << screen << profile->name(); return profile; } else { //qDebug() << "Could not get a system monitor profile"; return 0; } } const KoColorProfile *KisConfig::displayProfile(int screen) const { // if the user plays with the settings, they can override the display profile, in which case // we don't want the system setting. bool override = m_cfg.readEntry("monitorProfile/OverrideX11", false); //qDebug() << "KisConfig::displayProfile(). Override X11:" << override; const KoColorProfile *profile = 0; if (override) { //qDebug() << "\tGoing to get the screen profile"; profile = KisConfig::getScreenProfile(screen); } // if it fails. check the configuration if (!profile || !profile->isSuitableForDisplay()) { //ebug() << "\tGoing to get the monitor profile"; QString monitorProfileName = monitorProfile(screen); //qDebug() << "\t\tmonitorProfileName:" << monitorProfileName; if (!monitorProfileName.isEmpty()) { profile = KoColorSpaceRegistry::instance()->profileByName(monitorProfileName); } if (profile) { //qDebug() << "\t\tsuitable for display6" << profile->isSuitableForDisplay(); } else { //qDebug() << "\t\tstill no profile"; } } // if we still don't have a profile, or the profile isn't suitable for display, // we need to get a last-resort profile. the built-in sRGB is a good choice then. if (!profile || !profile->isSuitableForDisplay()) { //qDebug() << "\tnothing worked, going to get sRGB built-in"; profile = KoColorSpaceRegistry::instance()->profileByName("sRGB Built-in"); } if (profile) { //qDebug() << "\tKisConfig::displayProfile for screen" << screen << "is" << profile->name(); } else { //qDebug() << "\tCOuldn't get a display profile at all"; } return profile; } QString KisConfig::workingColorSpace() const { return m_cfg.readEntry("workingColorSpace", "RGBA"); } void KisConfig::setWorkingColorSpace(const QString & workingColorSpace) const { m_cfg.writeEntry("workingColorSpace", workingColorSpace); } QString KisConfig::printerColorSpace() const { //TODO currently only rgb8 is supported //return m_cfg.readEntry("printerColorSpace", "RGBA"); return QString("RGBA"); } void KisConfig::setPrinterColorSpace(const QString & printerColorSpace) const { m_cfg.writeEntry("printerColorSpace", printerColorSpace); } QString KisConfig::printerProfile() const { return m_cfg.readEntry("printerProfile", ""); } void KisConfig::setPrinterProfile(const QString & printerProfile) const { m_cfg.writeEntry("printerProfile", printerProfile); } bool KisConfig::useBlackPointCompensation() const { return m_cfg.readEntry("useBlackPointCompensation", true); } void KisConfig::setUseBlackPointCompensation(bool useBlackPointCompensation) const { m_cfg.writeEntry("useBlackPointCompensation", useBlackPointCompensation); } bool KisConfig::allowLCMSOptimization() const { return m_cfg.readEntry("allowLCMSOptimization", true); } void KisConfig::setAllowLCMSOptimization(bool allowLCMSOptimization) { m_cfg.writeEntry("allowLCMSOptimization", allowLCMSOptimization); } bool KisConfig::showRulers() const { return m_cfg.readEntry("showrulers", false); } void KisConfig::setShowRulers(bool rulers) const { m_cfg.writeEntry("showrulers", rulers); } qint32 KisConfig::pasteBehaviour() const { return m_cfg.readEntry("pasteBehaviour", 2); } void KisConfig::setPasteBehaviour(qint32 renderIntent) const { m_cfg.writeEntry("pasteBehaviour", renderIntent); } qint32 KisConfig::renderIntent() const { qint32 intent = m_cfg.readEntry("renderIntent", INTENT_PERCEPTUAL); if (intent > 3) intent = 3; if (intent < 0) intent = 0; return intent; } void KisConfig::setRenderIntent(qint32 renderIntent) const { if (renderIntent > 3) renderIntent = 3; if (renderIntent < 0) renderIntent = 0; m_cfg.writeEntry("renderIntent", renderIntent); } bool KisConfig::useOpenGL() const { if (qApp->applicationName() == "krita" || qApp->applicationName() == "kritaanimation") { //qDebug() << "use opengl" << m_cfg.readEntry("useOpenGL", true) << "success" << m_cfg.readEntry("canvasState", "OPENGL_SUCCESS"); QString canvasState = m_cfg.readEntry("canvasState", "OPENGL_SUCCESS"); return (m_cfg.readEntry("useOpenGL", true) && (canvasState == "OPENGL_SUCCESS" || canvasState == "TRY_OPENGL")); } else if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { return true; // for sketch and gemini } else { return false; } } void KisConfig::setUseOpenGL(bool useOpenGL) const { m_cfg.writeEntry("useOpenGL", useOpenGL); } int KisConfig::openGLFilteringMode() const { return m_cfg.readEntry("OpenGLFilterMode", 3); } void KisConfig::setOpenGLFilteringMode(int filteringMode) { m_cfg.writeEntry("OpenGLFilterMode", filteringMode); } bool KisConfig::useOpenGLTextureBuffer() const { return m_cfg.readEntry("useOpenGLTextureBuffer", true); } void KisConfig::setUseOpenGLTextureBuffer(bool useBuffer) { m_cfg.writeEntry("useOpenGLTextureBuffer", useBuffer); } int KisConfig::openGLTextureSize() const { return m_cfg.readEntry("textureSize", 256); } bool KisConfig::disableDoubleBuffering() const { return m_cfg.readEntry("disableDoubleBuffering", true); } void KisConfig::setDisableDoubleBuffering(bool disableDoubleBuffering) { m_cfg.writeEntry("disableDoubleBuffering", disableDoubleBuffering); } bool KisConfig::disableVSync() const { return m_cfg.readEntry("disableVSync", true); } void KisConfig::setDisableVSync(bool disableVSync) { m_cfg.writeEntry("disableVSync", disableVSync); } bool KisConfig::showAdvancedOpenGLSettings() const { return m_cfg.readEntry("showAdvancedOpenGLSettings", false); } bool KisConfig::forceOpenGLFenceWorkaround() const { return m_cfg.readEntry("forceOpenGLFenceWorkaround", false); } int KisConfig::numMipmapLevels() const { return m_cfg.readEntry("numMipmapLevels", 4); } int KisConfig::textureOverlapBorder() const { return 1 << qMax(0, numMipmapLevels()); } qint32 KisConfig::maxNumberOfThreads() { return m_cfg.readEntry("maxthreads", QThread::idealThreadCount()); } void KisConfig::setMaxNumberOfThreads(qint32 maxThreads) { m_cfg.writeEntry("maxthreads", maxThreads); } qint32 KisConfig::maxTilesInMem() const { return m_cfg.readEntry("maxtilesinmem", DEFAULT_MAX_TILES_MEM); } void KisConfig::setMaxTilesInMem(qint32 tiles) const { m_cfg.writeEntry("maxtilesinmem", tiles); } quint32 KisConfig::getGridMainStyle() const { quint32 v = m_cfg.readEntry("gridmainstyle", 0); if (v > 2) v = 2; return v; } void KisConfig::setGridMainStyle(quint32 v) const { m_cfg.writeEntry("gridmainstyle", v); } quint32 KisConfig::getGridSubdivisionStyle() const { quint32 v = m_cfg.readEntry("gridsubdivisionstyle", 1); if (v > 2) v = 2; return v; } void KisConfig::setGridSubdivisionStyle(quint32 v) const { m_cfg.writeEntry("gridsubdivisionstyle", v); } QColor KisConfig::getGridMainColor() const { QColor col(99, 99, 99); return m_cfg.readEntry("gridmaincolor", col); } void KisConfig::setGridMainColor(const QColor & v) const { m_cfg.writeEntry("gridmaincolor", v); } QColor KisConfig::getGridSubdivisionColor() const { QColor col(150, 150, 150); return m_cfg.readEntry("gridsubdivisioncolor", col); } void KisConfig::setGridSubdivisionColor(const QColor & v) const { m_cfg.writeEntry("gridsubdivisioncolor", v); } quint32 KisConfig::getGridHSpacing() const { qint32 v = m_cfg.readEntry("gridhspacing", 10); return (quint32)qMax(1, v); } void KisConfig::setGridHSpacing(quint32 v) const { m_cfg.writeEntry("gridhspacing", v); } quint32 KisConfig::getGridVSpacing() const { qint32 v = m_cfg.readEntry("gridvspacing", 10); return (quint32)qMax(1, v); } void KisConfig::setGridVSpacing(quint32 v) const { m_cfg.writeEntry("gridvspacing", v); } bool KisConfig::getGridSpacingAspect() const { bool v = m_cfg.readEntry("gridspacingaspect", false); return v; } void KisConfig::setGridSpacingAspect(bool v) const { m_cfg.writeEntry("gridspacingaspect", v); } quint32 KisConfig::getGridSubdivisions() const { qint32 v = m_cfg.readEntry("gridsubsivisons", 2); return (quint32)qMax(1, v); } void KisConfig::setGridSubdivisions(quint32 v) const { m_cfg.writeEntry("gridsubsivisons", v); } quint32 KisConfig::getGridOffsetX() const { qint32 v = m_cfg.readEntry("gridoffsetx", 0); return (quint32)qMax(0, v); } void KisConfig::setGridOffsetX(quint32 v) const { m_cfg.writeEntry("gridoffsetx", v); } quint32 KisConfig::getGridOffsetY() const { qint32 v = m_cfg.readEntry("gridoffsety", 0); return (quint32)qMax(0, v); } void KisConfig::setGridOffsetY(quint32 v) const { m_cfg.writeEntry("gridoffsety", v); } bool KisConfig::getGridOffsetAspect() const { bool v = m_cfg.readEntry("gridoffsetaspect", false); return v; } void KisConfig::setGridOffsetAspect(bool v) const { m_cfg.writeEntry("gridoffsetaspect", v); } qint32 KisConfig::checkSize() const { return m_cfg.readEntry("checksize", 32); } void KisConfig::setCheckSize(qint32 checksize) const { m_cfg.writeEntry("checksize", checksize); } bool KisConfig::scrollCheckers() const { return m_cfg.readEntry("scrollingcheckers", false); } void KisConfig::setScrollingCheckers(bool sc) const { m_cfg.writeEntry("scrollingcheckers", sc); } QColor KisConfig::canvasBorderColor() const { QColor color(QColor(128,128,128)); return m_cfg.readEntry("canvasBorderColor", color); } void KisConfig::setCanvasBorderColor(const QColor& color) const { m_cfg.writeEntry("canvasBorderColor", color); } bool KisConfig::hideScrollbars() const { return m_cfg.readEntry("hideScrollbars", false); } void KisConfig::setHideScrollbars(bool value) const { m_cfg.writeEntry("hideScrollbars", value); } QColor KisConfig::checkersColor1() const { QColor col(220, 220, 220); return m_cfg.readEntry("checkerscolor", col); } void KisConfig::setCheckersColor1(const QColor & v) const { m_cfg.writeEntry("checkerscolor", v); } QColor KisConfig::checkersColor2() const { return m_cfg.readEntry("checkerscolor2", QColor(Qt::white)); } void KisConfig::setCheckersColor2(const QColor & v) const { m_cfg.writeEntry("checkerscolor2", v); } bool KisConfig::antialiasCurves() const { return m_cfg.readEntry("antialiascurves", true); } void KisConfig::setAntialiasCurves(bool v) const { m_cfg.writeEntry("antialiascurves", v); } QColor KisConfig::selectionOverlayMaskColor() const { QColor def(255, 0, 0, 220); return m_cfg.readEntry("selectionOverlayMaskColor", def); } void KisConfig::setSelectionOverlayMaskColor(const QColor &color) { m_cfg.writeEntry("selectionOverlayMaskColor", color); } bool KisConfig::antialiasSelectionOutline() const { return m_cfg.readEntry("AntialiasSelectionOutline", false); } void KisConfig::setAntialiasSelectionOutline(bool v) const { m_cfg.writeEntry("AntialiasSelectionOutline", v); } bool KisConfig::showRootLayer() const { return m_cfg.readEntry("ShowRootLayer", false); } void KisConfig::setShowRootLayer(bool showRootLayer) const { m_cfg.writeEntry("ShowRootLayer", showRootLayer); } bool KisConfig::showGlobalSelection() const { return m_cfg.readEntry("ShowGlobalSelection", false); } void KisConfig::setShowGlobalSelection(bool showGlobalSelection) const { m_cfg.writeEntry("ShowGlobalSelection", showGlobalSelection); } bool KisConfig::showOutlineWhilePainting() const { return m_cfg.readEntry("ShowOutlineWhilePainting", true); } void KisConfig::setShowOutlineWhilePainting(bool showOutlineWhilePainting) const { m_cfg.writeEntry("ShowOutlineWhilePainting", showOutlineWhilePainting); } qreal KisConfig::outlineSizeMinimum() const { return m_cfg.readEntry("OutlineSizeMinimum", 1.0); } void KisConfig::setOutlineSizeMinimum(qreal outlineSizeMinimum) const { m_cfg.writeEntry("OutlineSizeMinimum", outlineSizeMinimum); } int KisConfig::autoSaveInterval() const { return m_cfg.readEntry("AutoSaveInterval", KisDocument::defaultAutoSave()); } void KisConfig::setAutoSaveInterval(int seconds) const { return m_cfg.writeEntry("AutoSaveInterval", seconds); } bool KisConfig::backupFile() const { return m_cfg.readEntry("CreateBackupFile", true); } void KisConfig::setBackupFile(bool backupFile) const { m_cfg.writeEntry("CreateBackupFile", backupFile); } bool KisConfig::showFilterGallery() const { return m_cfg.readEntry("showFilterGallery", false); } void KisConfig::setShowFilterGallery(bool showFilterGallery) const { m_cfg.writeEntry("showFilterGallery", showFilterGallery); } bool KisConfig::showFilterGalleryLayerMaskDialog() const { return m_cfg.readEntry("showFilterGalleryLayerMaskDialog", true); } void KisConfig::setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const { m_cfg.writeEntry("setShowFilterGalleryLayerMaskDialog", showFilterGallery); } QString KisConfig::defaultPainterlyColorModelId() const { return m_cfg.readEntry("defaultpainterlycolormodel", "KS6"); } void KisConfig::setDefaultPainterlyColorModelId(const QString& def) const { m_cfg.writeEntry("defaultpainterlycolormodel", def); } QString KisConfig::defaultPainterlyColorDepthId() const { return m_cfg.readEntry("defaultpainterlycolordepth", "F32"); } void KisConfig::setDefaultPainterlyColorDepthId(const QString& def) const { m_cfg.writeEntry("defaultpainterlycolordepth", def); } QString KisConfig::canvasState() const { return m_cfg.readEntry("canvasState", "OPENGL_NOT_TRIED"); } void KisConfig::setCanvasState(const QString& state) const { static QStringList acceptableStates; if (acceptableStates.isEmpty()) { acceptableStates << "OPENGL_SUCCESS" << "TRY_OPENGL" << "OPENGL_NOT_TRIED" << "OPENGL_FAILED"; } if (acceptableStates.contains(state)) { m_cfg.writeEntry("canvasState", state); m_cfg.sync(); } } bool KisConfig::paintopPopupDetached() const { return m_cfg.readEntry("PaintopPopupDetached", false); } void KisConfig::setPaintopPopupDetached(bool detached) const { m_cfg.writeEntry("PaintopPopupDetached", detached); } QString KisConfig::pressureTabletCurve() const { return m_cfg.readEntry("tabletPressureCurve","0,0;1,1;"); } void KisConfig::setPressureTabletCurve(const QString& curveString) const { m_cfg.writeEntry("tabletPressureCurve", curveString); } qreal KisConfig::vastScrolling() const { return m_cfg.readEntry("vastScrolling", 0.9); } void KisConfig::setVastScrolling(const qreal factor) const { m_cfg.writeEntry("vastScrolling", factor); } int KisConfig::presetChooserViewMode() const { return m_cfg.readEntry("presetChooserViewMode", 0); } void KisConfig::setPresetChooserViewMode(const int mode) const { m_cfg.writeEntry("presetChooserViewMode", mode); } bool KisConfig::firstRun() const { return m_cfg.readEntry("firstRun", true); } void KisConfig::setFirstRun(const bool first) const { m_cfg.writeEntry("firstRun", first); } int KisConfig::horizontalSplitLines() const { return m_cfg.readEntry("horizontalSplitLines", 1); } void KisConfig::setHorizontalSplitLines(const int numberLines) const { m_cfg.writeEntry("horizontalSplitLines", numberLines); } int KisConfig::verticalSplitLines() const { return m_cfg.readEntry("verticalSplitLines", 1); } void KisConfig::setVerticalSplitLines(const int numberLines) const { m_cfg.writeEntry("verticalSplitLines", numberLines); } bool KisConfig::clicklessSpacePan() const { return m_cfg.readEntry("clicklessSpacePan", true); } void KisConfig::setClicklessSpacePan(const bool toggle) const { m_cfg.writeEntry("clicklessSpacePan", toggle); } int KisConfig::hideDockersFullscreen() const { return m_cfg.readEntry("hideDockersFullScreen", (int)Qt::Checked); } void KisConfig::setHideDockersFullscreen(const int value) const { m_cfg.writeEntry("hideDockersFullScreen", value); } bool KisConfig::showDockerTitleBars() const { return m_cfg.readEntry("showDockerTitleBars", true); } void KisConfig::setShowDockerTitleBars(const bool value) const { m_cfg.writeEntry("showDockerTitleBars", value); } int KisConfig::hideMenuFullscreen() const { return m_cfg.readEntry("hideMenuFullScreen", (int)Qt::Checked); } void KisConfig::setHideMenuFullscreen(const int value) const { m_cfg.writeEntry("hideMenuFullScreen", value); } int KisConfig::hideScrollbarsFullscreen() const { return m_cfg.readEntry("hideScrollbarsFullScreen", (int)Qt::Checked); } void KisConfig::setHideScrollbarsFullscreen(const int value) const { m_cfg.writeEntry("hideScrollbarsFullScreen", value); } int KisConfig::hideStatusbarFullscreen() const { return m_cfg.readEntry("hideStatusbarFullScreen", (int)Qt::Checked); } void KisConfig::setHideStatusbarFullscreen(const int value) const { m_cfg.writeEntry("hideStatusbarFullScreen", value); } int KisConfig::hideTitlebarFullscreen() const { return m_cfg.readEntry("hideTitleBarFullscreen", (int)Qt::Checked); } void KisConfig::setHideTitlebarFullscreen(const int value) const { m_cfg.writeEntry("hideTitleBarFullscreen", value); } int KisConfig::hideToolbarFullscreen() const { return m_cfg.readEntry("hideToolbarFullscreen", (int)Qt::Checked); } void KisConfig::setHideToolbarFullscreen(const int value) const { m_cfg.writeEntry("hideToolbarFullscreen", value); } QStringList KisConfig::favoriteCompositeOps() const { return m_cfg.readEntry("favoriteCompositeOps", QStringList()); } void KisConfig::setFavoriteCompositeOps(const QStringList& compositeOps) const { m_cfg.writeEntry("favoriteCompositeOps", compositeOps); } QString KisConfig::exportConfiguration(const QString &filterId) const { return m_cfg.readEntry("ExportConfiguration-" + filterId, QString()); } void KisConfig::setExportConfiguration(const QString &filterId, const KisPropertiesConfiguration &properties) const { QString exportConfig = properties.toXML(); m_cfg.writeEntry("ExportConfiguration-" + filterId, exportConfig); } bool KisConfig::useOcio() const { #ifdef HAVE_OCIO return m_cfg.readEntry("Krita/Ocio/UseOcio", false); #else return false; #endif } void KisConfig::setUseOcio(bool useOCIO) const { m_cfg.writeEntry("Krita/Ocio/UseOcio", useOCIO); } int KisConfig::favoritePresets() const { return m_cfg.readEntry("favoritePresets", 10); } void KisConfig::setFavoritePresets(const int value) { m_cfg.writeEntry("favoritePresets", value); } KisConfig::OcioColorManagementMode KisConfig::ocioColorManagementMode() const { return (OcioColorManagementMode) m_cfg.readEntry("Krita/Ocio/OcioColorManagementMode", (int) INTERNAL); } void KisConfig::setOcioColorManagementMode(OcioColorManagementMode mode) const { m_cfg.writeEntry("Krita/Ocio/OcioColorManagementMode", (int) mode); } QString KisConfig::ocioConfigurationPath() const { return m_cfg.readEntry("Krita/Ocio/OcioConfigPath", QString()); } void KisConfig::setOcioConfigurationPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioConfigPath", path); } QString KisConfig::ocioLutPath() const { return m_cfg.readEntry("Krita/Ocio/OcioLutPath", QString()); } void KisConfig::setOcioLutPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioLutPath", path); } int KisConfig::ocioLutEdgeSize() const { return m_cfg.readEntry("Krita/Ocio/LutEdgeSize", 64); } void KisConfig::setOcioLutEdgeSize(int value) { m_cfg.writeEntry("Krita/Ocio/LutEdgeSize", value); } bool KisConfig::ocioLockColorVisualRepresentation() const { return m_cfg.readEntry("Krita/Ocio/OcioLockColorVisualRepresentation", false); } void KisConfig::setOcioLockColorVisualRepresentation(bool value) { m_cfg.writeEntry("Krita/Ocio/OcioLockColorVisualRepresentation", value); } QString KisConfig::defaultPalette() const { return m_cfg.readEntry("defaultPalette", QString()); } void KisConfig::setDefaultPalette(const QString& name) const { m_cfg.writeEntry("defaultPalette", name); } QString KisConfig::toolbarSlider(int sliderNumber) { QString def = "flow"; if (sliderNumber == 1) { def = "opacity"; } if (sliderNumber == 2) { def = "size"; } return m_cfg.readEntry(QString("toolbarslider_%1").arg(sliderNumber), def); } void KisConfig::setToolbarSlider(int sliderNumber, const QString &slider) { m_cfg.writeEntry(QString("toolbarslider_%1").arg(sliderNumber), slider); } +bool KisConfig::sliderLabels() const +{ + return m_cfg.readEntry("sliderLabels", true); +} + +void KisConfig::setSliderLabels(bool enabled) +{ + m_cfg.writeEntry("sliderLabels", enabled); +} + QString KisConfig::currentInputProfile() const { return m_cfg.readEntry("currentInputProfile", QString()); } void KisConfig::setCurrentInputProfile(const QString& name) { m_cfg.writeEntry("currentInputProfile", name); } bool KisConfig::useSystemMonitorProfile() const { return m_cfg.readEntry("ColorManagement/UseSystemMonitorProfile", false); } void KisConfig::setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const { m_cfg.writeEntry("ColorManagement/UseSystemMonitorProfile", _useSystemMonitorProfile); } bool KisConfig::presetStripVisible() const { return m_cfg.readEntry("presetStripVisible", true); } void KisConfig::setPresetStripVisible(bool visible) { m_cfg.writeEntry("presetStripVisible", visible); } bool KisConfig::scratchpadVisible() const { return m_cfg.readEntry("scratchpadVisible", true); } void KisConfig::setScratchpadVisible(bool visible) { m_cfg.writeEntry("scratchpadVisible", visible); } bool KisConfig::showSingleChannelAsColor() const { return m_cfg.readEntry("showSingleChannelAsColor", false); } void KisConfig::setShowSingleChannelAsColor(bool asColor) { m_cfg.writeEntry("showSingleChannelAsColor", asColor); } bool KisConfig::hidePopups() const { return m_cfg.readEntry("hidePopups", false); } void KisConfig::setHidePopups(bool hidepopups) { m_cfg.writeEntry("hidePopups", hidepopups); } int KisConfig::numDefaultLayers() const { return m_cfg.readEntry("NumberOfLayersForNewImage", 2); } void KisConfig::setNumDefaultLayers(int num) { m_cfg.writeEntry("NumberOfLayersForNewImage", num); } quint8 KisConfig::defaultBackgroundOpacity() const { return m_cfg.readEntry("BackgroundOpacityForNewImage", (int)OPACITY_OPAQUE_U8); } void KisConfig::setDefaultBackgroundOpacity(quint8 value) { m_cfg.writeEntry("BackgroundOpacityForNewImage", (int)value); } QColor KisConfig::defaultBackgroundColor() const { return m_cfg.readEntry("BackgroundColorForNewImage", QColor(Qt::white)); } void KisConfig::setDefaultBackgroundColor(QColor value) { m_cfg.writeEntry("BackgroundColorForNewImage", value); } KisConfig::BackgroundStyle KisConfig::defaultBackgroundStyle() const { return (KisConfig::BackgroundStyle)m_cfg.readEntry("BackgroundStyleForNewImage", (int)LAYER); } void KisConfig::setDefaultBackgroundStyle(KisConfig::BackgroundStyle value) { m_cfg.writeEntry("BackgroundStyleForNewImage", (int)value); } int KisConfig::lineSmoothingType() const { return m_cfg.readEntry("LineSmoothingType", 1); } void KisConfig::setLineSmoothingType(int value) { m_cfg.writeEntry("LineSmoothingType", value); } qreal KisConfig::lineSmoothingDistance() const { return m_cfg.readEntry("LineSmoothingDistance", 50.0); } void KisConfig::setLineSmoothingDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDistance", value); } qreal KisConfig::lineSmoothingTailAggressiveness() const { return m_cfg.readEntry("LineSmoothingTailAggressiveness", 0.15); } void KisConfig::setLineSmoothingTailAggressiveness(qreal value) { m_cfg.writeEntry("LineSmoothingTailAggressiveness", value); } bool KisConfig::lineSmoothingSmoothPressure() const { return m_cfg.readEntry("LineSmoothingSmoothPressure", false); } void KisConfig::setLineSmoothingSmoothPressure(bool value) { m_cfg.writeEntry("LineSmoothingSmoothPressure", value); } bool KisConfig::lineSmoothingScalableDistance() const { return m_cfg.readEntry("LineSmoothingScalableDistance", true); } void KisConfig::setLineSmoothingScalableDistance(bool value) { m_cfg.writeEntry("LineSmoothingScalableDistance", value); } qreal KisConfig::lineSmoothingDelayDistance() const { return m_cfg.readEntry("LineSmoothingDelayDistance", 50.0); } void KisConfig::setLineSmoothingDelayDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDelayDistance", value); } bool KisConfig::lineSmoothingUseDelayDistance() const { return m_cfg.readEntry("LineSmoothingUseDelayDistance", true); } void KisConfig::setLineSmoothingUseDelayDistance(bool value) { m_cfg.writeEntry("LineSmoothingUseDelayDistance", value); } bool KisConfig::lineSmoothingFinishStabilizedCurve() const { return m_cfg.readEntry("LineSmoothingFinishStabilizedCurve", true); } void KisConfig::setLineSmoothingFinishStabilizedCurve(bool value) { m_cfg.writeEntry("LineSmoothingFinishStabilizedCurve", value); } bool KisConfig::lineSmoothingStabilizeSensors() const { return m_cfg.readEntry("LineSmoothingStabilizeSensors", true); } void KisConfig::setLineSmoothingStabilizeSensors(bool value) { m_cfg.writeEntry("LineSmoothingStabilizeSensors", value); } int KisConfig::paletteDockerPaletteViewSectionSize() const { return m_cfg.readEntry("paletteDockerPaletteViewSectionSize", 12); } void KisConfig::setPaletteDockerPaletteViewSectionSize(int value) const { m_cfg.writeEntry("paletteDockerPaletteViewSectionSize", value); } int KisConfig::tabletEventsDelay() const { return m_cfg.readEntry("tabletEventsDelay", 10); } void KisConfig::setTabletEventsDelay(int value) { m_cfg.writeEntry("tabletEventsDelay", value); } bool KisConfig::testingAcceptCompressedTabletEvents() const { return m_cfg.readEntry("testingAcceptCompressedTabletEvents", false); } void KisConfig::setTestingAcceptCompressedTabletEvents(bool value) { m_cfg.writeEntry("testingAcceptCompressedTabletEvents", value); } bool KisConfig::testingCompressBrushEvents() const { return m_cfg.readEntry("testingCompressBrushEvents", false); } void KisConfig::setTestingCompressBrushEvents(bool value) { m_cfg.writeEntry("testingCompressBrushEvents", value); } bool KisConfig::useVerboseOpenGLDebugOutput() const { return m_cfg.readEntry("useVerboseOpenGLDebugOutput", false); } int KisConfig::workaroundX11SmoothPressureSteps() const { return m_cfg.readEntry("workaroundX11SmoothPressureSteps", 0); } bool KisConfig::showCanvasMessages() const { return m_cfg.readEntry("showOnCanvasMessages", true); } void KisConfig::setShowCanvasMessages(bool show) { m_cfg.writeEntry("showOnCanvasMessages", show); } const KoColorSpace* KisConfig::customColorSelectorColorSpace() const { const KoColorSpace *cs = 0; KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); if(cfg.readEntry("useCustomColorSpace", true)) { KoColorSpaceRegistry* csr = KoColorSpaceRegistry::instance(); cs = csr->colorSpace(cfg.readEntry("customColorSpaceModel", "RGBA"), cfg.readEntry("customColorSpaceDepthID", "U8"), cfg.readEntry("customColorSpaceProfile", "sRGB built-in - (lcms internal)")); } return cs; } void KisConfig::setCustomColorSelectorColorSpace(const KoColorSpace *cs) { KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); cfg.writeEntry("useCustomColorSpace", bool(cs)); if(cs) { cfg.writeEntry("customColorSpaceModel", cs->colorModelId().id()); cfg.writeEntry("customColorSpaceDepthID", cs->colorDepthId().id()); cfg.writeEntry("customColorSpaceProfile", cs->profile()->name()); } KisConfigNotifier::instance()->notifyConfigChanged(); } diff --git a/krita/ui/kis_config.h b/krita/ui/kis_config.h index 1d53ad7869..b788f10332 100644 --- a/krita/ui/kis_config.h +++ b/krita/ui/kis_config.h @@ -1,497 +1,500 @@ /* * Copyright (c) 2002 Patrick Julien * * 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_CONFIG_H_ #define KIS_CONFIG_H_ #include #include #include #include #include #include #include "kis_global.h" #include "kis_properties_configuration.h" #include "krita_export.h" class KoColorProfile; class KoColorSpace; class KRITAUI_EXPORT KisConfig { public: KisConfig(); ~KisConfig(); bool disableTouchOnCanvas() const; void setDisableTouchOnCanvas(bool value) const; bool useProjections() const; void setUseProjections(bool useProj) const; bool undoEnabled() const; void setUndoEnabled(bool undo) const; int undoStackLimit() const; void setUndoStackLimit(int limit) const; bool useCumulativeUndoRedo(); void setCumulativeUndoRedo(bool value); double stackT1(); void setStackT1(int T1); double stackT2(); void setStackT2(int T2); int stackN(); void setStackN(int N); qint32 defImageWidth() const; void defImageWidth(qint32 width) const; qint32 defImageHeight() const; void defImageHeight(qint32 height) const; double defImageResolution() const; void defImageResolution(double res) const; bool defAutoFrameBreakEnabled() const; void defAutoFrameBreakEnabled(bool state) const; bool defOnionSkinningEnabled() const; void defOnionSkinningEnabled(bool state) const; int defFps() const; void defFps(int value) const; int defLocalPlaybackRange() const; void defLocalPlaybackRange(int value) const; bool defLoopingEnabled() const; void defLoopingEnabled(bool state) const; /** * @return the id of the default color model used for creating new images. */ QString defColorModel() const; /** * set the id of the default color model used for creating new images. */ void defColorModel(const QString & model) const; /** * @return the id of the default color depth used for creating new images. */ QString defaultColorDepth() const; /** * set the id of the default color depth used for creating new images. */ void setDefaultColorDepth(const QString & depth) const; /** * @return the id of the default color profile used for creating new images. */ QString defColorProfile() const; /** * set the id of the default color profile used for creating new images. */ void defColorProfile(const QString & depth) const; enumCursorStyle cursorStyle() const; enumCursorStyle getDefaultCursorStyle() const; void setCursorStyle(enumCursorStyle style) const; /// get the profile the user has selected for the given screen QString monitorProfile(int screen) const; void setMonitorProfile(int screen, const QString & monitorProfile, bool override) const; QString monitorForScreen(int screen, const QString &defaultMonitor) const; void setMonitorForScreen(int screen, const QString& monitor); /// Get the actual profile to be used for the given screen, which is /// either the screen profile set by the color management system or /// the custom monitor profile set by the user, depending on the configuration const KoColorProfile *displayProfile(int screen) const; QString workingColorSpace() const; void setWorkingColorSpace(const QString & workingColorSpace) const; QString importProfile() const; void setImportProfile(const QString & importProfile) const; QString printerColorSpace() const; void setPrinterColorSpace(const QString & printerColorSpace) const; QString printerProfile() const; void setPrinterProfile(const QString & printerProfile) const; bool useBlackPointCompensation() const; void setUseBlackPointCompensation(bool useBlackPointCompensation) const; bool allowLCMSOptimization() const; void setAllowLCMSOptimization(bool allowLCMSOptimization); bool showRulers() const; void setShowRulers(bool rulers) const; qint32 pasteBehaviour() const; void setPasteBehaviour(qint32 behaviour) const; qint32 renderIntent() const; void setRenderIntent(qint32 renderIntent) const; bool useOpenGL() const; void setUseOpenGL(bool useOpenGL) const; int openGLFilteringMode() const; void setOpenGLFilteringMode(int filteringMode); bool useOpenGLTextureBuffer() const; void setUseOpenGLTextureBuffer(bool useBuffer); bool disableDoubleBuffering() const; void setDisableDoubleBuffering(bool disableDoubleBuffering); bool disableVSync() const; void setDisableVSync(bool disableVSync); bool showAdvancedOpenGLSettings() const; bool forceOpenGLFenceWorkaround() const; int numMipmapLevels() const; int openGLTextureSize() const; int textureOverlapBorder() const; qint32 maxNumberOfThreads(); void setMaxNumberOfThreads(qint32 numberOfThreads); /// Maximum tiles in memory (this is a guideline, not absolute) qint32 maxTilesInMem() const; void setMaxTilesInMem(qint32 tiles) const; quint32 getGridMainStyle() const; void setGridMainStyle(quint32 v) const; quint32 getGridSubdivisionStyle() const; void setGridSubdivisionStyle(quint32 v) const; QColor getGridMainColor() const; void setGridMainColor(const QColor & v) const; QColor getGridSubdivisionColor() const; void setGridSubdivisionColor(const QColor & v) const; quint32 getGridHSpacing() const; void setGridHSpacing(quint32 v) const; quint32 getGridVSpacing() const; void setGridVSpacing(quint32 v) const; bool getGridSpacingAspect() const; void setGridSpacingAspect(bool v) const; quint32 getGridSubdivisions() const; void setGridSubdivisions(quint32 v) const; quint32 getGridOffsetX() const; void setGridOffsetX(quint32 v) const; quint32 getGridOffsetY() const; void setGridOffsetY(quint32 v) const; bool getGridOffsetAspect() const; void setGridOffsetAspect(bool v) const; qint32 checkSize() const; void setCheckSize(qint32 checkSize) const; bool scrollCheckers() const; void setScrollingCheckers(bool scollCheckers) const; QColor checkersColor1() const; void setCheckersColor1(const QColor & v) const; QColor checkersColor2() const; void setCheckersColor2(const QColor & v) const; QColor canvasBorderColor() const; void setCanvasBorderColor(const QColor &color) const; bool hideScrollbars() const; void setHideScrollbars(bool value) const; bool antialiasCurves() const; void setAntialiasCurves(bool v) const; QColor selectionOverlayMaskColor() const; void setSelectionOverlayMaskColor(const QColor &color); bool antialiasSelectionOutline() const; void setAntialiasSelectionOutline(bool v) const; bool showRootLayer() const; void setShowRootLayer(bool showRootLayer) const; bool showGlobalSelection() const; void setShowGlobalSelection(bool showGlobalSelection) const; bool showOutlineWhilePainting() const; void setShowOutlineWhilePainting(bool showOutlineWhilePainting) const; qreal outlineSizeMinimum() const; void setOutlineSizeMinimum(qreal outlineSizeMinimum) const; int autoSaveInterval() const; void setAutoSaveInterval(int seconds) const; bool backupFile() const; void setBackupFile(bool backupFile) const; bool showFilterGallery() const; void setShowFilterGallery(bool showFilterGallery) const; bool showFilterGalleryLayerMaskDialog() const; void setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const; QString defaultPainterlyColorModelId() const; void setDefaultPainterlyColorModelId(const QString& def) const; QString defaultPainterlyColorDepthId() const; void setDefaultPainterlyColorDepthId(const QString& def) const; // OPENGL_SUCCESS, TRY_OPENGL, OPENGL_NOT_TRIED, OPENGL_FAILED QString canvasState() const; void setCanvasState(const QString& state) const; bool paintopPopupDetached() const; void setPaintopPopupDetached(bool detached) const; QString pressureTabletCurve() const; void setPressureTabletCurve(const QString& curveString) const; qreal vastScrolling() const; void setVastScrolling(const qreal factor) const; int presetChooserViewMode() const; void setPresetChooserViewMode(const int mode) const; bool firstRun() const; void setFirstRun(const bool firstRun) const; bool clicklessSpacePan() const; void setClicklessSpacePan(const bool toggle) const; int horizontalSplitLines() const; void setHorizontalSplitLines(const int numberLines) const; int verticalSplitLines() const; void setVerticalSplitLines(const int numberLines) const; int hideDockersFullscreen() const; void setHideDockersFullscreen(const int value) const; bool showDockerTitleBars() const; void setShowDockerTitleBars(const bool value) const; int hideMenuFullscreen() const; void setHideMenuFullscreen(const int value) const; int hideScrollbarsFullscreen() const; void setHideScrollbarsFullscreen(const int value) const; int hideStatusbarFullscreen() const; void setHideStatusbarFullscreen(const int value) const; int hideTitlebarFullscreen() const; void setHideTitlebarFullscreen(const int value) const; int hideToolbarFullscreen() const; void setHideToolbarFullscreen(const int value) const; QStringList favoriteCompositeOps() const; void setFavoriteCompositeOps(const QStringList& compositeOps) const; QString exportConfiguration(const QString &filterId) const; void setExportConfiguration(const QString &filterId, const KisPropertiesConfiguration &properties) const; bool useOcio() const; void setUseOcio(bool useOCIO) const; int favoritePresets() const; void setFavoritePresets(const int value); enum OcioColorManagementMode { INTERNAL = 0, OCIO_CONFIG, OCIO_ENVIRONMENT }; OcioColorManagementMode ocioColorManagementMode() const; void setOcioColorManagementMode(OcioColorManagementMode mode) const; QString ocioConfigurationPath() const; void setOcioConfigurationPath(const QString &path) const; QString ocioLutPath() const; void setOcioLutPath(const QString &path) const; int ocioLutEdgeSize() const; void setOcioLutEdgeSize(int value); bool ocioLockColorVisualRepresentation() const; void setOcioLockColorVisualRepresentation(bool value); bool useSystemMonitorProfile() const; void setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const; QString defaultPalette() const; void setDefaultPalette(const QString& name) const; QString toolbarSlider(int sliderNumber); void setToolbarSlider(int sliderNumber, const QString &slider); + bool sliderLabels() const; + void setSliderLabels(bool enabled); + QString currentInputProfile() const; void setCurrentInputProfile(const QString& name); bool presetStripVisible() const; void setPresetStripVisible(bool visible); bool scratchpadVisible() const; void setScratchpadVisible(bool visible); bool showSingleChannelAsColor() const; void setShowSingleChannelAsColor(bool asColor); bool hidePopups() const; void setHidePopups(bool hidepopups); int numDefaultLayers() const; void setNumDefaultLayers(int num); quint8 defaultBackgroundOpacity() const; void setDefaultBackgroundOpacity(quint8 value); QColor defaultBackgroundColor() const; void setDefaultBackgroundColor(QColor value); enum BackgroundStyle { LAYER = 0, PROJECTION = 1 }; BackgroundStyle defaultBackgroundStyle() const; void setDefaultBackgroundStyle(BackgroundStyle value); int lineSmoothingType() const; void setLineSmoothingType(int value); qreal lineSmoothingDistance() const; void setLineSmoothingDistance(qreal value); qreal lineSmoothingTailAggressiveness() const; void setLineSmoothingTailAggressiveness(qreal value); bool lineSmoothingSmoothPressure() const; void setLineSmoothingSmoothPressure(bool value); bool lineSmoothingScalableDistance() const; void setLineSmoothingScalableDistance(bool value); qreal lineSmoothingDelayDistance() const; void setLineSmoothingDelayDistance(qreal value); bool lineSmoothingUseDelayDistance() const; void setLineSmoothingUseDelayDistance(bool value); bool lineSmoothingFinishStabilizedCurve() const; void setLineSmoothingFinishStabilizedCurve(bool value); bool lineSmoothingStabilizeSensors() const; void setLineSmoothingStabilizeSensors(bool value); int paletteDockerPaletteViewSectionSize() const; void setPaletteDockerPaletteViewSectionSize(int value) const; int tabletEventsDelay() const; void setTabletEventsDelay(int value); bool testingAcceptCompressedTabletEvents() const; void setTestingAcceptCompressedTabletEvents(bool value); bool testingCompressBrushEvents() const; void setTestingCompressBrushEvents(bool value); const KoColorSpace* customColorSelectorColorSpace() const; void setCustomColorSelectorColorSpace(const KoColorSpace *cs); bool useDirtyPresets() const; void setUseDirtyPresets(bool value); bool useEraserBrushSize() const; void setUseEraserBrushSize(bool value); QColor getMDIBackgroundColor() const; void setMDIBackgroundColor(const QColor & v) const; QString getMDIBackgroundImage() const; void setMDIBackgroundImage(const QString & fileName) const; bool useVerboseOpenGLDebugOutput() const; int workaroundX11SmoothPressureSteps() const; bool showCanvasMessages() const; void setShowCanvasMessages(bool show); template void writeEntry(const QString& name, const T& value) { m_cfg.writeEntry(name, value); } template void writeList(const QString& name, const QList& value) { m_cfg.writeEntry(name, value); } template T readEntry(const QString& name, const T& defaultValue=T()) { return m_cfg.readEntry(name, defaultValue); } template QList readList(const QString& name, const QList& defaultValue=QList()) { return m_cfg.readEntry(name, defaultValue); } private: KisConfig(const KisConfig&); KisConfig& operator=(const KisConfig&) const; /// get the profile the color managment system has stored for the given screen static const KoColorProfile* getScreenProfile(int screen); private: mutable KConfigGroup m_cfg; }; #endif // KIS_CONFIG_H_ diff --git a/krita/ui/kis_paintop_box.cc b/krita/ui/kis_paintop_box.cc index 60a017e872..e7c0ea40e8 100644 --- a/krita/ui/kis_paintop_box.cc +++ b/krita/ui/kis_paintop_box.cc @@ -1,1089 +1,1106 @@ /* * kis_paintop_box.cc - part of KImageShop/Krayon/Krita * * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2009-2011 Sven Langkamp (sven.langkamp@gmail.com) * Copyright (c) 2010 Lukáš Tvrdý * Copyright (C) 2011 Silvio Heinrich * Copyright (C) 2011 Srikanth Tiyyagura * 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_paintop_box.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 #include #include "kis_canvas2.h" #include "kis_node_manager.h" #include "KisViewManager.h" #include "kis_factory2.h" #include "kis_canvas_resource_provider.h" #include "kis_resource_server_provider.h" #include "kis_favorite_resource_manager.h" #include "kis_config.h" #include "widgets/kis_popup_button.h" #include "widgets/kis_paintop_presets_popup.h" #include "widgets/kis_paintop_presets_chooser_popup.h" #include "widgets/kis_workspace_chooser.h" #include "widgets/kis_paintop_list_widget.h" #include "widgets/kis_slider_spin_box.h" #include "widgets/kis_cmb_composite.h" #include "widgets/kis_widget_chooser.h" #include "tool/kis_tool.h" #include "kis_signals_blocker.h" typedef KoResourceServer > KisPaintOpPresetResourceServer; typedef KoResourceServerAdapter > KisPaintOpPresetResourceServerAdapter; KisPaintopBox::KisPaintopBox(KisViewManager *view, QWidget *parent, const char *name) : QWidget(parent) , m_resourceProvider(view->resourceProvider()) , m_optionWidget(0) , m_settingsWidget(0) , m_presetWidget(0) , m_brushChooser(0) , m_viewManager(view) , m_previousNode(0) , m_currTabletToolID(KoInputDevice::invalid()) , m_presetsEnabled(true) , m_blockUpdate(false) , m_dirtyPresetsEnabled(false) , m_eraserBrushSizeEnabled(false) { Q_ASSERT(view != 0); KGlobal::mainComponent().dirs()->addResourceType("kis_defaultpresets", "data", "krita/defaultpresets/"); setObjectName(name); KisConfig cfg; m_dirtyPresetsEnabled = cfg.useDirtyPresets(); m_eraserBrushSizeEnabled = cfg.useEraserBrushSize(); KAcceleratorManager::setNoAccel(this); setWindowTitle(i18n("Painter's Toolchest")); m_settingsWidget = new KisPopupButton(this); m_settingsWidget->setIcon(koIcon("paintop_settings_02")); m_settingsWidget->setToolTip(i18n("Edit brush settings")); m_settingsWidget->setFixedSize(32, 32); m_presetWidget = new KisPopupButton(this); m_presetWidget->setIcon(koIcon("paintop_settings_01")); m_presetWidget->setToolTip(i18n("Choose brush preset")); m_presetWidget->setFixedSize(32, 32); m_eraseModeButton = new QToolButton(this); m_eraseModeButton->setFixedSize(32, 32); m_eraseModeButton->setCheckable(true); KisAction* eraseAction = new KisAction(i18n("Set eraser mode"), m_eraseModeButton); eraseAction->setActivationFlags(KisAction::ACTIVE_DEVICE); eraseAction->setIcon(koIcon("eraser-toggle")); eraseAction->setShortcut(Qt::Key_E); eraseAction->setCheckable(true); m_eraseModeButton->setDefaultAction(eraseAction); m_viewManager->actionCollection()->addAction("erase_action", eraseAction); eraserBrushSize = 0; // brush size changed when using erase mode m_reloadButton = new QToolButton(this); m_reloadButton->setFixedSize(32, 32); m_reloadButton->setCheckable(true); KisAction* reloadAction = new KisAction(i18n("Reload Original Preset"), m_reloadButton); reloadAction->setActivationFlags(KisAction::ACTIVE_DEVICE); reloadAction->setIcon(koIcon("reload_preset")); m_reloadButton->setDefaultAction(reloadAction); m_viewManager->actionCollection()->addAction("reload_preset_action", reloadAction); m_alphaLockButton = new QToolButton(this); m_alphaLockButton->setFixedSize(32, 32); m_alphaLockButton->setCheckable(true); KisAction* alphaLockAction = new KisAction(i18n("Preserve Alpha"), m_alphaLockButton); alphaLockAction->setActivationFlags(KisAction::ACTIVE_DEVICE); alphaLockAction->setIcon(koIcon("transparency-unlocked")); alphaLockAction->setCheckable(true); m_alphaLockButton->setDefaultAction(alphaLockAction); m_viewManager->actionCollection()->addAction("preserve_alpha", alphaLockAction); hMirrorButton = new QToolButton(this); hMirrorButton->setFixedSize(32, 32); hMirrorButton->setCheckable(true); m_hMirrorAction = new KisAction(i18n("Set horizontal mirror mode"), hMirrorButton); m_hMirrorAction->setIcon(themedIcon("symmetry-horizontal")); m_hMirrorAction->setActivationFlags(KisAction::ACTIVE_DEVICE); m_hMirrorAction->setCheckable(true); hMirrorButton->setDefaultAction(m_hMirrorAction); m_viewManager->actionCollection()->addAction("hmirror_action", m_hMirrorAction); vMirrorButton = new QToolButton(this); vMirrorButton->setFixedSize(32, 32); vMirrorButton->setCheckable(true); m_vMirrorAction = new KisAction(i18n("Set vertical mirror mode"), vMirrorButton); m_vMirrorAction->setActivationFlags(KisAction::ACTIVE_DEVICE); m_vMirrorAction->setIcon(themedIcon("symmetry-vertical")); m_vMirrorAction->setCheckable(true); vMirrorButton->setDefaultAction(m_vMirrorAction); m_viewManager->actionCollection()->addAction("vmirror_action", m_vMirrorAction); + const bool sliderLabels = cfg.sliderLabels(); + int sliderWidth; + + if (sliderLabels) { + sliderWidth = 150 * logicalDpiX() / 96; + } + else { + sliderWidth = 120 * logicalDpiX() / 96; + } for (int i = 0; i < 3; ++i) { m_sliderChooser[i] = new KisWidgetChooser(i + 1); - KisDoubleSliderSpinBox* slOpacity = m_sliderChooser[i]->addWidget("opacity", i18n("Opacity:")); - KisDoubleSliderSpinBox* slFlow = m_sliderChooser[i]->addWidget("flow" , i18n("Flow:")); - KisDoubleSliderSpinBox* slSize = m_sliderChooser[i]->addWidget("size" , i18n("Size:")); + KisDoubleSliderSpinBox* slOpacity; + KisDoubleSliderSpinBox* slFlow; + KisDoubleSliderSpinBox* slSize; + if (sliderLabels) { + slOpacity = m_sliderChooser[i]->addWidget("opacity"); + slFlow = m_sliderChooser[i]->addWidget("flow"); + slSize = m_sliderChooser[i]->addWidget("size"); + slOpacity->setPrefix(QString("%1 ").arg(i18n("Opacity:"))); + slFlow->setPrefix(QString("%1 ").arg(i18n("Flow:"))); + slSize->setPrefix(QString("%1 ").arg(i18n("Size:"))); + } + else { + slOpacity = m_sliderChooser[i]->addWidget("opacity", i18n("Opacity:")); + slFlow = m_sliderChooser[i]->addWidget("flow", i18n("Flow:")); + slSize = m_sliderChooser[i]->addWidget("size", i18n("Size:")); + } slOpacity->setRange(0.0, 1.0, 2); slOpacity->setValue(1.0); slOpacity->setSingleStep(0.05); - slOpacity->setMinimumWidth(120); + slOpacity->setMinimumWidth(sliderWidth); slFlow->setRange(0.0, 1.0, 2); slFlow->setValue(1.0); slFlow->setSingleStep(0.05); - slFlow->setMinimumWidth(120); + slFlow->setMinimumWidth(sliderWidth); slSize->setRange(0, 1000, 2); slSize->setValue(100); slSize->setSingleStep(1); slSize->setExponentRatio(3.0); - slSize->setMinimumWidth(120); + slSize->setMinimumWidth(sliderWidth); slSize->setSuffix(" px"); m_sliderChooser[i]->chooseWidget(cfg.toolbarSlider(i + 1)); } - - QLabel* labelMode = new QLabel(i18n("Mode: "), this); - labelMode->setAlignment(Qt::AlignVCenter | Qt::AlignRight); - m_cmbCompositeOp = new KisCompositeOpComboBox(); - m_cmbCompositeOp->setFixedHeight(30); + m_cmbCompositeOp->setFixedHeight(32); foreach(KAction * a, m_cmbCompositeOp->blendmodeActions()) { m_viewManager->actionCollection()->addAction(a->text(), a); } m_workspaceWidget = new KisPopupButton(this); m_workspaceWidget->setIcon(koIcon("workspace-chooser")); m_workspaceWidget->setToolTip(i18n("Choose workspace")); m_workspaceWidget->setFixedSize(32, 32); m_workspaceWidget->setPopupWidget(new KisWorkspaceChooser(view)); QHBoxLayout* baseLayout = new QHBoxLayout(this); m_paintopWidget = new QWidget(this); baseLayout->addWidget(m_paintopWidget); baseLayout->setContentsMargins(0, 0, 0, 0); m_layout = new QHBoxLayout(m_paintopWidget); m_layout->addWidget(m_settingsWidget); m_layout->addWidget(m_presetWidget); m_layout->setContentsMargins(0, 0, 0, 0); QWidget* compositeActions = new QWidget(this); QHBoxLayout* compositeLayout = new QHBoxLayout(compositeActions); - compositeLayout->addWidget(labelMode); compositeLayout->addWidget(m_cmbCompositeOp); compositeLayout->addWidget(m_eraseModeButton); compositeLayout->addWidget(m_alphaLockButton); - compositeLayout->setContentsMargins(8, 0, 0, 0); + compositeLayout->setContentsMargins(3, 0, 0, 0); compositeLayout->addWidget(m_reloadButton); KAction* action; action = new KAction(i18n("Brush composite"), this); view->actionCollection()->addAction("composite_actions", action); action->setDefaultWidget(compositeActions); action = new KAction(i18n("Brush option slider 1"), this); view->actionCollection()->addAction("brushslider1", action); action->setDefaultWidget(m_sliderChooser[0]); connect(action, SIGNAL(triggered()), m_sliderChooser[0], SLOT(showPopupWidget())); action = new KAction(i18n("Brush option slider 2"), this); view->actionCollection()->addAction("brushslider2", action); action->setDefaultWidget(m_sliderChooser[1]); connect(action, SIGNAL(triggered()), m_sliderChooser[1], SLOT(showPopupWidget())); action = new KAction(i18n("Brush option slider 3"), this); view->actionCollection()->addAction("brushslider3", action); action->setDefaultWidget(m_sliderChooser[2]); connect(action, SIGNAL(triggered()), m_sliderChooser[2], SLOT(showPopupWidget())); action = new KAction(i18n("Next Favourite Preset"), this); view->actionCollection()->addAction("next_favorite_preset", action); action->setShortcut(KShortcut(Qt::Key_Comma)); connect(action, SIGNAL(triggered()), this, SLOT(slotNextFavoritePreset())); action = new KAction(i18n("Previous Favourite Preset"), this); view->actionCollection()->addAction("previous_favorite_preset", action); action->setShortcut(KShortcut(Qt::Key_Period)); connect(action, SIGNAL(triggered()), this, SLOT(slotPreviousFavoritePreset())); action = new KAction(i18n("Switch to Previous Preset"), this); view->actionCollection()->addAction("previous_preset", action); action->setShortcut(KShortcut(Qt::Key_Slash)); connect(action, SIGNAL(triggered()), this, SLOT(slotSwitchToPreviousPreset())); QWidget* mirrorActions = new QWidget(this); QHBoxLayout* mirrorLayout = new QHBoxLayout(mirrorActions); mirrorLayout->addWidget(hMirrorButton); mirrorLayout->addWidget(vMirrorButton); mirrorLayout->setContentsMargins(0, 0, 0, 0); action = new KAction(i18n("Mirror"), this); view->actionCollection()->addAction("mirror_actions", action); action->setDefaultWidget(mirrorActions); action = new KAction(i18n("Workspaces"), this); view->actionCollection()->addAction("workspaces", action); action->setDefaultWidget(m_workspaceWidget); m_presetsPopup = new KisPaintOpPresetsPopup(m_resourceProvider); m_settingsWidget->setPopupWidget(m_presetsPopup); m_presetsPopup->switchDetached(false); m_presetsChooserPopup = new KisPaintOpPresetsChooserPopup(); m_presetsChooserPopup->setFixedSize(500, 600); m_presetWidget->setPopupWidget(m_presetsChooserPopup); m_prevCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); m_currCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); slotNodeChanged(view->activeNode()); // Get all the paintops QList keys = KisPaintOpRegistry::instance()->keys(); QList factoryList; foreach(const QString & paintopId, keys) { factoryList.append(KisPaintOpRegistry::instance()->get(paintopId)); } m_presetsPopup->setPaintOpList(factoryList); connect(m_presetsPopup , SIGNAL(paintopActivated(QString)) , SLOT(slotSetPaintop(QString))); connect(m_presetsPopup , SIGNAL(savePresetClicked()) , SLOT(slotSaveActivePreset())); connect(m_presetsPopup , SIGNAL(defaultPresetClicked()) , SLOT(slotSetupDefaultPreset())); connect(m_presetsPopup , SIGNAL(signalResourceSelected(KoResource*)), SLOT(resourceSelected(KoResource*))); connect(m_presetsPopup , SIGNAL(reloadPresetClicked()) , SLOT(slotReloadPreset())); connect(m_presetsPopup , SIGNAL(dirtyPresetToggled(bool)) , SLOT(slotDirtyPresetToggled(bool))); connect(m_presetsPopup , SIGNAL(eraserBrushSizeToggled(bool)) , SLOT(slotEraserBrushSizeToggled(bool))); connect(m_presetsChooserPopup, SIGNAL(resourceSelected(KoResource*)) , SLOT(resourceSelected(KoResource*))); connect(m_resourceProvider , SIGNAL(sigNodeChanged(const KisNodeSP)) , SLOT(slotNodeChanged(const KisNodeSP))); connect(m_cmbCompositeOp , SIGNAL(currentIndexChanged(int)) , SLOT(slotSetCompositeMode(int))); connect(eraseAction , SIGNAL(triggered(bool)) , SLOT(slotToggleEraseMode(bool))); connect(alphaLockAction , SIGNAL(triggered(bool)) , SLOT(slotToggleAlphaLockMode(bool))); connect(m_hMirrorAction , SIGNAL(triggered(bool)) , SLOT(slotHorizontalMirrorChanged(bool))); connect(m_vMirrorAction , SIGNAL(triggered(bool)) , SLOT(slotVerticalMirrorChanged(bool))); connect(reloadAction , SIGNAL(triggered()) , SLOT(slotReloadPreset())); connect(m_sliderChooser[0]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[0]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[0]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[1]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[1]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[1]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[2]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); connect(m_sliderChooser[2]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); connect(m_sliderChooser[2]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); //Needed to connect canvas to favorite resource manager connect(m_viewManager->resourceProvider(), SIGNAL(sigOpacityChanged(qreal)), SLOT(slotOpacityChanged(qreal))); connect(m_viewManager->resourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), SLOT(slotUnsetEraseMode())); m_favoriteResourceManager = new KisFavoriteResourceManager(this); connect(m_resourceProvider, SIGNAL(sigFGColorUsed(KoColor)), m_favoriteResourceManager, SLOT(slotAddRecentColor(KoColor))); connect(m_resourceProvider, SIGNAL(sigFGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotChangeFGColorSelector(KoColor))); connect(m_resourceProvider, SIGNAL(sigBGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotSetBGColor(KoColor))); // cold initialization m_favoriteResourceManager->slotChangeFGColorSelector(m_resourceProvider->fgColor()); m_favoriteResourceManager->slotSetBGColor(m_resourceProvider->bgColor()); connect(m_favoriteResourceManager, SIGNAL(sigSetFGColor(KoColor)), m_resourceProvider, SLOT(slotSetFGColor(KoColor))); connect(m_favoriteResourceManager, SIGNAL(sigSetBGColor(KoColor)), m_resourceProvider, SLOT(slotSetBGColor(KoColor))); connect(m_favoriteResourceManager, SIGNAL(sigEnableChangeColor(bool)), m_resourceProvider, SLOT(slotResetEnableFGChange(bool))); connect(view->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateSelectionIcon())); slotInputDeviceChanged(KoToolManager::instance()->currentInputDevice()); } KisPaintopBox::~KisPaintopBox() { KisConfig cfg; QMapIterator iter(m_tabletToolMap); while (iter.hasNext()) { iter.next(); if ((iter.key().pointer) == QTabletEvent::Eraser) { cfg.writeEntry(QString("LastEraser_%1").arg(iter.key().uniqueID) , iter.value().preset->name()); } else { cfg.writeEntry(QString("LastPreset_%1").arg(iter.key().uniqueID) , iter.value().preset->name()); } } // Do not delete the widget, since it it is global to the application, not owned by the view m_presetsPopup->setPaintOpSettingsWidget(0); qDeleteAll(m_paintopOptionWidgets); delete m_favoriteResourceManager; } void KisPaintopBox::restoreResource(KoResource* resource) { KisPaintOpPreset* preset = dynamic_cast(resource); if (preset) { setCurrentPaintop(preset->paintOp(), preset); m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } } void KisPaintopBox::resourceSelected(KoResource* resource) { KisPaintOpPreset* preset = dynamic_cast(resource); if (preset) { if (!preset->settings()->isLoadable()) return; setCurrentPaintopAndReload(preset->paintOp(), preset); m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } } QPixmap KisPaintopBox::paintopPixmap(const KoID& paintop) { QString pixmapName = KisPaintOpRegistry::instance()->pixmap(paintop); if (pixmapName.isEmpty()) return QPixmap(); return QPixmap(KisFactory::componentData().dirs()->findResource("kis_images", pixmapName)); } KoID KisPaintopBox::currentPaintop() { return m_resourceProvider->currentPreset()->paintOp(); } void KisPaintopBox::setCurrentPaintopAndReload(const KoID& paintop, KisPaintOpPresetSP preset) { if (!m_dirtyPresetsEnabled) { KisSignalsBlocker blocker(m_optionWidget); if (!preset->load()) { qWarning() << "failed to load the preset."; } } setCurrentPaintop(paintop, preset); } void KisPaintopBox::setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP preset) { if (m_resourceProvider->currentPreset()) { m_resourceProvider->setPreviousPaintOpPreset(m_resourceProvider->currentPreset()); if (m_optionWidget) { m_optionWidget->disconnect(this); m_optionWidget->hide(); } m_paintOpPresetMap[m_resourceProvider->currentPreset()->paintOp()] = m_resourceProvider->currentPreset(); m_tabletToolMap[m_currTabletToolID].preset = m_resourceProvider->currentPreset(); m_tabletToolMap[m_currTabletToolID].paintOpID = m_resourceProvider->currentPreset()->paintOp(); } preset = (!preset) ? activePreset(paintop) : preset; Q_ASSERT(preset && preset->settings()); if (!m_paintopOptionWidgets.contains(paintop)) m_paintopOptionWidgets[paintop] = KisPaintOpRegistry::instance()->get(paintop.id())->createSettingsWidget(this); m_optionWidget = m_paintopOptionWidgets[paintop]; preset->settings()->setOptionsWidget(m_optionWidget); m_optionWidget->setImage(m_viewManager->image()); m_optionWidget->setNode(m_viewManager->activeNode()); m_optionWidget->setConfiguration(preset->settings()); m_presetsPopup->setPaintOpSettingsWidget(m_optionWidget); Q_ASSERT(m_optionWidget && m_presetWidget); connect(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotUpdatePreset())); connect(m_optionWidget, SIGNAL(sigSaveLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotSaveLockedOptionToPreset(KisPropertiesConfiguration*))); connect(m_optionWidget, SIGNAL(sigDropLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotDropLockedOption(KisPropertiesConfiguration*))); connect(m_optionWidget, SIGNAL(sigConfigurationItemChanged()), this, SLOT(slotConfigurationItemChanged())); KisPaintOpFactory* paintOp = KisPaintOpRegistry::instance()->get(paintop.id()); QString pixFilename = KisFactory::componentData().dirs()->findResource("kis_images", paintOp->pixmap()); m_settingsWidget->setIcon(QIcon(pixFilename)); m_resourceProvider->setPaintOpPreset(preset); m_presetsPopup->setCurrentPaintOp(paintop.id()); if (m_presetsPopup->currentPaintOp() != paintop.id()) { // Must change the paintop as the current one is not supported // by the new colorspace. kWarning() << "current paintop " << paintop.name() << " was not set, not supported by colorspace"; } /** * We will get more update signals from the configuration widgets * but they might be delayed by some internal deferring timers, * so just call the slot directly */ slotUpdatePreset(); } KoID KisPaintopBox::defaultPaintOp() { return KoID("paintbrush"); } KisPaintOpPresetSP KisPaintopBox::defaultPreset(const KoID& paintOp) { QString defaultName = paintOp.id() + ".kpp"; QString path = KGlobal::mainComponent().dirs()->findResource("kis_defaultpresets", defaultName); KisPaintOpPresetSP preset = new KisPaintOpPreset(path); if (!preset->load()) { preset = KisPaintOpRegistry::instance()->defaultPreset(paintOp); } Q_ASSERT(preset); Q_ASSERT(preset->valid()); return preset; } KisPaintOpPresetSP KisPaintopBox::activePreset(const KoID& paintOp) { if (m_paintOpPresetMap[paintOp] == 0) { m_paintOpPresetMap[paintOp] = defaultPreset(paintOp); } return m_paintOpPresetMap[paintOp]; } void KisPaintopBox::updateCompositeOp(QString compositeOpID, bool localUpdate) { if (!m_optionWidget) return; KisSignalsBlocker blocker(m_optionWidget); KisNodeSP node = m_resourceProvider->currentNode(); if (node && node->paintDevice()) { if (!node->paintDevice()->colorSpace()->hasCompositeOp(compositeOpID)) compositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); m_cmbCompositeOp->blockSignals(true); m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID)); m_cmbCompositeOp->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(true); m_eraseModeButton->blockSignals(true); m_eraseModeButton->setChecked(compositeOpID == COMPOSITE_ERASE); m_eraseModeButton->defaultAction()->setChecked(compositeOpID == COMPOSITE_ERASE); m_eraseModeButton->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(false); if (compositeOpID != m_currCompositeOpID) { m_resourceProvider->currentPreset()->settings()->setPaintOpCompositeOp(compositeOpID); m_optionWidget->setConfiguration(m_resourceProvider->currentPreset()->settings().data()); if (!localUpdate) m_resourceProvider->setCurrentCompositeOp(compositeOpID); m_prevCompositeOpID = m_currCompositeOpID; m_currCompositeOpID = compositeOpID; } } } void KisPaintopBox::setWidgetState(int flags) { if (flags & (ENABLE_COMPOSITEOP | DISABLE_COMPOSITEOP)) { m_cmbCompositeOp->setEnabled(flags & ENABLE_COMPOSITEOP); m_eraseModeButton->setEnabled(flags & ENABLE_COMPOSITEOP); } if (flags & (ENABLE_PRESETS | DISABLE_PRESETS)) { m_presetWidget->setEnabled(flags & ENABLE_PRESETS); m_settingsWidget->setEnabled(flags & ENABLE_PRESETS); } for (int i = 0; i < 3; ++i) { if (flags & (ENABLE_OPACITY | DISABLE_OPACITY)) m_sliderChooser[i]->getWidget("opacity")->setEnabled(flags & ENABLE_OPACITY); if (flags & (ENABLE_FLOW | DISABLE_FLOW)) m_sliderChooser[i]->getWidget("flow")->setEnabled(flags & ENABLE_FLOW); if (flags & (ENABLE_SIZE | DISABLE_SIZE)) m_sliderChooser[i]->getWidget("size")->setEnabled(flags & ENABLE_SIZE); } } void KisPaintopBox::setSliderValue(const QString& sliderID, qreal value) { for (int i = 0; i < 3; ++i) { KisDoubleSliderSpinBox* slider = m_sliderChooser[i]->getWidget(sliderID); slider->blockSignals(true); slider->setValue(value); slider->blockSignals(false); } } void KisPaintopBox::slotSetPaintop(const QString& paintOpId) { if (KisPaintOpRegistry::instance()->get(paintOpId) != 0) { KoID id(paintOpId, KisPaintOpRegistry::instance()->get(paintOpId)->name()); setCurrentPaintop(id); } } void KisPaintopBox::slotInputDeviceChanged(const KoInputDevice& inputDevice) { TabletToolMap::iterator toolData = m_tabletToolMap.find(inputDevice); if (toolData == m_tabletToolMap.end()) { KisConfig cfg; KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); KisPaintOpPresetSP preset; if (inputDevice.pointer() == QTabletEvent::Eraser) { preset = rserver->resourceByName(cfg.readEntry(QString("LastEraser_%1").arg(inputDevice.uniqueTabletId()), "Eraser_circle")); } else { preset = rserver->resourceByName(cfg.readEntry(QString("LastPreset_%1").arg(inputDevice.uniqueTabletId()), "Basic_tip_default")); } if (!preset) { preset = rserver->resourceByName("Basic_tip_default"); } setCurrentPaintop(preset->paintOp(), preset); } else { setCurrentPaintop(toolData->paintOpID, toolData->preset); } m_currTabletToolID = TabletToolID(inputDevice); } void KisPaintopBox::slotCanvasResourceChanged(int /*key*/, const QVariant& /*v*/) { if (m_viewManager) { sender()->blockSignals(true); KisPaintOpPresetSP preset = m_viewManager->resourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); if (preset && m_resourceProvider->currentPreset()->name() != preset->name()) { QString compositeOp = preset->settings()->getString("CompositeOp"); updateCompositeOp(compositeOp); resourceSelected(preset.data()); } m_presetsChooserPopup->canvasResourceChanged(preset.data(), preset); if (m_resourceProvider->currentCompositeOp() != m_currCompositeOpID) { QString compositeOp = m_resourceProvider->currentCompositeOp(); m_cmbCompositeOp->blockSignals(true); m_cmbCompositeOp->selectCompositeOp(KoID(compositeOp)); m_cmbCompositeOp->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(true); m_eraseModeButton->blockSignals(true); m_eraseModeButton->setChecked(compositeOp == COMPOSITE_ERASE); m_eraseModeButton->defaultAction()->setChecked(compositeOp == COMPOSITE_ERASE); m_eraseModeButton->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(false); } sender()->blockSignals(false); } } void KisPaintopBox::slotSaveActivePreset() { KisPaintOpPresetSP curPreset = m_resourceProvider->currentPreset(); if (!curPreset) return; m_favoriteResourceManager->setBlockUpdates(true); KisPaintOpPresetSP newPreset = curPreset->clone(); KisPaintOpPresetResourceServer * rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); QString saveLocation = rServer->saveLocation(); QString presetName = m_presetsPopup->getPresetName(); QString presetFilename = saveLocation + presetName + newPreset->defaultFileExtension(); QStringList tags; KisPaintOpPresetSP resource = rServer->resourceByName(presetName); if (resource) { tags = rServer->assignedTagsList(resource.data()); rServer->removeResourceAndBlacklist(resource); } newPreset->setImage(m_presetsPopup->cutOutOverlay()); newPreset->setFilename(presetFilename); newPreset->setName(presetName); newPreset->setPresetDirty(false); rServer->addResource(newPreset); foreach(const QString & tag, tags) { rServer->addTag(newPreset.data(), tag); } // HACK ALERT! the server does not notify the observers // automatically, so we need to call theupdate manually! rServer->tagCategoryMembersChanged(); restoreResource(newPreset.data()); m_favoriteResourceManager->setBlockUpdates(false); } void KisPaintopBox::slotUpdatePreset() { if (!m_resourceProvider->currentPreset()) return; // block updates of avoid some over updating of the option widget m_blockUpdate = true; setSliderValue("size", m_resourceProvider->currentPreset()->settings()->paintOpSize().width()); { qreal opacity = m_resourceProvider->currentPreset()->settings()->paintOpOpacity(); m_resourceProvider->setOpacity(opacity); setSliderValue("opacity", opacity); setWidgetState(ENABLE_OPACITY); } { setSliderValue("flow", m_resourceProvider->currentPreset()->settings()->paintOpFlow()); setWidgetState(ENABLE_FLOW); } { updateCompositeOp(m_resourceProvider->currentPreset()->settings()->paintOpCompositeOp()); setWidgetState(ENABLE_COMPOSITEOP); } m_blockUpdate = false; } void KisPaintopBox::slotSetupDefaultPreset() { KisPaintOpPresetSP preset = defaultPreset(m_resourceProvider->currentPreset()->paintOp()); preset->settings()->setOptionsWidget(m_optionWidget); m_optionWidget->setConfiguration(preset->settings()); m_optionWidget->writeConfiguration(const_cast(preset->settings().data())); } void KisPaintopBox::slotNodeChanged(const KisNodeSP node) { if (m_previousNode.isValid() && m_previousNode->paintDevice()) disconnect(m_previousNode->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); // Reconnect colorspace change of node if (node && node->paintDevice()) { connect(node->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); m_resourceProvider->setCurrentCompositeOp(m_currCompositeOpID); m_previousNode = node; slotColorSpaceChanged(node->colorSpace()); } if (m_optionWidget) { m_optionWidget->setNode(node); } } void KisPaintopBox::slotColorSpaceChanged(const KoColorSpace* colorSpace) { m_cmbCompositeOp->validate(colorSpace); } void KisPaintopBox::slotToggleEraseMode(bool checked) { if (checked) { updateCompositeOp(COMPOSITE_ERASE); //add an option to enable eraser brush size if (m_eraserBrushSizeEnabled==true) { // remember brush size. set the eraser size to the normal brush size if not set normalBrushSize = m_sliderChooser[0]->getWidget("size")->value(); if (!eraserBrushSize) eraserBrushSize = normalBrushSize; } else { normalBrushSize = eraserBrushSize; eraserBrushSize = m_sliderChooser[0]->getWidget("size")->value(); } } else { updateCompositeOp(m_prevCompositeOpID); if (m_eraserBrushSizeEnabled==true) { // save eraser brush size as eraserBrushSize (they are all the same, so just grab the first one) eraserBrushSize = m_sliderChooser[0]->getWidget("size")->value(); } else { normalBrushSize = m_sliderChooser[0]->getWidget("size")->value(); } } //update value in UI (this is the main place the value is 'stored' in memory) int updateSize = checked ? eraserBrushSize : normalBrushSize; m_sliderChooser[0]->getWidget("size")->setValue(updateSize); m_sliderChooser[1]->getWidget("size")->setValue(updateSize); m_sliderChooser[2]->getWidget("size")->setValue(updateSize); toggleHighlightedButton(m_eraseModeButton); } void KisPaintopBox::slotSetCompositeMode(int index) { Q_UNUSED(index); if (m_resourceProvider->currentPreset()->settings()->hasProperty("CompositeOp")) { QString compositeOp = m_cmbCompositeOp->selectedCompositeOp().id(); updateCompositeOp(compositeOp); } } void KisPaintopBox::slotHorizontalMirrorChanged(bool value) { m_resourceProvider->setMirrorHorizontal(value); toggleHighlightedButton(hMirrorButton); } void KisPaintopBox::slotVerticalMirrorChanged(bool value) { m_resourceProvider->setMirrorVertical(value); toggleHighlightedButton(vMirrorButton); } void KisPaintopBox::sliderChanged(int n) { if (!m_optionWidget) // widget will not exist if the are no documents open return; KisSignalsBlocker blocker(m_optionWidget); m_optionWidget->writeConfiguration(const_cast(m_resourceProvider->currentPreset()->settings().data())); qreal opacity = m_sliderChooser[n]->getWidget("opacity")->value(); qreal flow = m_sliderChooser[n]->getWidget("flow")->value(); qreal size = m_sliderChooser[n]->getWidget("size")->value(); setSliderValue("opacity", opacity); setSliderValue("flow" , flow); setSliderValue("size" , size); if (m_presetsEnabled) { // IMPORTANT: set the PaintOp size before setting the other properties // it wont work the other way qreal sizeDiff = size - m_resourceProvider->currentPreset()->settings()->paintOpSize().width(); m_resourceProvider->currentPreset()->settings()->changePaintOpSize(sizeDiff, 0); m_resourceProvider->currentPreset()->settings()->setPaintOpOpacity(opacity); m_resourceProvider->currentPreset()->settings()->setPaintOpFlow(flow); KisLockedPropertiesProxy *propertiesProxy = KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(m_resourceProvider->currentPreset()->settings()); propertiesProxy->setProperty("OpacityValue", opacity); propertiesProxy->setProperty("FlowValue", flow); delete propertiesProxy; m_optionWidget->setConfiguration(m_resourceProvider->currentPreset()->settings().data()); } m_resourceProvider->setOpacity(opacity); m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset().data()); } void KisPaintopBox::slotSlider1Changed() { sliderChanged(0); } void KisPaintopBox::slotSlider2Changed() { sliderChanged(1); } void KisPaintopBox::slotSlider3Changed() { sliderChanged(2); } void KisPaintopBox::slotToolChanged(KoCanvasController* canvas, int toolId) { Q_UNUSED(canvas); Q_UNUSED(toolId); if (!m_viewManager->canvasBase()) return; QString id = KoToolManager::instance()->activeToolId(); KisTool* tool = dynamic_cast(KoToolManager::instance()->toolById(m_viewManager->canvasBase(), id)); if (tool) { int flags = tool->flags(); if (flags & KisTool::FLAG_USES_CUSTOM_COMPOSITEOP) { setWidgetState(ENABLE_COMPOSITEOP | ENABLE_OPACITY); } else { setWidgetState(DISABLE_COMPOSITEOP | DISABLE_OPACITY); } if (flags & KisTool::FLAG_USES_CUSTOM_PRESET) { setWidgetState(ENABLE_PRESETS | ENABLE_SIZE | ENABLE_FLOW); slotUpdatePreset(); m_presetsEnabled = true; } else { setWidgetState(DISABLE_PRESETS | DISABLE_SIZE | DISABLE_FLOW); m_presetsEnabled = false; } } else setWidgetState(DISABLE_ALL); } void KisPaintopBox::slotOpacityChanged(qreal opacity) { if (m_blockUpdate) { return; } m_blockUpdate = true; for (int i = 0; i < 3; ++i) { KisDoubleSliderSpinBox *opacitySlider = m_sliderChooser[i]->getWidget("opacity"); opacitySlider->blockSignals(true); opacitySlider->setValue(opacity); opacitySlider->blockSignals(false); } if (m_presetsEnabled) { m_resourceProvider->currentPreset()->settings()->setPaintOpOpacity(opacity); m_optionWidget->setConfiguration(m_resourceProvider->currentPreset()->settings().data()); } m_blockUpdate = false; } void KisPaintopBox::slotPreviousFavoritePreset() { if (!m_favoriteResourceManager) return; int i = 0; foreach (KisPaintOpPresetSP preset, m_favoriteResourceManager->favoritePresetList()) { if (m_resourceProvider->currentPreset() && m_resourceProvider->currentPreset()->name() == preset->name()) { if (i > 0) { m_favoriteResourceManager->slotChangeActivePaintop(i - 1); } else { m_favoriteResourceManager->slotChangeActivePaintop(m_favoriteResourceManager->numFavoritePresets() - 1); } return; } i++; } } void KisPaintopBox::slotNextFavoritePreset() { if (!m_favoriteResourceManager) return; int i = 0; foreach (KisPaintOpPresetSP preset, m_favoriteResourceManager->favoritePresetList()) { if (m_resourceProvider->currentPreset()->name() == preset->name()) { if (i < m_favoriteResourceManager->numFavoritePresets() - 1) { m_favoriteResourceManager->slotChangeActivePaintop(i + 1); } else { m_favoriteResourceManager->slotChangeActivePaintop(0); } return; } i++; } } void KisPaintopBox::slotSwitchToPreviousPreset() { if (m_resourceProvider->previousPreset()) { setCurrentPaintop(m_resourceProvider->previousPreset()->paintOp(), m_resourceProvider->previousPreset()); } } void KisPaintopBox::slotUnsetEraseMode() { if (m_currCompositeOpID == COMPOSITE_ERASE) { updateCompositeOp(m_prevCompositeOpID); } } void KisPaintopBox::slotToggleAlphaLockMode(bool checked) { if (checked) { m_alphaLockButton->actions()[0]->setIcon(koIcon("transparency-locked")); } else { m_alphaLockButton->actions()[0]->setIcon(koIcon("transparency-unlocked")); } toggleHighlightedButton(m_alphaLockButton); m_resourceProvider->setGlobalAlphaLock(checked); } void KisPaintopBox::toggleHighlightedButton(QToolButton* m_tool) { QPalette p = palette(); if (m_tool->isChecked()) { QPalette palette_highlight(p); palette_highlight.setColor(QPalette::Button, p.color(QPalette::Highlight)); m_tool->setPalette(palette_highlight); } else { m_tool->setPalette(p); } } void KisPaintopBox::slotReloadPreset() { KisSignalsBlocker blocker(m_optionWidget); //Here using the name and fetching the preset from the server was the only way the load was working. Otherwise it was not loading. KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); KisPaintOpPresetSP preset = rserver->resourceByName(m_resourceProvider->currentPreset()->name()); if (preset) { preset->load(); preset->settings()->setOptionsWidget(m_optionWidget); m_optionWidget->setConfiguration(preset->settings()); m_presetsPopup->resourceSelected(preset.data()); } slotUpdatePreset(); } void KisPaintopBox::slotConfigurationItemChanged() // Called only when UI is changed and not when preset is changed { m_optionWidget->writeConfiguration(const_cast(m_resourceProvider->currentPreset()->settings().data())); m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset().data()); m_presetsPopup->updateViewSettings(); } void KisPaintopBox::slotSaveLockedOptionToPreset(KisPropertiesConfiguration* p) { QMapIterator i(p->getProperties()); while (i.hasNext()) { i.next(); m_resourceProvider->currentPreset()->settings()->setProperty(i.key(), QVariant(i.value())); if (m_resourceProvider->currentPreset()->settings()->hasProperty(i.key() + "_previous")) { m_resourceProvider->currentPreset()->settings()->removeProperty(i.key() + "_previous"); } } slotConfigurationItemChanged(); } void KisPaintopBox::slotDropLockedOption(KisPropertiesConfiguration* p) { KisSignalsBlocker blocker(m_optionWidget); KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); { KisPaintOpPreset::DirtyStateSaver dirtySaver(preset.data()); QMapIterator i(p->getProperties()); while (i.hasNext()) { i.next(); if (preset->settings()->hasProperty(i.key() + "_previous")) { preset->settings()->setProperty(i.key(), preset->settings()->getProperty(i.key() + "_previous")); preset->settings()->removeProperty(i.key() + "_previous"); } } m_optionWidget->setConfiguration(preset->settings()); } slotUpdatePreset(); } void KisPaintopBox::slotDirtyPresetToggled(bool value) { if (!value) { slotReloadPreset(); m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset().data()); m_presetsPopup->updateViewSettings(); } m_dirtyPresetsEnabled = value; KisConfig cfg; cfg.setUseDirtyPresets(m_dirtyPresetsEnabled); } void KisPaintopBox::slotEraserBrushSizeToggled(bool value) { m_eraserBrushSizeEnabled = value; KisConfig cfg; cfg.setUseEraserBrushSize(m_eraserBrushSizeEnabled); } void KisPaintopBox::slotUpdateSelectionIcon() { m_hMirrorAction->setIcon(themedIcon("symmetry-horizontal")); m_vMirrorAction->setIcon(themedIcon("symmetry-vertical")); } diff --git a/krita/ui/widgets/kis_cmb_composite.cc b/krita/ui/widgets/kis_cmb_composite.cc index 9d54f74818..4beeb4b956 100644 --- a/krita/ui/widgets/kis_cmb_composite.cc +++ b/krita/ui/widgets/kis_cmb_composite.cc @@ -1,467 +1,469 @@ /* * kis_cmb_composite.cc - part of KImageShop/Krayon/Krita * * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2011 Silvio Heinrich * * 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_cmb_composite.h" #include #include #include "kis_composite_ops_model.h" #include "kis_categorized_item_delegate.h" #include ////////////////////////////////////////////////////////////////////////////////////////// // ---- KisCompositeOpListWidget ------------------------------------------------------ // KisCompositeOpListWidget::KisCompositeOpListWidget(QWidget* parent): KisCategorizedListView(false, parent), m_model(new KisSortedCompositeOpListModel(this)) { setModel(m_model); setItemDelegate(new KisCategorizedItemDelegate(true, this)); } KisCompositeOpListWidget::~KisCompositeOpListWidget() { } KoID KisCompositeOpListWidget::selectedCompositeOp() const { KoID op; if (m_model->entryAt(op, currentIndex())) { return op; } return KoCompositeOpRegistry::instance().getDefaultCompositeOp(); } ////////////////////////////////////////////////////////////////////////////////////////// // ---- KisCompositeOpComboBox -------------------------------------------------------- // KisCompositeOpComboBox::KisCompositeOpComboBox(QWidget* parent): QComboBox(parent), m_model(new KisSortedCompositeOpListModel(this)), m_allowToHidePopup(true) { m_view = new KisCategorizedListView(true); setMaxVisibleItems(100); setSizeAdjustPolicy(AdjustToContents); m_view->setResizeMode(QListView::Adjust); + setToolTip(i18n("Blending Mode")); + setModel(m_model); setView(m_view); setItemDelegate(new KisCategorizedItemDelegate(true, this)); connect(m_view, SIGNAL(sigCategoryToggled(const QModelIndex&, bool)), SLOT(slotCategoryToggled(const QModelIndex&, bool))); connect(m_view, SIGNAL(sigEntryChecked(const QModelIndex&)), SLOT(slotEntryChecked(const QModelIndex&))); selectCompositeOp(KoCompositeOpRegistry::instance().getDefaultCompositeOp()); KAction *action = 0; // // Cycle through blending modes // // Shift + + (plus) or – (minus) // KAction *action = new KAction(i18n("Next Blending Mode"), this); // action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_Plus)); // connect(action, SIGNAL(triggered()), SLOT(slotNextBlendingMode())); // m_actions << action; // action = new KAction(i18n("Previous Blending Mode"), this); // action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_Minus)); // connect(action, SIGNAL(triggered()), SLOT(slotPreviousBlendingMode())); // m_actions << action; // Normal // Shift + Alt + N action = new KAction(i18n("Select Normal Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_N)); connect(action, SIGNAL(triggered()), SLOT(slotNormal())); m_actions << action; // Dissolve // Shift + Alt + I action = new KAction(i18n("Select Dissolve Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_I)); connect(action, SIGNAL(triggered()), SLOT(slotDissolve())); m_actions << action; // Behind (Brush tool only) // Shift + Alt + Q action = new KAction(i18n("Select Behind Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_Q)); connect(action, SIGNAL(triggered()), SLOT(slotBehind())); m_actions << action; // Clear (Brush tool only) // Shift + Alt + R action = new KAction(i18n("Select Clear Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_R)); connect(action, SIGNAL(triggered()), SLOT(slotClear())); m_actions << action; // Darken // Shift + Alt + K action = new KAction(i18n("Select Darken Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_K)); connect(action, SIGNAL(triggered()), SLOT(slotDarken())); m_actions << action; // Multiply // Shift + Alt + M action = new KAction(i18n("Select Multiply Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_M)); connect(action, SIGNAL(triggered()), SLOT(slotMultiply())); m_actions << action; // Color Burn // Shift + Alt + B action = new KAction(i18n("Select Color Burn Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_B)); connect(action, SIGNAL(triggered()), SLOT(slotColorBurn())); m_actions << action; // Linear Burn // Shift + Alt + A action = new KAction(i18n("Select Linear Burn Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_A)); connect(action, SIGNAL(triggered()), SLOT(slotLinearBurn())); m_actions << action; // Lighten // Shift + Alt + G action = new KAction(i18n("Select Lighten Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_G)); connect(action, SIGNAL(triggered()), SLOT(slotLighten())); m_actions << action; // Screen // Shift + Alt + S action = new KAction(i18n("Select Screen Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_S)); connect(action, SIGNAL(triggered()), SLOT(slotScreen())); m_actions << action; // Color Dodge // Shift + Alt + D action = new KAction(i18n("Select Color Dodge Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_D)); connect(action, SIGNAL(triggered()), SLOT(slotColorDodge())); m_actions << action; // Linear Dodge // Shift + Alt + W action = new KAction(i18n("Select Linear Dodge Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_W)); connect(action, SIGNAL(triggered()), SLOT(slotLinearDodge())); m_actions << action; // Overlay // Shift + Alt + O action = new KAction(i18n("Select Overlay Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_O)); connect(action, SIGNAL(triggered()), SLOT(slotOverlay())); m_actions << action; // Soft Light // Shift + Alt + F action = new KAction(i18n("Select Soft Light Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_F)); connect(action, SIGNAL(triggered()), SLOT(slotSoftLight())); m_actions << action; // Hard Light // Shift + Alt + H action = new KAction(i18n("Select Hard Light Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_H)); connect(action, SIGNAL(triggered()), SLOT(slotHardLight())); m_actions << action; // Vivid Light // Shift + Alt + V action = new KAction(i18n("Select Vivid Light Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_V)); connect(action, SIGNAL(triggered()), SLOT(slotVividLight())); m_actions << action; // Linear Light // Shift + Alt + J action = new KAction(i18n("Select Linear Light Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_J)); connect(action, SIGNAL(triggered()), SLOT(slotLinearLight())); m_actions << action; // Pin Light // Shift + Alt + Z action = new KAction(i18n("Select Pin Light Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_Z)); connect(action, SIGNAL(triggered()), SLOT(slotPinLight())); m_actions << action; // Hard Mix // Shift + Alt + L action = new KAction(i18n("Select Hard Mix Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_L)); connect(action, SIGNAL(triggered()), SLOT(slotHardMix())); m_actions << action; // Difference // Shift + Alt + E action = new KAction(i18n("Select Difference Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_E)); connect(action, SIGNAL(triggered()), SLOT(slotDifference())); m_actions << action; // Exclusion // Shift + Alt + X action = new KAction(i18n("Select Exclusion Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_X)); connect(action, SIGNAL(triggered()), SLOT(slotExclusion())); m_actions << action; // Hue // Shift + Alt + U action = new KAction(i18n("Select Hue Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_U)); connect(action, SIGNAL(triggered()), SLOT(slotHue())); m_actions << action; // Saturation // Shift + Alt + T action = new KAction(i18n("Select Saturation Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_T)); connect(action, SIGNAL(triggered()), SLOT(slotSaturation())); m_actions << action; // Color // Shift + Alt + C action = new KAction(i18n("Select Color Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_C)); connect(action, SIGNAL(triggered()), SLOT(slotColor())); m_actions << action; // Luminosity // Shift + Alt + Y action = new KAction(i18n("Select Luminosity Blending Mode"), this); action->setShortcut(QKeySequence(Qt::SHIFT + Qt::ALT + Qt::Key_Y)); connect(action, SIGNAL(triggered()), SLOT(slotLuminosity())); m_actions << action; } KisCompositeOpComboBox::~KisCompositeOpComboBox() { delete m_view; } void KisCompositeOpComboBox::validate(const KoColorSpace *cs) { m_model->validate(cs); } void KisCompositeOpComboBox::selectCompositeOp(const KoID &op) { QModelIndex index = m_model->indexOf(op); setCurrentIndex(index.row()); } KoID KisCompositeOpComboBox::selectedCompositeOp() const { KoID op; if (m_model->entryAt(op, m_model->index(currentIndex(), 0))) { return op; } return KoCompositeOpRegistry::instance().getDefaultCompositeOp(); } QList KisCompositeOpComboBox::blendmodeActions() { return m_actions; } void KisCompositeOpComboBox::slotCategoryToggled(const QModelIndex& index, bool toggled) { Q_UNUSED(index); Q_UNUSED(toggled); //NOTE: this will (should) fit the size of the // popup widget to the view // don't know if this is expected behaviour // on all supported platforms. // Thre is nothing written about this in the docs. showPopup(); } void KisCompositeOpComboBox::slotEntryChecked(const QModelIndex& index) { Q_UNUSED(index); m_allowToHidePopup = false; } void KisCompositeOpComboBox::hidePopup() { if (m_allowToHidePopup) { QComboBox::hidePopup(); } else { QComboBox::showPopup(); } m_allowToHidePopup = true; } void KisCompositeOpComboBox::slotNextBlendingMode() { if (currentIndex() < count()) { setCurrentIndex(currentIndex() + 1); } } void KisCompositeOpComboBox::slotPreviousBlendingMode() { if (currentIndex() > 0) { setCurrentIndex(currentIndex() - 1); } } void KisCompositeOpComboBox::slotNormal() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_OVER)); } void KisCompositeOpComboBox::slotDissolve() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_DISSOLVE)); } void KisCompositeOpComboBox::slotBehind() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_BEHIND)); } void KisCompositeOpComboBox::slotClear() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_CLEAR)); } void KisCompositeOpComboBox::slotDarken() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_DARKEN)); } void KisCompositeOpComboBox::slotMultiply() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_MULT)); } void KisCompositeOpComboBox::slotColorBurn() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_BURN)); } void KisCompositeOpComboBox::slotLinearBurn() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_LINEAR_BURN)); } void KisCompositeOpComboBox::slotLighten() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_LIGHTEN)); } void KisCompositeOpComboBox::slotScreen() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_SCREEN)); } void KisCompositeOpComboBox::slotColorDodge() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_DODGE)); } void KisCompositeOpComboBox::slotLinearDodge() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_LINEAR_DODGE)); } void KisCompositeOpComboBox::slotOverlay() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_OVERLAY)); } void KisCompositeOpComboBox::slotSoftLight() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_SOFT_LIGHT_PHOTOSHOP)); } void KisCompositeOpComboBox::slotHardLight() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_HARD_LIGHT)); } void KisCompositeOpComboBox::slotVividLight() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_VIVID_LIGHT)); } void KisCompositeOpComboBox::slotLinearLight() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_LINEAR_LIGHT)); } void KisCompositeOpComboBox::slotPinLight() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_PIN_LIGHT)); } void KisCompositeOpComboBox::slotHardMix() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_HARD_MIX)); } void KisCompositeOpComboBox::slotDifference() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_DIFF)); } void KisCompositeOpComboBox::slotExclusion() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_EXCLUSION)); } void KisCompositeOpComboBox::slotHue() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_HUE)); } void KisCompositeOpComboBox::slotSaturation() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_SATURATION)); } void KisCompositeOpComboBox::slotColor() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_COLOR)); } void KisCompositeOpComboBox::slotLuminosity() { selectCompositeOp(KoCompositeOpRegistry::instance().getKoID(COMPOSITE_LUMINIZE)); } diff --git a/krita/ui/widgets/kis_slider_spin_box.cpp b/krita/ui/widgets/kis_slider_spin_box.cpp index 0e38667d12..83db96fb27 100644 --- a/krita/ui/widgets/kis_slider_spin_box.cpp +++ b/krita/ui/widgets/kis_slider_spin_box.cpp @@ -1,668 +1,678 @@ /* This file is part of the KDE project * Copyright (c) 2010 Justin Noel * Copyright (c) 2010 Cyrille Berger * * 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_slider_spin_box.h" #include #include #include #include #include #include #include #include #include #include #include #include "KisPart.h" #include "input/kis_input_manager.h" class KisAbstractSliderSpinBoxPrivate { public: QLineEdit* edit; QDoubleValidator* validator; bool upButtonDown; bool downButtonDown; int factor; int fastSliderStep; qreal slowFactor; qreal shiftPercent; bool shiftMode; + QString prefix; QString suffix; qreal exponentRatio; int value; int maximum; int minimum; int singleStep; QSpinBox* dummySpinBox; }; KisAbstractSliderSpinBox::KisAbstractSliderSpinBox(QWidget* parent, KisAbstractSliderSpinBoxPrivate* _d) : QWidget(parent) , d_ptr(_d) { Q_D(KisAbstractSliderSpinBox); d->upButtonDown = false; d->downButtonDown = false; d->edit = new QLineEdit(this); d->edit->setFrame(false); d->edit->setAlignment(Qt::AlignCenter); d->edit->hide(); d->edit->installEventFilter(this); //Make edit transparent d->edit->setAutoFillBackground(false); QPalette pal = d->edit->palette(); pal.setColor(QPalette::Base, Qt::transparent); d->edit->setPalette(pal); connect(d->edit, SIGNAL(editingFinished()), this, SLOT(editLostFocus())); d->validator = new QDoubleValidator(d->edit); d->edit->setValidator(d->validator); d->value = 0; d->minimum = 0; d->maximum = 100; d->factor = 1.0; d->singleStep = 1; d->fastSliderStep = 5; d->slowFactor = 0.1; d->shiftMode = false; setExponentRatio(1.0); //Set sane defaults setFocusPolicy(Qt::StrongFocus); setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); //dummy needed to fix a bug in the polyester theme d->dummySpinBox = new QSpinBox(this); d->dummySpinBox->hide(); } KisAbstractSliderSpinBox::~KisAbstractSliderSpinBox() { Q_D(KisAbstractSliderSpinBox); delete d; } void KisAbstractSliderSpinBox::showEdit() { Q_D(KisAbstractSliderSpinBox); if (d->edit->isVisible()) return; d->edit->setGeometry(progressRect(spinBoxOptions())); d->edit->setText(valueString()); d->edit->selectAll(); d->edit->show(); d->edit->setFocus(Qt::OtherFocusReason); update(); KisPart::currentInputManager()->slotFocusOnEnter(false); } void KisAbstractSliderSpinBox::hideEdit() { Q_D(KisAbstractSliderSpinBox); d->edit->hide(); update(); KisPart::currentInputManager()->slotFocusOnEnter(true); } void KisAbstractSliderSpinBox::paintEvent(QPaintEvent* e) { Q_D(KisAbstractSliderSpinBox); Q_UNUSED(e) QPainter painter(this); //Create options to draw spin box parts QStyleOptionSpinBox spinOpts = spinBoxOptions(); //Draw "SpinBox".Clip off the area of the lineEdit to avoid double //borders being drawn painter.save(); painter.setClipping(true); QRect eraseRect(QPoint(rect().x(), rect().y()), QPoint(progressRect(spinOpts).right(), rect().bottom())); painter.setClipRegion(QRegion(rect()).subtracted(eraseRect)); style()->drawComplexControl(QStyle::CC_SpinBox, &spinOpts, &painter, d->dummySpinBox); painter.setClipping(false); painter.restore(); //Create options to draw progress bar parts QStyleOptionProgressBar progressOpts = progressBarOptions(); //Draw "ProgressBar" in SpinBox style()->drawControl(QStyle::CE_ProgressBar, &progressOpts, &painter, 0); //Draw focus if necessary if (hasFocus() && d->edit->hasFocus()) { QStyleOptionFocusRect focusOpts; focusOpts.initFrom(this); focusOpts.rect = progressOpts.rect; focusOpts.backgroundColor = palette().color(QPalette::Window); style()->drawPrimitive(QStyle::PE_FrameFocusRect, &focusOpts, &painter, this); } } void KisAbstractSliderSpinBox::mousePressEvent(QMouseEvent* e) { Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); //Depress buttons or highlight slider //Also used to emulate mouse grab... if (e->buttons() & Qt::LeftButton) { if (upButtonRect(spinOpts).contains(e->pos())) { d->upButtonDown = true; } else if (downButtonRect(spinOpts).contains(e->pos())) { d->downButtonDown = true; } } else if (e->buttons() & Qt::RightButton) { showEdit(); } update(); } void KisAbstractSliderSpinBox::mouseReleaseEvent(QMouseEvent* e) { Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); //Step up/down for buttons //Emualting mouse grab too if (upButtonRect(spinOpts).contains(e->pos()) && d->upButtonDown) { setInternalValue(d->value + d->singleStep); } else if (downButtonRect(spinOpts).contains(e->pos()) && d->downButtonDown) { setInternalValue(d->value - d->singleStep); } else if (progressRect(spinOpts).contains(e->pos()) && !(d->edit->isVisible()) && !(d->upButtonDown || d->downButtonDown)) { //Snap to percentage for progress area setInternalValue(valueForX(e->pos().x(),e->modifiers())); } d->upButtonDown = false; d->downButtonDown = false; update(); } void KisAbstractSliderSpinBox::mouseMoveEvent(QMouseEvent* e) { Q_D(KisAbstractSliderSpinBox); if( e->modifiers() & Qt::ShiftModifier ) { if( !d->shiftMode ) { d->shiftPercent = pow( qreal(d->value - d->minimum)/qreal(d->maximum - d->minimum), 1/qreal(d->exponentRatio) ); d->shiftMode = true; } } else { d->shiftMode = false; } //Respect emulated mouse grab. if (e->buttons() & Qt::LeftButton && !(d->downButtonDown || d->upButtonDown)) { setInternalValue(valueForX(e->pos().x(),e->modifiers())); update(); } } void KisAbstractSliderSpinBox::keyPressEvent(QKeyEvent* e) { Q_D(KisAbstractSliderSpinBox); switch (e->key()) { case Qt::Key_Up: case Qt::Key_Right: setInternalValue(d->value + d->singleStep); break; case Qt::Key_Down: case Qt::Key_Left: setInternalValue(d->value - d->singleStep); break; case Qt::Key_Shift: d->shiftPercent = pow( qreal(d->value - d->minimum)/qreal(d->maximum - d->minimum), 1/qreal(d->exponentRatio) ); d->shiftMode = true; break; case Qt::Key_Enter: //Line edit isn't "accepting" key strokes... case Qt::Key_Return: case Qt::Key_Escape: case Qt::Key_Control: case Qt::Key_Alt: case Qt::Key_AltGr: case Qt::Key_Super_L: case Qt::Key_Super_R: break; default: showEdit(); d->edit->event(e); break; } } void KisAbstractSliderSpinBox::wheelEvent(QWheelEvent *e) { Q_D(KisAbstractSliderSpinBox); if ( e->delta() > 0) { setInternalValue(d->value + d->singleStep); } else { setInternalValue(d->value - d->singleStep); } update(); e->accept(); } bool KisAbstractSliderSpinBox::eventFilter(QObject* recv, QEvent* e) { Q_D(KisAbstractSliderSpinBox); if (recv == static_cast(d->edit) && e->type() == QEvent::KeyRelease) { QKeyEvent* keyEvent = static_cast(e); switch (keyEvent->key()) { case Qt::Key_Enter: case Qt::Key_Return: setInternalValue(d->edit->text().toDouble()*d->factor); hideEdit(); return true; case Qt::Key_Escape: hideEdit(); return true; default: break; } } return false; } QSize KisAbstractSliderSpinBox::sizeHint() const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); - QFontMetrics fm(font()); + QFont ft(font()); + // The plastique style uses bold font in progressbars + ft.setBold(true); + QFontMetrics fm(ft); //We need at least 50 pixels or things start to look bad - int w = qMax(fm.width(QString::number(d->maximum)), 50); + int w = qMax(fm.width(d->prefix + QString::number(d->maximum) + d->suffix)+qRound(0.2*logicalDpiX()), 50); QSize hint(w, d->edit->sizeHint().height() + 3); //Getting the size of the buttons is a pain as the calcs require a rect //that is "big enough". We run the calc twice to get the "smallest" buttons //This code was inspired by QAbstractSpinBox QSize extra(35, 6); spinOpts.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &spinOpts, QStyle::SC_SpinBoxEditField, this).size(); spinOpts.rect.setSize(hint + extra); extra += hint - style()->subControlRect(QStyle::CC_SpinBox, &spinOpts, QStyle::SC_SpinBoxEditField, this).size(); hint += extra; spinOpts.rect = rect(); return style()->sizeFromContents(QStyle::CT_SpinBox, &spinOpts, hint, 0) .expandedTo(QApplication::globalStrut()); } QSize KisAbstractSliderSpinBox::minimumSizeHint() const { return sizeHint(); } QStyleOptionSpinBox KisAbstractSliderSpinBox::spinBoxOptions() const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox opts; opts.initFrom(this); opts.frame = false; opts.buttonSymbols = QAbstractSpinBox::UpDownArrows; opts.subControls = QStyle::SC_SpinBoxUp | QStyle::SC_SpinBoxDown; //Disable non-logical buttons if (d->value == d->minimum) { opts.stepEnabled = QAbstractSpinBox::StepUpEnabled; } else if (d->value == d->maximum) { opts.stepEnabled = QAbstractSpinBox::StepDownEnabled; } else { opts.stepEnabled = QAbstractSpinBox::StepUpEnabled | QAbstractSpinBox::StepDownEnabled; } //Deal with depressed buttons if (d->upButtonDown) { opts.activeSubControls = QStyle::SC_SpinBoxUp; } else if (d->downButtonDown) { opts.activeSubControls = QStyle::SC_SpinBoxDown; } else { opts.activeSubControls = 0; } return opts; } QStyleOptionProgressBar KisAbstractSliderSpinBox::progressBarOptions() const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); //Create opts for drawing the progress portion QStyleOptionProgressBar progressOpts; progressOpts.initFrom(this); progressOpts.maximum = d->maximum; progressOpts.minimum = d->minimum; qreal minDbl = d->minimum; qreal dValues = (d->maximum - minDbl); progressOpts.progress = dValues * pow((d->value - minDbl) / dValues, 1.0 / d->exponentRatio) + minDbl; - progressOpts.text = valueString() + d->suffix; + progressOpts.text = d->prefix + valueString() + d->suffix; progressOpts.textAlignment = Qt::AlignCenter; progressOpts.textVisible = !(d->edit->isVisible()); //Change opts rect to be only the ComboBox's text area progressOpts.rect = progressRect(spinOpts); return progressOpts; } QRect KisAbstractSliderSpinBox::progressRect(const QStyleOptionSpinBox& spinBoxOptions) const { return style()->subControlRect(QStyle::CC_SpinBox, &spinBoxOptions, QStyle::SC_SpinBoxEditField); } QRect KisAbstractSliderSpinBox::upButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const { return style()->subControlRect(QStyle::CC_SpinBox, &spinBoxOptions, QStyle::SC_SpinBoxUp); } QRect KisAbstractSliderSpinBox::downButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const { return style()->subControlRect(QStyle::CC_SpinBox, &spinBoxOptions, QStyle::SC_SpinBoxDown); } int KisAbstractSliderSpinBox::valueForX(int x, Qt::KeyboardModifiers modifiers) const { const Q_D(KisAbstractSliderSpinBox); QStyleOptionSpinBox spinOpts = spinBoxOptions(); //Adjust for magic number in style code (margins) QRect correctedProgRect = progressRect(spinOpts).adjusted(2, 2, -2, -2); //Compute the distance of the progress bar, in pixel qreal leftDbl = correctedProgRect.left(); qreal xDbl = x - leftDbl; //Compute the ration of the progress bar used, linearly (ignoring the exponent) qreal rightDbl = correctedProgRect.right(); qreal minDbl = d->minimum; qreal maxDbl = d->maximum; qreal dValues = (maxDbl - minDbl); qreal percent = (xDbl / (rightDbl - leftDbl)); //If SHIFT is pressed, movement should be slowed. if( modifiers & Qt::ShiftModifier ) { percent = d->shiftPercent + ( percent - d->shiftPercent ) * d->slowFactor; } //Final value qreal realvalue = ((dValues * pow(percent, d->exponentRatio)) + minDbl); //If key CTRL is pressed, round to the closest step. if( modifiers & Qt::ControlModifier ) { qreal fstep = d->fastSliderStep; if( modifiers & Qt::ShiftModifier ) { fstep*=d->slowFactor; } realvalue = floor( (realvalue+fstep/2) / fstep ) * fstep; } //Return the value return int(realvalue); } +void KisAbstractSliderSpinBox::setPrefix(const QString& prefix) +{ + Q_D(KisAbstractSliderSpinBox); + d->prefix = prefix; +} + void KisAbstractSliderSpinBox::setSuffix(const QString& suffix) { Q_D(KisAbstractSliderSpinBox); d->suffix = suffix; } void KisAbstractSliderSpinBox::setExponentRatio(qreal dbl) { Q_D(KisAbstractSliderSpinBox); Q_ASSERT(dbl > 0); d->exponentRatio = dbl; } void KisAbstractSliderSpinBox::contextMenuEvent(QContextMenuEvent* event) { event->accept(); } void KisAbstractSliderSpinBox::editLostFocus() { // only hide on focus lost, if editing is finished that will be handled in eventFilter Q_D(KisAbstractSliderSpinBox); if (!d->edit->hasFocus()) { hideEdit(); } } class KisSliderSpinBoxPrivate : public KisAbstractSliderSpinBoxPrivate { }; KisSliderSpinBox::KisSliderSpinBox(QWidget* parent) : KisAbstractSliderSpinBox(parent, new KisSliderSpinBoxPrivate) { setRange(0,99); } KisSliderSpinBox::~KisSliderSpinBox() { } void KisSliderSpinBox::setRange(int minimum, int maximum) { Q_D(KisSliderSpinBox); d->minimum = minimum; d->maximum = maximum; d->fastSliderStep = (maximum-minimum+1)/20; d->validator->setRange(minimum, maximum, 0); update(); } int KisSliderSpinBox::minimum() const { const Q_D(KisSliderSpinBox); return d->minimum; } void KisSliderSpinBox::setMinimum(int minimum) { Q_D(KisSliderSpinBox); setRange(minimum, d->maximum); } int KisSliderSpinBox::maximum() const { const Q_D(KisSliderSpinBox); return d->maximum; } void KisSliderSpinBox::setMaximum(int maximum) { Q_D(KisSliderSpinBox); setRange(d->minimum, maximum); } int KisSliderSpinBox::fastSliderStep() const { const Q_D(KisSliderSpinBox); return d->fastSliderStep; } void KisSliderSpinBox::setFastSliderStep(int step) { Q_D(KisSliderSpinBox); d->fastSliderStep = step; } int KisSliderSpinBox::value() { Q_D(KisSliderSpinBox); return d->value; } void KisSliderSpinBox::setValue(int value) { setInternalValue(value); update(); } QString KisSliderSpinBox::valueString() const { const Q_D(KisSliderSpinBox); return QString::number(d->value, 'f', d->validator->decimals()); } void KisSliderSpinBox::setSingleStep(int value) { Q_D(KisSliderSpinBox); d->singleStep = value; } void KisSliderSpinBox::setPageStep(int value) { Q_UNUSED(value); } void KisSliderSpinBox::setInternalValue(int _value) { Q_D(KisAbstractSliderSpinBox); d->value = qBound(d->minimum, _value, d->maximum); emit(valueChanged(value())); } class KisDoubleSliderSpinBoxPrivate : public KisAbstractSliderSpinBoxPrivate { }; KisDoubleSliderSpinBox::KisDoubleSliderSpinBox(QWidget* parent) : KisAbstractSliderSpinBox(parent, new KisDoubleSliderSpinBoxPrivate) { } KisDoubleSliderSpinBox::~KisDoubleSliderSpinBox() { } void KisDoubleSliderSpinBox::setRange(qreal minimum, qreal maximum, int decimals) { Q_D(KisDoubleSliderSpinBox); d->factor = pow(10.0, decimals); d->minimum = minimum * d->factor; d->maximum = maximum * d->factor; //This code auto-compute a new step when pressing control. //A flag defaulting to "do not change the fast step" should be added, but it implies changing every call if(maximum - minimum >= 2.0 || decimals <= 0) { //Quick step on integers d->fastSliderStep = int(pow(10.0, decimals)); } else if(decimals == 1) { d->fastSliderStep = (maximum-minimum)*d->factor/10; } else { d->fastSliderStep = (maximum-minimum)*d->factor/20; } d->validator->setRange(minimum, maximum, decimals); update(); setValue(value()); } qreal KisDoubleSliderSpinBox::minimum() const { const Q_D(KisAbstractSliderSpinBox); return d->minimum / d->factor; } void KisDoubleSliderSpinBox::setMinimum(qreal minimum) { Q_D(KisAbstractSliderSpinBox); setRange(minimum, d->maximum); } qreal KisDoubleSliderSpinBox::maximum() const { const Q_D(KisAbstractSliderSpinBox); return d->maximum / d->factor; } void KisDoubleSliderSpinBox::setMaximum(qreal maximum) { Q_D(KisAbstractSliderSpinBox); setRange(d->minimum, maximum); } qreal KisDoubleSliderSpinBox::fastSliderStep() const { const Q_D(KisAbstractSliderSpinBox); return d->fastSliderStep; } void KisDoubleSliderSpinBox::setFastSliderStep(qreal step) { Q_D(KisAbstractSliderSpinBox); d->fastSliderStep = step; } qreal KisDoubleSliderSpinBox::value() { Q_D(KisAbstractSliderSpinBox); return (qreal)d->value / d->factor; } void KisDoubleSliderSpinBox::setValue(qreal value) { Q_D(KisAbstractSliderSpinBox); setInternalValue(d->value = qRound(value * d->factor)); update(); } void KisDoubleSliderSpinBox::setSingleStep(qreal value) { Q_D(KisAbstractSliderSpinBox); d->singleStep = value * d->factor; } QString KisDoubleSliderSpinBox::valueString() const { const Q_D(KisAbstractSliderSpinBox); return QString::number((qreal)d->value / d->factor, 'f', d->validator->decimals()); } void KisDoubleSliderSpinBox::setInternalValue(int _value) { Q_D(KisAbstractSliderSpinBox); d->value = qBound(d->minimum, _value, d->maximum); emit(valueChanged(value())); } diff --git a/krita/ui/widgets/kis_slider_spin_box.h b/krita/ui/widgets/kis_slider_spin_box.h index 4ce641a66a..37622501f0 100644 --- a/krita/ui/widgets/kis_slider_spin_box.h +++ b/krita/ui/widgets/kis_slider_spin_box.h @@ -1,147 +1,148 @@ /* This file is part of the KDE project * Copyright (c) 2010 Justin Noel * * 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. */ #ifndef KISSLIDERSPINBOX_H #define KISSLIDERSPINBOX_H #include #include #include #include class KisAbstractSliderSpinBoxPrivate; class KisSliderSpinBoxPrivate; class KisDoubleSliderSpinBoxPrivate; /** * XXX: when inactive, also show the progress bar part as inactive! */ class KRITAUI_EXPORT KisAbstractSliderSpinBox : public QWidget { Q_OBJECT Q_DISABLE_COPY(KisAbstractSliderSpinBox) Q_DECLARE_PRIVATE(KisAbstractSliderSpinBox) protected: explicit KisAbstractSliderSpinBox(QWidget* parent, KisAbstractSliderSpinBoxPrivate*); public: virtual ~KisAbstractSliderSpinBox(); void showEdit(); void hideEdit(); + void setPrefix(const QString& prefix); void setSuffix(const QString& suffix); void setExponentRatio(qreal dbl); protected: virtual void paintEvent(QPaintEvent* e); virtual void mousePressEvent(QMouseEvent* e); virtual void mouseReleaseEvent(QMouseEvent* e); virtual void mouseMoveEvent(QMouseEvent* e); virtual void keyPressEvent(QKeyEvent* e); virtual void wheelEvent(QWheelEvent *); virtual bool eventFilter(QObject* recv, QEvent* e); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; QStyleOptionSpinBox spinBoxOptions() const; QStyleOptionProgressBar progressBarOptions() const; QRect progressRect(const QStyleOptionSpinBox& spinBoxOptions) const; QRect upButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const; QRect downButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const; int valueForX(int x, Qt::KeyboardModifiers modifiers = Qt::NoModifier) const; virtual QString valueString() const = 0; virtual void setInternalValue(int value) = 0; protected Q_SLOTS: void contextMenuEvent(QContextMenuEvent * event); void editLostFocus(); protected: KisAbstractSliderSpinBoxPrivate* const d_ptr; }; class KRITAUI_EXPORT KisSliderSpinBox : public KisAbstractSliderSpinBox { Q_OBJECT Q_DECLARE_PRIVATE(KisSliderSpinBox) Q_PROPERTY( int minimum READ minimum WRITE setMinimum ) Q_PROPERTY( int maximum READ maximum WRITE setMaximum ) public: KisSliderSpinBox(QWidget* parent = 0); ~KisSliderSpinBox(); void setRange(int minimum, int maximum); int minimum() const; void setMinimum(int minimum); int maximum() const; void setMaximum(int maximum); int fastSliderStep() const; void setFastSliderStep(int step); ///Get the value, don't use value() int value(); ///Set the value, don't use setValue() void setValue(int value); void setSingleStep(int value); void setPageStep(int value); protected: virtual QString valueString() const; virtual void setInternalValue(int value); Q_SIGNALS: void valueChanged(int value); }; class KRITAUI_EXPORT KisDoubleSliderSpinBox : public KisAbstractSliderSpinBox { Q_OBJECT Q_DECLARE_PRIVATE(KisDoubleSliderSpinBox) public: KisDoubleSliderSpinBox(QWidget* parent = 0); ~KisDoubleSliderSpinBox(); void setRange(qreal minimum, qreal maximum, int decimals = 0); qreal minimum() const; void setMinimum(qreal minimum); qreal maximum() const; void setMaximum(qreal maximum); qreal fastSliderStep() const; void setFastSliderStep(qreal step); qreal value(); void setValue(qreal value); void setSingleStep(qreal value); protected: virtual QString valueString() const; virtual void setInternalValue(int value); Q_SIGNALS: void valueChanged(qreal value); }; #endif //kISSLIDERSPINBOX_H diff --git a/krita/ui/widgets/kis_widget_chooser.cpp b/krita/ui/widgets/kis_widget_chooser.cpp index 3a699a8063..7a2494bb4e 100644 --- a/krita/ui/widgets/kis_widget_chooser.cpp +++ b/krita/ui/widgets/kis_widget_chooser.cpp @@ -1,239 +1,256 @@ /* * Copyright (c) 2011 Silvio Heinrich * * 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_widget_chooser.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_config.h" KisWidgetChooser::KisWidgetChooser(int id, QWidget* parent) : QFrame(parent) , m_chooserid(id) { // QFrame::setFrameStyle(QFrame::StyledPanel|QFrame::Raised); m_acceptIcon = koIcon("list-add"); m_buttons = new QButtonGroup(); m_popup = new QFrame(0, Qt::Popup); m_arrowButton = new QToolButton(); m_popup->setFrameStyle(QFrame::Panel|QFrame::Raised); m_arrowButton->setIcon(arrowIcon()); + m_arrowButton->setFixedWidth(m_arrowButton->sizeHint().height()/2); m_arrowButton->setAutoRaise(true); connect(m_arrowButton, SIGNAL(clicked(bool)), SLOT(slotButtonPressed())); } KisWidgetChooser::~KisWidgetChooser() { delete m_buttons; } QIcon KisWidgetChooser::arrowIcon() { QImage image(16, 16, QImage::Format_ARGB32); image.fill(0); QStylePainter painter(&image, this); QStyleOption option; option.rect = image.rect(); option.palette = palette(); option.state = QStyle::State_Enabled; option.palette.setBrush(QPalette::ButtonText, Qt::black); // Force color to black painter.setBrush(Qt::black); painter.setPen(Qt::black); painter.drawPrimitive(QStyle::PE_IndicatorArrowDown, option); return QIcon(QPixmap::fromImage(image)); } void KisWidgetChooser::addWidget(const QString& id, const QString& label, QWidget* widget) { if(id.isEmpty()) { delete widget; return; } removeWidget(id); - m_widgets.push_back(Data(id, widget, new QLabel(label))); + + if (label.isEmpty()) { + m_widgets.push_back(Data(id, widget, 0)); + } + else { + m_widgets.push_back(Data(id, widget, new QLabel(label))); + } delete m_popup->layout(); m_popup->setLayout(createPopupLayout()); m_popup->adjustSize(); delete QWidget::layout(); QWidget::setLayout(createLayout()); } QLayout* KisWidgetChooser::createLayout() { QHBoxLayout* layout = new QHBoxLayout(); - layout->setContentsMargins(2, 0, 0, 0); + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); for(Iterator i=m_widgets.begin(); i!=m_widgets.end(); ++i) { if(i->choosen) { - layout->addWidget(i->label); + if (i->label) { + layout->addWidget(i->label); + } layout->addWidget(i->widget); break; } } layout->addWidget(m_arrowButton); return layout; } QLayout* KisWidgetChooser::createPopupLayout() { QGridLayout* layout = new QGridLayout(); int row = 0; int idx = 0; - - layout->setContentsMargins(2, 0, 0, 0); + + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); QButtonGroup* group = new QButtonGroup(); QList buttons = m_buttons->buttons(); for(Iterator i=m_widgets.begin(); i!=m_widgets.end(); ++i) { if(!i->choosen) { if(row == buttons.size()) { QToolButton* bn = new QToolButton(); bn->setIcon(m_acceptIcon); bn->setAutoRaise(true); buttons.push_back(bn); } - layout->addWidget(i->label , row, 0); - layout->addWidget(i->widget , row, 1); - layout->addWidget(buttons[row], row, 2); + if (i->label) { + layout->addWidget(i->label , row, 0); + layout->addWidget(i->widget , row, 1); + layout->addWidget(buttons[row], row, 2); + } + else { + layout->addWidget(i->widget , row, 0); + layout->addWidget(buttons[row], row, 1); + } group->addButton(buttons[row], idx); ++row; } ++idx; } for(int i=row; ichoosen) { delete m_popup->layout(); m_popup->setLayout(createPopupLayout()); m_popup->adjustSize(); } else delete QWidget::layout(); - delete data->label; + if (data->label) { + delete data->label; + } delete data->widget; m_widgets.erase(data); } } QWidget* KisWidgetChooser::chooseWidget(const QString& id) { QWidget* choosenWidget = 0; for(Iterator i=m_widgets.begin(); i!=m_widgets.end(); ++i) { if(i->id == id) { choosenWidget = i->widget; i->choosen = true; } else i->choosen = false; } delete m_popup->layout(); m_popup->setLayout(createPopupLayout()); m_popup->adjustSize(); delete QWidget::layout(); QWidget::setLayout(createLayout()); KisConfig cfg; cfg.setToolbarSlider(m_chooserid, id); return choosenWidget; } QWidget* KisWidgetChooser::getWidget(const QString& id) const { ConstIterator data = qFind(m_widgets.begin(), m_widgets.end(), Data(id)); if(data != m_widgets.end()) return data->widget; return 0; } void KisWidgetChooser::showPopupWidget() { QSize popSize = m_popup->size(); - QRect popupRect(QFrame::mapToGlobal(QPoint(0, QFrame::height())), popSize); + QRect popupRect(QFrame::mapToGlobal(QPoint(-1, QFrame::height())), popSize); // Get the available geometry of the screen which contains this KisPopupButton QRect screenRect = QApplication::desktop()->availableGeometry(this); // Make sure the popup is not drawn outside the screen area if(popupRect.right() > screenRect.right()) popupRect.translate(screenRect.right() - popupRect.right(), 0); if(popupRect.left() < screenRect.left()) popupRect.translate(screenRect.left() - popupRect.left(), 0); if(popupRect.bottom() > screenRect.bottom()) popupRect.translate(0, -popupRect.height()); m_popup->setGeometry(popupRect); m_popup->show(); } void KisWidgetChooser::slotButtonPressed() { showPopupWidget(); } void KisWidgetChooser::slotWidgetChoosen(int index) { chooseWidget(m_widgets[index].id); m_popup->hide(); } diff --git a/krita/ui/widgets/kis_widget_chooser.h b/krita/ui/widgets/kis_widget_chooser.h index 5f7528b704..cd8bbe5328 100644 --- a/krita/ui/widgets/kis_widget_chooser.h +++ b/krita/ui/widgets/kis_widget_chooser.h @@ -1,100 +1,100 @@ /* * Copyright (c) 2011 Silvio Heinrich * * 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 H_KIS_WIDGET_CHOOSER_H_ #define H_KIS_WIDGET_CHOOSER_H_ #include #include #include #include class QToolButton; class QLabel; class QButtonGroup; class KRITAUI_EXPORT KisWidgetChooser: public QFrame { Q_OBJECT struct Data { Data(const QString& ID): id(ID), widget(0), label(0), choosen(false) { } Data(const Data& d): id(d.id), widget(d.widget), label(d.label), choosen(d.choosen) { } Data(const QString& ID, QWidget* w, QLabel* l): id(ID), widget(w), label(l), choosen(false) { } friend bool operator == (const Data& a, const Data& b) { return a.id == b.id; } QString id; QWidget* widget; QLabel* label; bool choosen; }; typedef QList::iterator Iterator; typedef QList::const_iterator ConstIterator; public: KisWidgetChooser(int id, QWidget* parent=0); ~KisWidgetChooser(); QWidget* chooseWidget(const QString& id); void addWidget(const QString& id, const QString& label, QWidget* widget); QWidget* getWidget(const QString& id) const; template - TWidget* addWidget(const QString& id, const QString& label) { + TWidget* addWidget(const QString& id, const QString& label = "") { TWidget* widget = new TWidget(); addWidget(id, label, widget); return widget; } template TWidget* getWidget(const QString& id) const { return dynamic_cast(getWidget(id)); } public Q_SLOTS: void showPopupWidget(); private: void removeWidget(const QString& id); QLayout* createPopupLayout(); QLayout* createLayout(); QIcon arrowIcon(); protected Q_SLOTS: void slotButtonPressed(); void slotWidgetChoosen(int index); private: int m_chooserid; QIcon m_acceptIcon; QToolButton* m_arrowButton; QButtonGroup* m_buttons; QFrame* m_popup; QString m_choosenID; QList m_widgets; }; #endif // H_KIS_WIDGET_CHOOSER_H_