Krita Source Code Documentation
Loading...
Searching...
No Matches
presethistory_dock.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2015 Boudewijn Rempt <boud@valdyas.org>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6
8
9#include <QAction>
10#include <QActionGroup>
11#include <QMenu>
12#include <QHBoxLayout>
13#include <QListWidget>
14#include <QImage>
15#include <QInputDialog>
16
17#include <klocalizedstring.h>
18
20#include <KoCanvasBase.h>
21
22#include "kis_config.h"
23#include "kis_canvas2.h"
24#include "KisViewManager.h"
25#include "kis_paintop_box.h"
29#include <KisKineticScroller.h>
31#include <kis_types.h>
32
33#define ICON_SIZE 48
34
36 : QListWidget(parent)
37{}
38
40{
41 if (e->button() == Qt::LeftButton)
42 {
43 Q_EMIT mouseReleased(currentItem());
44 }
45 QListWidget::mouseReleaseEvent(e); // forward the event to the QListWidget
46}
47
49 : QDockWidget(i18n("Brush Preset History"))
50{
52 m_presetHistory->setIconSize(QSize(ICON_SIZE, ICON_SIZE));
53 m_presetHistory->setDragEnabled(false);
54 m_presetHistory->setSelectionBehavior(QAbstractItemView::SelectRows);
55 m_presetHistory->setSelectionMode(QAbstractItemView::SingleSelection);
56 m_presetHistory->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
57 m_presetHistory->setContextMenuPolicy(Qt::CustomContextMenu);
58 setWidget(m_presetHistory);
59
60 m_sortingModes = new QActionGroup(this);
61 m_actionSortStatic = new QAction(i18n("Static Positions"), m_sortingModes);
62 m_actionSortStatic->setCheckable(true);
63 m_actionSortMostRecent = new QAction(i18n("Move to Top on Use"), m_sortingModes);
64 m_actionSortMostRecent->setCheckable(true);
65 m_actionSortBubble = new QAction(i18n("Bubble Up on Repeated Use"), m_sortingModes);
66 m_actionSortBubble->setCheckable(true);
67
69 if( scroller ) {
70 connect(scroller, SIGNAL(stateChanged(QScroller::State)), this, SLOT(slotScrollerStateChanged(QScroller::State)));
71 }
72
74
75 connect(m_resourceModel, SIGNAL(modelReset()), this, SLOT(updatePresets()));
76 connect(m_resourceModel, SIGNAL(rowsRemoved(const QModelIndex, int, int)), this, SLOT(updatePresets()));
77 connect(m_resourceModel, SIGNAL(dataChanged(const QModelIndex, const QModelIndex, const QVector<int>)), this, SLOT(updatePresets()));
78
79 connect(m_presetHistory, SIGNAL(mouseReleased(QListWidgetItem*)), SLOT(presetSelected(QListWidgetItem*)));
80 connect(m_sortingModes, SIGNAL(triggered(QAction*)), SLOT(slotSortingModeChanged(QAction*)));
81 connect(m_presetHistory, SIGNAL(customContextMenuRequested(QPoint)), SLOT(slotContextMenuRequest(QPoint)));
82}
83
85{
86 setEnabled(canvas != 0);
87
88 if (m_canvas) {
89 m_canvas->disconnectCanvasObserver(this);
90 disconnect(m_canvas->resourceManager());
91 }
92
93 m_canvas = dynamic_cast<KisCanvas2*>(canvas);
94
95 if (!m_canvas || !m_canvas->viewManager() || !m_canvas->resourceManager()) return;
96
97 connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), SLOT(canvasResourceChanged(int,QVariant)));
98
99 if (!m_initialized) {
100 KisConfig cfg(true);
101 QStringList presetHistory = cfg.readEntry<QString>("presethistory", "").split(",", Qt::SkipEmptyParts);
102
103 m_presetLimit = cfg.readEntry("presethistoryLimit", 10);
104
105 Q_FOREACH (const QString &p, presetHistory) {
106 if (m_resourceModel->resourcesForName(p).count()>0) {
107 KoResourceSP resource = m_resourceModel->resourcesForName(p).first();
108 if (resource) {
109 addPreset(p, QPixmap::fromImage(resource->image()), resource->resourceId());
110 }
111 }
112 }
113 int ordering = cfg.readEntry("presethistorySorting", int(DisplayOrder::Static));
114 m_sorting = qBound(DisplayOrder::Static, static_cast<DisplayOrder>(ordering), DisplayOrder::Bubbling);
115
116 switch (m_sorting) {
118 m_actionSortStatic->setChecked(true);
119 break;
121 m_actionSortMostRecent->setChecked(true);
122 break;
124 m_actionSortBubble->setChecked(true);
125 }
126
127 QVariant currentPreset = m_canvas->resourceManager()->resource(KoCanvasResource::CurrentPaintOpPreset);
129 m_initialized = true;
130 }
131}
132
134{
135 m_canvas = 0;
136 setEnabled(false);
137 QStringList presetHistory;
138 for(int i = 0; i < m_presetHistory->count(); i++) {
139 QListWidgetItem *item = m_presetHistory->item(i);
140 presetHistory.insert(0, item->text());
141 }
142 KisConfig cfg(false);
143 cfg.writeEntry("presethistory", presetHistory.join(","));
144}
145
146void PresetHistoryDock::presetSelected(QListWidgetItem *item)
147{
148 if (item) {
149 int oldPosition = m_presetHistory->currentRow();
150 updatePresetState(oldPosition);
151 int id = item->data(ResourceID).toInt();
153 m_block = true;
154 m_canvas->viewManager()->paintOpBox()->resourceSelected(preset);
155 m_block = false;
156 }
157}
158
159void PresetHistoryDock::canvasResourceChanged(int key, const QVariant& v)
160{
161 if (m_block) return;
162
164 KisPaintOpPresetSP preset = v.value<KisPaintOpPresetSP>();
165 if (preset) {
166 for (int i = 0; i < m_presetHistory->count(); ++i) {
167 if (preset->name() == m_presetHistory->item(i)->text()) {
169 return;
170 }
171 }
172 addPreset(preset->name(), QPixmap::fromImage(preset->image()), preset->resourceId());
173 }
174 }
175}
176
178{
179 if (action == m_actionSortStatic) {
181 } else if (action == m_actionSortMostRecent) {
183 } else if (action == m_actionSortBubble) {
185 }
186 KisConfig cfg(false);
187 cfg.writeEntry("presethistorySorting", int(m_sorting));
188}
189
191{
192 m_presetLimit = presetLimit;
193 while (m_presetHistory->count() > m_presetLimit) {
194 delete m_presetHistory->takeItem(m_presetHistory->count()-1);
195 }
196 KisConfig cfg(false);
197 cfg.writeEntry("presethistoryLimit", m_presetLimit);
198}
199
201 bool ok;
202 int i = QInputDialog::getInt(this, i18n("Set Number of Brushes Shown"),
203 i18n("Number of Brushes Shown:"), m_presetLimit, 1, 100, 10, &ok);
204 if (ok && i != m_presetLimit) {
206 }
207}
208
210{
211 switch (m_sorting) {
212 case Static:
213 m_presetHistory->setCurrentRow(position);
214 break;
215 case MostRecent:
216 m_presetHistory->insertItem(0, m_presetHistory->takeItem(position));
217 m_presetHistory->setCurrentRow(0);
218 break;
219 case Bubbling:
220 position = bubblePreset(position);
221 m_presetHistory->setCurrentRow(position);
222 };
223}
224
226{
227 QListWidgetItem *item = m_presetHistory->item(position);
228 if (position == 0) {
229 // topmost item cannot bubble, its bubble state stays until
230 // below item tries to bubble, so state can be set unconditionally
231 item->setData(BubbleMarkerRole, QVariant(true));
232 return position;
233 }
234
235 if (!item->data(BubbleMarkerRole).toBool()) {
236 // first activation effectively makes the entry rival the list position above
237 // (unless that one is already marked to bubble too) but it won't raise in position
238 // until it gets activated again so its position is clearly defined as above
239 item->setData(BubbleMarkerRole, QVariant(true));
240 return position;
241 }
242 else {
243 item->setData(BubbleMarkerRole, QVariant(false));
244 int topPosition = position - 1;
245 for (; topPosition >= 0; --topPosition) {
246 QListWidgetItem *topItem = m_presetHistory->item(topPosition);
247 if (topItem->data(BubbleMarkerRole).toBool()) {
248 topItem->setData(BubbleMarkerRole, QVariant(false));
249 }
250 else {
251 break;
252 }
253 }
254 // if all above items want to bubble too, nothing happens besides resetting bubble state
255 if (topPosition >= 0) {
256 // since a group of items may bubble together, the net effect is
257 // that the item above this range moves below that group
258 QListWidgetItem *topItem = m_presetHistory->takeItem(topPosition);
259 m_presetHistory->insertItem(position, topItem);
260 return position - 1;
261 }
262 }
263 return position;
264}
265
266void PresetHistoryDock::addPreset(QString name, QIcon icon, int resourceId)
267{
268 if (resourceId >= 0) {
269 QListWidgetItem *item = new QListWidgetItem(icon, name);
270 item->setData(BubbleMarkerRole, QVariant(false));
271 item->setData(ResourceID, resourceId);
272 m_presetHistory->insertItem(0, item);
273 m_presetHistory->setCurrentRow(0);
274 if (m_presetHistory->count() > m_presetLimit) {
275 delete m_presetHistory->takeItem(m_presetLimit);
276 }
277 }
278
279}
280
282{
283 for (int i = 0; i < m_presetHistory->count(); ++i) {
284 QListWidgetItem *item = m_presetHistory->item(i);
285 int id = item->data(ResourceID).toInt();
286 QModelIndex index = m_resourceModel->indexForResourceId(id);
287 if (index.isValid()) {
288 item->setIcon(QPixmap::fromImage(index.data(Qt::UserRole + KisAbstractResourceModel::Thumbnail).value<QImage>()));
289 item->setText(index.data(Qt::UserRole + KisAbstractResourceModel::Name).toString());
290 } else {
291 delete m_presetHistory->takeItem(i);
292 }
293 }
294}
295
297{
298 QMenu contextMenu;
299 QListWidgetItem *presetItem = m_presetHistory->itemAt(pos);
300 QAction *actionForget = 0;
301 if (presetItem) {
302 actionForget = new QAction(i18n("Forget \"%1\"", presetItem->text()), &contextMenu);
303 contextMenu.addAction(actionForget);
304 }
305 contextMenu.addAction(i18n("Clear History"), m_presetHistory, SLOT(clear()));
306 contextMenu.addSeparator();
307 contextMenu.addSection(i18n("History Behavior:"));
308 contextMenu.addAction(m_actionSortStatic);
309 contextMenu.addAction(m_actionSortMostRecent);
310 contextMenu.addAction(m_actionSortBubble);
311 contextMenu.addSeparator();
312 contextMenu.addAction(i18n("Configure Number of Brushes Shown..."), this, SLOT(showPresetLimitDialog()));
313 QAction *triggered = contextMenu.exec(m_presetHistory->mapToGlobal(pos));
314
315 if (presetItem && triggered == actionForget) {
316 // deleting a QListWidgetItem removes it from the QListWidget automatically
317 delete presetItem;
318 }
319}
const Params2D p
qreal v
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
void writeEntry(const QString &name, const T &value)
Definition kis_config.h:779
T readEntry(const QString &name, const T &defaultValue=T())
Definition kis_config.h:789
KoResourceSP resourceForId(int id) const
QVector< KoResourceSP > resourcesForName(QString name) const
QModelIndex indexForResourceId(int resourceId) const override
indexFromResource
static KisResourceServerProvider * instance()
KisPaintOpPresetResourceServer * paintOpPresetServer()
KisResourceModel * resourceModel() const
void addPreset(QString name, QIcon icon, int resourceId)
int bubblePreset(int position)
void slotPresetLimitChanged(int presetLimit)
QActionGroup * m_sortingModes
void slotScrollerStateChanged(QScroller::State state)
void slotSortingModeChanged(QAction *action)
KisResourceModel * m_resourceModel
void setCanvas(KoCanvasBase *canvas) override
void presetSelected(QListWidgetItem *item)
void updatePresetState(int position)
void canvasResourceChanged(int key, const QVariant &v)
QPointer< KisCanvas2 > m_canvas
QAction * m_actionSortMostRecent
PresetHistoryList * m_presetHistory
void unsetCanvas() override
void slotContextMenuRequest(const QPoint &pos)
void mouseReleaseEvent(QMouseEvent *e) override
void mouseReleased(QListWidgetItem *item)
PresetHistoryList(QWidget *parent=nullptr)
KRITAWIDGETUTILS_EXPORT QScroller * createPreconfiguredScroller(QAbstractScrollArea *target)
#define ICON_SIZE