Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_statusbar.cc
Go to the documentation of this file.
1/* This file is part of KimageShop^WKrayon^WKrita
2 *
3 * SPDX-FileCopyrightText: 2006 Boudewijn Rempt <boud@valdyas.org>
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8#include "kis_statusbar.h"
9
10#include <QToolButton>
11#include <QAction>
12#include <QToolTip>
13#include <QStatusBar>
14
15#include <ksqueezedtextlabel.h>
16#include <klocalizedstring.h>
17#include <kformat.h>
18
19#include <KoColorProfile.h>
20#include <KoColorSpace.h>
21#include <KoToolManager.h>
22#include <KoViewConverter.h>
23#include <QHBoxLayout>
24
25#include <KisUsageLogger.h>
26
27#include <kis_icon_utils.h>
28
29#include <kis_types.h>
30#include <kis_image.h>
31#include <kis_selection.h>
32#include <kis_paint_device.h>
35
36#include "KisView.h"
37#include "KisDocument.h"
38#include "KisViewManager.h"
39#include "canvas/kis_canvas2.h"
40#include "kis_progress_widget.h"
41#include "kis_zoom_manager.h"
42#include <KisAngleSelector.h>
44#include <kis_signals_blocker.h>
45
46#include "KisMainWindow.h"
47#include "kis_config.h"
48
50
51enum {
54};
55
57 : m_viewManager(viewManager)
58 , m_imageView(0)
59 , m_statusBar(0)
60{
61}
62
64{
65 m_selectionStatus = new QToolButton();
66 m_selectionStatus->setObjectName("selection status");
67 m_selectionStatus->setIconSize(QSize(16,16));
68 m_selectionStatus->setAutoRaise(true);
69 m_selectionStatus->setEnabled(false);
71
72 m_statusBar = m_viewManager->mainWindow()->statusBar();
73
74 connect(m_selectionStatus, SIGNAL(clicked()), m_viewManager->selectionManager(), SLOT(slotToggleSelectionDecoration()));
75 connect(m_viewManager->selectionManager(), SIGNAL(displaySelectionChanged()), SLOT(updateSelectionToolTip()));
76 connect(m_viewManager->mainWindow(), SIGNAL(themeChanged()), this, SLOT(updateSelectionIcon()));
77
79 m_selectionStatus->setVisible(false);
80
81 m_statusBarStatusLabel = new KSqueezedTextLabel();
82 m_statusBarStatusLabel->setObjectName("statsBarStatusLabel");
83 m_statusBarStatusLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
84 m_statusBarStatusLabel->setContentsMargins(5, 5, 5, 5);
85 connect(KoToolManager::instance(), SIGNAL(changedStatusText(QString)),
86 m_statusBarStatusLabel, SLOT(setText(QString)));
88 m_statusBarStatusLabel->setVisible(false);
89
90 m_statusBarProfileLabel = new KSqueezedTextLabel();
91 m_statusBarProfileLabel->setObjectName("statsBarProfileLabel");
92 m_statusBarProfileLabel->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
93 m_statusBarProfileLabel->setContentsMargins(5, 5, 5, 5);
95 m_statusBarProfileLabel->setVisible(false);
96
98 m_progress->setObjectName("ProgressBar");
100 m_progress->setVisible(false);
102
104 m_progressUpdater->setAutoNestNames(true);
105
106 m_extraWidgetsParent = new QFrame;
107 m_extraWidgetsParent->setMinimumWidth(50);
108 m_extraWidgetsParent->setObjectName("Extra Widgets Parent");
109 m_extraWidgetsLayout = new QHBoxLayout;
110 m_extraWidgetsLayout->setContentsMargins(0, 0, 0, 0);
111 m_extraWidgetsLayout->setObjectName("Extra Widgets Layout");
114
116 m_memoryReportBox->setObjectName("memoryReportBox");
117 m_memoryReportBox->setFlat(true);
118 m_memoryReportBox->setContentsMargins(5, 5, 5, 5);
119 m_memoryReportBox->setMinimumWidth(120);
121 m_memoryReportBox->setVisible(false);
122
123 connect(m_memoryReportBox, SIGNAL(clicked()), SLOT(showMemoryInfoToolTip()));
124
126 SIGNAL(sigUpdateMemoryStatistics()),
127 SLOT(imageSizeChanged()));
128
130 m_canvasAngleSelector->setRange(-360.00, 360.0);
135
136 connect(m_canvasAngleSelector, SIGNAL(angleChanged(qreal)), SLOT(slotCanvasAngleSelectorAngleChanged(qreal)));
137 m_canvasAngleSelector->setVisible(false);
138}
139
143
145{
146 if (m_imageView) {
147 if (m_imageView->canvasBase()) {
148 m_imageView->canvasBase()->canvasController()->proxyObject->disconnect(this);
149 }
150 m_imageView->disconnect(this);
151 removeStatusBarItem(m_imageView->zoomManager()->zoomActionWidget());
152 m_imageView = 0;
153 }
154
155 if (imageView) {
156 m_imageView = imageView;
157 m_canvasAngleSelector->setVisible(true);
158 connect(m_imageView, SIGNAL(sigColorSpaceChanged(const KoColorSpace*)),
159 this, SLOT(updateStatusBarProfileLabel()));
160 connect(m_imageView, SIGNAL(sigProfileChanged(const KoColorProfile*)),
161 this, SLOT(updateStatusBarProfileLabel()));
162 connect(m_imageView, SIGNAL(sigSizeChanged(QPointF,QPointF)),
163 this, SLOT(imageSizeChanged()));
168 addStatusBarItem(m_imageView->zoomManager()->zoomActionWidget());
169 }
170 else {
171 m_canvasAngleSelector->setVisible(false);
172 }
173
175}
176
177void KisStatusBar::addStatusBarItem(QWidget *widget, int stretch, bool permanent)
178{
179 StatusBarItem sbItem(widget);
180 if (permanent) {
181 m_statusBar->addPermanentWidget(widget, stretch);
182 }
183 else {
184 m_statusBar->addWidget(widget, stretch);
185 }
186 widget->setVisible(true);
187 m_statusBarItems.append(sbItem);
188}
189
191{
192 int i = 0;
193 Q_FOREACH(const StatusBarItem& sbItem, m_statusBarItems) {
194 if (sbItem.widget() == widget) {
195 break;
196 }
197 i++;
198 }
199
200 if (i < m_statusBarItems.count()) {
201 m_statusBar->removeWidget(m_statusBarItems[i].widget());
202 m_statusBarItems.remove(i);
203 }
204}
205
207{
208 Q_FOREACH(const StatusBarItem& sbItem, m_statusBarItems) {
209 sbItem.hide();
210 }
211}
212
214{
215 Q_FOREACH(const StatusBarItem& sbItem, m_statusBarItems) {
216 sbItem.show();
217 }
218}
219
220
222{
224
225 QString sizeText;
226 KisImageWSP image = m_imageView ? m_imageView->image() : 0;
227 if (image) {
228 qint32 w = image->width();
229 qint32 h = image->height();
230 sizeText = i18nc("@info:status width x height (file size)", "%1 &x %2 (%3)", w, h, m_shortMemoryTag);
231 } else {
232 sizeText = m_shortMemoryTag;
233 }
234
236 m_memoryReportBox->setText(sizeText);
238}
239
241{
242 QIcon icon;
243 if (!m_viewManager->selectionManager()->displaySelection()) {
244 icon = KisIconUtils::loadIcon("selection-mode_invisible");
245 } else if (m_viewManager->selectionManager()->showSelectionAsMask()) {
246 icon = KisIconUtils::loadIcon("selection-mode_mask");
247 } else /* if (!m_view->selectionManager()->showSelectionAsMask()) */ {
248 icon = KisIconUtils::loadIcon("selection-mode_ants");
249 }
250 m_selectionStatus->setIcon(icon);
251}
252
254{
258 const KFormat format;
259
260 const QString imageStatsMsg =
261 i18nc("tooltip on statusbar memory reporting button (image stats)",
262 "Image size:\t %1\n"
263 " - layers:\t\t %2\n"
264 " - projections:\t %3\n"
265 " - instant preview:\t %4\n",
266 format.formatByteSize(stats.imageSize),
267 format.formatByteSize(stats.layersSize),
268 format.formatByteSize(stats.projectionsSize),
269 format.formatByteSize(stats.lodSize));
270
271 const QString memoryStatsMsg =
272 i18nc("tooltip on statusbar memory reporting button (total stats)",
273 "Memory used:\t %1 / %2\n"
274 " image data:\t %3 / %4\n"
275 " pool:\t\t %5 / %6\n"
276 " undo data:\t %7\n"
277 "\n"
278 "Swap used:\t %8",
279 format.formatByteSize(stats.totalMemorySize),
280 format.formatByteSize(stats.totalMemoryLimit),
281
282 format.formatByteSize(stats.realMemorySize),
283 format.formatByteSize(stats.tilesHardLimit),
284
285 format.formatByteSize(stats.poolSize),
286 format.formatByteSize(stats.tilesPoolLimit),
287
288 format.formatByteSize(stats.historicalMemorySize),
289 format.formatByteSize(stats.swapSize));
290
291 QString longStats = imageStatsMsg + "\n" + memoryStatsMsg;
292
293 QString shortStats = format.formatByteSize(stats.imageSize);
294 QIcon icon;
295 const qint64 warnLevel = stats.tilesHardLimit - stats.tilesHardLimit / 8;
296
297 if (stats.imageSize > warnLevel ||
298 stats.realMemorySize > warnLevel) {
299
302 KisUsageLogger::log(QString("WARNING: %1 is running out of memory:%2\n").arg(m_imageView->document()->path()).arg(longStats));
303 }
304
305 icon = KisIconUtils::loadIcon("warning");
306 QString suffix =
307 i18nc("tooltip on statusbar memory reporting button",
308 "\n\nWARNING:\tOut of memory! Swapping has been started.\n"
309 "\t\tPlease configure more RAM for Krita in Settings dialog");
310 longStats += suffix;
311
312
313 }
314
315 m_shortMemoryTag = shortStats;
316 m_longMemoryTag = longStats;
317 m_memoryStatusIcon = icon;
318
322}
323
325{
326 QToolTip::showText(QCursor::pos(), m_memoryReportBox->toolTip(), m_memoryReportBox);
327}
328
330{
331 KisCanvas2 *canvas = m_viewManager->canvasBase();
332 if (!canvas) return;
333
334 KisCanvasController *canvasController = dynamic_cast<KisCanvasController*>(canvas->canvasController());
335 if (canvasController) {
336 canvasController->rotateCanvas(angle - canvas->rotationAngle());
337 }
338}
339
341{
342 KisCanvas2 *canvas = m_viewManager->canvasBase();
343 if (!canvas) return;
344
345 const qreal angleDiff = qAbs(m_canvasAngleSelector->angle()) -
346 qAbs(canvas->rotationAngle());
347
348 // Only update the UI if the angle difference is big enough. This improves the performance.
349 if (qAbs(angleDiff) >= 0.01) {
352 }
353}
354
356{
358
359 KisSelectionSP selection = m_viewManager->selection();
360 if (selection) {
361 m_selectionStatus->setEnabled(true);
362
363 QRect r = selection->selectedExactRect();
364
365 QString displayMode =
366 !m_viewManager->selectionManager()->displaySelection() ?
367 i18n("Hidden") :
368 (m_viewManager->selectionManager()->showSelectionAsMask() ?
369 i18n("Mask") : i18n("Ants"));
370
371 m_selectionStatus->setToolTip(
372 i18n("Selection: x = %1 y = %2 width = %3 height = %4\n"
373 "Display Mode: %5",
374 r.x(), r.y(), r.width(), r.height(), displayMode));
375 } else {
376 m_selectionStatus->setEnabled(false);
377 m_selectionStatus->setToolTip(i18n("No Selection"));
378 }
379}
380
382{
383 Q_UNUSED(image);
385}
386
388{
389 if (m_statusBarProfileLabel == 0) {
390 return;
391 }
392
393 if (!image) return;
394 if (image->profile() == 0) {
395 m_statusBarProfileLabel->setText(i18n("No profile"));
396 } else {
397 m_statusBarProfileLabel->setText(i18nc("<color space> <image profile>", "%1 %2", image->colorSpace()->name(), image->profile()->name()));
398 }
399
400}
401
402void KisStatusBar::setHelp(const QString &t)
403{
404 Q_UNUSED(t);
405}
406
408{
409 if (!m_imageView) return;
410
411 setProfile(m_imageView->image());
412}
413
418
419void KisStatusBar::addExtraWidget(QWidget *widget)
420{
421 m_extraWidgetsLayout->addWidget(widget);
422}
423
425{
426 m_extraWidgetsLayout->removeWidget(widget);
427}
428
connect(this, SIGNAL(optionsChanged()), this, SLOT(saveOptions()))
@ IncreasingDirection_Clockwise
A widget with several options to select an angle.
@ FlipOptionsMode_ContextMenu
The flip options are shown only as a context menu when right-clicking the gauge widget.
qreal angle() const
Gets the current angle.
void setFlipOptionsMode(FlipOptionsMode newMode)
Sets the mode in which the flip options should be shown.
void setIncreasingDirection(KisAngleGauge::IncreasingDirection newIncreasingDirection)
Sets the increasing direction in the angle gauge.
void useFlatSpinBox(bool newUseFlatSpinBox)
Sets if the spin box should be flat.
void setAngle(qreal newAngle)
Sets the current angle.
void setRange(qreal newMinimum, qreal newMaximum)
Sets the minimum and maximum values for the angle.
qreal rotationAngle() const
canvas rotation in degrees
void rotateCanvas(qreal angle, const std::optional< KoViewTransformStillPoint > &stillPoint, bool isNativeGesture=false)
const KoColorSpace * colorSpace() const
qint32 width() const
qint32 height() const
const KoColorProfile * profile() const
void setCurrentMemory(qint64 memory)
void setImageWeight(qint64 memory)
KoProgressProxy * progressProxy()
QToolButton * m_selectionStatus
void updateStatusBarProfileLabel()
void setSelection(KisImageWSP image)
void removeStatusBarItem(QWidget *widget)
QIcon m_memoryStatusIcon
QString m_longMemoryTag
void showMemoryInfoToolTip()
QPointer< KisView > m_imageView
QString m_shortMemoryTag
void updateSelectionIcon()
void updateSelectionToolTip()
void addStatusBarItem(QWidget *widget, int stretch=0, bool permanent=false)
KSqueezedTextLabel * m_statusBarProfileLabel
void slotCanvasAngleSelectorAngleChanged(qreal angle)
QScopedPointer< KoProgressUpdater > m_progressUpdater
void removeExtraWidget(QWidget *widget)
void sigCancellationRequested()
void updateMemoryStatus()
QVector< StatusBarItem > m_statusBarItems
QPointer< KisViewManager > m_viewManager
bool m_memoryWarningLogged
QWidget * m_extraWidgetsParent
KisAngleSelector * m_canvasAngleSelector
void setProfile(KisImageWSP image)
KSqueezedTextLabel * m_statusBarStatusLabel
void setView(QPointer< KisView > imageView)
QBoxLayout * m_extraWidgetsLayout
KisProgressWidget * m_progress
void slotCanvasRotationChanged()
KisStatusBar(KisViewManager *view)
void addExtraWidget(QWidget *widget)
void hideAllStatusBarItems()
~KisStatusBar() override
void setHelp(const QString &t)
QPointer< QStatusBar > m_statusBar
void imageSizeChanged()
KisMemoryReportButton * m_memoryReportBox
void showAllStatusBarItems()
KoProgressUpdater * progressUpdater()
static void log(const QString &message)
Logs with date/time.
KoCanvasController * canvasController() const
void documentRotationChanged(qreal angle)
static KoToolManager * instance()
Return the toolmanager singleton.
@ IMAGE_SIZE_ID
@ POINTER_POSITION_ID
QIcon loadIcon(const QString &name)
Statistics fetchMemoryStatistics(KisImageSP image) const
static KisMemoryStatisticsServer * instance()
QRect selectedExactRect() const
Slow, but exact way of determining the rectangle that encloses the selection.