PrintPreview.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065
  1. /**
  2. * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
  3. *
  4. * This file is part of the QCAD project.
  5. *
  6. * QCAD is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * QCAD is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with QCAD.
  18. */
  19. include("scripts/Edit/DrawingPreferences/PageSettings/PageSettings.js");
  20. include("scripts/File/File.js");
  21. include("scripts/File/NewFile/NewFile.js");
  22. include("scripts/File/Print/Print.js");
  23. include("scripts/sprintf.js");
  24. /**
  25. * Switches the current document to print preview mode.
  26. * In print preview mode, the paper is shown in the background of
  27. * the drawing.
  28. */
  29. function PrintPreview(guiAction) {
  30. EAction.call(this, guiAction);
  31. }
  32. PrintPreview.prototype = new EAction();
  33. PrintPreview.includeBasePath = includeBasePath;
  34. PrintPreview.instance = undefined;
  35. PrintPreview.getInstance = function() {
  36. return PrintPreview.instance;
  37. };
  38. PrintPreview.isRunning = function() {
  39. var di = EAction.getDocumentInterface();
  40. if (isNull(di)) {
  41. return false;
  42. }
  43. var a = di.getDefaultAction();
  44. var ga = a.getGuiAction();
  45. if (isNull(ga)) {
  46. return true;
  47. }
  48. else {
  49. return false;
  50. }
  51. };
  52. /**
  53. * Starts the print preview.
  54. */
  55. PrintPreview.start = function(initialAction, instance) {
  56. var appWin = RMainWindowQt.getMainWindow();
  57. // appWin.enabled = false;
  58. var di = EAction.getDocumentInterface();
  59. var doc = di.getDocument();
  60. var a = di.getDefaultAction();
  61. a.finishEvent();
  62. if (isNull(instance)) {
  63. PrintPreview.instance = new PrintPreviewImpl();
  64. }
  65. else {
  66. PrintPreview.instance = instance;
  67. }
  68. if (!isNull(initialAction)) {
  69. PrintPreview.instance.initialAction = initialAction;
  70. }
  71. // auto setup:
  72. var buttons = makeQMessageBoxStandardButtons(QMessageBox.Yes, QMessageBox.No);
  73. var paperSizeMM = Print.getPaperSizeMM(doc);
  74. var paperSizeName = Print.getPaperSizeNameFromSize(paperSizeMM);
  75. var paperSizeAccepted = doc.getVariable("PageSettings/PaperSizeAccepted");
  76. if (paperSizeName==="" && paperSizeAccepted!==true) {
  77. // custom paper size:
  78. // ask user to adjust to default paper size:
  79. var defaultPaperSizeName = Print.getDefaultPaperSizeName(doc);
  80. var ret = QMessageBox.warning(
  81. appWin,
  82. qsTr("Auto Paper Size"),
  83. qsTr("The paper size is set to a custom size (%1x%2mm). Do you want to change it to the default paper size of your printer (%3)?").arg(paperSizeMM.width()).arg(paperSizeMM.height()).arg(defaultPaperSizeName),
  84. buttons
  85. );
  86. if (ret===QMessageBox.Yes) {
  87. var paperUnit = Print.getPaperUnit(doc);
  88. var defPaperSize = Print.getDefaultPaperSizeMM();
  89. var w = RUnit.convert(defPaperSize.width(), RS.Millimeter, paperUnit);
  90. doc.setVariable("PageSettings/PaperWidth", w);
  91. var h = RUnit.convert(defPaperSize.height(), RS.Millimeter, paperUnit);
  92. doc.setVariable("PageSettings/PaperHeight", h);
  93. doc.setVariable("MultiPageSettings/Columns", 1);
  94. doc.setVariable("MultiPageSettings/Rows", 1);
  95. // 10mm margin:
  96. var m = RUnit.convert(10, RS.Millimeter, paperUnit);
  97. doc.setVariable("MultiPageSettings/GlueMarginsLeft", m);
  98. doc.setVariable("MultiPageSettings/GlueMarginsTop", m);
  99. doc.setVariable("MultiPageSettings/GlueMarginsRight", m);
  100. doc.setVariable("MultiPageSettings/GlueMarginsBottom", m);
  101. }
  102. else {
  103. // store information that paper size was accepted as is (don't show dialog again):
  104. doc.setVariable("PageSettings/PaperSizeAccepted", true);
  105. }
  106. }
  107. var bbPaper = Print.getPaperBox(doc);
  108. bbPaper.growXY(bbPaper.getWidth()/100, bbPaper.getHeight()/100);
  109. var bbDoc = doc.getBoundingBox();
  110. var positionAccepted = doc.getVariable("PageSettings/PositionAccepted");
  111. // check if paper contains drawing:
  112. if (!bbPaper.containsBox(bbDoc) && !positionAccepted) {
  113. var initialZoom = appWin.property("PrintPreview/InitialZoom");
  114. if (initialZoom!=="View") {
  115. var ret = QMessageBox.warning(appWin,
  116. qsTr("Auto fit"),
  117. qsTr("Auto fit drawing to paper?"),
  118. buttons);
  119. if (ret===QMessageBox.Yes) {
  120. appWin.setProperty("PrintPreview/InitialZoom", "Auto");
  121. }
  122. else {
  123. doc.setVariable("PageSettings/PositionAccepted", true);
  124. }
  125. }
  126. }
  127. di.setDefaultAction(PrintPreview.instance);
  128. var ga = RGuiAction.getByScriptFile("scripts/File/PrintPreview/PrintPreview.js")
  129. if (!isNull(ga)) {
  130. ga.setChecked(true);
  131. }
  132. //appWin.enabled = true;
  133. };
  134. /**
  135. * Exits the print preview.
  136. */
  137. PrintPreview.exit = function() {
  138. //var appWin = RMainWindowQt.getMainWindow();
  139. //appWin.enabled = false;
  140. var di = EAction.getDocumentInterface();
  141. var a = di.getDefaultAction();
  142. a.finishEvent();
  143. NewFile.setupDefaultAction(di);
  144. var ga = RGuiAction.getByScriptFile("scripts/File/PrintPreview/PrintPreview.js")
  145. if (!isNull(ga)) {
  146. ga.setChecked(false);
  147. }
  148. //appWin.enabled = true;
  149. };
  150. PrintPreview.prototype.beginEvent = function() {
  151. if (PrintPreview.isRunning()) {
  152. // exit print preview:
  153. PrintPreview.exit();
  154. }
  155. else {
  156. // start print preview:
  157. PrintPreview.start();
  158. }
  159. this.terminate();
  160. };
  161. /**
  162. * Implementation of interactive print preview action.
  163. * Intended to be used as default action.
  164. */
  165. function PrintPreviewImpl(guiAction) {
  166. // parent class can be DefaultAction or other configured
  167. // default action:
  168. var defaultActionClass = NewFile.getDefaultActionClass();
  169. this.parentClass = global[defaultActionClass];
  170. this.parentClass.call(this, guiAction);
  171. this.enableSlotPaperSizeChanged = false;
  172. this.setUiOptions(PrintPreviewImpl.includeBasePath + "/PrintPreview.ui");
  173. this.panningOffset = false;
  174. this.panOffsetOrigin = new RVector();
  175. this.updateDisabled = false;
  176. if (RSettings.getBoolValue("GraphicsView/SystemCursors", false)===true) {
  177. this.cursor = new QCursor(Qt.OpenHandCursor);
  178. }
  179. else {
  180. var bitmap = new QBitmap(PrintPreviewImpl.includeBasePath + "/PrintPreviewOffsetCursor.png", "PNG");
  181. var mask = new QBitmap(PrintPreviewImpl.includeBasePath + "/PrintPreviewOffsetCursorMask.png", "PNG");
  182. this.cursor = new QCursor(bitmap, mask, 15, 13);
  183. }
  184. this.view = undefined;
  185. this.saveView = false;
  186. this.savedScale = undefined;
  187. this.savedOffset = undefined;
  188. this.savedColumns = undefined;
  189. this.savedRows = undefined;
  190. this.optOutRelativeZeroResume = true;
  191. }
  192. PrintPreviewImpl.prototype = NewFile.getDefaultAction(false);
  193. PrintPreviewImpl.includeBasePath = includeBasePath;
  194. PrintPreviewImpl.State = {
  195. SettingOffset : 100
  196. };
  197. PrintPreviewImpl.prototype.beginEvent = function() {
  198. var di = this.getDocumentInterface();
  199. var appWin = RMainWindowQt.getMainWindow();
  200. var initialZoom = appWin.property("PrintPreview/InitialZoom");
  201. if (initialZoom==="View") {
  202. this.savedScale = Print.getScale(this.getDocument());
  203. this.savedOffset = Print.getOffset(this.getDocument());
  204. this.savedColumns = Print.getColumns(this.getDocument());
  205. this.savedRows = Print.getRows(this.getDocument());
  206. this.saveView = true;
  207. }
  208. // if (!isNull(this.guiAction)) {
  209. // this.guiAction.setChecked(true);
  210. // }
  211. // globals:
  212. //PrintPreview.setRunning(true);
  213. //PrintPreview.setInstance(this);
  214. var mdiChild = EAction.getMdiChild();
  215. this.view = mdiChild.getLastKnownViewWithFocus();
  216. di.disableUpdates();
  217. this.parentClass.prototype.beginEvent.call(this);
  218. di.enableUpdates();
  219. if (!isNull(this.view)) {
  220. var document = this.getDocument();
  221. this.bgColor = this.view.getBackgroundColor();
  222. this.updateBackgroundDecoration();
  223. if (!isNull(this.view.getScene())) {
  224. if (RSettings.getBoolValue("GraphicsView/AutoSwitchLinetypes", false)===true) {
  225. this.view.getScene().setScreenBasedLinetypes(false);
  226. var ltModeAction = RGuiAction.getByScriptFile("scripts/View/LinetypeMode/LinetypeMode.js");
  227. ltModeAction.setChecked(false);
  228. }
  229. }
  230. // needed to update linetype pattern scaling according to drawing scale:
  231. di.regenerateScenes();
  232. }
  233. var action = RGuiAction.getByScriptFile("scripts/Edit/DrawingPreferences/DrawingPreferences.js");
  234. action.triggered.connect(this, this.updateBackgroundDecoration);
  235. if (initialZoom==="Auto") {
  236. // auto fit drawing and auto set orientation:
  237. this.slotAutoFitDrawing(true);
  238. appWin.setProperty("PrintPreview/InitialZoom", "Stored");
  239. }
  240. else if (initialZoom==="View") {
  241. Print.setColumns(di, 1);
  242. Print.setRows(di, 1);
  243. this.slotAutoFitBox(this.view.getBox());
  244. appWin.setProperty("PrintPreview/InitialZoom", "Stored");
  245. }
  246. if (this.initialAction==="Print") {
  247. this.slotPrint();
  248. }
  249. else if (this.initialAction==="PdfExport") {
  250. this.slotPdfExport();
  251. }
  252. // create listener to update preview when preferences changed:
  253. this.pAdapter = new RPreferencesListenerAdapter();
  254. appWin.addPreferencesListener(this.pAdapter);
  255. this.pAdapter.preferencesUpdated.connect(this, this.updateFromPreferences);
  256. this.bAdapter = new RBlockListenerAdapter();
  257. appWin.addBlockListener(this.bAdapter);
  258. this.bAdapter.blocksUpdated.connect(this, this.updateBackgroundTransform);
  259. this.bAdapter.currentBlockSet.connect(this, this.updateBackgroundTransform);
  260. this.bAdapter.blocksUpdated.connect(this, this.updateBackgroundDecoration);
  261. this.bAdapter.currentBlockSet.connect(this, this.updateBackgroundDecoration);
  262. };
  263. /**
  264. * Handles additional state changes for offset moving state.
  265. */
  266. PrintPreviewImpl.prototype.setState = function(state) {
  267. this.parentClass.prototype.setState.call(this, state);
  268. if (this.state === PrintPreviewImpl.State.SettingOffset) {
  269. this.getDocumentInterface().setClickMode(RAction.PickingDisabled);
  270. this.setCursor(this.cursor, "PrintPreviewOffsetCursor");
  271. EAction.showMainTools();
  272. EAction.getMainWindow().setLeftMouseTip(qsTr("Drag to move paper"));
  273. EAction.getMainWindow().setRightMouseTip(qsTr("Done"));
  274. }
  275. var optionsToolBar = EAction.getOptionsToolBar();
  276. var offsetButton = optionsToolBar.findChild("Offset");
  277. if (offsetButton) {
  278. offsetButton.checked = (this.state == PrintPreviewImpl.State.SettingOffset);
  279. }
  280. };
  281. PrintPreviewImpl.prototype.suspendEvent = function() {
  282. EAction.prototype.suspendEvent.call(this);
  283. };
  284. PrintPreviewImpl.prototype.finishEvent = function() {
  285. this.parentClass.prototype.finishEvent.call(this);
  286. var di = this.getDocumentInterface();
  287. var appWin = RMainWindowQt.getMainWindow();
  288. var initialZoom = appWin.property("PrintPreview/InitialZoom");
  289. if (!isNull(this.view)) {
  290. this.view.setPrintPreview(false);
  291. this.view.setBackgroundColor(this.bgColor);
  292. this.view.setColorMode(RGraphicsView.FullColor);
  293. this.view.clearBackground();
  294. if (!isNull(this.view.getScene())) {
  295. if (RSettings.getBoolValue("GraphicsView/AutoSwitchLinetypes", false)===true) {
  296. this.view.getScene().setScreenBasedLinetypes(true);
  297. var ltModeAction = RGuiAction.getByScriptFile("scripts/View/LinetypeMode/LinetypeMode.js");
  298. ltModeAction.setChecked(true);
  299. }
  300. }
  301. // needed to update pattern scaling without using drawing scale:
  302. if (!isNull(di)) {
  303. di.regenerateScenes();
  304. }
  305. var action = RGuiAction.getByScriptFile("scripts/Edit/DrawingPreferences/DrawingPreferences.js");
  306. action.triggered.disconnect(this, this.updateBackgroundDecoration);
  307. }
  308. //PrintPreviewImpl.setRunning(false);
  309. //PrintPreviewImpl.setInstance(undefined);
  310. if (this.saveView===true) {
  311. if (!isNull(this.savedScale)) {
  312. Print.setScale(di, this.savedScale);
  313. }
  314. if (!isNull(this.savedOffset)) {
  315. Print.setOffset(di, this.savedOffset);
  316. }
  317. if (!isNull(this.savedColumns)) {
  318. Print.setColumns(di, this.savedColumns);
  319. }
  320. if (!isNull(this.savedRows)) {
  321. Print.setRows(di, this.savedRows);
  322. }
  323. }
  324. if (!isNull(this.pAdapter)) {
  325. appWin.removePreferencesListener(this.pAdapter);
  326. destr(this.pAdapter);
  327. }
  328. if (!isNull(this.bAdapter)) {
  329. appWin.removeBlockListener(this.bAdapter);
  330. destr(this.bAdapter);
  331. }
  332. };
  333. /**
  334. * Implements moving of paper (offset).
  335. */
  336. PrintPreviewImpl.prototype.mousePressEvent = function(event) {
  337. if (this.state === PrintPreviewImpl.State.SettingOffset) {
  338. if (event.button() == Qt.LeftButton &&
  339. event.modifiers().valueOf() != Qt.ControlModifier.valueOf()) {
  340. this.panOffsetOrigin = event.getScreenPosition();
  341. this.panningOffset = true;
  342. }
  343. }
  344. else {
  345. this.parentClass.prototype.mousePressEvent.call(this, event);
  346. }
  347. };
  348. /**
  349. * Reimplemented from EAction to prevent that a right-click closes the
  350. * print preview.
  351. */
  352. //PrintPreviewImpl.prototype.mouseReleaseEvent = function(event) {
  353. // if (event.button() == Qt.RightButton) {
  354. // if (this.state!=DefaultAction.State.Neutral) {
  355. // EAction.getDocumentInterface().clearPreview();
  356. // EAction.getDocumentInterface().repaintViews();
  357. // this.setState(DefaultAction.State.Neutral);
  358. // }
  359. // }
  360. // else {
  361. // this.parentClass.prototype.mouseReleaseEvent.call(this, event);
  362. // }
  363. //};
  364. /**
  365. * Implements moving of paper (offset).
  366. */
  367. PrintPreviewImpl.prototype.mouseMoveEvent = function(event) {
  368. if (this.state !== PrintPreviewImpl.State.SettingOffset) {
  369. this.parentClass.prototype.mouseMoveEvent.call(this, event);
  370. return;
  371. }
  372. if (event.buttons().valueOf() & Qt.LeftButton.valueOf() &&
  373. event.modifiers().valueOf() != Qt.ControlModifier.valueOf()) {
  374. if (!this.panningOffset) {
  375. return;
  376. }
  377. var panTarget = event.getScreenPosition();
  378. var panDelta = panTarget.operator_subtract(this.panOffsetOrigin);
  379. if (Math.abs(panDelta.x) < 1 && Math.abs(panDelta.y) < 1) {
  380. return;
  381. }
  382. this.panOffsetOrigin = panTarget;
  383. var di = this.getDocumentInterface();
  384. var document = di.getDocument();
  385. var offset = Print.getOffset(document);
  386. offset.x += this.view.mapDistanceFromView(panDelta.x);
  387. offset.y -= this.view.mapDistanceFromView(panDelta.y);
  388. // update document variables
  389. Print.setOffset(di, offset);
  390. this.updateBackgroundTransform();
  391. this.view.regenerate();
  392. }
  393. };
  394. /**
  395. * Reimplementation from EAction. Implements initialization of options
  396. * toolbar from member variables.
  397. */
  398. PrintPreviewImpl.prototype.showUiOptions = function(resume) {
  399. this.updateDisabled = true;
  400. EAction.prototype.showUiOptions.call(this, resume);
  401. this.updateDisabled = false;
  402. var optionsToolBar = EAction.getOptionsToolBar();
  403. var widgets = getWidgets(optionsToolBar);
  404. var document = this.getDocument();
  405. var di = this.getDocumentInterface();
  406. var scaleString = Print.getScaleString(document);
  407. var mod = document.isModified();
  408. // note: this modifies the document:
  409. this.initScaleCombo();
  410. // update option toolbar widgets
  411. widgets["ShowPaperBorders"].blockSignals(true);
  412. widgets["ShowPaperBorders"].checked = Print.getShowPaperBorders(document);
  413. widgets["ShowPaperBorders"].blockSignals(false);
  414. widgets["PrintCropMarks"].blockSignals(true);
  415. widgets["PrintCropMarks"].checked = Print.getPrintCropMarks(document);
  416. widgets["PrintCropMarks"].blockSignals(false);
  417. var scaleCombo = widgets["Scale"];
  418. scaleCombo.blockSignals(true);
  419. scaleCombo.setEditText(scaleString);
  420. di.disableUpdates();
  421. this.slotScaleChanged(scaleString);
  422. di.enableUpdates();
  423. scaleCombo.blockSignals(false);
  424. var action = RGuiAction.getByScriptFile("scripts/Edit/DrawingPreferences/DrawingPreferences.js");
  425. widgets["ShowMoreOptions"].setDefaultAction(action);
  426. switch(Print.getColorMode(document)) {
  427. case RGraphicsView.FullColor:
  428. widgets["FullColor"].blockSignals(true);
  429. widgets["FullColor"].checked=true;
  430. widgets["FullColor"].blockSignals(false);
  431. break;
  432. case RGraphicsView.GrayScale:
  433. widgets["Grayscale"].blockSignals(true);
  434. widgets["Grayscale"].checked=true;
  435. widgets["Grayscale"].blockSignals(false);
  436. break;
  437. case RGraphicsView.BlackWhite:
  438. widgets["BlackWhite"].blockSignals(true);
  439. widgets["BlackWhite"].checked=true;
  440. widgets["BlackWhite"].blockSignals(false);
  441. break;
  442. }
  443. if (Print.getHairlineMode(document)) {
  444. if (!isNull(widgets["Hairline"])) {
  445. widgets["Hairline"].blockSignals(true);
  446. widgets["Hairline"].checked=true;
  447. widgets["Hairline"].blockSignals(false);
  448. }
  449. }
  450. widgets["Portrait"].blockSignals(true);
  451. widgets["Landscape"].blockSignals(true);
  452. if (Print.getPageOrientationEnum(document) === RS.Portrait) {
  453. widgets["Portrait"].checked=true;
  454. } else {
  455. widgets["Landscape"].checked=true;
  456. }
  457. widgets["Landscape"].blockSignals(false);
  458. widgets["Portrait"].blockSignals(false);
  459. // workaround for FS#2356 - File > Close: Closing dialog stays open after clicking Save
  460. document.setModified(mod);
  461. };
  462. /**
  463. * Initializes the scale combo box in the options toolbar with defaults.
  464. */
  465. PrintPreviewImpl.prototype.initUiOptions = function(resume, optionsToolBar) {
  466. this.initScaleCombo();
  467. };
  468. PrintPreviewImpl.prototype.initScaleCombo = function() {
  469. var document = this.getDocument();
  470. if (isNull(document)) {
  471. return;
  472. }
  473. var optionsToolBar = EAction.getOptionsToolBar();
  474. var scaleCombo = optionsToolBar.findChild("Scale");
  475. scaleCombo.blockSignals(true);
  476. var prev = scaleCombo.currentText;
  477. scaleCombo.clear();
  478. scaleCombo.setScale(true, document.getUnit())
  479. // var scales = this.getScales();
  480. // for (var i=0; i<scales.length; ++i) {
  481. // scaleCombo.addItem(scales[i]);
  482. // }
  483. scaleCombo.setEditText(prev);
  484. scaleCombo.blockSignals(false);
  485. };
  486. PrintPreviewImpl.prototype.hideUiOptions = function() {
  487. EAction.prototype.hideUiOptions.call(this, false);
  488. };
  489. /**
  490. * Called to update the background decoration (paper borders) if the scale
  491. * or paper settings change.
  492. */
  493. PrintPreviewImpl.prototype.updateBackgroundDecoration = function() {
  494. var document = this.getDocument();
  495. if (isNull(document) || isNull(this.view)) {
  496. return;
  497. }
  498. // initialize graphics view for printing / print preview:
  499. this.view.setBackgroundColor(Print.getBackgroundColor(document));
  500. this.view.setColorMode(Print.getColorMode(document));
  501. this.view.setHairlineMode(Print.getHairlineMode(document));
  502. this.view.setPrintPreview(true);
  503. this.view.clearBackground();
  504. var pages = Print.getPages(document);
  505. var backgroundColor = Print.getBackgroundColor(document);
  506. var i, color, path;
  507. if (pages.length===0) {
  508. qWarning("PrintPreviewImpl.prototype.updateBackgroundDecoration: no pages");
  509. return;
  510. }
  511. var colBg;
  512. var colShadow;
  513. var colBorder;
  514. if (RSettings.hasDarkGuiBackground()) {
  515. colBg = "#888888";
  516. colShadow = "#333333";
  517. colBorder = "black";
  518. }
  519. else {
  520. colBg = "lightgray";
  521. colShadow = "gray";
  522. colBorder = "#c8c8c8";
  523. }
  524. path = new RPainterPath();
  525. path.setPen(new QPen(Qt.NoPen));
  526. path.setBrush(new QBrush(new QColor(colBg)));
  527. path.addRect(new QRectF(-1.0e8, -1.0e8, 2.0e8, 2.0e8));
  528. this.view.addToBackground(RGraphicsSceneDrawable.createFromPainterPath(path));
  529. // page border with shadow
  530. if (Print.getShowPaperBorders(document)) {
  531. // shadow
  532. for (i = 0; i < pages.length; ++i) {
  533. path = new RPainterPath();
  534. path.setPen(new QPen(Qt.NoPen));
  535. path.setBrush(new QBrush(new QColor(colShadow)));
  536. this.drawShadow(path, pages[i]);
  537. this.view.addToBackground(RGraphicsSceneDrawable.createFromPainterPath(path));
  538. }
  539. // paper background
  540. for (i = 0; i < pages.length; ++i) {
  541. path = new RPainterPath();
  542. path.setPen(new QPen(Qt.NoPen));
  543. color = new QColor(backgroundColor.red(), backgroundColor.green(),
  544. backgroundColor.blue());
  545. path.setBrush(new QBrush(color));
  546. this.drawPaper(path, pages[i]);
  547. this.view.addToBackground(RGraphicsSceneDrawable.createFromPainterPath(path));
  548. }
  549. // paper border
  550. for (i = 0; i < pages.length; ++i) {
  551. path = new RPainterPath();
  552. path.setPen(new QPen(new QColor(colBorder)));
  553. path.setBrush(new QBrush(Qt.NoBrush));
  554. this.drawPaper(path, pages[i]);
  555. this.view.addToBackground(RGraphicsSceneDrawable.createFromPainterPath(path));
  556. }
  557. }
  558. // glue margins and page borders as blue rectangle:
  559. path = new RPainterPath();
  560. path.setPen(new QPen(new QColor(0x84, 0x84, 0xff)));
  561. if (!Print.getShowPaperBorders(document)) {
  562. color = new QColor(backgroundColor.red(), backgroundColor.green(), backgroundColor.blue());
  563. path.setBrush(new QBrush(color));
  564. } else {
  565. path.setBrush(new QBrush(Qt.NoBrush));
  566. }
  567. if (pages.length===0) {
  568. qWarning("PrintPreviewImpl.js: no pages");
  569. }
  570. for (i = 0; i < pages.length; ++i) {
  571. this.drawGlueMargins(path, pages[i]);
  572. }
  573. this.view.addToBackground(RGraphicsSceneDrawable.createFromPainterPath(path));
  574. // hook for page tags, footer, etc.:
  575. this.addDecorations(pages);
  576. // crop marks:
  577. if (Print.getPrintCropMarks(document)) {
  578. for ( i = 0; i < pages.length; ++i) {
  579. path = new RPainterPath();
  580. Print.drawCropMarks(document, path, pages[i], false);
  581. this.view.addToBackground(RGraphicsSceneDrawable.createFromPainterPath(path));
  582. }
  583. }
  584. this.view.regenerate(true);
  585. };
  586. /**
  587. * Overwritable hook to add more decorations to the print preview.
  588. */
  589. PrintPreviewImpl.prototype.addDecorations = function(pages) {};
  590. /**
  591. * Updates the background decoration transformation.
  592. */
  593. PrintPreviewImpl.prototype.updateBackgroundTransform = function() {
  594. var document = this.getDocument();
  595. if (isNull(document)) {
  596. return;
  597. }
  598. var scale = Print.getScale(document);
  599. var offset = Print.getOffset(document);
  600. // the smaller the scale, the bigger the paper is shown,
  601. // relative to the drawing:
  602. var unitScale = RUnit.convert(1.0, RS.Millimeter, document.getUnit());
  603. var factor = 1.0 / scale * unitScale;
  604. if (!isNull(this.view)) {
  605. this.view.setBackgroundTransform(factor, offset);
  606. }
  607. };
  608. /**
  609. * Draws the paper border for the given page.
  610. */
  611. PrintPreviewImpl.prototype.drawPaper = function(path, border) {
  612. var document = this.getDocument();
  613. var paperBorder = Print.getPaperBorder(document, border);
  614. if (!paperBorder.isValid()) {
  615. return;
  616. }
  617. path.addRect(paperBorder);
  618. };
  619. /**
  620. * Draws the glue margins for the given page.
  621. */
  622. PrintPreviewImpl.prototype.drawGlueMargins = function(path, border) {
  623. if (!border.isValid()) {
  624. return;
  625. }
  626. path.addRect(border);
  627. };
  628. /**
  629. * Draws the shadow for the given page.
  630. */
  631. PrintPreviewImpl.prototype.drawShadow = function(path, border) {
  632. var document = this.getDocument();
  633. var paper = Print.getPaperBorder(document, border);
  634. var offset = Print.getPaperSizeMM(document).width() * 0.02;
  635. var shadow = paper.adjusted(offset, -offset, offset, -offset);
  636. if (!shadow.isValid()) {
  637. return;
  638. }
  639. path.addRect(shadow);
  640. };
  641. PrintPreviewImpl.prototype.slotPdfExport = function() {
  642. var appWin = EAction.getMainWindow();
  643. var fileName = this.getDocument().getFileName();
  644. var initialFileName = QDir.homePath();
  645. if (fileName!=="") {
  646. var fileInfo = new QFileInfo(fileName);
  647. initialFileName = fileInfo.absoluteFilePath();
  648. }
  649. var filterStrings = [ "PDF File (*.pdf)", "PDF/A-1B File (*.pdf)"];
  650. if (RSettings.getQtVersion()<0x050A00) {
  651. filterStrings = [ "PDF File (*.pdf)" ];
  652. }
  653. filterStrings = translateFilterStrings(filterStrings);
  654. var ret = File.getSaveFileName(appWin, qsTr("Export to PDF"),
  655. initialFileName, filterStrings);
  656. if (isNull(ret)) {
  657. return;
  658. }
  659. var pdfFile = ret[0];
  660. var pdfVersion = undefined;
  661. if (ret[1].indexOf("PDF/A")!==-1) {
  662. pdfVersion = "A-1B";
  663. }
  664. appWin.handleUserMessage(qsTr("Exporting to %1...").arg(pdfFile));
  665. var success = this.slotPrint(pdfFile, pdfVersion);
  666. if (success) {
  667. appWin.handleUserMessage(qsTr("Export complete: %1").arg(pdfFile));
  668. }
  669. else {
  670. appWin.handleUserWarning(qsTr("Export failed (cannot open file for writing): %1").arg(pdfFile));
  671. }
  672. };
  673. /**
  674. * Called when user clicks the PDF export button in the options toolbar.
  675. */
  676. PrintPreviewImpl.slotPdfExport = function() {
  677. var pp = PrintPreviewImpl.getInstance();
  678. pp.slotPdfExport();
  679. };
  680. PrintPreviewImpl.prototype.slotPrint = function(pdfFile, pdfVersion) {
  681. return PrintPreviewImpl.slotPrint(pdfFile, pdfVersion);
  682. };
  683. /**
  684. * Prints the drawing or exports it to the given PDF file.
  685. */
  686. PrintPreviewImpl.slotPrint = function(pdfFile, pdfVersion) {
  687. var mdiChild = EAction.getMdiChild();
  688. var view = mdiChild.getLastKnownViewWithFocus();
  689. var print = new Print(undefined, EAction.getDocument(), view);
  690. return print.print(pdfFile, undefined, pdfVersion);
  691. };
  692. /**
  693. * Called whenever the user changes the drawing scale in the print preview.
  694. */
  695. PrintPreviewImpl.prototype.slotScaleChanged = function(scaleString) {
  696. if (this.updateDisabled===true) {
  697. return;
  698. }
  699. var di = this.getDocumentInterface();
  700. if (isNull(di) || this.updateDisabled===true) {
  701. return;
  702. }
  703. Print.setScaleString(di, scaleString);
  704. this.updateBackgroundTransform();
  705. // update pattern scale according to drawing scale:
  706. di.regenerateScenes();
  707. };
  708. PrintPreviewImpl.setScale = function(di, scale) {
  709. PrintPreviewImpl.setScaleString(di, sprintf("%.6f", scale));
  710. };
  711. PrintPreviewImpl.setScaleString = function(di, scaleString) {
  712. Print.setScaleString(di, scaleString);
  713. PrintPreviewImpl.updateScaleString(document);
  714. };
  715. PrintPreviewImpl.updateScaleString = function(document) {
  716. var optionsToolBar = EAction.getOptionsToolBar();
  717. var scaleCombo = optionsToolBar.findChild("Scale");
  718. if (Print.getScale(document) != RMath.parseScale(scaleCombo.currentText)) {
  719. scaleCombo.blockSignals(true);
  720. scaleCombo.setEditText(Print.getScaleString(document));
  721. scaleCombo.blockSignals(false);
  722. }
  723. };
  724. /**
  725. * Triggered by the offset tool button in the options toolbar.
  726. * Activates / deactivates the offset tool.
  727. */
  728. PrintPreviewImpl.prototype.slotOffsetChanged = function(checked) {
  729. if (this.updateDisabled===true) {
  730. return;
  731. }
  732. if (checked) {
  733. this.setState(PrintPreviewImpl.State.SettingOffset);
  734. }
  735. else {
  736. this.setState(DefaultAction.State.Neutral);
  737. }
  738. };
  739. /**
  740. * Triggered by the "Done" button in the options toolbar.
  741. * Terminates this action and returns to normal drawing mode.
  742. */
  743. PrintPreviewImpl.prototype.slotDone = function() {
  744. PrintPreview.exit();
  745. };
  746. /**
  747. * Triggered by the b/w button in the options toolbar.
  748. * Activates / deactivates the black white mode.
  749. */
  750. PrintPreviewImpl.prototype.slotFullColorChanged = function(checked) {
  751. if (this.updateDisabled===true) {
  752. return;
  753. }
  754. if (checked) {
  755. Print.setColorMode(this.getDocumentInterface(), RGraphicsView.FullColor);
  756. this.colorModeUpdate();
  757. }
  758. };
  759. PrintPreviewImpl.prototype.slotBlackWhiteChanged = function(checked) {
  760. if (this.updateDisabled===true) {
  761. return;
  762. }
  763. if (checked) {
  764. Print.setColorMode(this.getDocumentInterface(), RGraphicsView.BlackWhite);
  765. this.colorModeUpdate();
  766. }
  767. };
  768. PrintPreviewImpl.prototype.slotGrayscaleChanged = function(checked) {
  769. if (this.updateDisabled===true) {
  770. return;
  771. }
  772. if (checked) {
  773. Print.setColorMode(this.getDocumentInterface(), RGraphicsView.GrayScale);
  774. this.colorModeUpdate();
  775. }
  776. };
  777. PrintPreviewImpl.prototype.colorModeUpdate = function() {
  778. if (!isNull(this.view)) {
  779. this.view.setColorMode(Print.getColorMode(this.getDocument()));
  780. this.view.regenerate(true);
  781. }
  782. };
  783. PrintPreviewImpl.prototype.slotHairlineChanged = function(checked) {
  784. if (this.updateDisabled===true) {
  785. return;
  786. }
  787. Print.setHairlineMode(this.getDocumentInterface(), checked);
  788. if (!isNull(this.view)) {
  789. this.view.setHairlineMode(checked)
  790. this.view.regenerate(true);
  791. }
  792. };
  793. /**
  794. * Page borders toggled in options toolbar.
  795. */
  796. PrintPreviewImpl.prototype.slotShowPaperBordersChanged = function(checked) {
  797. if (this.updateDisabled===true) {
  798. return;
  799. }
  800. var di = this.getDocumentInterface();
  801. Print.setShowPaperBorders(di, checked);
  802. this.updateBackgroundDecoration();
  803. };
  804. /**
  805. * Crop marks toggled in options toolbar.
  806. */
  807. PrintPreviewImpl.prototype.slotPrintCropMarksChanged = function(checked) {
  808. if (this.updateDisabled===true) {
  809. return;
  810. }
  811. var di = this.getDocumentInterface();
  812. Print.setPrintCropMarks(di, checked);
  813. this.updateBackgroundDecoration();
  814. };
  815. /**
  816. * Auto fit box to page.
  817. */
  818. PrintPreviewImpl.prototype.slotAutoFitBox = function(box) {
  819. var di = this.getDocumentInterface();
  820. var doc = di.getDocument();
  821. Print.autoFitBox(di, box);
  822. PrintPreviewImpl.updateScaleString(doc);
  823. // needed to update pattern scaling according to drawing scale:
  824. //var di = this.getDocumentInterface();
  825. di.regenerateScenes();
  826. this.updateBackgroundTransform();
  827. //this.slotAutoZoomToPage();
  828. this.updateBackgroundDecoration();
  829. this.showUiOptions(true);
  830. };
  831. /**
  832. * Auto fit drawing button clicked in options toolbar.
  833. */
  834. PrintPreviewImpl.prototype.slotAutoFitDrawing = function(ori) {
  835. var di = this.getDocumentInterface();
  836. var document = di.getDocument();
  837. Print.autoFitDrawing(di, ori);
  838. PrintPreviewImpl.updateScaleString(document);
  839. // needed to update pattern scaling according to drawing scale:
  840. di.regenerateScenes();
  841. this.updateBackgroundTransform();
  842. this.slotAutoZoomToPage();
  843. this.updateBackgroundDecoration();
  844. this.showUiOptions(true);
  845. };
  846. PrintPreviewImpl.prototype.slotAutoCenter = function() {
  847. Print.autoCenter(this.getDocumentInterface());
  848. this.updateBackgroundTransform();
  849. this.slotAutoZoomToPage();
  850. this.updateBackgroundDecoration();
  851. };
  852. PrintPreviewImpl.prototype.slotPortraitChanged = function() {
  853. if (this.updateDisabled===true) {
  854. return;
  855. }
  856. var di = this.getDocumentInterface();
  857. Print.setPageOrientationEnum(di, RS.Portrait);
  858. this.updateBackgroundDecoration();
  859. this.slotAutoZoomToPage();
  860. };
  861. PrintPreviewImpl.prototype.slotLandscapeChanged = function() {
  862. if (this.updateDisabled===true) {
  863. return;
  864. }
  865. var di = this.getDocumentInterface();
  866. Print.setPageOrientationEnum(di, RS.Landscape);
  867. this.updateBackgroundDecoration();
  868. this.slotAutoZoomToPage();
  869. };
  870. /**
  871. * \return Maximum extents of paper
  872. */
  873. PrintPreviewImpl.prototype.getPaperBox = function() {
  874. return Print.getPaperBox(this.getDocument());
  875. };
  876. PrintPreviewImpl.prototype.slotAutoZoomToPage = function() {
  877. if (!isNull(this.view)) {
  878. var pBox = this.getPaperBox();
  879. this.view.zoomTo(pBox, 10);
  880. }
  881. };
  882. /**
  883. * Updates the background (paper preview) transform when page settings
  884. * are changed (e.g. offset).
  885. */
  886. PrintPreviewImpl.prototype.updateFromPreferences = function() {
  887. this.showUiOptions(true);
  888. this.updateBackgroundDecoration();
  889. this.updateBackgroundTransform();
  890. };