TDE graphics utilities
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1410 lines
43KB

  1. /*
  2. Copyright (c) 2003,2004,2005 Clarence Dang <dang@kde.org>
  3. All rights reserved.
  4. Redistribution and use in source and binary forms, with or without
  5. modification, are permitted provided that the following conditions
  6. are met:
  7. 1. Redistributions of source code must retain the above copyright
  8. notice, this list of conditions and the following disclaimer.
  9. 2. Redistributions in binary form must reproduce the above copyright
  10. notice, this list of conditions and the following disclaimer in the
  11. documentation and/or other materials provided with the distribution.
  12. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  13. IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  14. OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  15. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  16. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  17. NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  18. DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  19. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  20. (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  21. THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  22. */
  23. #include <kpmainwindow.h>
  24. #include <tqcstring.h>
  25. #include <tqdatastream.h>
  26. #include <tqpaintdevicemetrics.h>
  27. #include <tqpainter.h>
  28. #include <tqsize.h>
  29. #include <dcopclient.h>
  30. #include <tdeapplication.h>
  31. #include <tdeaction.h>
  32. #include <tdeconfig.h>
  33. #include <kdebug.h>
  34. #include <tdefiledialog.h>
  35. #include <kiconloader.h>
  36. #include <kimagefilepreview.h>
  37. #include <kimageio.h>
  38. #include <tdeio/netaccess.h>
  39. #include <tdelocale.h>
  40. #include <tdemessagebox.h>
  41. #include <kprinter.h>
  42. #include <tdestdaccel.h>
  43. #include <kstdaction.h>
  44. #include <kscan.h>
  45. #include <kpdefs.h>
  46. #include <kpdocument.h>
  47. #include <kpdocumentsaveoptionswidget.h>
  48. #include <kptool.h>
  49. #include <kpview.h>
  50. #include <kpviewmanager.h>
  51. // private
  52. void kpMainWindow::setupFileMenuActions ()
  53. {
  54. #if DEBUG_KP_MAIN_WINDOW
  55. kdDebug () << "kpMainWindow::setupFileMenuActions()" << endl;
  56. #endif
  57. TDEActionCollection *ac = actionCollection ();
  58. m_actionNew = KStdAction::openNew (TQT_TQOBJECT(this), TQT_SLOT (slotNew ()), ac);
  59. m_actionOpen = KStdAction::open (TQT_TQOBJECT(this), TQT_SLOT (slotOpen ()), ac);
  60. m_actionOpenRecent = KStdAction::openRecent (TQT_TQOBJECT(this), TQT_SLOT (slotOpenRecent (const KURL &)), ac);
  61. m_actionOpenRecent->loadEntries (kapp->config ());
  62. #if DEBUG_KP_MAIN_WINDOW
  63. kdDebug () << "\trecent URLs=" << m_actionOpenRecent->items () << endl;
  64. #endif
  65. m_actionSave = KStdAction::save (TQT_TQOBJECT(this), TQT_SLOT (slotSave ()), ac);
  66. m_actionSaveAs = KStdAction::saveAs (TQT_TQOBJECT(this), TQT_SLOT (slotSaveAs ()), ac);
  67. m_actionExport = new TDEAction (i18n ("E&xport..."), 0,
  68. TQT_TQOBJECT(this), TQT_SLOT (slotExport ()), ac, "file_export");
  69. m_actionScan = new TDEAction (i18n ("Scan..."), SmallIcon ("scanner"), 0,
  70. TQT_TQOBJECT(this), TQT_SLOT (slotScan ()), ac, "file_scan");
  71. //m_actionRevert = KStdAction::revert (this, TQT_SLOT (slotRevert ()), ac);
  72. m_actionReload = new TDEAction (i18n ("Reloa&d"), TDEStdAccel::reload (),
  73. TQT_TQOBJECT(this), TQT_SLOT (slotReload ()), ac, "file_revert");
  74. slotEnableReload ();
  75. m_actionPrint = KStdAction::print (TQT_TQOBJECT(this), TQT_SLOT (slotPrint ()), ac);
  76. m_actionPrintPreview = KStdAction::printPreview (TQT_TQOBJECT(this), TQT_SLOT (slotPrintPreview ()), ac);
  77. m_actionMail = KStdAction::mail (TQT_TQOBJECT(this), TQT_SLOT (slotMail ()), ac);
  78. m_actionSetAsWallpaperCentered = new TDEAction (i18n ("Set as Wa&llpaper (Centered)"), 0,
  79. TQT_TQOBJECT(this), TQT_SLOT (slotSetAsWallpaperCentered ()), ac, "file_set_as_wallpaper_centered");
  80. m_actionSetAsWallpaperTiled = new TDEAction (i18n ("Set as Wallpaper (&Tiled)"), 0,
  81. TQT_TQOBJECT(this), TQT_SLOT (slotSetAsWallpaperTiled ()), ac, "file_set_as_wallpaper_tiled");
  82. m_actionClose = KStdAction::close (TQT_TQOBJECT(this), TQT_SLOT (slotClose ()), ac);
  83. m_actionQuit = KStdAction::quit (TQT_TQOBJECT(this), TQT_SLOT (slotQuit ()), ac);
  84. m_scanDialog = 0;
  85. enableFileMenuDocumentActions (false);
  86. }
  87. // private
  88. void kpMainWindow::enableFileMenuDocumentActions (bool enable)
  89. {
  90. // m_actionNew
  91. // m_actionOpen
  92. // m_actionOpenRecent
  93. m_actionSave->setEnabled (enable);
  94. m_actionSaveAs->setEnabled (enable);
  95. m_actionExport->setEnabled (enable);
  96. // m_actionReload
  97. m_actionPrint->setEnabled (enable);
  98. m_actionPrintPreview->setEnabled (enable);
  99. m_actionMail->setEnabled (enable);
  100. m_actionSetAsWallpaperCentered->setEnabled (enable);
  101. m_actionSetAsWallpaperTiled->setEnabled (enable);
  102. m_actionClose->setEnabled (enable);
  103. // m_actionQuit->setEnabled (enable);
  104. }
  105. // private
  106. void kpMainWindow::addRecentURL (const KURL &url)
  107. {
  108. #if DEBUG_KP_MAIN_WINDOW
  109. kdDebug () << "kpMainWindow::addRecentURL(" << url << ")" << endl;
  110. #endif
  111. if (url.isEmpty ())
  112. return;
  113. TDEConfig *cfg = kapp->config ();
  114. // TDEConfig::readEntry() does not actually reread from disk, hence doesn't
  115. // realise what other processes have done e.g. Settings / Show Path
  116. cfg->reparseConfiguration ();
  117. // HACK: Something might have changed interprocess.
  118. // If we could PROPAGATE: interprocess, then this wouldn't be required.
  119. m_actionOpenRecent->loadEntries (cfg);
  120. m_actionOpenRecent->addURL (url);
  121. m_actionOpenRecent->saveEntries (cfg);
  122. cfg->sync ();
  123. #if DEBUG_KP_MAIN_WINDOW
  124. kdDebug () << "\tnew recent URLs=" << m_actionOpenRecent->items () << endl;
  125. #endif
  126. // TODO: PROPAGATE: interprocess
  127. if (TDEMainWindow::memberList)
  128. {
  129. #if DEBUG_KP_MAIN_WINDOW
  130. kdDebug () << "\thave memberList" << endl;
  131. #endif
  132. for (TQPtrList <TDEMainWindow>::const_iterator it = TDEMainWindow::memberList->begin ();
  133. it != TDEMainWindow::memberList->end ();
  134. it++)
  135. {
  136. kpMainWindow *mw = dynamic_cast <kpMainWindow *> (*it);
  137. if (!mw)
  138. {
  139. kdError () << "kpMainWindow::addRecentURL() given fake kpMainWindow: " << (*it) << endl;
  140. continue;
  141. }
  142. #if DEBUG_KP_MAIN_WINDOW
  143. kdDebug () << "\t\tmw=" << mw << endl;
  144. #endif
  145. if (mw != this)
  146. {
  147. // WARNING: Do not use TDERecentFilesAction::setItems()
  148. // - it does not work since only its superclass,
  149. // TDESelectAction, implements setItems() and can't
  150. // update TDERecentFilesAction's URL list.
  151. // Avoid URL memory leak in TDERecentFilesAction::loadEntries().
  152. mw->m_actionOpenRecent->clearURLList ();
  153. mw->m_actionOpenRecent->loadEntries (cfg);
  154. #if DEBUG_KP_MAIN_WINDOW
  155. kdDebug () << "\t\t\tcheck recent URLs="
  156. << mw->m_actionOpenRecent->items () << endl;
  157. #endif
  158. }
  159. }
  160. }
  161. }
  162. // private slot
  163. void kpMainWindow::slotNew ()
  164. {
  165. if (toolHasBegunShape ())
  166. tool ()->endShapeInternal ();
  167. if (m_document)
  168. {
  169. kpMainWindow *win = new kpMainWindow ();
  170. win->show ();
  171. }
  172. else
  173. {
  174. open (KURL (), true/*create an empty doc*/);
  175. }
  176. }
  177. // private
  178. TQSize kpMainWindow::defaultDocSize () const
  179. {
  180. // TDEConfig::readEntry() does not actually reread from disk, hence doesn't
  181. // realise what other processes have done e.g. Settings / Show Path
  182. kapp->config ()->reparseConfiguration ();
  183. TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupGeneral);
  184. TDEConfigBase *cfg = cfgGroupSaver.config ();
  185. TQSize docSize = cfg->readSizeEntry (kpSettingLastDocSize);
  186. if (docSize.isEmpty ())
  187. {
  188. docSize = TQSize (400, 300);
  189. }
  190. else
  191. {
  192. // Don't get too big or you'll thrash (or even lock up) the computer
  193. // just by opening a window
  194. docSize = TQSize (TQMIN (2048, docSize.width ()),
  195. TQMIN (2048, docSize.height ()));
  196. }
  197. return docSize;
  198. }
  199. // private
  200. void kpMainWindow::saveDefaultDocSize (const TQSize &size)
  201. {
  202. #if DEBUG_KP_MAIN_WINDOW
  203. kdDebug () << "\tCONFIG: saving Last Doc Size = " << size << endl;
  204. #endif
  205. TDEConfigGroupSaver cfgGroupSaver (kapp->config (), kpSettingsGroupGeneral);
  206. TDEConfigBase *cfg = cfgGroupSaver.config ();
  207. cfg->writeEntry (kpSettingLastDocSize, size);
  208. cfg->sync ();
  209. }
  210. // private
  211. bool kpMainWindow::shouldOpenInNewWindow () const
  212. {
  213. return (m_document && !m_document->isEmpty ());
  214. }
  215. // private
  216. void kpMainWindow::setDocumentChoosingWindow (kpDocument *doc)
  217. {
  218. // need new window?
  219. if (shouldOpenInNewWindow ())
  220. {
  221. // send doc to new window
  222. kpMainWindow *win = new kpMainWindow (doc);
  223. win->show ();
  224. }
  225. else
  226. {
  227. // set up views, doc signals
  228. setDocument (doc);
  229. }
  230. }
  231. // private
  232. kpDocument *kpMainWindow::openInternal (const KURL &url,
  233. const TQSize &fallbackDocSize,
  234. bool newDocSameNameIfNotExist)
  235. {
  236. // create doc
  237. kpDocument *newDoc = new kpDocument (fallbackDocSize.width (),
  238. fallbackDocSize.height (),
  239. this);
  240. if (!newDoc->open (url, newDocSameNameIfNotExist))
  241. {
  242. delete newDoc;
  243. return 0;
  244. }
  245. // Send document to current or new window.
  246. setDocumentChoosingWindow (newDoc);
  247. return newDoc;
  248. }
  249. // private
  250. bool kpMainWindow::open (const KURL &url, bool newDocSameNameIfNotExist)
  251. {
  252. kpDocument *newDoc = openInternal (url,
  253. defaultDocSize (),
  254. newDocSameNameIfNotExist);
  255. if (newDoc)
  256. {
  257. if (newDoc->isFromURL (false/*don't bother checking exists*/))
  258. addRecentURL (url);
  259. return true;
  260. }
  261. else
  262. {
  263. return false;
  264. }
  265. }
  266. // private
  267. KURL::List kpMainWindow::askForOpenURLs (const TQString &caption, const TQString &startURL,
  268. bool allowMultipleURLs)
  269. {
  270. TQStringList mimeTypes = KImageIO::mimeTypes (KImageIO::Reading);
  271. #if DEBUG_KP_MAIN_WINDOW
  272. TQStringList sortedMimeTypes = mimeTypes;
  273. sortedMimeTypes.sort ();
  274. kdDebug () << "kpMainWindow::askForURLs(allowMultiple="
  275. << allowMultipleURLs
  276. << ")" << endl
  277. << "\tmimeTypes=" << mimeTypes << endl
  278. << "\tsortedMimeTypes=" << sortedMimeTypes << endl;
  279. #endif
  280. TQString filter = mimeTypes.join (" ");
  281. KFileDialog fd (startURL, filter, this, "fd", true/*modal*/);
  282. fd.setCaption (caption);
  283. fd.setOperationMode (KFileDialog::Opening);
  284. if (allowMultipleURLs)
  285. fd.setMode (KFile::Files);
  286. fd.setPreviewWidget (new KImageFilePreview (&fd));
  287. if (fd.exec ())
  288. return fd.selectedURLs ();
  289. else
  290. return KURL::List ();
  291. }
  292. // private slot
  293. void kpMainWindow::slotOpen ()
  294. {
  295. if (toolHasBegunShape ())
  296. tool ()->endShapeInternal ();
  297. const KURL::List urls = askForOpenURLs (i18n ("Open Image"),
  298. m_document ? m_document->url ().url () : TQString());
  299. for (KURL::List::const_iterator it = urls.begin ();
  300. it != urls.end ();
  301. it++)
  302. {
  303. open (*it);
  304. }
  305. }
  306. // private slot
  307. void kpMainWindow::slotOpenRecent (const KURL &url)
  308. {
  309. #if DEBUG_KP_MAIN_WINDOW
  310. kdDebug () << "kpMainWindow::slotOpenRecent(" << url << ")" << endl;
  311. kdDebug () << "\titems=" << m_actionOpenRecent->items () << endl;
  312. #endif
  313. if (toolHasBegunShape ())
  314. tool ()->endShapeInternal ();
  315. open (url);
  316. // If the open is successful, addRecentURL() would have bubbled up the
  317. // URL in the File / Open Recent action. As a side effect, the URL is
  318. // deselected.
  319. //
  320. // If the open fails, we should deselect the URL:
  321. //
  322. // 1. for consistency
  323. //
  324. // 2. because it has not been opened.
  325. //
  326. m_actionOpenRecent->setCurrentItem (-1);
  327. }
  328. // private slot
  329. void kpMainWindow::slotScan ()
  330. {
  331. #if DEBUG_KP_MAIN_WINDOW
  332. kdDebug () << "kpMainWindow::slotScan() scanDialog=" << m_scanDialog << endl;
  333. #endif
  334. if (toolHasBegunShape ())
  335. tool ()->endShapeInternal ();
  336. if (!m_scanDialog)
  337. {
  338. // Create scan dialog by looking for plugin.
  339. // [takes about 500ms on 350Mhz]
  340. m_scanDialog = KScanDialog::getScanDialog (this, "scandialog", true/*modal*/);
  341. // No scanning support (tdegraphics/libkscan) installed?
  342. // [Remove $TDEDIR/share/servicetypes/kscan.desktop and
  343. // $TDEDIR/share/services/scanservice.desktop to simulate this]
  344. if (!m_scanDialog)
  345. {
  346. #if DEBUG_KP_MAIN_WINDOW
  347. kdDebug () << "\tcould not create scan dialog" << endl;
  348. #endif
  349. // Instead, we could try to create the scan dialog in the ctor
  350. // and just disable the action in the first place, removing
  351. // the need for this dialog.
  352. //
  353. // But this increases startup time and is a bit risky e.g. if
  354. // the scan support hangs, KolourPaint would not be able to be
  355. // started at all.
  356. //
  357. // Also, disabling the action is bad because the scan support
  358. // can be installed while KolourPaint is still running.
  359. KMessageBox::sorry (this,
  360. i18n ("Scanning support is not installed."),
  361. i18n ("No Scanning Support"));
  362. return;
  363. }
  364. #if DEBUG_KP_MAIN_WINDOW
  365. kdDebug () << "\tcreated scanDialog=" << m_scanDialog << endl;
  366. #endif
  367. connect (m_scanDialog, TQT_SIGNAL (finalImage (const TQImage &, int)),
  368. TQT_SLOT (slotScanned (const TQImage &, int)));
  369. }
  370. #if DEBUG_KP_MAIN_WINDOW
  371. kdDebug () << "\tcalling setup" << endl;
  372. #endif
  373. // Bring up dialog to select scan device.
  374. if (m_scanDialog->setup ())
  375. {
  376. #if DEBUG_KP_MAIN_WINDOW
  377. kdDebug () << "\t\tOK - showing dialog" << endl;
  378. #endif
  379. // Called only if scanner configured/available.
  380. //
  381. // In reality, this seems to be called even if you press "Cancel" in
  382. // the KScanDialog::setup() dialog!
  383. m_scanDialog->show ();
  384. }
  385. else
  386. {
  387. // Have never seen this code path execute even if "Cancel" is pressed.
  388. #if DEBUG_KP_MAIN_WINDOW
  389. kdDebug () << "\t\tFAIL" << endl;
  390. #endif
  391. }
  392. }
  393. // private slot
  394. void kpMainWindow::slotScanned (const TQImage &image, int)
  395. {
  396. #if DEBUG_KP_MAIN_WINDOW
  397. kdDebug () << "kpMainWindow::slotScanned() image.rect=" << image.rect () << endl;
  398. #endif
  399. #if DEBUG_KP_MAIN_WINDOW
  400. kdDebug () << "\thiding dialog" << endl;
  401. #endif
  402. // (KScanDialog does not close itself after a scan is made)
  403. //
  404. // Close the dialog, first thing:
  405. //
  406. // 1. This means that any dialogs we bring up won't be nested on top.
  407. //
  408. // 2. We don't want to return from this method but forget to close
  409. // the dialog. So do it before anything else.
  410. m_scanDialog->hide ();
  411. // (just in case there's some drawing between slotScan() exiting and
  412. // us being called)
  413. if (toolHasBegunShape ())
  414. tool ()->endShapeInternal ();
  415. // TODO: Maybe this code should be moved into kpdocument.cpp -
  416. // since it resembles the responsibilities of kpDocument::open().
  417. // Convert TQImage to kpDocument's image format, gathering meta info
  418. // from TQImage.
  419. kpDocumentSaveOptions saveOptions;
  420. kpDocumentMetaInfo metaInfo;
  421. const TQPixmap pixmap = kpDocument::convertToPixmapAsLosslessAsPossible (
  422. image,
  423. kpMainWindow::pasteWarnAboutLossInfo (),
  424. &saveOptions,
  425. &metaInfo);
  426. if (pixmap.isNull ())
  427. {
  428. #if DEBUG_KP_MAIN_WINDOW
  429. kdDebug () << "\tcould not convert to pixmap" << endl;
  430. #endif
  431. KMessageBox::sorry (this,
  432. i18n ("Cannot scan - out of graphics memory."),
  433. i18n ("Cannot Scan"));
  434. return;
  435. }
  436. // Create document from image and meta info.
  437. kpDocument *doc = new kpDocument (pixmap.width (), pixmap.height (), this);
  438. doc->setPixmap (pixmap);
  439. doc->setSaveOptions (saveOptions);
  440. doc->setMetaInfo (metaInfo);
  441. // Send document to current or new window.
  442. setDocumentChoosingWindow (doc);
  443. }
  444. // private slot
  445. bool kpMainWindow::save (bool localOnly)
  446. {
  447. if (m_document->url ().isEmpty () ||
  448. KImageIO::mimeTypes (KImageIO::Writing)
  449. .findIndex (m_document->saveOptions ()->mimeType ()) < 0 ||
  450. // SYNC: kpDocument::getPixmapFromFile() can't determine quality
  451. // from file so it has been set initially to an invalid value.
  452. (m_document->saveOptions ()->mimeTypeHasConfigurableQuality () &&
  453. m_document->saveOptions ()->qualityIsInvalid ()) ||
  454. (localOnly && !m_document->url ().isLocalFile ()))
  455. {
  456. return saveAs (localOnly);
  457. }
  458. else
  459. {
  460. if (m_document->save (false/*no overwrite prompt*/,
  461. !m_document->savedAtLeastOnceBefore ()/*lossy prompt*/))
  462. {
  463. addRecentURL (m_document->url ());
  464. return true;
  465. }
  466. else
  467. return false;
  468. }
  469. }
  470. // private slot
  471. bool kpMainWindow::slotSave ()
  472. {
  473. if (toolHasBegunShape ())
  474. tool ()->endShapeInternal ();
  475. return save ();
  476. }
  477. // private
  478. KURL kpMainWindow::askForSaveURL (const TQString &caption,
  479. const TQString &startURL,
  480. const TQPixmap &pixmapToBeSaved,
  481. const kpDocumentSaveOptions &startSaveOptions,
  482. const kpDocumentMetaInfo &docMetaInfo,
  483. const TQString &forcedSaveOptionsGroup,
  484. bool localOnly,
  485. kpDocumentSaveOptions *chosenSaveOptions,
  486. bool isSavingForFirstTime,
  487. bool *allowOverwritePrompt,
  488. bool *allowLossyPrompt)
  489. {
  490. #if DEBUG_KP_MAIN_WINDOW
  491. kdDebug () << "kpMainWindow::askForURL() startURL=" << startURL << endl;
  492. startSaveOptions.printDebug ("\tstartSaveOptions");
  493. #endif
  494. bool reparsedConfiguration = false;
  495. // TDEConfig::readEntry() does not actually reread from disk, hence doesn't
  496. // realise what other processes have done e.g. Settings / Show Path
  497. // so reparseConfiguration() must be called
  498. #define SETUP_READ_CFG() \
  499. if (!reparsedConfiguration) \
  500. { \
  501. kapp->config ()->reparseConfiguration (); \
  502. reparsedConfiguration = true; \
  503. } \
  504. \
  505. TDEConfigGroupSaver cfgGroupSaver (kapp->config (), forcedSaveOptionsGroup); \
  506. TDEConfigBase *cfg = cfgGroupSaver.config ();
  507. if (chosenSaveOptions)
  508. *chosenSaveOptions = kpDocumentSaveOptions ();
  509. if (allowOverwritePrompt)
  510. *allowOverwritePrompt = true; // play it safe for now
  511. if (allowLossyPrompt)
  512. *allowLossyPrompt = true; // play it safe for now
  513. kpDocumentSaveOptions fdSaveOptions = startSaveOptions;
  514. TQStringList mimeTypes = KImageIO::mimeTypes (KImageIO::Writing);
  515. #if DEBUG_KP_MAIN_WINDOW
  516. TQStringList sortedMimeTypes = mimeTypes;
  517. sortedMimeTypes.sort ();
  518. kdDebug () << "\tmimeTypes=" << mimeTypes << endl
  519. << "\tsortedMimeTypes=" << sortedMimeTypes << endl;
  520. #endif
  521. if (mimeTypes.isEmpty ())
  522. {
  523. kdError () << "No KImageIO output mimetypes!" << endl;
  524. return KURL ();
  525. }
  526. #define MIME_TYPE_IS_VALID() (!fdSaveOptions.mimeTypeIsInvalid () && \
  527. mimeTypes.findIndex (fdSaveOptions.mimeType ()) >= 0)
  528. if (!MIME_TYPE_IS_VALID ())
  529. {
  530. #if DEBUG_KP_MAIN_WINDOW
  531. kdDebug () << "\tmimeType=" << fdSaveOptions.mimeType ()
  532. << " not valid, get default" << endl;
  533. #endif
  534. SETUP_READ_CFG ();
  535. fdSaveOptions.setMimeType (kpDocumentSaveOptions::defaultMimeType (cfg));
  536. if (!MIME_TYPE_IS_VALID ())
  537. {
  538. #if DEBUG_KP_MAIN_WINDOW
  539. kdDebug () << "\tmimeType=" << fdSaveOptions.mimeType ()
  540. << " not valid, get hardcoded" << endl;
  541. #endif
  542. if (mimeTypes.findIndex ("image/png") > -1)
  543. fdSaveOptions.setMimeType ("image/png");
  544. else if (mimeTypes.findIndex ("image/x-bmp") > -1)
  545. fdSaveOptions.setMimeType ("image/x-bmp");
  546. else
  547. fdSaveOptions.setMimeType (mimeTypes.first ());
  548. }
  549. }
  550. #undef MIME_TYPE_IN_LIST
  551. if (fdSaveOptions.colorDepthIsInvalid ())
  552. {
  553. SETUP_READ_CFG ();
  554. fdSaveOptions.setColorDepth (kpDocumentSaveOptions::defaultColorDepth (cfg));
  555. fdSaveOptions.setDither (kpDocumentSaveOptions::defaultDither (cfg));
  556. }
  557. if (fdSaveOptions.qualityIsInvalid ())
  558. {
  559. SETUP_READ_CFG ();
  560. fdSaveOptions.setQuality (kpDocumentSaveOptions::defaultQuality (cfg));
  561. }
  562. #if DEBUG_KP_MAIN_WINDOW
  563. fdSaveOptions.printDebug ("\tcorrected saveOptions passed to fileDialog");
  564. #endif
  565. kpDocumentSaveOptionsWidget *saveOptionsWidget =
  566. new kpDocumentSaveOptionsWidget (pixmapToBeSaved,
  567. fdSaveOptions,
  568. docMetaInfo,
  569. this);
  570. KFileDialog fd (startURL, TQString(), this, "fd", true/*modal*/,
  571. saveOptionsWidget);
  572. saveOptionsWidget->setVisualParent (&fd);
  573. fd.setCaption (caption);
  574. fd.setOperationMode (KFileDialog::Saving);
  575. #if DEBUG_KP_MAIN_WINDOW
  576. kdDebug () << "\tmimeTypes=" << mimeTypes << endl;
  577. #endif
  578. fd.setMimeFilter (mimeTypes, fdSaveOptions.mimeType ());
  579. if (localOnly)
  580. fd.setMode (KFile::File | KFile::LocalOnly);
  581. connect (&fd, TQT_SIGNAL (filterChanged (const TQString &)),
  582. saveOptionsWidget, TQT_SLOT (setMimeType (const TQString &)));
  583. if (fd.exec ())
  584. {
  585. kpDocumentSaveOptions newSaveOptions = saveOptionsWidget->documentSaveOptions ();
  586. #if DEBUG_KP_MAIN_WINDOW
  587. newSaveOptions.printDebug ("\tnewSaveOptions");
  588. #endif
  589. TDEConfigGroupSaver cfgGroupSaver (kapp->config (), forcedSaveOptionsGroup);
  590. TDEConfigBase *cfg = cfgGroupSaver.config ();
  591. // Save options user forced - probably want to use them in future
  592. kpDocumentSaveOptions::saveDefaultDifferences (cfg,
  593. fdSaveOptions, newSaveOptions);
  594. cfg->sync ();
  595. if (chosenSaveOptions)
  596. *chosenSaveOptions = newSaveOptions;
  597. bool shouldAllowOverwritePrompt =
  598. (fd.selectedURL () != startURL ||
  599. newSaveOptions.mimeType () != startSaveOptions.mimeType ());
  600. if (allowOverwritePrompt)
  601. {
  602. *allowOverwritePrompt = shouldAllowOverwritePrompt;
  603. #if DEBUG_KP_MAIN_WINDOW
  604. kdDebug () << "\tallowOverwritePrompt=" << *allowOverwritePrompt << endl;
  605. #endif
  606. }
  607. if (allowLossyPrompt)
  608. {
  609. // SYNC: kpDocumentSaveOptions elements - everything except quality
  610. // (one quality setting is "just as lossy" as another so no
  611. // need to continually warn due to quality change)
  612. *allowLossyPrompt =
  613. (isSavingForFirstTime ||
  614. shouldAllowOverwritePrompt ||
  615. newSaveOptions.mimeType () != startSaveOptions.mimeType () ||
  616. newSaveOptions.colorDepth () != startSaveOptions.colorDepth () ||
  617. newSaveOptions.dither () != startSaveOptions.dither ());
  618. #if DEBUG_KP_MAIN_WINDOW
  619. kdDebug () << "\tallowLossyPrompt=" << *allowLossyPrompt << endl;
  620. #endif
  621. }
  622. #if DEBUG_KP_MAIN_WINDOW
  623. kdDebug () << "\tselectedURL=" << fd.selectedURL () << endl;
  624. #endif
  625. return fd.selectedURL ();
  626. }
  627. else
  628. return KURL ();
  629. #undef SETUP_READ_CFG
  630. }
  631. // private slot
  632. bool kpMainWindow::saveAs (bool localOnly)
  633. {
  634. #if DEBUG_KP_MAIN_WINDOW
  635. kdDebug () << "kpMainWindow::saveAs URL=" << m_document->url () << endl;
  636. #endif
  637. kpDocumentSaveOptions chosenSaveOptions;
  638. bool allowOverwritePrompt, allowLossyPrompt;
  639. KURL chosenURL = askForSaveURL (i18n ("Save Image As"),
  640. m_document->url ().url (),
  641. m_document->pixmapWithSelection (),
  642. *m_document->saveOptions (),
  643. *m_document->metaInfo (),
  644. kpSettingsGroupFileSaveAs,
  645. localOnly,
  646. &chosenSaveOptions,
  647. !m_document->savedAtLeastOnceBefore (),
  648. &allowOverwritePrompt,
  649. &allowLossyPrompt);
  650. if (chosenURL.isEmpty ())
  651. return false;
  652. if (!m_document->saveAs (chosenURL, chosenSaveOptions,
  653. allowOverwritePrompt,
  654. allowLossyPrompt))
  655. {
  656. return false;
  657. }
  658. addRecentURL (chosenURL);
  659. return true;
  660. }
  661. // private slot
  662. bool kpMainWindow::slotSaveAs ()
  663. {
  664. if (toolHasBegunShape ())
  665. tool ()->endShapeInternal ();
  666. return saveAs ();
  667. }
  668. // private slot
  669. bool kpMainWindow::slotExport ()
  670. {
  671. #if DEBUG_KP_MAIN_WINDOW
  672. kdDebug () << "kpMainWindow::slotExport()" << endl;
  673. #endif
  674. if (toolHasBegunShape ())
  675. tool ()->endShapeInternal ();
  676. kpDocumentSaveOptions chosenSaveOptions;
  677. bool allowOverwritePrompt, allowLossyPrompt;
  678. KURL chosenURL = askForSaveURL (i18n ("Export"),
  679. m_lastExportURL.url (),
  680. m_document->pixmapWithSelection (),
  681. m_lastExportSaveOptions,
  682. *m_document->metaInfo (),
  683. kpSettingsGroupFileExport,
  684. false/*allow remote files*/,
  685. &chosenSaveOptions,
  686. m_exportFirstTime,
  687. &allowOverwritePrompt,
  688. &allowLossyPrompt);
  689. if (chosenURL.isEmpty ())
  690. return false;
  691. if (!kpDocument::savePixmapToFile (m_document->pixmapWithSelection (),
  692. chosenURL,
  693. chosenSaveOptions, *m_document->metaInfo (),
  694. allowOverwritePrompt,
  695. allowLossyPrompt,
  696. this))
  697. {
  698. return false;
  699. }
  700. addRecentURL (chosenURL);
  701. m_lastExportURL = chosenURL;
  702. m_lastExportSaveOptions = chosenSaveOptions;
  703. m_exportFirstTime = false;
  704. return true;
  705. }
  706. // private slot
  707. void kpMainWindow::slotEnableReload ()
  708. {
  709. m_actionReload->setEnabled (m_document);
  710. }
  711. // private slot
  712. bool kpMainWindow::slotReload ()
  713. {
  714. if (toolHasBegunShape ())
  715. tool ()->endShapeInternal ();
  716. if (!m_document)
  717. return false;
  718. KURL oldURL = m_document->url ();
  719. if (m_document->isModified ())
  720. {
  721. int result = KMessageBox::Cancel;
  722. if (m_document->isFromURL (false/*don't bother checking exists*/) && !oldURL.isEmpty ())
  723. {
  724. result = KMessageBox::warningContinueCancel (this,
  725. i18n ("The document \"%1\" has been modified.\n"
  726. "Reloading will lose all changes since you last saved it.\n"
  727. "Are you sure?")
  728. .arg (m_document->prettyFilename ()),
  729. TQString()/*caption*/,
  730. i18n ("&Reload"));
  731. }
  732. else
  733. {
  734. result = KMessageBox::warningContinueCancel (this,
  735. i18n ("The document \"%1\" has been modified.\n"
  736. "Reloading will lose all changes.\n"
  737. "Are you sure?")
  738. .arg (m_document->prettyFilename ()),
  739. TQString()/*caption*/,
  740. i18n ("&Reload"));
  741. }
  742. if (result != KMessageBox::Continue)
  743. return false;
  744. }
  745. kpDocument *doc = 0;
  746. // If it's _supposed to_ come from a URL or it exists
  747. if (m_document->isFromURL (false/*don't bother checking exists*/) ||
  748. (!oldURL.isEmpty () && TDEIO::NetAccess::exists (oldURL, true/*open*/, this)))
  749. {
  750. #if DEBUG_KP_MAIN_WINDOW
  751. kdDebug () << "kpMainWindow::slotReload() reloading from disk!" << endl;
  752. #endif
  753. doc = new kpDocument (1, 1, this);
  754. if (!doc->open (oldURL))
  755. {
  756. delete doc; doc = 0;
  757. return false;
  758. }
  759. addRecentURL (oldURL);
  760. }
  761. else
  762. {
  763. #if DEBUG_KP_MAIN_WINDOW
  764. kdDebug () << "kpMainWindow::slotReload() create doc" << endl;
  765. #endif
  766. doc = new kpDocument (m_document->constructorWidth (),
  767. m_document->constructorHeight (),
  768. this);
  769. doc->setURL (oldURL, false/*not from URL*/);
  770. }
  771. setDocument (doc);
  772. return true;
  773. }
  774. // private
  775. void kpMainWindow::sendFilenameToPrinter (KPrinter *printer)
  776. {
  777. KURL url = m_document->url ();
  778. if (!url.isEmpty ())
  779. {
  780. int dot;
  781. TQString fileName = url.fileName ();
  782. dot = fileName.findRev ('.');
  783. // file.ext but not .hidden-file?
  784. if (dot > 0)
  785. fileName.truncate (dot);
  786. #if DEBUG_KP_MAIN_WINDOW
  787. kdDebug () << "kpMainWindow::sendFilenameToPrinter() fileName="
  788. << fileName
  789. << " dir="
  790. << url.directory ()
  791. << endl;
  792. #endif
  793. printer->setDocName (fileName);
  794. printer->setDocFileName (fileName);
  795. printer->setDocDirectory (url.directory ());
  796. }
  797. }
  798. static const double InchesPerMeter = 100 / 2.54;
  799. // TODO: GUI should allow viewing & changing of DPI.
  800. static bool shouldPrintImageCenteredOnPage ()
  801. {
  802. #if DEBUG_KP_MAIN_WINDOW
  803. kdDebug () << "kpmainwindow_file.cpp:shouldPrintImageCenteredOnPage()" << endl;
  804. #endif
  805. bool ret;
  806. TDEConfigGroupSaver cfgGroupSaver (TDEGlobal::config (),
  807. kpSettingsGroupGeneral);
  808. TDEConfigBase *cfg = cfgGroupSaver.config ();
  809. if (cfg->hasKey (kpSettingPrintImageCenteredOnPage))
  810. {
  811. ret = cfg->readBoolEntry (kpSettingPrintImageCenteredOnPage);
  812. #if DEBUG_KP_MAIN_WINDOW
  813. kdDebug () << "\tread: " << ret << endl;
  814. #endif
  815. }
  816. else
  817. {
  818. ret = true;
  819. #if DEBUG_KP_MAIN_WINDOW
  820. kdDebug () << "\tfirst time - writing default: " << ret << endl;
  821. #endif
  822. cfg->writeEntry (kpSettingPrintImageCenteredOnPage, ret);
  823. cfg->sync ();
  824. }
  825. return ret;
  826. }
  827. // private
  828. void kpMainWindow::sendPixmapToPrinter (KPrinter *printer,
  829. bool showPrinterSetupDialog)
  830. {
  831. // Get image to be printed.
  832. TQPixmap pixmap = m_document->pixmapWithSelection ();
  833. // Get image DPI.
  834. double pixmapDotsPerMeterX =
  835. double (m_document->metaInfo ()->dotsPerMeterX ());
  836. double pixmapDotsPerMeterY =
  837. double (m_document->metaInfo ()->dotsPerMeterY ());
  838. #if DEBUG_KP_MAIN_WINDOW
  839. kdDebug () << "kpMainWindow::sendPixmapToPrinter() pixmap:"
  840. << " width=" << pixmap.width ()
  841. << " height=" << pixmap.height ()
  842. << " dotsPerMeterX=" << pixmapDotsPerMeterX
  843. << " dotsPerMeterY=" << pixmapDotsPerMeterY
  844. << endl;
  845. #endif
  846. // Image DPI invalid (e.g. new image, could not read from file
  847. // or TQt3 doesn't implement DPI for JPEG)?
  848. if (pixmapDotsPerMeterX < 1 || pixmapDotsPerMeterY < 1)
  849. {
  850. // Even if just one DPI dimension is invalid, mutate both DPI
  851. // dimensions as we have no information about the intended
  852. // aspect ratio anyway (and other dimension likely to be invalid).
  853. // When rendering text onto a document, the fonts are rasterised
  854. // according to the screen's DPI.
  855. // TODO: I think we should use the image's DPI. Technically
  856. // possible?
  857. //
  858. // So no matter what computer you draw text on, you get
  859. // the same pixels.
  860. //
  861. // So we must print at the screen's DPI to get the right text size.
  862. //
  863. // Unfortunately, this means that moving to a different screen DPI
  864. // affects printing. If you edited the image at a different screen
  865. // DPI than when you print, you get incorrect results. Furthermore,
  866. // this is bogus if you don't have text in your image. Worse still,
  867. // what if you have multiple screens connected to the same computer
  868. // with different DPIs?
  869. // TODO: mysteriously, someone else is setting this to 96dpi always.
  870. TQPaintDeviceMetrics screenMetrics (&pixmap/*screen element*/);
  871. const int dpiX = screenMetrics.logicalDpiX (),
  872. dpiY = screenMetrics.logicalDpiY ();
  873. #if DEBUG_KP_MAIN_WINDOW
  874. kdDebug () << "\tusing screen dpi: x=" << dpiX << " y=" << dpiY << endl;
  875. #endif
  876. pixmapDotsPerMeterX = dpiX * InchesPerMeter;
  877. pixmapDotsPerMeterY = dpiY * InchesPerMeter;
  878. }
  879. // Get page size (excluding margins).
  880. // Coordinate (0,0) is the X here:
  881. // mmmmm
  882. // mX m
  883. // m m m = margin
  884. // m m
  885. // mmmmm
  886. TQPaintDeviceMetrics printerMetrics (printer);
  887. const int printerWidthMM = printerMetrics.widthMM ();
  888. const int printerHeightMM = printerMetrics.heightMM ();
  889. #if DEBUG_KP_MAIN_WINDOW
  890. kdDebug () << "\tprinter: widthMM=" << printerWidthMM
  891. << " heightMM=" << printerHeightMM
  892. << endl;
  893. #endif
  894. double dpiX = pixmapDotsPerMeterX / InchesPerMeter;
  895. double dpiY = pixmapDotsPerMeterY / InchesPerMeter;
  896. #if DEBUG_KP_MAIN_WINDOW
  897. kdDebug () << "\tpixmap: dpiX=" << dpiX << " dpiY=" << dpiY << endl;
  898. #endif
  899. //
  900. // If image doesn't fit on page at intended DPI, change the DPI.
  901. //
  902. const double scaleDpiX = (pixmap.width () / (printerWidthMM / 25.4))
  903. / dpiX;
  904. const double scaleDpiY = (pixmap.height () / (printerHeightMM / 25.4))
  905. / dpiY;
  906. const double scaleDpi = TQMAX (scaleDpiX, scaleDpiY);
  907. #if DEBUG_KP_MAIN_WINDOW
  908. kdDebug () << "\t\tscaleDpi: x=" << scaleDpiX << " y=" << scaleDpiY
  909. << " --> scale at " << scaleDpi << " to fit?"
  910. << endl;
  911. #endif
  912. // Need to increase resolution to fit page?
  913. if (scaleDpi > 1.0)
  914. {
  915. dpiX *= scaleDpi;
  916. dpiY *= scaleDpi;
  917. #if DEBUG_KP_MAIN_WINDOW
  918. kdDebug () << "\t\t\tto fit page, scaled to:"
  919. << " dpiX=" << dpiX << " dpiY=" << dpiY << endl;
  920. #endif
  921. }
  922. // Make sure DPIs are equal as that's all TQPrinter::setResolution()
  923. // supports. We do this in such a way that we only ever stretch an
  924. // image, to avoid losing information. Don't antialias as the printer
  925. // will do that to translate our DPI to its physical resolution and
  926. // double-antialiasing looks bad.
  927. if (dpiX > dpiY)
  928. {
  929. #if DEBUG_KP_MAIN_WINDOW
  930. kdDebug () << "\tdpiX > dpiY; stretching pixmap height to equalise DPIs to dpiX="
  931. << dpiX << endl;
  932. #endif
  933. kpPixmapFX::scale (&pixmap,
  934. pixmap.width (),
  935. TQMAX (1, tqRound (pixmap.height () * dpiX / dpiY)),
  936. false/*don't antialias*/);
  937. dpiY = dpiX;
  938. }
  939. else if (dpiY > dpiX)
  940. {
  941. #if DEBUG_KP_MAIN_WINDOW
  942. kdDebug () << "\tdpiY > dpiX; stretching pixmap width to equalise DPIs to dpiY="
  943. << dpiY << endl;
  944. #endif
  945. kpPixmapFX::scale (&pixmap,
  946. TQMAX (1, tqRound (pixmap.width () * dpiY / dpiX)),
  947. pixmap.height (),
  948. false/*don't antialias*/);
  949. dpiX = dpiY;
  950. }
  951. // ASSERT: dpiX == dpiY
  952. // TQPrinter::setResolution() has to be called before TQPrinter::setup().
  953. printer->setResolution (TQMAX (1, tqRound (dpiX)));
  954. double originX = 0, originY = 0;
  955. // Centre image on page?
  956. if (shouldPrintImageCenteredOnPage ())
  957. {
  958. originX = (printerWidthMM * dpiX / 25.4 - pixmap.width ()) / 2;
  959. originY = (printerHeightMM * dpiY / 25.4 - pixmap.height ()) / 2;
  960. }
  961. #if DEBUG_KP_MAIN_WINDOW
  962. kdDebug () << "\torigin: x=" << originX << " y=" << originY << endl;
  963. #endif
  964. sendFilenameToPrinter (printer);
  965. if (showPrinterSetupDialog)
  966. {
  967. // The user can mutate margins at their own risk in this dialog.
  968. // It doesn't seem to affect the size of the page as reported
  969. // by TQPaintDeviceMetrics::{width,height}MM().
  970. if (!printer->setup (this))
  971. return;
  972. }
  973. // Send pixmap to printer.
  974. TQPainter painter;
  975. painter.begin (printer);
  976. painter.drawPixmap (tqRound (originX), tqRound (originY), pixmap);
  977. painter.end ();
  978. }
  979. // private slot
  980. void kpMainWindow::slotPrint ()
  981. {
  982. if (toolHasBegunShape ())
  983. tool ()->endShapeInternal ();
  984. KPrinter printer;
  985. sendPixmapToPrinter (&printer, true/*showPrinterSetupDialog*/);
  986. }
  987. // private slot
  988. void kpMainWindow::slotPrintPreview ()
  989. {
  990. if (toolHasBegunShape ())
  991. tool ()->endShapeInternal ();
  992. // TODO: get it to reflect default printer's settings
  993. KPrinter printer (false/*separate settings from ordinary printer*/);
  994. // TODO: pass "this" as parent
  995. printer.setPreviewOnly (true);
  996. sendPixmapToPrinter (&printer, false/*don't showPrinterSetupDialog*/);
  997. }
  998. // private slot
  999. void kpMainWindow::slotMail ()
  1000. {
  1001. if (toolHasBegunShape ())
  1002. tool ()->endShapeInternal ();
  1003. if (m_document->url ().isEmpty ()/*no name*/ ||
  1004. !m_document->isFromURL () ||
  1005. m_document->isModified ()/*needs to be saved*/)
  1006. {
  1007. int result = KMessageBox::questionYesNo (this,
  1008. i18n ("You must save this image before sending it.\n"
  1009. "Do you want to save it?"),
  1010. TQString(),
  1011. KStdGuiItem::save (), KStdGuiItem::cancel ());
  1012. if (result == KMessageBox::Yes)
  1013. {
  1014. if (!save ())
  1015. {
  1016. // save failed or aborted - don't email
  1017. return;
  1018. }
  1019. }
  1020. else
  1021. {
  1022. // don't want to save - don't email
  1023. return;
  1024. }
  1025. }
  1026. kapp->invokeMailer (
  1027. TQString()/*to*/,
  1028. TQString()/*cc*/,
  1029. TQString()/*bcc*/,
  1030. m_document->prettyFilename()/*subject*/,
  1031. TQString()/*body*/,
  1032. TQString()/*messageFile*/,
  1033. TQStringList (m_document->url ().url ())/*attachments*/);
  1034. }
  1035. // private
  1036. void kpMainWindow::setAsWallpaper (bool centered)
  1037. {
  1038. if (m_document->url ().isEmpty ()/*no name*/ ||
  1039. !m_document->url ().isLocalFile ()/*remote file*/ ||
  1040. !m_document->isFromURL () ||
  1041. m_document->isModified ()/*needs to be saved*/)
  1042. {
  1043. TQString question;
  1044. if (!m_document->url ().isLocalFile ())
  1045. {
  1046. question = i18n ("Before this image can be set as the wallpaper, "
  1047. "you must save it as a local file.\n"
  1048. "Do you want to save it?");
  1049. }
  1050. else
  1051. {
  1052. question = i18n ("Before this image can be set as the wallpaper, "
  1053. "you must save it.\n"
  1054. "Do you want to save it?");
  1055. }
  1056. int result = KMessageBox::questionYesNo (this,
  1057. question, TQString(),
  1058. KStdGuiItem::save (), KStdGuiItem::cancel ());
  1059. if (result == KMessageBox::Yes)
  1060. {
  1061. // save() is smart enough to pop up a filedialog if it's a
  1062. // remote file that should be saved locally
  1063. if (!save (true/*localOnly*/))
  1064. {
  1065. // save failed or aborted - don't set the wallpaper
  1066. return;
  1067. }
  1068. }
  1069. else
  1070. {
  1071. // don't want to save - don't set wallpaper
  1072. return;
  1073. }
  1074. }
  1075. TQByteArray data;
  1076. TQDataStream dataStream (data, IO_WriteOnly);
  1077. // write path
  1078. #if DEBUG_KP_MAIN_WINDOW
  1079. kdDebug () << "kpMainWindow::setAsWallpaper() path="
  1080. << m_document->url ().path () << endl;
  1081. #endif
  1082. dataStream << TQString (m_document->url ().path ());
  1083. // write position:
  1084. //
  1085. // SYNC: tdebase/kcontrol/background/bgsettings.h:
  1086. // 1 = Centered
  1087. // 2 = Tiled
  1088. // 6 = Scaled
  1089. // 9 = lastWallpaperMode
  1090. //
  1091. // Why restrict the user to Centered & Tiled?
  1092. // Why don't we let the user choose if it should be common to all desktops?
  1093. // Why don't we rewrite the Background control page?
  1094. //
  1095. // Answer: This is supposed to be a quick & convenient feature.
  1096. //
  1097. // If you want more options, go to kcontrol for that kind of
  1098. // flexiblity. We don't want to slow down average users, who see way too
  1099. // many dialogs already and probably haven't even heard of "Centered Maxpect"...
  1100. //
  1101. dataStream << int (centered ? 1 : 2);
  1102. // I'm going to all this trouble because the user might not have tdebase
  1103. // installed so tdebase/kdesktop/KBackgroundIface.h might not be around
  1104. // to be compiled in (where user == developer :))
  1105. if (!TDEApplication::dcopClient ()->send ("kdesktop", "KBackgroundIface",
  1106. "setWallpaper(TQString,int)", data))
  1107. {
  1108. KMessageBox::sorry (this, i18n ("Could not change wallpaper."));
  1109. }
  1110. }
  1111. // private slot
  1112. void kpMainWindow::slotSetAsWallpaperCentered ()
  1113. {
  1114. if (toolHasBegunShape ())
  1115. tool ()->endShapeInternal ();
  1116. setAsWallpaper (true/*centered*/);
  1117. }
  1118. // private slot
  1119. void kpMainWindow::slotSetAsWallpaperTiled ()
  1120. {
  1121. if (toolHasBegunShape ())
  1122. tool ()->endShapeInternal ();
  1123. setAsWallpaper (false/*tiled*/);
  1124. }
  1125. // private slot
  1126. void kpMainWindow::slotClose ()
  1127. {
  1128. if (toolHasBegunShape ())
  1129. tool ()->endShapeInternal ();
  1130. #if DEBUG_KP_MAIN_WINDOW
  1131. kdDebug () << "kpMainWindow::slotClose()" << endl;
  1132. #endif
  1133. if (!queryClose ())
  1134. return;
  1135. setDocument (0);
  1136. }
  1137. // private slot
  1138. void kpMainWindow::slotQuit ()
  1139. {
  1140. if (toolHasBegunShape ())
  1141. tool ()->endShapeInternal ();
  1142. #if DEBUG_KP_MAIN_WINDOW
  1143. kdDebug () << "kpMainWindow::slotQuit()" << endl;
  1144. #endif
  1145. close (); // will call queryClose()
  1146. }