1 /*
2    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
3    Copyright (c) 2011 Martin Koller <kollix@aon.at>
4    All rights reserved.
5 
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9 
10    1. Redistributions of source code must retain the above copyright
11       notice, this list of conditions and the following disclaimer.
12    2. Redistributions in binary form must reproduce the above copyright
13       notice, this list of conditions and the following disclaimer in the
14       documentation and/or other materials provided with the distribution.
15 
16    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 
29 #include "mainWindow/kpMainWindow.h"
30 #include "kpMainWindowPrivate.h"
31 
32 #include <QActionGroup>
33 #include <QList>
34 
35 #include <KActionCollection>
36 #include <KSharedConfig>
37 #include <KConfigGroup>
38 #include "kpLogCategories.h"
39 #include <KLocalizedString>
40 
41 #include "widgets/toolbars/kpColorToolBar.h"
42 #include "commands/kpCommandHistory.h"
43 #include "document/kpDocument.h"
44 #include "layers/selections/image/kpImageSelectionTransparency.h"
45 #include "tools/kpTool.h"
46 #include "tools/kpToolAction.h"
47 #include "tools/flow/kpToolBrush.h"
48 #include "tools/flow/kpToolColorEraser.h"
49 #include "tools/kpToolColorPicker.h"
50 #include "tools/polygonal/kpToolCurve.h"
51 #include "tools/selection/image/kpToolEllipticalSelection.h"
52 #include "tools/rectangular/kpToolEllipse.h"
53 #include "tools/flow/kpToolEraser.h"
54 #include "tools/kpToolFloodFill.h"
55 #include "tools/selection/image/kpToolFreeFormSelection.h"
56 #include "tools/polygonal/kpToolLine.h"
57 #include "tools/flow/kpToolPen.h"
58 #include "tools/polygonal/kpToolPolygon.h"
59 #include "tools/polygonal/kpToolPolyline.h"
60 #include "tools/rectangular/kpToolRectangle.h"
61 #include "tools/selection/image/kpToolRectSelection.h"
62 #include "tools/rectangular/kpToolRoundedRectangle.h"
63 #include "environments/tools/selection/kpToolSelectionEnvironment.h"
64 #include "tools/flow/kpToolSpraycan.h"
65 #include "tools/selection/text/kpToolText.h"
66 #include "widgets/toolbars/kpToolToolBar.h"
67 #include "widgets/toolbars/options/kpToolWidgetOpaqueOrTransparent.h"
68 #include "tools/kpToolZoom.h"
69 #include "commands/imagelib/transforms/kpTransformResizeScaleCommand.h"
70 #include "kpViewScrollableContainer.h"
71 #include "views/kpZoomedView.h"
72 
73 //---------------------------------------------------------------------
74 
75 // private
toolSelectionEnvironment()76 kpToolSelectionEnvironment *kpMainWindow::toolSelectionEnvironment ()
77 {
78     if (!d->toolSelectionEnvironment) {
79         d->toolSelectionEnvironment = new kpToolSelectionEnvironment (this);
80     }
81 
82     return d->toolSelectionEnvironment;
83 }
84 
85 //---------------------------------------------------------------------
86 
87 // private
toolEnvironment()88 kpToolEnvironment *kpMainWindow::toolEnvironment ()
89 {
90     // It's fine to return a more complex environment than required.
91     return toolSelectionEnvironment ();
92 }
93 
94 //---------------------------------------------------------------------
95 
96 // private
setupToolActions()97 void kpMainWindow::setupToolActions ()
98 {
99     kpToolSelectionEnvironment *toolSelEnv = toolSelectionEnvironment ();
100     kpToolEnvironment *toolEnv = toolEnvironment ();
101 
102     d->tools.append (d->toolFreeFormSelection = new kpToolFreeFormSelection (toolSelEnv, this));
103     d->tools.append (d->toolRectSelection = new kpToolRectSelection (toolSelEnv, this));
104 
105     d->tools.append (d->toolEllipticalSelection = new kpToolEllipticalSelection (toolSelEnv, this));
106     d->tools.append (d->toolText = new kpToolText (toolSelEnv, this));
107 
108     d->tools.append (d->toolLine = new kpToolLine (toolEnv, this));
109     d->tools.append (d->toolPen = new kpToolPen (toolEnv, this));
110 
111     d->tools.append (d->toolEraser = new kpToolEraser (toolEnv, this));
112     d->tools.append (d->toolBrush = new kpToolBrush (toolEnv, this));
113 
114     d->tools.append (d->toolFloodFill = new kpToolFloodFill (toolEnv, this));
115     d->tools.append (d->toolColorPicker = new kpToolColorPicker (toolEnv, this));
116 
117     d->tools.append (d->toolColorEraser = new kpToolColorEraser (toolEnv, this));
118     d->tools.append (d->toolSpraycan = new kpToolSpraycan (toolEnv, this));
119 
120     d->tools.append (d->toolRoundedRectangle = new kpToolRoundedRectangle (toolEnv, this));
121     d->tools.append (d->toolRectangle = new kpToolRectangle (toolEnv, this));
122 
123     d->tools.append (d->toolPolygon = new kpToolPolygon (toolEnv, this));
124     d->tools.append (d->toolEllipse = new kpToolEllipse (toolEnv, this));
125 
126     d->tools.append (d->toolPolyline = new kpToolPolyline (toolEnv, this));
127     d->tools.append (d->toolCurve = new kpToolCurve (toolEnv, this));
128 
129     d->tools.append (d->toolZoom = new kpToolZoom (toolEnv, this));
130 
131 
132     KActionCollection *ac = actionCollection ();
133 
134     d->actionPrevToolOptionGroup1 = ac->addAction (QStringLiteral("prev_tool_option_group_1"));
135     d->actionPrevToolOptionGroup1->setText (i18n ("Previous Tool Option (Group #1)"));
136     ac->setDefaultShortcuts (d->actionPrevToolOptionGroup1, kpTool::shortcutForKey (Qt::Key_1));
137     connect (d->actionPrevToolOptionGroup1, &QAction::triggered,
138              this, &kpMainWindow::slotActionPrevToolOptionGroup1);
139 
140     d->actionNextToolOptionGroup1 = ac->addAction (QStringLiteral("next_tool_option_group_1"));
141     d->actionNextToolOptionGroup1->setText (i18n ("Next Tool Option (Group #1)"));
142     ac->setDefaultShortcuts (d->actionNextToolOptionGroup1, kpTool::shortcutForKey (Qt::Key_2));
143     connect (d->actionNextToolOptionGroup1, &QAction::triggered,
144              this, &kpMainWindow::slotActionNextToolOptionGroup1);
145 
146     d->actionPrevToolOptionGroup2 = ac->addAction (QStringLiteral("prev_tool_option_group_2"));
147     d->actionPrevToolOptionGroup2->setText (i18n ("Previous Tool Option (Group #2)"));
148     ac->setDefaultShortcuts (d->actionPrevToolOptionGroup2, kpTool::shortcutForKey (Qt::Key_3));
149     connect (d->actionPrevToolOptionGroup2, &QAction::triggered,
150              this, &kpMainWindow::slotActionPrevToolOptionGroup2);
151 
152     d->actionNextToolOptionGroup2 = ac->addAction (QStringLiteral("next_tool_option_group_2"));
153     d->actionNextToolOptionGroup2->setText (i18n ("Next Tool Option (Group #2)"));
154     ac->setDefaultShortcuts (d->actionNextToolOptionGroup2, kpTool::shortcutForKey (Qt::Key_4));
155     connect (d->actionNextToolOptionGroup2, &QAction::triggered,
156              this, &kpMainWindow::slotActionNextToolOptionGroup2);
157 
158 
159     //
160     // Implemented in this file (kpMainWindow_Tools.cpp), not
161     // kpImageWindow_Image.cpp since they're really setting tool options.
162     //
163 
164     d->actionDrawOpaque = ac->add <KToggleAction> (QStringLiteral("image_draw_opaque"));
165     d->actionDrawOpaque->setText (i18n ("&Draw Opaque"));
166     connect (d->actionDrawOpaque, &QAction::triggered,
167              this, &kpMainWindow::slotActionDrawOpaqueToggled);
168 
169     d->actionDrawColorSimilarity = ac->addAction (QStringLiteral("image_draw_color_similarity"));
170     d->actionDrawColorSimilarity->setText (i18n ("Draw With Color Similarity..."));
171     connect (d->actionDrawColorSimilarity, &QAction::triggered,
172              this, &kpMainWindow::slotActionDrawColorSimilarity);
173 }
174 
175 //---------------------------------------------------------------------
176 
177 // private
createToolBox()178 void kpMainWindow::createToolBox ()
179 {
180     d->toolToolBar = new kpToolToolBar(QStringLiteral("Tool Box"), 2/*columns/rows*/, this);
181     d->toolToolBar->setWindowTitle(i18n("Tool Box"));
182 
183     connect (d->toolToolBar, &kpToolToolBar::sigToolSelected,
184              this, &kpMainWindow::slotToolSelected);
185 
186     connect (d->toolToolBar, &kpToolToolBar::toolWidgetOptionSelected,
187              this, &kpMainWindow::updateToolOptionPrevNextActionsEnabled);
188 
189     connect (d->toolToolBar->toolWidgetOpaqueOrTransparent(),
190              &kpToolWidgetOpaqueOrTransparent::isOpaqueChanged,
191              this, &kpMainWindow::updateActionDrawOpaqueChecked);
192 
193     updateActionDrawOpaqueChecked ();
194 
195     for (auto *tool : d->tools) {
196       d->toolToolBar->registerTool(tool);
197     }
198 
199     // (from config file)
200     readLastTool ();
201 }
202 
203 //---------------------------------------------------------------------
204 
205 // private
enableToolsDocumentActions(bool enable)206 void kpMainWindow::enableToolsDocumentActions (bool enable)
207 {
208 #if DEBUG_KP_MAIN_WINDOW
209     qCDebug(kpLogMainWindow) << "kpMainWindow::enableToolsDocumentsAction(" << enable << ")";
210 #endif
211 
212     d->toolActionsEnabled = enable;
213 
214     if (enable && !d->toolToolBar->isEnabled ())
215     {
216         kpTool *previousTool = d->toolToolBar->previousTool ();
217 
218         // select tool for enabled Tool Box
219 
220         if (previousTool) {
221             d->toolToolBar->selectPreviousTool ();
222         }
223         else
224         {
225             if (d->lastToolNumber >= 0 && d->lastToolNumber < d->tools.count ()) {
226                 d->toolToolBar->selectTool (d->tools.at (d->lastToolNumber));
227             }
228             else {
229                 d->toolToolBar->selectTool (d->toolPen);
230             }
231         }
232     }
233     else if (!enable && d->toolToolBar->isEnabled ())
234     {
235         // don't have a disabled Tool Box with a checked Tool
236         d->toolToolBar->selectTool (nullptr);
237     }
238 
239 
240     d->toolToolBar->setEnabled (enable);
241 
242 
243     for (auto *tool : d->tools)
244     {
245       kpToolAction *action = tool->action();
246       if (!enable && action->isChecked()) {
247           action->setChecked(false);
248       }
249 
250       action->setEnabled(enable);
251     }
252 
253 
254     updateToolOptionPrevNextActionsEnabled ();
255     updateActionDrawOpaqueEnabled ();
256 }
257 
258 //---------------------------------------------------------------------
259 
260 // private slot
updateToolOptionPrevNextActionsEnabled()261 void kpMainWindow::updateToolOptionPrevNextActionsEnabled ()
262 {
263     const bool enable = d->toolActionsEnabled;
264 
265 
266     d->actionPrevToolOptionGroup1->setEnabled (enable &&
267         d->toolToolBar->shownToolWidget (0) &&
268         d->toolToolBar->shownToolWidget (0)->hasPreviousOption ());
269     d->actionNextToolOptionGroup1->setEnabled (enable &&
270         d->toolToolBar->shownToolWidget (0) &&
271         d->toolToolBar->shownToolWidget (0)->hasNextOption ());
272 
273     d->actionPrevToolOptionGroup2->setEnabled (enable &&
274         d->toolToolBar->shownToolWidget (1) &&
275         d->toolToolBar->shownToolWidget (1)->hasPreviousOption ());
276     d->actionNextToolOptionGroup2->setEnabled (enable &&
277         d->toolToolBar->shownToolWidget (1) &&
278         d->toolToolBar->shownToolWidget (1)->hasNextOption ());
279 }
280 
281 //---------------------------------------------------------------------
282 
283 // private slot
updateActionDrawOpaqueChecked()284 void kpMainWindow::updateActionDrawOpaqueChecked ()
285 {
286 #if DEBUG_KP_MAIN_WINDOW
287     qCDebug(kpLogMainWindow) << "kpMainWindow::updateActionDrawOpaqueChecked()";
288 #endif
289 
290     const bool drawOpaque =
291         (d->toolToolBar->toolWidgetOpaqueOrTransparent ()->selectedRow () == 0);
292 #if DEBUG_KP_MAIN_WINDOW
293     qCDebug(kpLogMainWindow) << "\tdrawOpaque=" << drawOpaque;
294 #endif
295 
296     d->actionDrawOpaque->setChecked (drawOpaque);
297 }
298 
299 //---------------------------------------------------------------------
300 
301 // private
updateActionDrawOpaqueEnabled()302 void kpMainWindow::updateActionDrawOpaqueEnabled ()
303 {
304 #if DEBUG_KP_MAIN_WINDOW
305     qCDebug(kpLogMainWindow) << "kpMainWindow::updateActionDrawOpaqueEnabled()";
306 #endif
307 
308     const bool enable = d->toolActionsEnabled;
309 
310 #if DEBUG_KP_MAIN_WINDOW
311     qCDebug(kpLogMainWindow) << "\tenable=" << enable
312               << " tool=" << (tool () ? tool ()->objectName () : nullptr)
313               << " (is selection=" << toolIsASelectionTool () << ")";
314 #endif
315 
316     d->actionDrawOpaque->setEnabled (enable && toolIsASelectionTool ());
317 }
318 
319 //---------------------------------------------------------------------
320 
321 // public
toolsActionGroup()322 QActionGroup *kpMainWindow::toolsActionGroup ()
323 {
324     if (!d->toolsActionGroup) {
325         d->toolsActionGroup = new QActionGroup (this);
326     }
327 
328     return d->toolsActionGroup;
329 }
330 
331 //---------------------------------------------------------------------
332 
333 // public
tool() const334 kpTool *kpMainWindow::tool () const
335 {
336     return d->toolToolBar ? d->toolToolBar->tool () : nullptr;
337 }
338 
339 //---------------------------------------------------------------------
340 
341 // public
toolHasBegunShape() const342 bool kpMainWindow::toolHasBegunShape () const
343 {
344     kpTool *currentTool = tool ();
345     return (currentTool && currentTool->hasBegunShape ());
346 }
347 
348 //---------------------------------------------------------------------
349 
350 // public
toolIsASelectionTool(bool includingTextTool) const351 bool kpMainWindow::toolIsASelectionTool (bool includingTextTool) const
352 {
353     kpTool *currentTool = tool ();
354 
355     return ((currentTool == d->toolFreeFormSelection) ||
356             (currentTool == d->toolRectSelection) ||
357             (currentTool == d->toolEllipticalSelection) ||
358             (currentTool == d->toolText && includingTextTool));
359 }
360 
361 //---------------------------------------------------------------------
362 
363 // public
toolIsTextTool() const364 bool kpMainWindow::toolIsTextTool () const
365 {
366     return (tool () == d->toolText);
367 }
368 
369 //---------------------------------------------------------------------
370 
371 
372 // private
toolEndShape()373 void kpMainWindow::toolEndShape ()
374 {
375     if (toolHasBegunShape ()) {
376         tool ()->endShapeInternal ();
377     }
378 }
379 
380 //---------------------------------------------------------------------
381 
382 // public
imageSelectionTransparency() const383 kpImageSelectionTransparency kpMainWindow::imageSelectionTransparency () const
384 {
385     kpToolWidgetOpaqueOrTransparent *oot = d->toolToolBar->toolWidgetOpaqueOrTransparent ();
386     Q_ASSERT (oot);
387 
388     return kpImageSelectionTransparency (oot->isOpaque (), backgroundColor (), d->colorToolBar->colorSimilarity ());
389 }
390 
391 //---------------------------------------------------------------------
392 
393 // public
setImageSelectionTransparency(const kpImageSelectionTransparency & transparency,bool forceColorChange)394 void kpMainWindow::setImageSelectionTransparency (const kpImageSelectionTransparency &transparency, bool forceColorChange)
395 {
396 #if DEBUG_KP_MAIN_WINDOW && 1
397     qCDebug(kpLogMainWindow) << "kpMainWindow::setImageSelectionTransparency() isOpaque=" << transparency.isOpaque ()
398                << " color=" << (transparency.transparentColor ().isValid () ? (int *) transparency.transparentColor ().toQRgb () : nullptr)
399                << " forceColorChange=" << forceColorChange;
400 #endif
401 
402     kpToolWidgetOpaqueOrTransparent *oot = d->toolToolBar->toolWidgetOpaqueOrTransparent ();
403     Q_ASSERT (oot);
404 
405     d->settingImageSelectionTransparency++;
406 
407     oot->setOpaque (transparency.isOpaque ());
408     if (transparency.isTransparent () || forceColorChange)
409     {
410         d->colorToolBar->setColor (1, transparency.transparentColor ());
411         d->colorToolBar->setColorSimilarity (transparency.colorSimilarity ());
412     }
413 
414     d->settingImageSelectionTransparency--;
415 }
416 
417 //---------------------------------------------------------------------
418 
419 // public
settingImageSelectionTransparency() const420 int kpMainWindow::settingImageSelectionTransparency () const
421 {
422     return d->settingImageSelectionTransparency;
423 }
424 
425 //---------------------------------------------------------------------
426 
427 // private slot
slotToolSelected(kpTool * tool)428 void kpMainWindow::slotToolSelected (kpTool *tool)
429 {
430 #if DEBUG_KP_MAIN_WINDOW
431     qCDebug(kpLogMainWindow) << "kpMainWindow::slotToolSelected (" << tool << ")";
432 #endif
433 
434     kpTool *previousTool = d->toolToolBar ? d->toolToolBar->previousTool () : nullptr;
435 
436     if (previousTool)
437     {
438         disconnect (previousTool, &kpTool::movedAndAboutToDraw,
439                     this, &kpMainWindow::slotDragScroll);
440 
441         disconnect (previousTool, &kpTool::endedDraw,
442                     this, &kpMainWindow::slotEndDragScroll);
443 
444         disconnect (previousTool, &kpTool::cancelledShape,
445                     this, &kpMainWindow::slotEndDragScroll);
446 
447         disconnect (previousTool, &kpTool::userMessageChanged,
448                     this, &kpMainWindow::recalculateStatusBarMessage);
449 
450         disconnect (previousTool, &kpTool::userShapePointsChanged,
451                     this, &kpMainWindow::recalculateStatusBarShape);
452 
453         disconnect (previousTool, &kpTool::userShapeSizeChanged,
454                     this, &kpMainWindow::recalculateStatusBarShape);
455 
456 
457         disconnect (d->colorToolBar, &kpColorToolBar::colorsSwapped,
458                     previousTool, &kpTool::slotColorsSwappedInternal);
459 
460         disconnect (d->colorToolBar, &kpColorToolBar::foregroundColorChanged,
461                     previousTool, &kpTool::slotForegroundColorChangedInternal);
462 
463         disconnect (d->colorToolBar, &kpColorToolBar::backgroundColorChanged,
464                     previousTool, &kpTool::slotBackgroundColorChangedInternal);
465 
466 
467         disconnect (d->colorToolBar, &kpColorToolBar::colorSimilarityChanged,
468                     previousTool, &kpTool::slotColorSimilarityChangedInternal);
469     }
470 
471     if (tool)
472     {
473         connect (tool, &kpTool::movedAndAboutToDraw,
474                  this, &kpMainWindow::slotDragScroll);
475 
476         connect (tool, &kpTool::endedDraw,
477                  this, &kpMainWindow::slotEndDragScroll);
478 
479         connect (tool, &kpTool::cancelledShape,
480                  this, &kpMainWindow::slotEndDragScroll);
481 
482         connect (tool, &kpTool::userMessageChanged,
483                  this, &kpMainWindow::recalculateStatusBarMessage);
484 
485         connect (tool, &kpTool::userShapePointsChanged,
486                  this, &kpMainWindow::recalculateStatusBarShape);
487 
488         connect (tool, &kpTool::userShapeSizeChanged,
489                  this, &kpMainWindow::recalculateStatusBarShape);
490 
491         recalculateStatusBar ();
492 
493 
494         connect (d->colorToolBar, &kpColorToolBar::colorsSwapped,
495                  tool, &kpTool::slotColorsSwappedInternal);
496 
497         connect (d->colorToolBar, &kpColorToolBar::foregroundColorChanged,
498                  tool, &kpTool::slotForegroundColorChangedInternal);
499 
500         connect (d->colorToolBar, &kpColorToolBar::backgroundColorChanged,
501                  tool, &kpTool::slotBackgroundColorChangedInternal);
502 
503         connect (d->colorToolBar, &kpColorToolBar::colorSimilarityChanged,
504                  tool, &kpTool::slotColorSimilarityChangedInternal);
505 
506 
507         saveLastTool ();
508     }
509 
510     updateToolOptionPrevNextActionsEnabled ();
511     updateActionDrawOpaqueEnabled ();
512 }
513 
514 //---------------------------------------------------------------------
515 
516 // private
readLastTool()517 void kpMainWindow::readLastTool ()
518 {
519     KConfigGroup cfg (KSharedConfig::openConfig (), kpSettingsGroupTools);
520 
521     d->lastToolNumber = cfg.readEntry (kpSettingLastTool, -1);
522 }
523 
524 //---------------------------------------------------------------------
525 
526 // private
toolNumber() const527 int kpMainWindow::toolNumber() const
528 {
529     for (int i = 0; i < d->tools.count(); i++)
530       if ( d->tools[i] == tool() )
531         return i;
532 
533     return -1;
534 }
535 
536 //---------------------------------------------------------------------
537 
538 // private
saveLastTool()539 void kpMainWindow::saveLastTool ()
540 {
541     int number = toolNumber ();
542     if ( (number < 0) || (number >= d->tools.count()) )
543       return;
544 
545     KConfigGroup cfg (KSharedConfig::openConfig (), kpSettingsGroupTools);
546 
547     cfg.writeEntry (kpSettingLastTool, number);
548     cfg.sync ();
549 }
550 
551 //---------------------------------------------------------------------
552 
553 // private
maybeDragScrollingMainView() const554 bool kpMainWindow::maybeDragScrollingMainView () const
555 {
556     return (tool () && d->mainView &&
557             tool ()->viewUnderStartPoint () == d->mainView);
558 }
559 
560 //---------------------------------------------------------------------
561 
562 // private slot
slotDragScroll(const QPoint & docPoint,const QPoint & docLastPoint,int zoomLevel,bool * scrolled)563 bool kpMainWindow::slotDragScroll (const QPoint &docPoint,
564                                    const QPoint &docLastPoint,
565                                    int zoomLevel,
566                                    bool *scrolled)
567 {
568   Q_UNUSED(docPoint)
569   Q_UNUSED(docLastPoint)
570 
571 #if DEBUG_KP_MAIN_WINDOW
572     qCDebug(kpLogMainWindow) << "kpMainWindow::slotDragScroll() maybeDragScrolling="
573                << maybeDragScrollingMainView ();
574 #endif
575 
576     if (maybeDragScrollingMainView ())
577     {
578         return d->scrollView->beginDragScroll(zoomLevel, scrolled);
579     }
580 
581     return false;
582 }
583 
584 //---------------------------------------------------------------------
585 
586 // private slot
slotEndDragScroll()587 bool kpMainWindow::slotEndDragScroll ()
588 {
589     // (harmless if haven't started drag scroll)
590     return d->scrollView->endDragScroll ();
591 }
592 
593 //---------------------------------------------------------------------
594 
595 
596 // private slot
slotBeganDocResize()597 void kpMainWindow::slotBeganDocResize ()
598 {
599     toolEndShape ();
600 
601     recalculateStatusBarShape ();
602 }
603 
604 //---------------------------------------------------------------------
605 
606 // private slot
slotContinuedDocResize(const QSize &)607 void kpMainWindow::slotContinuedDocResize (const QSize &)
608 {
609     recalculateStatusBarShape ();
610 }
611 
612 //---------------------------------------------------------------------
613 
614 // private slot
slotCancelledDocResize()615 void kpMainWindow::slotCancelledDocResize ()
616 {
617     recalculateStatusBar ();
618 }
619 
620 //---------------------------------------------------------------------
621 
622 // private slot
slotEndedDocResize(const QSize & size)623 void kpMainWindow::slotEndedDocResize (const QSize &size)
624 {
625 #define DOC_RESIZE_COMPLETED()           \
626 {                                        \
627     d->docResizeToBeCompleted = false;    \
628     recalculateStatusBar ();             \
629 }
630 
631     // Prevent statusbar updates
632     d->docResizeToBeCompleted = true;
633 
634     d->docResizeWidth = (size.width () > 0 ? size.width () : 1);
635     d->docResizeHeight = (size.height () > 0 ? size.height () : 1);
636 
637     if (d->docResizeWidth == d->document->width () &&
638         d->docResizeHeight == d->document->height ())
639     {
640         DOC_RESIZE_COMPLETED ();
641         return;
642     }
643 
644 
645     // Blank status to avoid confusion if dialog comes up
646     setStatusBarMessage ();
647     setStatusBarShapePoints ();
648     setStatusBarShapeSize ();
649 
650 
651     if (kpTool::warnIfBigImageSize (d->document->width (),
652             d->document->height (),
653             d->docResizeWidth, d->docResizeHeight,
654             i18n ("<qt><p>Resizing the image to"
655                     " %1x%2 may take a substantial amount of memory."
656                     " This can reduce system"
657                     " responsiveness and cause other application resource"
658                     " problems.</p>"
659 
660                     "<p>Are you sure you want to resize the"
661                     " image?</p></qt>",
662                   d->docResizeWidth,
663                   d->docResizeHeight),
664             i18nc ("@title:window", "Resize Image?"),
665             i18n ("R&esize Image"),
666             this))
667     {
668         d->commandHistory->addCommand (
669             new kpTransformResizeScaleCommand (
670                 false/*doc, not sel*/,
671                 d->docResizeWidth, d->docResizeHeight,
672                 kpTransformResizeScaleCommand::Resize,
673                 commandEnvironment ()));
674 
675         saveDefaultDocSize (QSize (d->docResizeWidth, d->docResizeHeight));
676     }
677 
678 
679     DOC_RESIZE_COMPLETED ();
680 
681 #undef DOC_RESIZE_COMPLETED
682 }
683 
684 //---------------------------------------------------------------------
685 
686 // private slot
slotDocResizeMessageChanged(const QString & string)687 void kpMainWindow::slotDocResizeMessageChanged (const QString &string)
688 {
689 #if DEBUG_KP_MAIN_WINDOW
690     qCDebug(kpLogMainWindow) << "kpMainWindow::slotDocResizeMessageChanged(" << string
691                << ") docResizeToBeCompleted=" << d->docResizeToBeCompleted;
692 #else
693     (void) string;
694 #endif
695 
696     if (d->docResizeToBeCompleted) {
697         return;
698     }
699 
700     recalculateStatusBarMessage ();
701 }
702 
703 //---------------------------------------------------------------------
704 
705 
706 // private slot
slotActionPrevToolOptionGroup1()707 void kpMainWindow::slotActionPrevToolOptionGroup1 ()
708 {
709     if (!d->toolToolBar->shownToolWidget (0)) {
710         return;
711     }
712 
713     // We don't call toolEndShape() here because we want #23 in the file BUGS
714     // to later work.
715 
716     d->toolToolBar->shownToolWidget (0)->selectPreviousOption ();
717     updateToolOptionPrevNextActionsEnabled ();
718 }
719 
720 //---------------------------------------------------------------------
721 
722 // private slot
slotActionNextToolOptionGroup1()723 void kpMainWindow::slotActionNextToolOptionGroup1 ()
724 {
725     if (!d->toolToolBar->shownToolWidget (0)) {
726         return;
727     }
728 
729     // We don't call toolEndShape() here because we want #23 in the file BUGS
730     // to later work.
731 
732     d->toolToolBar->shownToolWidget (0)->selectNextOption ();
733     updateToolOptionPrevNextActionsEnabled ();
734 }
735 
736 //---------------------------------------------------------------------
737 
738 
739 // private slot
slotActionPrevToolOptionGroup2()740 void kpMainWindow::slotActionPrevToolOptionGroup2 ()
741 {
742     if (!d->toolToolBar->shownToolWidget (1)) {
743         return;
744     }
745 
746     // We don't call toolEndShape() here because we want #23 in the file BUGS
747     // to later work.
748 
749     d->toolToolBar->shownToolWidget (1)->selectPreviousOption ();
750     updateToolOptionPrevNextActionsEnabled ();
751 }
752 
753 //---------------------------------------------------------------------
754 
755 // private slot
slotActionNextToolOptionGroup2()756 void kpMainWindow::slotActionNextToolOptionGroup2 ()
757 {
758     if (!d->toolToolBar->shownToolWidget (1)) {
759         return;
760     }
761 
762     // We don't call toolEndShape() here because we want #23 in the file BUGS
763     // to later work.
764 
765     d->toolToolBar->shownToolWidget (1)->selectNextOption ();
766     updateToolOptionPrevNextActionsEnabled ();
767 }
768 
769 //---------------------------------------------------------------------
770 
771 // private slot
slotActionDrawOpaqueToggled()772 void kpMainWindow::slotActionDrawOpaqueToggled ()
773 {
774 #if DEBUG_KP_MAIN_WINDOW
775     qCDebug(kpLogMainWindow) << "kpMainWindow::slotActionDrawOpaqueToggled()";
776 #endif
777     toolEndShape ();
778 
779     // TODO: How does this differ to setImageSelectionTransparency()?
780 
781     // ("kpToolWidgetBase::" is to access one overload shadowed by the override
782     //  of the other overload)
783     d->toolToolBar->toolWidgetOpaqueOrTransparent ()->kpToolWidgetBase::setSelected (
784         (d->actionDrawOpaque->isChecked () ?
785             0/*row 0 = opaque*/ :
786             1/*row 1 = transparent*/),
787         0/*column*/);
788 }
789 
790 //---------------------------------------------------------------------
791 
792 // private slot
slotActionDrawColorSimilarity()793 void kpMainWindow::slotActionDrawColorSimilarity ()
794 {
795 #if DEBUG_KP_MAIN_WINDOW
796     qCDebug(kpLogMainWindow) << "kpMainWindow::slotActionDrawColorSimilarity()";
797 #endif
798     toolEndShape ();
799 
800     d->colorToolBar->openColorSimilarityDialog ();
801 }
802 
803 //---------------------------------------------------------------------
804 
805 
806 // public slots
807 
808 #define SLOT_TOOL(toolName)                       \
809 void kpMainWindow::slotTool##toolName ()          \
810 {                                                 \
811     if (!d->toolToolBar)                           \
812         return;                                   \
813                                                   \
814     if (tool () == d->tool##toolName)              \
815         return;                                   \
816                                                   \
817     d->toolToolBar->selectTool (d->tool##toolName); \
818 }
819 
820 
821 SLOT_TOOL (RectSelection)
822 SLOT_TOOL (EllipticalSelection)
823 SLOT_TOOL (FreeFormSelection)
824 SLOT_TOOL (Text)
825