there is no moc file generated for this class
[kdegraphics.git] / kolourpaint / mainWindow / kpMainWindow_File.cpp
blob1cc8a0e02b32ec78c2992d5ec5b158ebc8546a48
2 /*
3 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org>
4 Copyright (c) 2007 Martin Koller <m.koller@surfeu.at>
5 Copyright (c) 2007 John Layt <john@layt.net>
6 All rights reserved.
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright
15 notice, this list of conditions and the following disclaimer in the
16 documentation and/or other materials provided with the distribution.
18 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include <kpMainWindow.h>
32 #include <kpMainWindowPrivate.h>
34 #include <qdatastream.h>
35 #include <QDBusInterface>
36 #include <QDesktopWidget>
37 #include <qpainter.h>
38 #include <qpixmap.h>
39 #include <qsize.h>
40 #include <QtDBus>
41 #include <QtGui/QPrinter>
42 #include <QtGui/QPrintDialog>
44 #include <kapplication.h>
45 #include <kaction.h>
46 #include <kactioncollection.h>
47 #include <kconfig.h>
48 #include <kconfiggroup.h>
49 #include <kdebug.h>
50 #include <kfiledialog.h>
51 #include <kglobal.h>
52 #include <kiconloader.h>
53 #include <kimagefilepreview.h>
54 #include <kimageio.h>
55 #include <kio/netaccess.h>
56 #include <klocale.h>
57 #include <kmessagebox.h>
58 #include <krecentfilesaction.h>
59 #include <kscan.h>
60 #include <kstandardshortcut.h>
61 #include <kstandardaction.h>
62 #include <ktoolinvocation.h>
63 #include <kdeprintdialog.h>
64 #include <kprintpreview.h>
66 #include <kpCommandHistory.h>
67 #include <kpDefs.h>
68 #include <kpDocument.h>
69 #include <kpDocumentMetaInfoCommand.h>
70 #include <kpDocumentMetaInfoDialog.h>
71 #include <kpDocumentSaveOptionsWidget.h>
72 #include <kpPixmapFX.h>
73 #include <kpPrintDialogPage.h>
74 #include <kpView.h>
75 #include <kpViewManager.h>
78 // private
79 void kpMainWindow::setupFileMenuActions ()
81 #if DEBUG_KP_MAIN_WINDOW
82 kDebug () << "kpMainWindow::setupFileMenuActions()";
83 #endif
84 KActionCollection *ac = actionCollection ();
86 d->actionNew = KStandardAction::openNew (this, SLOT (slotNew ()), ac);
87 d->actionOpen = KStandardAction::open (this, SLOT (slotOpen ()), ac);
89 d->actionOpenRecent = KStandardAction::openRecent (this, SLOT (slotOpenRecent (const KUrl &)), ac);
90 d->actionOpenRecent->loadEntries (KGlobal::config ()->group (kpSettingsGroupRecentFiles));
91 #if DEBUG_KP_MAIN_WINDOW
92 kDebug () << "\trecent URLs=" << d->actionOpenRecent->items ();
93 #endif
95 d->actionSave = KStandardAction::save (this, SLOT (slotSave ()), ac);
96 d->actionSaveAs = KStandardAction::saveAs (this, SLOT (slotSaveAs ()), ac);
98 d->actionExport = ac->addAction("file_export");
99 d->actionExport->setText (i18n ("E&xport..."));
100 d->actionExport->setIcon (KIcon ("document-export"));
101 connect(d->actionExport, SIGNAL(triggered(bool) ), SLOT (slotExport ()));
103 d->actionScan = ac->addAction("file_scan");
104 d->actionScan->setText (i18n ("Scan..."));
105 d->actionScan->setIcon (SmallIcon ("scanner"));
106 connect(d->actionScan, SIGNAL(triggered(bool) ), SLOT (slotScan ()));
108 d->actionProperties = ac->addAction ("file_properties");
109 d->actionProperties->setText (i18n ("Properties"));
110 d->actionProperties->setIcon (KIcon ("document-properties"));
111 connect (d->actionProperties, SIGNAL (triggered (bool)), SLOT (slotProperties ()));
113 //d->actionRevert = KStandardAction::revert (this, SLOT (slotRevert ()), ac);
114 d->actionReload = ac->addAction ("file_revert");
115 d->actionReload->setText (i18n ("Reloa&d"));
116 d->actionReload->setIcon (KIcon ("view-refresh"));
117 connect(d->actionReload, SIGNAL(triggered(bool) ), SLOT (slotReload ()));
118 d->actionReload->setShortcuts(KStandardShortcut::reload ());
119 slotEnableReload ();
121 d->actionPrint = KStandardAction::print (this, SLOT (slotPrint ()), ac);
122 d->actionPrintPreview = KStandardAction::printPreview (this, SLOT (slotPrintPreview ()), ac);
124 d->actionMail = KStandardAction::mail (this, SLOT (slotMail ()), ac);
126 d->actionSetAsWallpaperCentered = ac->addAction ("file_set_as_wallpaper_centered");
127 d->actionSetAsWallpaperCentered->setText (i18n ("Set as Wa&llpaper (Centered)"));
128 connect(d->actionSetAsWallpaperCentered, SIGNAL(triggered(bool) ), SLOT (slotSetAsWallpaperCentered ()));
129 d->actionSetAsWallpaperTiled = ac->addAction ("file_set_as_wallpaper_tiled");
130 d->actionSetAsWallpaperTiled->setText (i18n ("Set as Wallpaper (&Tiled)"));
131 connect(d->actionSetAsWallpaperTiled, SIGNAL(triggered(bool) ), SLOT (slotSetAsWallpaperTiled ()));
133 d->actionClose = KStandardAction::close (this, SLOT (slotClose ()), ac);
134 d->actionQuit = KStandardAction::quit (this, SLOT (slotQuit ()), ac);
136 d->scanDialog = 0;
138 enableFileMenuDocumentActions (false);
141 // private
142 void kpMainWindow::enableFileMenuDocumentActions (bool enable)
144 // d->actionNew
145 // d->actionOpen
147 // d->actionOpenRecent
149 d->actionSave->setEnabled (enable);
150 d->actionSaveAs->setEnabled (enable);
152 d->actionExport->setEnabled (enable);
154 // d->actionScan
156 d->actionProperties->setEnabled (enable);
158 // d->actionReload
160 d->actionPrint->setEnabled (enable);
161 d->actionPrintPreview->setEnabled (enable);
163 d->actionMail->setEnabled (enable);
165 d->actionSetAsWallpaperCentered->setEnabled (enable);
166 d->actionSetAsWallpaperTiled->setEnabled (enable);
168 d->actionClose->setEnabled (enable);
169 // d->actionQuit->setEnabled (enable);
172 // private
173 void kpMainWindow::addRecentURL (const KUrl &url_)
175 // HACK: KRecentFilesAction::loadEntries() clears the KRecentFilesAction::d->urls
176 // map.
178 // So afterwards, the URL ref, our method is given, points to an
179 // element in this now-cleared map (see KRecentFilesAction::urlSelected(QAction*)).
180 // Accessing it would result in a crash.
182 // To avoid the crash, make a copy of it before calling
183 // loadEntries() and use this copy, instead of the to-be-dangling
184 // ref.
185 const KUrl url = url_;
187 #if DEBUG_KP_MAIN_WINDOW
188 kDebug () << "kpMainWindow::addRecentURL(" << url << ")";
189 #endif
190 if (url.isEmpty ())
191 return;
194 KSharedConfig::Ptr cfg = KGlobal::config();
196 // KConfig::readEntry() does not actually reread from disk, hence doesn't
197 // realize what other processes have done e.g. Settings / Show Path
198 cfg->reparseConfiguration ();
200 #if DEBUG_KP_MAIN_WINDOW
201 kDebug () << "\trecent URLs=" << d->actionOpenRecent->items ();
202 #endif
203 // HACK: Something might have changed interprocess.
204 // If we could PROPAGATE: interprocess, then this wouldn't be required.
205 d->actionOpenRecent->loadEntries (cfg->group (kpSettingsGroupRecentFiles));
206 #if DEBUG_KP_MAIN_WINDOW
207 kDebug () << "\tafter loading config=" << d->actionOpenRecent->items ();
208 #endif
210 d->actionOpenRecent->addUrl (url);
212 d->actionOpenRecent->saveEntries (cfg->group (kpSettingsGroupRecentFiles));
213 cfg->sync ();
215 #if DEBUG_KP_MAIN_WINDOW
216 kDebug () << "\tnew recent URLs=" << d->actionOpenRecent->items ();
217 #endif
220 // TODO: PROPAGATE: interprocess
221 // TODO: Is this loop safe since a KMainWindow later along in the list,
222 // could be closed as the code in the body almost certainly re-enters
223 // the event loop? Problem for KDE 3 as well, I think.
224 foreach (KMainWindow *kmw, KMainWindow::memberList ())
226 Q_ASSERT (dynamic_cast <kpMainWindow *> (kmw));
227 kpMainWindow *mw = static_cast <kpMainWindow *> (kmw);
229 #if DEBUG_KP_MAIN_WINDOW
230 kDebug () << "\t\tmw=" << mw;
231 #endif
233 if (mw != this)
235 // WARNING: Do not use KRecentFilesAction::setItems()
236 // - it does not work since only its superclass,
237 // KSelectAction, implements setItems() and can't
238 // update KRecentFilesAction's URL list.
240 // Avoid URL memory leak in KRecentFilesAction::loadEntries().
241 mw->d->actionOpenRecent->clear ();
243 mw->d->actionOpenRecent->loadEntries (cfg->group (kpSettingsGroupRecentFiles));
244 #if DEBUG_KP_MAIN_WINDOW
245 kDebug () << "\t\t\tcheck recent URLs="
246 << mw->d->actionOpenRecent->items () << endl;
247 #endif
253 // private slot
254 // TODO: Disable action if
255 // (d->configOpenImagesInSameWindow && d->document && d->document->isEmpty())
256 // as it does nothing if this is true.
257 void kpMainWindow::slotNew ()
259 toolEndShape ();
261 if (d->document && !d->configOpenImagesInSameWindow)
263 // A document -- empty or otherwise -- is open.
264 // Force open a new window. In contrast, open() might not open
265 // a new window in this case.
266 kpMainWindow *win = new kpMainWindow ();
267 win->show ();
269 else
271 open (KUrl (), true/*create an empty doc*/);
276 // private
277 QSize kpMainWindow::defaultDocSize () const
279 // KConfig::readEntry() does not actually reread from disk, hence doesn't
280 // realize what other processes have done e.g. Settings / Show Path
281 KGlobal::config ()->reparseConfiguration ();
283 KConfigGroup cfg (KGlobal::config (), kpSettingsGroupGeneral);
285 QSize docSize = cfg.readEntry (kpSettingLastDocSize, QSize ());
287 if (docSize.isEmpty ())
289 docSize = QSize (400, 300);
291 else
293 // Don't get too big or you'll thrash (or even lock up) the computer
294 // just by opening a window
295 docSize = QSize (qMin (2048, docSize.width ()),
296 qMin (2048, docSize.height ()));
299 return docSize;
302 // private
303 void kpMainWindow::saveDefaultDocSize (const QSize &size)
305 #if DEBUG_KP_MAIN_WINDOW
306 kDebug () << "\tCONFIG: saving Last Doc Size = " << size;
307 #endif
309 KConfigGroup cfg (KGlobal::config (), kpSettingsGroupGeneral);
311 cfg.writeEntry (kpSettingLastDocSize, size);
312 cfg.sync ();
316 // private
317 bool kpMainWindow::shouldOpen ()
319 if (d->configOpenImagesInSameWindow)
321 #if DEBUG_KP_MAIN_WINDOW
322 kDebug () << "\topenImagesInSameWindow";
323 #endif
324 // (this brings up a dialog and might save the current doc)
325 if (!queryCloseDocument ())
327 #if DEBUG_KP_MAIN_WINDOW
328 kDebug () << "\t\tqueryCloseDocument() aborts open";
329 #endif
330 return false;
334 return true;
337 // private
338 void kpMainWindow::setDocumentChoosingWindow (kpDocument *doc)
340 // Want new window?
341 if (d->document && !d->document->isEmpty () &&
342 !d->configOpenImagesInSameWindow)
344 #if DEBUG_KP_MAIN_WINDOW
345 kDebug () << "\topen in new window";
346 #endif
347 // Send doc to new window.
348 kpMainWindow *win = new kpMainWindow (doc);
349 win->show ();
351 else
353 #if DEBUG_KP_MAIN_WINDOW
354 kDebug () << "\topen in same window";
355 #endif
356 // (sets up views, doc signals)
357 setDocument (doc);
362 // private
363 kpDocument *kpMainWindow::openInternal (const KUrl &url,
364 const QSize &fallbackDocSize,
365 bool newDocSameNameIfNotExist)
367 // If using OpenImagesInSameWindow mode, ask whether to close the
368 // current document.
369 if (!shouldOpen ())
370 return 0;
372 // Create/open doc.
373 kpDocument *newDoc = new kpDocument (fallbackDocSize.width (),
374 fallbackDocSize.height (),
375 documentEnvironment ());
376 if (!newDoc->open (url, newDocSameNameIfNotExist))
378 #if DEBUG_KP_MAIN_WINDOW
379 kDebug () << "\topen failed";
380 #endif
381 delete newDoc;
382 return 0;
385 #if DEBUG_KP_MAIN_WINDOW
386 kDebug () << "\topen OK";
387 #endif
388 // Send document to current or new window.
389 setDocumentChoosingWindow (newDoc);
391 return newDoc;
394 // private
395 bool kpMainWindow::open (const KUrl &url, bool newDocSameNameIfNotExist)
397 #if DEBUG_KP_MAIN_WINDOW
398 kDebug () << "kpMainWindow::open(" << url
399 << ",newDocSameNameIfNotExist=" << newDocSameNameIfNotExist
400 << ")" << endl;
401 #endif
403 kpDocument *newDoc = openInternal (url,
404 defaultDocSize (),
405 newDocSameNameIfNotExist);
406 if (newDoc)
408 if (newDoc->isFromURL (false/*don't bother checking exists*/))
409 addRecentURL (url);
410 return true;
412 else
414 return false;
419 // private
420 KUrl::List kpMainWindow::askForOpenURLs (const QString &caption, const QString &startURL,
421 bool allowMultipleURLs)
423 QStringList mimeTypes = KImageIO::mimeTypes (KImageIO::Reading);
424 #if DEBUG_KP_MAIN_WINDOW
425 QStringList sortedMimeTypes = mimeTypes;
426 sortedMimeTypes.sort ();
427 kDebug () << "kpMainWindow::askForURLs(allowMultiple="
428 << allowMultipleURLs
429 << ")" << endl
430 << "\tmimeTypes=" << mimeTypes << endl
431 << "\tsortedMimeTypes=" << sortedMimeTypes << endl;
432 #endif
433 QString filter = mimeTypes.join (" ");
435 KFileDialog fd (startURL, filter, this);
436 fd.setCaption (caption);
437 fd.setOperationMode (KFileDialog::Opening);
439 if (allowMultipleURLs)
440 fd.setMode (KFile::Files);
442 // COMPAT: Doesn't work. KFileDialog bug.
443 fd.setPreviewWidget (new KImageFilePreview (&fd));
445 if (fd.exec ())
446 return fd.selectedUrls ();
447 else
448 return KUrl::List ();
451 // private slot
452 void kpMainWindow::slotOpen ()
454 toolEndShape ();
457 const KUrl::List urls = askForOpenURLs (i18n ("Open Image"),
458 d->document ? d->document->url ().url () : QString());
460 for (KUrl::List::const_iterator it = urls.begin ();
461 it != urls.end ();
462 it++)
464 open (*it);
468 // private slot
469 void kpMainWindow::slotOpenRecent (const KUrl &url)
471 #if DEBUG_KP_MAIN_WINDOW
472 kDebug () << "kpMainWindow::slotOpenRecent(" << url << ")";
473 kDebug () << "\titems=" << d->actionOpenRecent->items ();
474 #endif
476 toolEndShape ();
478 open (url);
480 // If the open is successful, addRecentURL() would have bubbled up the
481 // URL in the File / Open Recent action. As a side effect, the URL is
482 // deselected.
484 // If the open fails, we should deselect the URL:
486 // 1. for consistency
488 // 2. because it has not been opened.
490 d->actionOpenRecent->setCurrentItem (-1);
494 // private slot
495 void kpMainWindow::slotScan ()
497 #if DEBUG_KP_MAIN_WINDOW
498 kDebug () << "kpMainWindow::slotScan() scanDialog=" << d->scanDialog;
499 #endif
501 toolEndShape ();
504 if (!d->scanDialog)
506 // Create scan dialog by looking for plugin.
507 // [takes about 500ms on 350Mhz]
508 d->scanDialog = KScanDialog::getScanDialog (this);
510 // No scanning support (kdegraphics/libkscan) installed?
511 // [Remove $KDEDIR/share/servicetypes/kscan.desktop and
512 // $KDEDIR/share/services/scanservice.desktop to simulate this]
513 if (!d->scanDialog)
515 #if DEBUG_KP_MAIN_WINDOW
516 kDebug () << "\tcould not create scan dialog";
517 #endif
518 // Instead, we could try to create the scan dialog in the ctor
519 // and just disable the action in the first place, removing
520 // the need for this dialog.
522 // But this increases startup time and is a bit risky e.g. if
523 // the scan support hangs, KolourPaint would not be able to be
524 // started at all.
526 // Also, disabling the action is bad because the scan support
527 // can be installed while KolourPaint is still running.
528 KMessageBox::sorry (this,
529 i18n ("Scanning support is not installed."),
530 i18n ("No Scanning Support"));
531 return;
534 #if DEBUG_KP_MAIN_WINDOW
535 kDebug () << "\tcreated scanDialog=" << d->scanDialog;
536 #endif
537 connect (d->scanDialog, SIGNAL (finalImage (const QImage &, int)),
538 SLOT (slotScanned (const QImage &, int)));
542 // If using OpenImagesInSameWindow mode, ask whether to close the
543 // current document.
545 // Do this after scan support is detected. Because if it's not, what
546 // would be the point of closing the document?
548 // Ideally, we would do this after the user presses "Final Scan" in
549 // the scan dialog and before the scan begins (if the user wants to
550 // cancel the scan operation, it would be annoying to offer this choice
551 // only after the slow scan is completed) but the KScanDialog API does
552 // not allow this. So we settle for doing this before any
553 // scan dialogs are shown. We don't do this between KScanDialog::setup()
554 // and KScanDialog::exec() as it could be confusing alternating between
555 // scanning and KolourPaint dialogs.
556 if (!shouldOpen ())
557 return;
560 #if DEBUG_KP_MAIN_WINDOW
561 kDebug () << "\tcalling setup";
562 #endif
563 // Bring up dialog to select scan device.
564 // If there is no scanner, we find that this does not bring up a dialog
565 // but still returns true.
566 if (d->scanDialog->setup ())
568 #if DEBUG_KP_MAIN_WINDOW
569 kDebug () << "\t\tOK - showing dialog";
570 #endif
571 // Called only if scanner configured/available.
573 // In reality, this seems to be called even if you press "Cancel" in
574 // the KScanDialog::setup() dialog!
576 // We use exec() to make sure it's modal. show() seems to work too
577 // but better safe than sorry.
578 d->scanDialog->exec ();
580 else
582 // Have never seen this code path execute even if "Cancel" is pressed.
583 #if DEBUG_KP_MAIN_WINDOW
584 kDebug () << "\t\tFAIL";
585 #endif
589 // private slot
590 void kpMainWindow::slotScanned (const QImage &image, int)
592 #if DEBUG_KP_MAIN_WINDOW
593 kDebug () << "kpMainWindow::slotScanned() image.rect=" << image.rect ();
594 #endif
596 #if DEBUG_KP_MAIN_WINDOW
597 kDebug () << "\thiding dialog";
598 #endif
599 // (KScanDialog does not close itself after a scan is made)
601 // Close the dialog, first thing:
603 // 1. This means that any dialogs we bring up won't be nested on top.
605 // 2. We don't want to return from this method but forget to close
606 // the dialog. So do it before anything else.
607 d->scanDialog->hide ();
609 // (just in case there's some drawing between slotScan() exiting and
610 // us being called)
611 toolEndShape ();
614 // TODO: Maybe this code should be moved into kpdocument.cpp -
615 // since it resembles the responsibilities of kpDocument::open().
617 // Convert QImage to kpDocument's image format, gathering meta info
618 // from QImage.
619 kpDocumentSaveOptions saveOptions;
620 kpDocumentMetaInfo metaInfo;
621 const QPixmap pixmap = kpDocument::convertToPixmapAsLosslessAsPossible (
622 image,
623 kpMainWindow::pasteWarnAboutLossInfo (),
624 &saveOptions,
625 &metaInfo);
627 if (pixmap.isNull ())
629 #if DEBUG_KP_MAIN_WINDOW
630 kDebug () << "\tcould not convert to pixmap";
631 #endif
632 KMessageBox::sorry (this,
633 i18n ("Cannot scan - out of graphics memory."),
634 i18n ("Cannot Scan"));
635 return;
639 // Create document from image and meta info.
640 kpDocument *doc = new kpDocument (pixmap.width (), pixmap.height (),
641 documentEnvironment ());
642 doc->setImage (pixmap);
643 doc->setSaveOptions (saveOptions);
644 doc->setMetaInfo (metaInfo);
647 // Send document to current or new window.
648 setDocumentChoosingWindow (doc);
652 // private slot
653 void kpMainWindow::slotProperties ()
655 toolEndShape ();
657 kpDocumentMetaInfoDialog dialog (document ()->metaInfo (), this);
659 if (dialog.exec () && !dialog.isNoOp ())
661 commandHistory ()->addCommand (
662 new kpDocumentMetaInfoCommand (
663 i18n ("Document Properties"),
664 dialog.metaInfo ()/*new*/, *document ()->metaInfo ()/*old*/,
665 commandEnvironment ()));
670 // private slot
671 bool kpMainWindow::save (bool localOnly)
673 if (d->document->url ().isEmpty () ||
674 !KImageIO::mimeTypes (KImageIO::Writing)
675 .contains (d->document->saveOptions ()->mimeType ()) ||
676 // SYNC: kpDocument::getPixmapFromFile() can't determine quality
677 // from file so it has been set initially to an invalid value.
678 (d->document->saveOptions ()->mimeTypeHasConfigurableQuality () &&
679 d->document->saveOptions ()->qualityIsInvalid ()) ||
680 (localOnly && !d->document->url ().isLocalFile ()))
682 return saveAs (localOnly);
684 else
686 if (d->document->save (false/*no overwrite prompt*/,
687 !d->document->savedAtLeastOnceBefore ()/*lossy prompt*/))
689 addRecentURL (d->document->url ());
690 return true;
692 else
693 return false;
697 // private slot
698 bool kpMainWindow::slotSave ()
700 toolEndShape ();
702 return save ();
705 // private
706 KUrl kpMainWindow::askForSaveURL (const QString &caption,
707 const QString &startURL,
708 const kpImage &imageToBeSaved,
709 const kpDocumentSaveOptions &startSaveOptions,
710 const kpDocumentMetaInfo &docMetaInfo,
711 const QString &forcedSaveOptionsGroup,
712 bool localOnly,
713 kpDocumentSaveOptions *chosenSaveOptions,
714 bool isSavingForFirstTime,
715 bool *allowOverwritePrompt,
716 bool *allowLossyPrompt)
718 #if DEBUG_KP_MAIN_WINDOW
719 kDebug () << "kpMainWindow::askForURL() startURL=" << startURL;
720 startSaveOptions.printDebug ("\tstartSaveOptions");
721 #endif
723 bool reparsedConfiguration = false;
725 // KConfig::readEntry() does not actually reread from disk, hence doesn't
726 // realize what other processes have done e.g. Settings / Show Path
727 // so reparseConfiguration() must be called
728 #define SETUP_READ_CFG() \
729 if (!reparsedConfiguration) \
731 KGlobal::config ()->reparseConfiguration (); \
732 reparsedConfiguration = true; \
735 KConfigGroup cfg (KGlobal::config (), forcedSaveOptionsGroup); \
738 if (chosenSaveOptions)
739 *chosenSaveOptions = kpDocumentSaveOptions ();
741 if (allowOverwritePrompt)
742 *allowOverwritePrompt = true; // play it safe for now
744 if (allowLossyPrompt)
745 *allowLossyPrompt = true; // play it safe for now
748 kpDocumentSaveOptions fdSaveOptions = startSaveOptions;
750 QStringList mimeTypes = KImageIO::mimeTypes (KImageIO::Writing);
751 #if DEBUG_KP_MAIN_WINDOW
752 QStringList sortedMimeTypes = mimeTypes;
753 sortedMimeTypes.sort ();
754 kDebug () << "\tmimeTypes=" << mimeTypes
755 << "\tsortedMimeTypes=" << sortedMimeTypes << endl;
756 #endif
757 if (mimeTypes.isEmpty ())
759 kError () << "No KImageIO output mimetypes!" << endl;
760 return KUrl ();
763 #define MIME_TYPE_IS_VALID() (!fdSaveOptions.mimeTypeIsInvalid () && \
764 mimeTypes.contains (fdSaveOptions.mimeType ()))
765 if (!MIME_TYPE_IS_VALID ())
767 #if DEBUG_KP_MAIN_WINDOW
768 kDebug () << "\tmimeType=" << fdSaveOptions.mimeType ()
769 << " not valid, get default" << endl;
770 #endif
772 SETUP_READ_CFG ();
774 fdSaveOptions.setMimeType (kpDocumentSaveOptions::defaultMimeType (cfg));
777 if (!MIME_TYPE_IS_VALID ())
779 #if DEBUG_KP_MAIN_WINDOW
780 kDebug () << "\tmimeType=" << fdSaveOptions.mimeType ()
781 << " not valid, get hardcoded" << endl;
782 #endif
783 if (mimeTypes.contains ("image/png"))
784 fdSaveOptions.setMimeType ("image/png");
785 else if (mimeTypes.contains ("image/bmp"))
786 fdSaveOptions.setMimeType ("image/bmp");
787 else
788 fdSaveOptions.setMimeType (mimeTypes.first ());
791 #undef MIME_TYPE_IN_LIST
793 if (fdSaveOptions.colorDepthIsInvalid ())
795 SETUP_READ_CFG ();
797 fdSaveOptions.setColorDepth (kpDocumentSaveOptions::defaultColorDepth (cfg));
798 fdSaveOptions.setDither (kpDocumentSaveOptions::defaultDither (cfg));
801 if (fdSaveOptions.qualityIsInvalid ())
803 SETUP_READ_CFG ();
805 fdSaveOptions.setQuality (kpDocumentSaveOptions::defaultQuality (cfg));
807 #if DEBUG_KP_MAIN_WINDOW
808 fdSaveOptions.printDebug ("\tcorrected saveOptions passed to fileDialog");
809 #endif
811 kpDocumentSaveOptionsWidget *saveOptionsWidget =
812 new kpDocumentSaveOptionsWidget (imageToBeSaved,
813 fdSaveOptions,
814 docMetaInfo,
815 this);
817 KFileDialog fd (startURL, QString(), this,
818 saveOptionsWidget);
819 saveOptionsWidget->setVisualParent (&fd);
820 fd.setCaption (caption);
821 fd.setOperationMode (KFileDialog::Saving);
822 #if DEBUG_KP_MAIN_WINDOW
823 kDebug () << "\tmimeTypes=" << mimeTypes;
824 #endif
825 fd.setMimeFilter (mimeTypes, fdSaveOptions.mimeType ());
826 if (localOnly)
827 fd.setMode (KFile::File | KFile::LocalOnly);
829 connect (&fd, SIGNAL (filterChanged (const QString &)),
830 saveOptionsWidget, SLOT (setMimeType (const QString &)));
833 if (fd.exec ())
835 kpDocumentSaveOptions newSaveOptions = saveOptionsWidget->documentSaveOptions ();
836 #if DEBUG_KP_MAIN_WINDOW
837 newSaveOptions.printDebug ("\tnewSaveOptions");
838 #endif
840 KConfigGroup cfg (KGlobal::config (), forcedSaveOptionsGroup);
842 // Save options user forced - probably want to use them in future
843 kpDocumentSaveOptions::saveDefaultDifferences (cfg,
844 fdSaveOptions, newSaveOptions);
845 cfg.sync ();
848 if (chosenSaveOptions)
849 *chosenSaveOptions = newSaveOptions;
852 bool shouldAllowOverwritePrompt =
853 (fd.selectedUrl () != startURL ||
854 newSaveOptions.mimeType () != startSaveOptions.mimeType ());
855 if (allowOverwritePrompt)
857 *allowOverwritePrompt = shouldAllowOverwritePrompt;
858 #if DEBUG_KP_MAIN_WINDOW
859 kDebug () << "\tallowOverwritePrompt=" << *allowOverwritePrompt;
860 #endif
863 if (allowLossyPrompt)
865 // SYNC: kpDocumentSaveOptions elements - everything except quality
866 // (one quality setting is "just as lossy" as another so no
867 // need to continually warn due to quality change)
868 *allowLossyPrompt =
869 (isSavingForFirstTime ||
870 shouldAllowOverwritePrompt ||
871 newSaveOptions.mimeType () != startSaveOptions.mimeType () ||
872 newSaveOptions.colorDepth () != startSaveOptions.colorDepth () ||
873 newSaveOptions.dither () != startSaveOptions.dither ());
874 #if DEBUG_KP_MAIN_WINDOW
875 kDebug () << "\tallowLossyPrompt=" << *allowLossyPrompt;
876 #endif
880 #if DEBUG_KP_MAIN_WINDOW
881 kDebug () << "\tselectedUrl=" << fd.selectedUrl ();
882 #endif
883 return fd.selectedUrl ();
885 else
886 return KUrl ();
887 #undef SETUP_READ_CFG
891 // private slot
892 bool kpMainWindow::saveAs (bool localOnly)
894 #if DEBUG_KP_MAIN_WINDOW
895 kDebug () << "kpMainWindow::saveAs URL=" << d->document->url ();
896 #endif
898 kpDocumentSaveOptions chosenSaveOptions;
899 bool allowOverwritePrompt, allowLossyPrompt;
900 KUrl chosenURL = askForSaveURL (i18n ("Save Image As"),
901 d->document->url ().url (),
902 d->document->imageWithSelection (),
903 *d->document->saveOptions (),
904 *d->document->metaInfo (),
905 kpSettingsGroupFileSaveAs,
906 localOnly,
907 &chosenSaveOptions,
908 !d->document->savedAtLeastOnceBefore (),
909 &allowOverwritePrompt,
910 &allowLossyPrompt);
913 if (chosenURL.isEmpty ())
914 return false;
917 if (!d->document->saveAs (chosenURL, chosenSaveOptions,
918 allowOverwritePrompt,
919 allowLossyPrompt))
921 return false;
925 addRecentURL (chosenURL);
927 return true;
930 // private slot
931 bool kpMainWindow::slotSaveAs ()
933 toolEndShape ();
935 return saveAs ();
938 // private slot
939 bool kpMainWindow::slotExport ()
941 #if DEBUG_KP_MAIN_WINDOW
942 kDebug () << "kpMainWindow::slotExport()";
943 #endif
945 toolEndShape ();
948 kpDocumentSaveOptions chosenSaveOptions;
949 bool allowOverwritePrompt, allowLossyPrompt;
950 KUrl chosenURL = askForSaveURL (i18n ("Export"),
951 d->lastExportURL.url (),
952 d->document->imageWithSelection (),
953 d->lastExportSaveOptions,
954 *d->document->metaInfo (),
955 kpSettingsGroupFileExport,
956 false/*allow remote files*/,
957 &chosenSaveOptions,
958 d->exportFirstTime,
959 &allowOverwritePrompt,
960 &allowLossyPrompt);
963 if (chosenURL.isEmpty ())
964 return false;
967 if (!kpDocument::savePixmapToFile (d->document->imageWithSelection (),
968 chosenURL,
969 chosenSaveOptions, *d->document->metaInfo (),
970 allowOverwritePrompt,
971 allowLossyPrompt,
972 this))
974 return false;
978 addRecentURL (chosenURL);
981 d->lastExportURL = chosenURL;
982 d->lastExportSaveOptions = chosenSaveOptions;
984 d->exportFirstTime = false;
986 return true;
990 // private slot
991 void kpMainWindow::slotEnableReload ()
993 d->actionReload->setEnabled (d->document);
996 // private slot
997 bool kpMainWindow::slotReload ()
999 toolEndShape ();
1001 Q_ASSERT (d->document);
1004 KUrl oldURL = d->document->url ();
1007 if (d->document->isModified ())
1009 int result = KMessageBox::Cancel;
1011 if (d->document->isFromURL (false/*don't bother checking exists*/) && !oldURL.isEmpty ())
1013 result = KMessageBox::warningContinueCancel (this,
1014 i18n ("The document \"%1\" has been modified.\n"
1015 "Reloading will lose all changes since you last saved it.\n"
1016 "Are you sure?",
1017 d->document->prettyFilename ()),
1018 QString()/*caption*/,
1019 KGuiItem(i18n ("&Reload")));
1021 else
1023 result = KMessageBox::warningContinueCancel (this,
1024 i18n ("The document \"%1\" has been modified.\n"
1025 "Reloading will lose all changes.\n"
1026 "Are you sure?",
1027 d->document->prettyFilename ()),
1028 QString()/*caption*/,
1029 KGuiItem(i18n ("&Reload")));
1032 if (result != KMessageBox::Continue)
1033 return false;
1037 kpDocument *doc = 0;
1039 // If it's _supposed to_ come from a URL or it exists
1040 if (d->document->isFromURL (false/*don't bother checking exists*/) ||
1041 (!oldURL.isEmpty () && KIO::NetAccess::exists (oldURL, KIO::NetAccess::SourceSide/*open*/, this)))
1043 #if DEBUG_KP_MAIN_WINDOW
1044 kDebug () << "kpMainWindow::slotReload() reloading from disk!";
1045 #endif
1047 doc = new kpDocument (1, 1, documentEnvironment ());
1048 if (!doc->open (oldURL))
1050 delete doc; doc = 0;
1051 return false;
1054 addRecentURL (oldURL);
1056 else
1058 #if DEBUG_KP_MAIN_WINDOW
1059 kDebug () << "kpMainWindow::slotReload() create doc";
1060 #endif
1062 doc = new kpDocument (d->document->constructorWidth (),
1063 d->document->constructorHeight (),
1064 documentEnvironment ());
1065 doc->setURL (oldURL, false/*not from URL*/);
1069 setDocument (doc);
1071 return true;
1075 // private
1076 void kpMainWindow::sendDocumentNameToPrinter (QPrinter *printer)
1078 KUrl url = d->document->url ();
1079 if (!url.isEmpty ())
1081 int dot;
1083 QString fileName = url.fileName ();
1084 dot = fileName.lastIndexOf ('.');
1086 // file.ext but not .hidden-file?
1087 if (dot > 0)
1088 fileName.truncate (dot);
1090 #if DEBUG_KP_MAIN_WINDOW
1091 kDebug () << "kpMainWindow::sendDocumentNameToPrinter() fileName="
1092 << fileName
1093 << " dir="
1094 << url.directory ()
1095 << endl;
1096 #endif
1097 printer->setDocName (fileName);
1102 // private
1103 void kpMainWindow::sendImageToPrinter (QPrinter *printer,
1104 bool showPrinterSetupDialog)
1106 // Get image to be printed.
1107 kpImage image = d->document->imageWithSelection ();
1110 // Get image DPI.
1111 double imageDotsPerMeterX =
1112 double (d->document->metaInfo ()->dotsPerMeterX ());
1113 double imageDotsPerMeterY =
1114 double (d->document->metaInfo ()->dotsPerMeterY ());
1115 #if DEBUG_KP_MAIN_WINDOW
1116 kDebug () << "kpMainWindow::sendImageToPrinter() image:"
1117 << " width=" << image.width ()
1118 << " height=" << image.height ()
1119 << " dotsPerMeterX=" << imageDotsPerMeterX
1120 << " dotsPerMeterY=" << imageDotsPerMeterY
1121 << endl;
1122 #endif
1124 // Image DPI invalid (e.g. new image, could not read from file
1125 // or Qt3 doesn't implement DPI for JPEG)?
1126 if (imageDotsPerMeterX <= 0 || imageDotsPerMeterY <= 0)
1128 // Even if just one DPI dimension is invalid, mutate both DPI
1129 // dimensions as we have no information about the intended
1130 // aspect ratio anyway (and other dimension likely to be invalid).
1132 // When rendering text onto a document, the fonts are rasterised
1133 // according to the screen's DPI.
1134 // TODO: I think we should use the image's DPI. Technically
1135 // possible?
1137 // So no matter what computer you draw text on, you get
1138 // the same pixels.
1140 // So we must print at the screen's DPI to get the right text size.
1142 // Unfortunately, this means that moving to a different screen DPI
1143 // affects printing. If you edited the image at a different screen
1144 // DPI than when you print, you get incorrect results. Furthermore,
1145 // this is bogus if you don't have text in your image. Worse still,
1146 // what if you have multiple screens connected to the same computer
1147 // with different DPIs?
1148 // TODO: mysteriously, someone else is setting this to 96dpi always.
1149 QPixmap arbitraryScreenElement;
1150 const QPaintDevice *screenDevice = &arbitraryScreenElement;
1151 const int dpiX = screenDevice->logicalDpiX (),
1152 dpiY = screenDevice->logicalDpiY ();
1153 #if DEBUG_KP_MAIN_WINDOW
1154 kDebug () << "\tusing screen dpi: x=" << dpiX << " y=" << dpiY;
1155 #endif
1157 imageDotsPerMeterX = dpiX * KP_INCHES_PER_METER;
1158 imageDotsPerMeterY = dpiY * KP_INCHES_PER_METER;
1162 // Get page size (excluding margins).
1163 // Coordinate (0,0) is the X here:
1164 // mmmmm
1165 // mX m
1166 // m m m = margin
1167 // m m
1168 // mmmmm
1169 const int printerWidthMM = printer->widthMM ();
1170 const int printerHeightMM = printer->heightMM ();
1171 #if DEBUG_KP_MAIN_WINDOW
1172 kDebug () << "\tprinter: widthMM=" << printerWidthMM
1173 << " heightMM=" << printerHeightMM
1174 << endl;
1175 #endif
1178 double dpiX = imageDotsPerMeterX / KP_INCHES_PER_METER;
1179 double dpiY = imageDotsPerMeterY / KP_INCHES_PER_METER;
1180 #if DEBUG_KP_MAIN_WINDOW
1181 kDebug () << "\timage: dpiX=" << dpiX << " dpiY=" << dpiY;
1182 #endif
1186 // If image doesn't fit on page at intended DPI, change the DPI.
1189 const double scaleDpiX =
1190 (image.width () / (printerWidthMM / KP_MILLIMETERS_PER_INCH))
1191 / dpiX;
1192 const double scaleDpiY =
1193 (image.height () / (printerHeightMM / KP_MILLIMETERS_PER_INCH))
1194 / dpiY;
1195 const double scaleDpi = qMax (scaleDpiX, scaleDpiY);
1196 #if DEBUG_KP_MAIN_WINDOW
1197 kDebug () << "\t\tscaleDpi: x=" << scaleDpiX << " y=" << scaleDpiY
1198 << " --> scale at " << scaleDpi << " to fit?"
1199 << endl;
1200 #endif
1202 // Need to increase resolution to fit page?
1203 if (scaleDpi > 1.0)
1205 dpiX *= scaleDpi;
1206 dpiY *= scaleDpi;
1207 #if DEBUG_KP_MAIN_WINDOW
1208 kDebug () << "\t\t\tto fit page, scaled to:"
1209 << " dpiX=" << dpiX << " dpiY=" << dpiY << endl;
1210 #endif
1214 // Make sure DPIs are equal as that's all QPrinter::setResolution()
1215 // supports. We do this in such a way that we only ever stretch an
1216 // image, to avoid losing information. Don't antialias as the printer
1217 // will do that to translate our DPI to its physical resolution and
1218 // double-antialiasing looks bad.
1219 if (dpiX > dpiY)
1221 #if DEBUG_KP_MAIN_WINDOW
1222 kDebug () << "\tdpiX > dpiY; stretching image height to equalise DPIs to dpiX="
1223 << dpiX << endl;
1224 #endif
1225 kpPixmapFX::scale (&image,
1226 image.width (),
1227 qMax (1, qRound (image.height () * dpiX / dpiY)),
1228 false/*don't antialias*/);
1230 dpiY = dpiX;
1232 else if (dpiY > dpiX)
1234 #if DEBUG_KP_MAIN_WINDOW
1235 kDebug () << "\tdpiY > dpiX; stretching image width to equalise DPIs to dpiY="
1236 << dpiY << endl;
1237 #endif
1238 kpPixmapFX::scale (&image,
1239 qMax (1, qRound (image.width () * dpiY / dpiX)),
1240 image.height (),
1241 false/*don't antialias*/);
1243 dpiX = dpiY;
1246 Q_ASSERT (dpiX == dpiY);
1249 // QPrinter::setResolution() has to be called before QPrinter::setup().
1250 printer->setResolution (qMax (1, qRound (dpiX)));
1253 sendDocumentNameToPrinter (printer);
1256 if (showPrinterSetupDialog)
1258 kpPrintDialogPage *optionsPage = new kpPrintDialogPage (this);
1259 optionsPage->setPrintImageCenteredOnPage (d->configPrintImageCenteredOnPage);
1261 QPrintDialog *printDialog =
1262 KdePrint::createPrintDialog (
1263 printer,
1264 QList <QWidget *> () << optionsPage,
1265 this);
1266 printDialog->setWindowTitle (i18n ("Print Image"));
1268 // Display dialog.
1269 const bool wantToPrint = printDialog->exec ();
1271 if (optionsPage->printImageCenteredOnPage () !=
1272 d->configPrintImageCenteredOnPage)
1274 // Save config option even if the dialog was cancelled.
1275 d->configPrintImageCenteredOnPage = optionsPage->printImageCenteredOnPage ();
1277 KConfigGroup cfg (KGlobal::config (), kpSettingsGroupGeneral);
1278 cfg.writeEntry (kpSettingPrintImageCenteredOnPage,
1279 d->configPrintImageCenteredOnPage);
1280 cfg.sync ();
1283 delete printDialog;
1285 if (!wantToPrint)
1286 return;
1290 double originX = 0, originY = 0;
1292 // Center image on page?
1293 if (d->configPrintImageCenteredOnPage)
1295 originX =
1296 (printerWidthMM * dpiX / KP_MILLIMETERS_PER_INCH - image.width ())
1297 / 2;
1298 originY =
1299 (printerHeightMM * dpiY / KP_MILLIMETERS_PER_INCH - image.height ())
1300 / 2;
1303 #if DEBUG_KP_MAIN_WINDOW
1304 kDebug () << "\torigin: x=" << originX << " y=" << originY;
1305 #endif
1308 // Send image to printer.
1309 QPainter painter;
1310 painter.begin (printer);
1311 painter.drawPixmap (qRound (originX), qRound (originY), image);
1312 painter.end ();
1316 // private slot
1317 void kpMainWindow::slotPrint ()
1319 toolEndShape ();
1321 QPrinter printer;
1323 sendImageToPrinter (&printer, true/*showPrinterSetupDialog*/);
1326 // private slot
1327 void kpMainWindow::slotPrintPreview ()
1329 toolEndShape ();
1331 QPrinter printer;
1333 KPrintPreview printPreview (&printer);
1335 sendImageToPrinter (&printer, false/*don't showPrinterSetupDialog*/);
1337 printPreview.exec ();
1341 // private slot
1342 void kpMainWindow::slotMail ()
1344 toolEndShape ();
1346 if (d->document->url ().isEmpty ()/*no name*/ ||
1347 !d->document->isFromURL () ||
1348 d->document->isModified ()/*needs to be saved*/)
1350 int result = KMessageBox::questionYesNo (this,
1351 i18n ("You must save this image before sending it.\n"
1352 "Do you want to save it?"),
1353 QString(),
1354 KStandardGuiItem::save (), KStandardGuiItem::cancel ());
1356 if (result == KMessageBox::Yes)
1358 if (!save ())
1360 // save failed or aborted - don't email
1361 return;
1364 else
1366 // don't want to save - don't email
1367 return;
1371 KToolInvocation::invokeMailer (
1372 QString::null/*to*/, //krazy:exclude=nullstrassign for old broken gcc
1373 QString()/*cc*/,
1374 QString()/*bcc*/,
1375 d->document->prettyFilename()/*subject*/,
1376 QString()/*body*/,
1377 QString()/*messageFile*/,
1378 QStringList (d->document->url ().url ())/*attachments*/);
1382 // private
1383 void kpMainWindow::setAsWallpaper (bool centered)
1385 if (d->document->url ().isEmpty ()/*no name*/ ||
1386 !d->document->url ().isLocalFile ()/*remote file*/ ||
1387 !d->document->isFromURL () ||
1388 d->document->isModified ()/*needs to be saved*/)
1390 QString question;
1392 if (!d->document->url ().isLocalFile ())
1394 question = i18n ("Before this image can be set as the wallpaper, "
1395 "you must save it as a local file.\n"
1396 "Do you want to save it?");
1398 else
1400 question = i18n ("Before this image can be set as the wallpaper, "
1401 "you must save it.\n"
1402 "Do you want to save it?");
1405 int result = KMessageBox::questionYesNo (this,
1406 question, QString(),
1407 KStandardGuiItem::save (), KStandardGuiItem::cancel ());
1409 if (result == KMessageBox::Yes)
1411 // save() is smart enough to pop up a filedialog if it's a
1412 // remote file that should be saved locally
1413 if (!save (true/*localOnly*/))
1415 // save failed or aborted - don't set the wallpaper
1416 return;
1419 else
1421 // don't want to save - don't set wallpaper
1422 return;
1427 QByteArray data;
1428 QDataStream dataStream (&data, QIODevice::WriteOnly);
1430 // write path
1431 #if DEBUG_KP_MAIN_WINDOW
1432 kDebug () << "kpMainWindow::setAsWallpaper() path="
1433 << d->document->url ().path () << endl;
1434 #endif
1435 dataStream << QString (d->document->url ().path ());
1437 // write position:
1439 // SYNC: kdebase/kcontrol/background/bgsettings.h:
1440 // 1 = Centered
1441 // 2 = Tiled
1442 // 6 = Scaled
1443 // 9 = lastWallpaperMode
1445 // Why restrict the user to Centered & Tiled?
1446 // Why don't we let the user choose if it should be common to all desktops?
1447 // Why don't we rewrite the Background control page?
1449 // Answer: This is supposed to be a quick & convenient feature.
1451 // If you want more options, go to kcontrol for that kind of
1452 // flexiblity. We don't want to slow down average users, who see way too
1453 // many dialogs already and probably haven't even heard of "Centered Maxpect"...
1455 dataStream << int (centered ? 1 : 2);
1458 // I'm going to all this trouble because the user might not have kdebase
1459 // installed so kdebase/kdesktop/KBackgroundIface.h might not be around
1460 // to be compiled in (where user == developer :))
1461 // COMPAT
1463 #ifdef Q_WS_X11
1464 int konq_screen_number = KApplication::desktop()->primaryScreen();
1465 QByteArray appname;
1466 if (konq_screen_number == 0)
1467 appname = "org.kde.kdesktop";
1468 else
1469 appname = "org.kde.kdesktop-screen-" + QByteArray::number(konq_screen_number);
1470 QDBusInterface kdesktop(appname, "/Background", "org.kde.kdesktop.Background");
1471 QDBusReply<void> retVal = kdesktop.call( "setWallpaper", QString (d->document->url ().path ()), int (centered ? 1 : 2) );
1472 if (!retVal.isValid())
1474 KMessageBox::sorry (this, i18n ("Could not change wallpaper."));
1476 #else
1477 #ifdef __GNUC__
1478 #warning "Setting wallpaper not implemented in non-X11"
1479 #endif
1480 #endif
1483 // private slot
1484 void kpMainWindow::slotSetAsWallpaperCentered ()
1486 toolEndShape ();
1488 setAsWallpaper (true/*centered*/);
1491 // private slot
1492 void kpMainWindow::slotSetAsWallpaperTiled ()
1494 toolEndShape ();
1496 setAsWallpaper (false/*tiled*/);
1500 // private
1501 bool kpMainWindow::queryCloseDocument ()
1503 toolEndShape ();
1505 if (!d->document || !d->document->isModified ())
1506 return true; // ok to close current doc
1508 int result = KMessageBox::warningYesNoCancel (this,
1509 i18n ("The document \"%1\" has been modified.\n"
1510 "Do you want to save it?",
1511 d->document->prettyFilename ()),
1512 QString()/*caption*/,
1513 KStandardGuiItem::save (), KStandardGuiItem::discard ());
1515 switch (result)
1517 case KMessageBox::Yes:
1518 return slotSave (); // close only if save succeeds
1519 case KMessageBox::No:
1520 return true; // close without saving
1521 default:
1522 return false; // don't close current doc
1526 // private virtual [base KMainWindow]
1527 bool kpMainWindow::queryClose ()
1529 #if DEBUG_KP_MAIN_WINDOW
1530 kDebug () << "kpMainWindow::queryClose()";
1531 #endif
1532 toolEndShape ();
1534 if (!queryCloseDocument ())
1535 return false;
1537 if (!queryCloseColors ())
1538 return false;
1540 return true;
1543 // private slot
1544 void kpMainWindow::slotClose ()
1546 toolEndShape ();
1548 #if DEBUG_KP_MAIN_WINDOW
1549 kDebug () << "kpMainWindow::slotClose()";
1550 #endif
1552 if (!queryCloseDocument ())
1553 return;
1555 setDocument (0);
1558 // private slot
1559 void kpMainWindow::slotQuit ()
1561 toolEndShape ();
1563 #if DEBUG_KP_MAIN_WINDOW
1564 kDebug () << "kpMainWindow::slotQuit()";
1565 #endif
1567 close (); // will call queryClose()