1 2 /* 3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 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 #ifndef KP_MAIN_WINDOW_H 30 #define KP_MAIN_WINDOW_H 31 32 33 #include <QUrl> 34 35 #include <kxmlguiwindow.h> 36 37 #include "kpDefs.h" 38 #include "pixmapfx/kpPixmapFX.h" 39 #include "imagelib/kpImage.h" 40 41 42 class QAction; 43 class QActionGroup; 44 class QDragEnterEvent; 45 class QDropEvent; 46 class QMenu; 47 class QMoveEvent; 48 class QPoint; 49 class QRect; 50 class QSize; 51 52 class KConfigGroup; 53 class KToolBar; 54 class QPrinter; 55 56 class kpColor; 57 class kpColorCells; 58 class kpColorToolBar; 59 class kpCommand; 60 class kpCommandEnvironment; 61 class kpCommandHistory; 62 class kpDocument; 63 class kpDocumentEnvironment; 64 class kpDocumentMetaInfo; 65 class kpDocumentSaveOptions; 66 class kpViewManager; 67 class kpImageSelectionTransparency; 68 class kpTextStyle; 69 class kpThumbnail; 70 class kpTool; 71 class kpToolEnvironment; 72 class kpToolSelectionEnvironment; 73 class kpToolToolBar; 74 class kpTransformDialogEnvironment; 75 class kpAbstractSelection; 76 77 class kpMainWindow : public KXmlGuiWindow 78 { 79 Q_OBJECT 80 81 public: 82 // Opens a new window with a blank document. 83 kpMainWindow (); 84 85 // Opens a new window with the document specified by <url> 86 // or creates a blank document if <url> could not be opened. 87 kpMainWindow (const QUrl &url); 88 89 // Opens a new window with the document <newDoc> 90 // (<newDoc> can be 0 although this would result in a new 91 // window without a document at all). 92 kpMainWindow (kpDocument *newDoc); 93 94 void finalizeGUI(KXMLGUIClient *client) override; 95 96 private: 97 void readGeneralSettings (); 98 void readThumbnailSettings (); 99 100 void init (); 101 102 // (only called for restoring a previous session e.g. starting KDE with 103 // a previously saved session; it's not called on normal KolourPaint 104 // startup) 105 void readProperties (const KConfigGroup &configGroup) override; 106 // (only called for saving the current session e.g. logging out of KDE 107 // with the KolourPaint window open; it's not called on normal KolourPaint 108 // exit) 109 void saveProperties (KConfigGroup &configGroup) override; 110 111 public: 112 ~kpMainWindow () override; 113 114 public: 115 kpDocument *document () const; 116 kpDocumentEnvironment *documentEnvironment (); 117 kpViewManager *viewManager () const; 118 kpColorToolBar *colorToolBar () const; 119 kpColorCells *colorCells () const; 120 kpToolToolBar *toolToolBar () const; 121 kpCommandHistory *commandHistory () const; 122 kpCommandEnvironment *commandEnvironment (); 123 124 private: 125 void setupActions (); 126 void enableDocumentActions (bool enable = true); 127 128 void setDocument (kpDocument *newDoc); 129 130 void dragEnterEvent (QDragEnterEvent *e) override; 131 void dropEvent (QDropEvent *e) override; 132 void moveEvent (QMoveEvent *e) override; 133 134 private slots: 135 void slotScrollViewAfterScroll (); 136 void slotUpdateCaption (); 137 void slotDocumentRestored (); 138 139 140 // 141 // Tools 142 // 143 144 private: 145 kpToolSelectionEnvironment *toolSelectionEnvironment (); 146 kpToolEnvironment *toolEnvironment (); 147 148 void setupToolActions (); 149 void createToolBox (); 150 void enableToolsDocumentActions (bool enable = true); 151 152 private slots: 153 void updateToolOptionPrevNextActionsEnabled (); 154 void updateActionDrawOpaqueChecked (); 155 private: 156 void updateActionDrawOpaqueEnabled (); 157 158 public: 159 QActionGroup *toolsActionGroup (); 160 161 kpTool *tool () const; 162 163 bool toolHasBegunShape () const; 164 bool toolIsASelectionTool (bool includingTextTool = true) const; 165 bool toolIsTextTool () const; 166 167 private: 168 // Ends the current shape. If there is no shape currently being drawn, 169 // it does nothing. 170 // 171 // In general, call this at the start of every kpMainWindow slot, 172 // directly invoked by the _user_ (by activating an action or via another 173 // way), so that: 174 // 175 // 1. The document contains the pixels of that shape: 176 // 177 // Most tools have the shape, currently being drawn, layered above the 178 // document as a kpTempImage. In other words, the document does not 179 // yet contain the pixels of that shape. By ending the shape, the layer 180 // is pushed down onto the document so that it now contains those 181 // pixels. Your slot can now safely read the document as it's now 182 // consistent with what's on the screen. 183 // 184 // For example, consider the case where a line is being dragged out and 185 // CTRL+I is pressed to invert the image, while the mouse is still held 186 // down. The CTRL+I invert code (kpMainWindow::slotInvertColors()) must 187 // push the line kpTempImage onto the document before the invert can 188 // meaningfully proceed (else the invert will see the state of the document 189 // before the line was dragged out). 190 // 191 // Note that selection layers are not pushed down by this method. 192 // This is a feature, not a bug. The user would be annoyed if e.g. 193 // slotSave() happened to push down the selection. Use 194 // kpDocument::imageWithSelection() to get around this problem. You 195 // should still call toolEndShape() even if a selection is active 196 // -- this ends selection "shapes", which are actually things like 197 // selection moves or smearing operations, rather than the selections 198 // themselves. 199 // 200 // AND/OR: 201 // 202 // 2. The current tool is no longer in a drawing state: 203 // 204 // If your slot is going to bring up a new main window or modal dialog 205 // or at least some widget that acquires mouse or keyboard focus, this 206 // could confuse the tool if the tool is in the middle of a drawing 207 // operation. 208 // 209 // Do not call this in slots not invoked by the user. For instance, 210 // calling this method in response to an internal timer tick would be 211 // wrong. The user's drawing operation would unexpectedly finish and 212 // this would bewilder and irritate the user. 213 // 214 // TODO: Help / KolourPaint Handbook does not call this. I'm sure there 215 // are a few other actions that don't call this but should. 216 void toolEndShape (); 217 218 public: 219 kpImageSelectionTransparency imageSelectionTransparency () const; 220 // The drawing background color is set to <transparency>.transparentColor() 221 // if the <transparency> is in Transparent mode or if <forceColorChange> 222 // is true (not the default). [x] 223 // 224 // If <transparency> is in Opaque mode and <forceColorChange> is false, 225 // the background color is not changed because: 226 // 227 // 1. It is ignored by the selection in Opaque mode anyway. 228 // 2. This avoids irritating the user with an unnecessary background 229 // color change. 230 // 231 // The only case where you should set <forceColorChange> to true is in 232 // kpToolImageSelectionTransparencyCommand to ensure that the state 233 // is identical to when the command was constructed. 234 // Later: I don't think setting it to true is ever necessary since: 235 // 236 // 1. The background color only counts in Transparent mode. 237 // 238 // 2. Any kpToolImageSelectionTransparencyCommand that switches to 239 // Transparent mode will automatically set the background 240 // color due to the first part of [x] anyway. 241 // 242 // The other fields of <transparency> are copied into the main window 243 // as expected. 244 void setImageSelectionTransparency (const kpImageSelectionTransparency &transparency, 245 bool forceColorChange = false); 246 int settingImageSelectionTransparency () const; 247 248 private slots: 249 void slotToolSelected (kpTool *tool); 250 251 private: 252 void readLastTool (); 253 int toolNumber () const; 254 void saveLastTool (); 255 256 private: 257 bool maybeDragScrollingMainView () const; 258 private slots: 259 bool slotDragScroll (const QPoint &docPoint, 260 const QPoint &docLastPoint, 261 int zoomLevel, 262 bool *didSomething); 263 bool slotEndDragScroll (); 264 265 private slots: 266 void slotBeganDocResize (); 267 void slotContinuedDocResize (const QSize &size); 268 void slotCancelledDocResize (); 269 void slotEndedDocResize (const QSize &size); 270 271 void slotDocResizeMessageChanged (const QString &string); 272 273 private slots: 274 void slotActionPrevToolOptionGroup1 (); 275 void slotActionNextToolOptionGroup1 (); 276 void slotActionPrevToolOptionGroup2 (); 277 void slotActionNextToolOptionGroup2 (); 278 279 void slotActionDrawOpaqueToggled (); 280 void slotActionDrawColorSimilarity (); 281 282 public slots: 283 void slotToolRectSelection(); 284 void slotToolEllipticalSelection(); 285 void slotToolFreeFormSelection(); 286 void slotToolText(); 287 288 // 289 // File Menu 290 // 291 292 private: 293 void setupFileMenuActions (); 294 void enableFileMenuDocumentActions (bool enable = true); 295 296 void addRecentURL (const QUrl &url); 297 298 private slots: 299 void slotNew (); 300 301 private: 302 QSize defaultDocSize () const; 303 void saveDefaultDocSize (const QSize &size); 304 305 private: 306 bool shouldOpen (); 307 void setDocumentChoosingWindow (kpDocument *doc); 308 309 private: 310 kpDocument *openInternal (const QUrl &url, 311 const QSize &fallbackDocSize, 312 bool newDocSameNameIfNotExist); 313 // Same as above except that it: 314 // 315 // 1. Assumes a default fallback document size. 316 // 2. If the URL is successfully opened (with the special exception of 317 // the "kolourpaint doesnotexist.png" case), it is bubbled up to the 318 // top in the Recent Files Action. 319 // 320 // As a result of this behavior, this should only be called in response 321 // to a user open request e.g. File / Open or "kolourpaint doesexist.png". 322 // It should not be used for session restore - in that case, it does not 323 // make sense to bubble the Recent Files list. 324 bool open (const QUrl &url, bool newDocSameNameIfNotExist = false); 325 326 QList<QUrl> askForOpenURLs(const QString &caption, 327 bool allowMultipleURLs = true); 328 329 private slots: 330 void slotOpen (); 331 void slotOpenRecent (const QUrl &url); 332 void slotRecentListCleared(); 333 334 #if HAVE_KSANE 335 void slotScan (); 336 void slotScanned (const QImage &image, int); 337 #endif // HAVE_KSANE 338 339 void slotScreenshot(); 340 void slotMakeScreenshot(); 341 342 void slotProperties (); 343 344 bool save (bool localOnly = false); 345 bool slotSave (); 346 347 private: 348 QUrl askForSaveURL (const QString &caption, 349 const QString &startURL, 350 const kpImage &imageToBeSaved, 351 const kpDocumentSaveOptions &startSaveOptions, 352 const kpDocumentMetaInfo &docMetaInfo, 353 const QString &forcedSaveOptionsGroup, 354 bool localOnly, 355 kpDocumentSaveOptions *chosenSaveOptions, 356 bool isSavingForFirstTime, 357 bool *allowLossyPrompt); 358 359 private slots: 360 bool saveAs (bool localOnly = false); 361 bool slotSaveAs (); 362 363 bool slotExport (); 364 365 void slotEnableReload (); 366 bool slotReload (); 367 void sendPreviewToPrinter(QPrinter *printer); 368 369 private: 370 void sendDocumentNameToPrinter (QPrinter *printer); 371 void setPrinterPageOrientation(QPrinter *printer); 372 void sendImageToPrinter(QPrinter *printer, bool showPrinterSetupDialog); 373 374 private slots: 375 void slotPrint (); 376 void slotPrintPreview (); 377 378 void slotMail (); 379 380 bool queryCloseDocument (); 381 bool queryClose () override; 382 383 void slotClose (); 384 void slotQuit (); 385 386 387 // 388 // Edit Menu 389 // 390 391 private: 392 void setupEditMenuActions (); 393 void enableEditMenuDocumentActions (bool enable = true); 394 395 public: 396 QMenu *selectionToolRMBMenu (); 397 398 private slots: 399 void slotCut (); 400 void slotCopy (); 401 void slotEnablePaste (); 402 private: 403 QRect calcUsefulPasteRect (int imageWidth, int imageHeight); 404 // (it is possible to paste a selection border i.e. a selection with no content) 405 void paste (const kpAbstractSelection &sel, 406 bool forceTopLeft = false); 407 public: 408 // (<forceNewTextSelection> is ignored if <text> is empty) 409 void pasteText (const QString &text, 410 bool forceNewTextSelection = false, 411 const QPoint &newTextSelectionTopLeft = KP_INVALID_POINT); 412 void pasteTextAt (const QString &text, const QPoint &point, 413 // Allow tiny adjustment of <point> so that mouse 414 // pointer is not exactly on top of the topLeft of 415 // any new text selection (so that it doesn't look 416 // weird by being on top of a resize handle just after 417 // a paste). 418 bool allowNewTextSelectionPointShift = false); 419 public slots: 420 void slotPaste (); 421 private slots: 422 void slotPasteInNewWindow (); 423 public slots: 424 void slotDelete (); 425 426 void slotSelectAll (); 427 private: 428 void addDeselectFirstCommand (kpCommand *cmd); 429 public slots: 430 void slotDeselect (); 431 private slots: 432 void slotCopyToFile (); 433 void slotPasteFromFile (); 434 435 436 // 437 // View Menu 438 // 439 440 private: 441 void setupViewMenuActions (); 442 443 bool viewMenuDocumentActionsEnabled () const; 444 void enableViewMenuDocumentActions (bool enable = true); 445 void actionShowGridUpdate (); 446 void updateMainViewGrid (); 447 QRect mapToGlobal (const QRect &rect) const; 448 QRect mapFromGlobal (const QRect &rect) const; 449 450 private slots: 451 void slotShowGridToggled (); 452 453 454 // 455 // View Menu - Zoom 456 // 457 458 private: 459 void setupViewMenuZoomActions (); 460 void enableViewMenuZoomDocumentActions (bool enable); 461 462 void sendZoomListToActionZoom (); 463 464 void zoomToPre (int zoomLevel); 465 void zoomToPost (); 466 467 public: 468 void zoomTo (int zoomLevel, bool centerUnderCursor = false); 469 void zoomToRect (const QRect &normalizedDocRect, 470 bool accountForGrips, 471 bool careAboutWidth, bool careAboutHeight); 472 473 public slots: 474 void slotActualSize (); 475 void slotFitToPage (); 476 void slotFitToWidth (); 477 void slotFitToHeight (); 478 479 public: 480 void zoomIn (bool centerUnderCursor = false); 481 void zoomOut (bool centerUnderCursor = false); 482 483 public slots: 484 void slotZoomIn (); 485 void slotZoomOut (); 486 487 private: 488 void zoomAccordingToZoomAction (bool centerUnderCursor = false); 489 490 private slots: 491 void slotZoom (); 492 493 494 // 495 // View Menu - Thumbnail 496 // 497 498 private: 499 void setupViewMenuThumbnailActions (); 500 void enableViewMenuThumbnailDocumentActions (bool enable); 501 502 private slots: 503 void slotDestroyThumbnail (); 504 void slotDestroyThumbnailInitatedByUser (); 505 void slotCreateThumbnail (); 506 507 public: 508 void notifyThumbnailGeometryChanged (); 509 510 private slots: 511 void slotSaveThumbnailGeometry (); 512 void slotShowThumbnailToggled (); 513 void updateThumbnailZoomed (); 514 void slotZoomedThumbnailToggled (); 515 void slotThumbnailShowRectangleToggled (); 516 517 private: 518 void enableViewZoomedThumbnail (bool enable = true); 519 void enableViewShowThumbnailRectangle (bool enable = true); 520 void enableThumbnailOptionActions (bool enable = true); 521 void createThumbnailView (); 522 void destroyThumbnailView (); 523 void updateThumbnail (); 524 525 526 // 527 // Image Menu 528 // 529 530 private: 531 kpTransformDialogEnvironment *transformDialogEnvironment (); 532 533 bool isSelectionActive () const; 534 bool isTextSelection () const; 535 536 QString autoCropText () const; 537 538 void setupImageMenuActions (); 539 void enableImageMenuDocumentActions (bool enable = true); 540 541 private slots: 542 void slotImageMenuUpdateDueToSelection (); 543 544 public: 545 kpColor backgroundColor (bool ofSelection = false) const; 546 void addImageOrSelectionCommand (kpCommand *cmd, 547 bool addSelCreateCmdIfSelAvail = true, 548 bool addSelContentCmdIfSelAvail = true); 549 550 public slots: 551 void slotCrop (); 552 553 private slots: 554 void slotResizeScale (); 555 void slotAutoCrop (); 556 void slotFlip (); 557 void slotMirror (); 558 559 void slotRotate (); 560 void slotRotate270 (); 561 void slotRotate90 (); 562 563 void slotSkew (); 564 void slotConvertToBlackAndWhite (); 565 void slotConvertToGrayscale (); 566 void slotInvertColors (); 567 void slotClear (); 568 void slotMakeConfidential(); 569 void slotMoreEffects (); 570 571 572 // 573 // Colors Menu 574 // 575 576 private: 577 void setupColorsMenuActions (); 578 void createColorBox (); 579 void enableColorsMenuDocumentActions (bool enable); 580 private slots: 581 void slotUpdateColorsDeleteRowActionEnabled (); 582 583 private: 584 void deselectActionColorsKDE (); 585 586 bool queryCloseColors (); 587 588 private: 589 void openDefaultColors (); 590 private slots: 591 void slotColorsDefault (); 592 593 private: 594 bool openKDEColors (const QString &name); 595 private slots: 596 void slotColorsKDE (); 597 598 private: 599 bool openColors (const QUrl &url); 600 private slots: 601 void slotColorsOpen (); 602 603 void slotColorsReload (); 604 605 bool slotColorsSave (); 606 bool slotColorsSaveAs (); 607 608 void slotColorsAppendRow (); 609 void slotColorsDeleteRow (); 610 611 612 // 613 // Settings Menu 614 // 615 616 private: 617 void setupSettingsMenuActions (); 618 void enableSettingsMenuDocumentActions (bool enable = true); 619 620 private slots: 621 void slotFullScreen (); 622 623 void slotEnableSettingsShowPath (); 624 void slotShowPathToggled (); 625 void slotDrawAntiAliasedToggled(bool on); 626 627 void slotKeyBindings (); 628 629 // 630 // Status Bar 631 // 632 633 private: 634 enum 635 { 636 StatusBarItemShapePoints, 637 StatusBarItemShapeSize, 638 StatusBarItemDocSize, 639 StatusBarItemDocDepth, 640 StatusBarItemZoom 641 }; 642 643 void addPermanentStatusBarItem (int id, int maxTextLen); 644 void createStatusBar (); 645 646 void setStatusBarDocDepth (int depth = 0); 647 648 private slots: 649 void setStatusBarMessage (const QString &message = QString()); 650 void setStatusBarShapePoints (const QPoint &startPoint = KP_INVALID_POINT, 651 const QPoint &endPoint = KP_INVALID_POINT); 652 void setStatusBarShapeSize (const QSize &size = KP_INVALID_SIZE); 653 void setStatusBarDocSize (const QSize &size = KP_INVALID_SIZE); 654 void setStatusBarZoom (int zoom = 0); 655 656 void recalculateStatusBarMessage (); 657 void recalculateStatusBarShape (); 658 659 void recalculateStatusBar (); 660 661 662 // 663 // Text ToolBar 664 // 665 666 private: 667 void setupTextToolBarActions (); 668 void readAndApplyTextSettings (); 669 670 public: 671 void enableTextToolBarActions (bool enable = true); 672 673 private slots: 674 void slotTextFontFamilyChanged (); 675 void slotTextFontSizeChanged (); 676 void slotTextBoldChanged (); 677 void slotTextItalicChanged (); 678 void slotTextUnderlineChanged (); 679 void slotTextStrikeThruChanged (); 680 681 public: 682 KToolBar *textToolBar (); 683 bool isTextStyleBackgroundOpaque () const; 684 kpTextStyle textStyle () const; 685 void setTextStyle (const kpTextStyle &textStyle_); 686 int settingTextStyle () const; 687 688 private: 689 struct kpMainWindowPrivate *d; 690 }; 691 692 #endif // KP_MAIN_WINDOW_H 693