File indexing completed on 2024-04-28 04:20:20

0001 
0002 /*
0003    Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
0004    All rights reserved.
0005 
0006    Redistribution and use in source and binary forms, with or without
0007    modification, are permitted provided that the following conditions
0008    are met:
0009 
0010    1. Redistributions of source code must retain the above copyright
0011       notice, this list of conditions and the following disclaimer.
0012    2. Redistributions in binary form must reproduce the above copyright
0013       notice, this list of conditions and the following disclaimer in the
0014       documentation and/or other materials provided with the distribution.
0015 
0016    THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0017    IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0018    OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
0019    IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
0020    INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
0021    NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0022    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0023    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0024    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
0025    THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0026 */
0027 
0028 
0029 #ifndef KP_MAIN_WINDOW_H
0030 #define KP_MAIN_WINDOW_H
0031 
0032 
0033 #include <QUrl>
0034 
0035 #include <kxmlguiwindow.h>
0036 
0037 #include "kpDefs.h"
0038 #include "pixmapfx/kpPixmapFX.h"
0039 #include "imagelib/kpImage.h"
0040 
0041 
0042 class QAction;
0043 class QActionGroup;
0044 class QDragEnterEvent;
0045 class QDropEvent;
0046 class QMenu;
0047 class QMoveEvent;
0048 class QPoint;
0049 class QRect;
0050 class QSize;
0051 
0052 class KConfigGroup;
0053 class KToolBar;
0054 class QPrinter;
0055 
0056 class kpColor;
0057 class kpColorCells;
0058 class kpColorToolBar;
0059 class kpCommand;
0060 class kpCommandEnvironment;
0061 class kpCommandHistory;
0062 class kpDocument;
0063 class kpDocumentEnvironment;
0064 class kpDocumentMetaInfo;
0065 class kpDocumentSaveOptions;
0066 class kpViewManager;
0067 class kpImageSelectionTransparency;
0068 class kpTextStyle;
0069 class kpThumbnail;
0070 class kpTool;
0071 class kpToolEnvironment;
0072 class kpToolSelectionEnvironment;
0073 class kpToolToolBar;
0074 class kpTransformDialogEnvironment;
0075 class kpAbstractSelection;
0076 
0077 class kpMainWindow : public KXmlGuiWindow
0078 {
0079 Q_OBJECT
0080 
0081 public:
0082     // Opens a new window with a blank document.
0083     kpMainWindow ();
0084 
0085     // Opens a new window with the document specified by <url>
0086     // or creates a blank document if <url> could not be opened.
0087     explicit kpMainWindow (const QUrl &url);
0088 
0089     // Opens a new window with the document <newDoc>
0090     // (<newDoc> can be 0 although this would result in a new
0091     //  window without a document at all).
0092     explicit kpMainWindow (kpDocument *newDoc);
0093 
0094     void finalizeGUI(KXMLGUIClient *client) override;
0095 
0096 private:
0097     void readGeneralSettings ();
0098     void readThumbnailSettings ();
0099 
0100     void init ();
0101 
0102     // (only called for restoring a previous session e.g. starting KDE with
0103     //  a previously saved session; it's not called on normal KolourPaint
0104     //  startup)
0105     void readProperties (const KConfigGroup &configGroup) override;
0106     // (only called for saving the current session e.g. logging out of KDE
0107     //  with the KolourPaint window open; it's not called on normal KolourPaint
0108     //  exit)
0109     void saveProperties (KConfigGroup &configGroup) override;
0110 
0111 public:
0112     ~kpMainWindow () override;
0113 
0114 public:
0115     kpDocument *document () const;
0116     kpDocumentEnvironment *documentEnvironment ();
0117     kpViewManager *viewManager () const;
0118     kpColorToolBar *colorToolBar () const;
0119     kpColorCells *colorCells () const;
0120     kpToolToolBar *toolToolBar () const;
0121     kpCommandHistory *commandHistory () const;
0122     kpCommandEnvironment *commandEnvironment ();
0123 
0124 private:
0125     void setupActions ();
0126     void enableDocumentActions (bool enable = true);
0127 
0128     void setDocument (kpDocument *newDoc);
0129 
0130     void dragEnterEvent (QDragEnterEvent *e) override;
0131     void dropEvent (QDropEvent *e) override;
0132     void moveEvent (QMoveEvent *e) override;
0133 
0134 private Q_SLOTS:
0135     void slotScrollViewAfterScroll ();
0136     void slotUpdateCaption ();
0137     void slotDocumentRestored ();
0138 
0139 
0140 //
0141 // Tools
0142 //
0143 
0144 private:
0145     kpToolSelectionEnvironment *toolSelectionEnvironment ();
0146     kpToolEnvironment *toolEnvironment ();
0147 
0148     void setupToolActions ();
0149     void createToolBox ();
0150     void enableToolsDocumentActions (bool enable = true);
0151 
0152 private Q_SLOTS:
0153     void updateToolOptionPrevNextActionsEnabled ();
0154     void updateActionDrawOpaqueChecked ();
0155 private:
0156     void updateActionDrawOpaqueEnabled ();
0157 
0158 public:
0159     QActionGroup *toolsActionGroup ();
0160 
0161     kpTool *tool () const;
0162 
0163     bool toolHasBegunShape () const;
0164     bool toolIsASelectionTool (bool includingTextTool = true) const;
0165     bool toolIsTextTool () const;
0166 
0167 private:
0168     // Ends the current shape.  If there is no shape currently being drawn,
0169     // it does nothing.
0170     //
0171     // In general, call this at the start of every kpMainWindow slot,
0172     // directly invoked by the _user_ (by activating an action or via another
0173     // way), so that:
0174     //
0175     // 1. The document contains the pixels of that shape:
0176     //
0177     //    Most tools have the shape, currently being drawn, layered above the
0178     //    document as a kpTempImage.  In other words, the document does not
0179     //    yet contain the pixels of that shape.  By ending the shape, the layer
0180     //    is pushed down onto the document so that it now contains those
0181     //    pixels.  Your slot can now safely read the document as it's now
0182     //    consistent with what's on the screen.
0183     //
0184     //    For example, consider the case where a line is being dragged out and
0185     //    CTRL+I is pressed to invert the image, while the mouse is still held
0186     //    down.  The CTRL+I invert code (kpMainWindow::slotInvertColors()) must
0187     //    push the line kpTempImage onto the document before the invert can
0188     //    meaningfully proceed (else the invert will see the state of the document
0189     //    before the line was dragged out).
0190     //
0191     //    Note that selection layers are not pushed down by this method.
0192     //    This is a feature, not a bug.  The user would be annoyed if e.g.
0193     //    slotSave() happened to push down the selection.  Use
0194     //    kpDocument::imageWithSelection() to get around this problem.  You
0195     //    should still call toolEndShape() even if a selection is active
0196     //    -- this ends selection "shapes", which are actually things like
0197     //    selection moves or smearing operations, rather than the selections
0198     //    themselves.
0199     //
0200     // AND/OR:
0201     //
0202     // 2. The current tool is no longer in a drawing state:
0203     //
0204     //    If your slot is going to bring up a new main window or modal dialog
0205     //    or at least some widget that acquires mouse or keyboard focus, this
0206     //    could confuse the tool if the tool is in the middle of a drawing
0207     //    operation.
0208     //
0209     // Do not call this in slots not invoked by the user.  For instance,
0210     // calling this method in response to an internal timer tick would be
0211     // wrong.  The user's drawing operation would unexpectedly finish and
0212     // this would bewilder and irritate the user.
0213     //
0214     // TODO: Help / KolourPaint Handbook does not call this.  I'm sure there
0215     //       are a few other actions that don't call this but should.
0216     void toolEndShape ();
0217 
0218 public:
0219     kpImageSelectionTransparency imageSelectionTransparency () const;
0220     // The drawing background color is set to <transparency>.transparentColor()
0221     // if the <transparency> is in Transparent mode or if <forceColorChange>
0222     // is true (not the default).  [x]
0223     //
0224     // If <transparency> is in Opaque mode and <forceColorChange> is false,
0225     // the background color is not changed because:
0226     //
0227     //   1. It is ignored by the selection in Opaque mode anyway.
0228     //   2. This avoids irritating the user with an unnecessary background
0229     //      color change.
0230     //
0231     // The only case where you should set <forceColorChange> to true is in
0232     // kpToolImageSelectionTransparencyCommand to ensure that the state
0233     // is identical to when the command was constructed.
0234     // Later: I don't think setting it to true is ever necessary since:
0235     //
0236     //          1. The background color only counts in Transparent mode.
0237     //
0238     //          2. Any kpToolImageSelectionTransparencyCommand that switches to
0239     //             Transparent mode will automatically set the background
0240     //             color due to the first part of [x] anyway.
0241     //
0242     // The other fields of <transparency> are copied into the main window
0243     // as expected.
0244     void setImageSelectionTransparency (const kpImageSelectionTransparency &transparency,
0245                                    bool forceColorChange = false);
0246     int settingImageSelectionTransparency () const;
0247 
0248 private Q_SLOTS:
0249     void slotToolSelected (kpTool *tool);
0250 
0251 private:
0252     void readLastTool ();
0253     int toolNumber () const;
0254     void saveLastTool ();
0255 
0256 private:
0257     bool maybeDragScrollingMainView () const;
0258 private Q_SLOTS:
0259     bool slotDragScroll (const QPoint &docPoint,
0260                          const QPoint &docLastPoint,
0261                          int zoomLevel,
0262                          bool *didSomething);
0263     bool slotEndDragScroll ();
0264 
0265 private Q_SLOTS:
0266     void slotBeganDocResize ();
0267     void slotContinuedDocResize (const QSize &size);
0268     void slotCancelledDocResize ();
0269     void slotEndedDocResize (const QSize &size);
0270 
0271     void slotDocResizeMessageChanged (const QString &string);
0272 
0273 private Q_SLOTS:
0274     void slotActionPrevToolOptionGroup1 ();
0275     void slotActionNextToolOptionGroup1 ();
0276     void slotActionPrevToolOptionGroup2 ();
0277     void slotActionNextToolOptionGroup2 ();
0278 
0279     void slotActionDrawOpaqueToggled ();
0280     void slotActionDrawColorSimilarity ();
0281 
0282 public Q_SLOTS:
0283     void slotToolRectSelection();
0284     void slotToolEllipticalSelection();
0285     void slotToolFreeFormSelection();
0286     void slotToolText();
0287 
0288 //
0289 // File Menu
0290 //
0291 
0292 private:
0293     void setupFileMenuActions ();
0294     void enableFileMenuDocumentActions (bool enable = true);
0295 
0296     void addRecentURL (const QUrl &url);
0297 
0298 private Q_SLOTS:
0299     void slotNew ();
0300 
0301 private:
0302     QSize defaultDocSize () const;
0303     void saveDefaultDocSize (const QSize &size);
0304 
0305 private:
0306     bool shouldOpen ();
0307     void setDocumentChoosingWindow (kpDocument *doc);
0308 
0309 private:
0310     kpDocument *openInternal (const QUrl &url,
0311         const QSize &fallbackDocSize,
0312         bool newDocSameNameIfNotExist);
0313     // Same as above except that it:
0314     //
0315     // 1. Assumes a default fallback document size.
0316     // 2. If the URL is successfully opened (with the special exception of
0317     //    the "kolourpaint doesnotexist.png" case), it is bubbled up to the
0318     //    top in the Recent Files Action.
0319     //
0320     // As a result of this behavior, this should only be called in response
0321     // to a user open request e.g. File / Open or "kolourpaint doesexist.png".
0322     // It should not be used for session restore - in that case, it does not
0323     // make sense to bubble the Recent Files list.
0324     bool open (const QUrl &url, bool newDocSameNameIfNotExist = false);
0325 
0326     QList<QUrl> askForOpenURLs(const QString &caption,
0327                               bool allowMultipleURLs = true);
0328 
0329 private Q_SLOTS:
0330     void slotOpen ();
0331     void slotOpenRecent (const QUrl &url);
0332     void slotRecentListCleared();
0333 
0334 #if HAVE_KSANE
0335     void slotScan ();
0336     void slotScanned (const QImage &image, int);
0337 #endif // HAVE_KSANE
0338 
0339     void slotScreenshot();
0340     void slotMakeScreenshot();
0341 
0342     void slotProperties ();
0343 
0344     bool save (bool localOnly = false);
0345     bool slotSave ();
0346 
0347 private:
0348     QUrl askForSaveURL (const QString &caption,
0349                         const QString &startURL,
0350                         const kpImage &imageToBeSaved,
0351                         const kpDocumentSaveOptions &startSaveOptions,
0352                         const kpDocumentMetaInfo &docMetaInfo,
0353                         const QString &forcedSaveOptionsGroup,
0354                         bool localOnly,
0355                         kpDocumentSaveOptions *chosenSaveOptions,
0356                         bool isSavingForFirstTime,
0357                         bool *allowLossyPrompt);
0358 
0359 private Q_SLOTS:
0360     bool saveAs (bool localOnly = false);
0361     bool slotSaveAs ();
0362 
0363     bool slotExport ();
0364 
0365     void slotEnableReload ();
0366     bool slotReload ();
0367     void sendPreviewToPrinter(QPrinter *printer);
0368 
0369 private:
0370     void sendDocumentNameToPrinter (QPrinter *printer);
0371     void setPrinterPageOrientation(QPrinter *printer);
0372     void sendImageToPrinter(QPrinter *printer, bool showPrinterSetupDialog);
0373 
0374 private Q_SLOTS:
0375     void slotPrint ();
0376     void slotPrintPreview ();
0377 
0378     void slotMail ();
0379 
0380     bool queryCloseDocument ();
0381     bool queryClose () override;
0382 
0383     void slotClose ();
0384     void slotQuit ();
0385 
0386 
0387 //
0388 // Edit Menu
0389 //
0390 
0391 private:
0392     void setupEditMenuActions ();
0393     void enableEditMenuDocumentActions (bool enable = true);
0394 
0395 public:
0396     QMenu *selectionToolRMBMenu ();
0397 
0398 private Q_SLOTS:
0399     void slotCut ();
0400     void slotCopy ();
0401     void slotEnablePaste ();
0402 private:
0403     QRect calcUsefulPasteRect (int imageWidth, int imageHeight);
0404     // (it is possible to paste a selection border i.e. a selection with no content)
0405     void paste (const kpAbstractSelection &sel,
0406                 bool forceTopLeft = false);
0407 public:
0408     // (<forceNewTextSelection> is ignored if <text> is empty)
0409     void pasteText (const QString &text,
0410                     bool forceNewTextSelection = false,
0411                     const QPoint &newTextSelectionTopLeft = KP_INVALID_POINT);
0412     void pasteTextAt (const QString &text, const QPoint &point,
0413                       // Allow tiny adjustment of <point> so that mouse
0414                       // pointer is not exactly on top of the topLeft of
0415                       // any new text selection (so that it doesn't look
0416                       // weird by being on top of a resize handle just after
0417                       // a paste).
0418                       bool allowNewTextSelectionPointShift = false);
0419 public Q_SLOTS:
0420     void slotPaste ();
0421 private Q_SLOTS:
0422     void slotPasteInNewWindow ();
0423 public Q_SLOTS:
0424     void slotDelete ();
0425 
0426     void slotSelectAll ();
0427 private:
0428     void addDeselectFirstCommand (kpCommand *cmd);
0429 public Q_SLOTS:
0430     void slotDeselect ();
0431 private Q_SLOTS:
0432     void slotCopyToFile ();
0433     void slotPasteFromFile ();
0434 
0435 
0436 //
0437 // View Menu
0438 //
0439 
0440 private:
0441     void setupViewMenuActions ();
0442 
0443     bool viewMenuDocumentActionsEnabled () const;
0444     void enableViewMenuDocumentActions (bool enable = true);
0445     void actionShowGridUpdate ();
0446     void updateMainViewGrid ();
0447     QRect mapToGlobal (const QRect &rect) const;
0448     QRect mapFromGlobal (const QRect &rect) const;
0449 
0450 private Q_SLOTS:
0451     void slotShowGridToggled ();
0452 
0453 
0454 //
0455 // View Menu - Zoom
0456 //
0457 
0458 private:
0459     void setupViewMenuZoomActions ();
0460     void enableViewMenuZoomDocumentActions (bool enable);
0461 
0462     void sendZoomListToActionZoom ();
0463 
0464     void zoomToPre (int zoomLevel);
0465     void zoomToPost ();
0466 
0467 public:
0468     void zoomTo (int zoomLevel, bool centerUnderCursor = false);
0469     void zoomToRect (const QRect &normalizedDocRect,
0470         bool accountForGrips,
0471         bool careAboutWidth, bool careAboutHeight);
0472 
0473 public Q_SLOTS:
0474     void slotActualSize ();
0475     void slotFitToPage ();
0476     void slotFitToWidth ();
0477     void slotFitToHeight ();
0478 
0479 public:
0480     void zoomIn (bool centerUnderCursor = false);
0481     void zoomOut (bool centerUnderCursor = false);
0482 
0483 public Q_SLOTS:
0484     void slotZoomIn ();
0485     void slotZoomOut ();
0486 
0487 private:
0488     void zoomAccordingToZoomAction (bool centerUnderCursor = false);
0489 
0490 private Q_SLOTS:
0491     void slotZoom ();
0492 
0493 
0494 //
0495 // View Menu - Thumbnail
0496 //
0497 
0498 private:
0499     void setupViewMenuThumbnailActions ();
0500     void enableViewMenuThumbnailDocumentActions (bool enable);
0501 
0502 private Q_SLOTS:
0503     void slotDestroyThumbnail ();
0504     void slotDestroyThumbnailInitatedByUser ();
0505     void slotCreateThumbnail ();
0506 
0507 public:
0508     void notifyThumbnailGeometryChanged ();
0509 
0510 private Q_SLOTS:
0511     void slotSaveThumbnailGeometry ();
0512     void slotShowThumbnailToggled ();
0513     void updateThumbnailZoomed ();
0514     void slotZoomedThumbnailToggled ();
0515     void slotThumbnailShowRectangleToggled ();
0516 
0517 private:
0518     void enableViewZoomedThumbnail (bool enable = true);
0519     void enableViewShowThumbnailRectangle (bool enable = true);
0520     void enableThumbnailOptionActions (bool enable = true);
0521     void createThumbnailView ();
0522     void destroyThumbnailView ();
0523     void updateThumbnail ();
0524 
0525 
0526 //
0527 // Image Menu
0528 //
0529 
0530 private:
0531     kpTransformDialogEnvironment *transformDialogEnvironment ();
0532 
0533     bool isSelectionActive () const;
0534     bool isTextSelection () const;
0535 
0536     QString autoCropText () const;
0537 
0538     void setupImageMenuActions ();
0539     void enableImageMenuDocumentActions (bool enable = true);
0540 
0541 private Q_SLOTS:
0542     void slotImageMenuUpdateDueToSelection ();
0543 
0544 public:
0545     kpColor backgroundColor (bool ofSelection = false) const;
0546     void addImageOrSelectionCommand (kpCommand *cmd,
0547                                      bool addSelCreateCmdIfSelAvail = true,
0548                                      bool addSelContentCmdIfSelAvail = true);
0549 
0550 public Q_SLOTS:
0551     void slotCrop ();
0552 
0553 private Q_SLOTS:
0554     void slotResizeScale ();
0555     void slotAutoCrop ();
0556     void slotFlip ();
0557     void slotMirror ();
0558 
0559     void slotRotate ();
0560     void slotRotate270 ();
0561     void slotRotate90 ();
0562 
0563     void slotSkew ();
0564     void slotConvertToBlackAndWhite ();
0565     void slotConvertToGrayscale ();
0566     void slotInvertColors ();
0567     void slotClear ();
0568     void slotMakeConfidential();
0569     void slotMoreEffects ();
0570 
0571 
0572 //
0573 // Colors Menu
0574 //
0575 
0576 private:
0577     void setupColorsMenuActions ();
0578     void createColorBox ();
0579     void enableColorsMenuDocumentActions (bool enable);
0580 private Q_SLOTS:
0581     void slotUpdateColorsDeleteRowActionEnabled ();
0582 
0583 private:
0584     void deselectActionColorsKDE ();
0585 
0586     bool queryCloseColors ();
0587 
0588 private:
0589     void openDefaultColors ();
0590 private Q_SLOTS:
0591     void slotColorsDefault ();
0592 
0593 private:
0594     bool openKDEColors (const QString &name);
0595 private Q_SLOTS:
0596     void slotColorsKDE ();
0597 
0598 private:
0599     bool openColors (const QUrl &url);
0600 private Q_SLOTS:
0601     void slotColorsOpen ();
0602 
0603     void slotColorsReload ();
0604 
0605     bool slotColorsSave ();
0606     bool slotColorsSaveAs ();
0607 
0608     void slotColorsAppendRow ();
0609     void slotColorsDeleteRow ();
0610 
0611 
0612 //
0613 // Settings Menu
0614 //
0615 
0616 private:
0617     void setupSettingsMenuActions ();
0618     void enableSettingsMenuDocumentActions (bool enable = true);
0619 
0620 private Q_SLOTS:
0621     void slotFullScreen ();
0622 
0623     void slotEnableSettingsShowPath ();
0624     void slotShowPathToggled ();
0625     void slotDrawAntiAliasedToggled(bool on);
0626 
0627     void slotKeyBindings ();
0628 
0629 //
0630 // Status Bar
0631 //
0632 
0633 private:
0634     enum
0635     {
0636         StatusBarItemShapePoints,
0637         StatusBarItemShapeSize,
0638         StatusBarItemDocSize,
0639         StatusBarItemDocDepth,
0640         StatusBarItemZoom
0641     };
0642 
0643     void addPermanentStatusBarItem (int id, int maxTextLen);
0644     void createStatusBar ();
0645 
0646     void setStatusBarDocDepth (int depth = 0);
0647 
0648 private Q_SLOTS:
0649     void setStatusBarMessage (const QString &message = QString());
0650     void setStatusBarShapePoints (const QPoint &startPoint = KP_INVALID_POINT,
0651                                   const QPoint &endPoint = KP_INVALID_POINT);
0652     void setStatusBarShapeSize (const QSize &size = KP_INVALID_SIZE);
0653     void setStatusBarDocSize (const QSize &size = KP_INVALID_SIZE);
0654     void setStatusBarZoom (int zoom = 0);
0655 
0656     void recalculateStatusBarMessage ();
0657     void recalculateStatusBarShape ();
0658 
0659     void recalculateStatusBar ();
0660 
0661 
0662 //
0663 // Text ToolBar
0664 //
0665 
0666 private:
0667     void setupTextToolBarActions ();
0668     void readAndApplyTextSettings ();
0669 
0670 public:
0671     void enableTextToolBarActions (bool enable = true);
0672 
0673 private Q_SLOTS:
0674     void slotTextFontFamilyChanged ();
0675     void slotTextFontSizeChanged ();
0676     void slotTextBoldChanged ();
0677     void slotTextItalicChanged ();
0678     void slotTextUnderlineChanged ();
0679     void slotTextStrikeThruChanged ();
0680 
0681 public:
0682     KToolBar *textToolBar ();
0683     bool isTextStyleBackgroundOpaque () const;
0684     kpTextStyle textStyle () const;
0685     void setTextStyle (const kpTextStyle &textStyle_);
0686     int settingTextStyle () const;
0687 
0688 private:
0689     struct kpMainWindowPrivate *d;
0690 };
0691 
0692 #endif  // KP_MAIN_WINDOW_H