ViewportWidget.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  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/library.js");
  20. include("scripts/sprintf.js");
  21. if (exists("scripts/Navigation/DefaultNavigation/DefaultNavigation.js")) {
  22. include("scripts/Navigation/DefaultNavigation/DefaultNavigation.js");
  23. }
  24. ViewportWidget.templateDir = autoPath("scripts/Widgets/ViewportWidget/Templates");
  25. /**
  26. * A viewport widget encapsulates one graphics view and might provide means to navigate
  27. * (scroll bars) and other widgets that are available for every graphics view.
  28. *
  29. * \param vpNumber Number of viewport. There can be up to four viewports
  30. * available for example in an MDI child (tab). This number is used to identify
  31. * the viewport settings in configuration files and document settings.
  32. * \param vpWidget Viewport widget that will contain the viewport
  33. * after initialization.
  34. */
  35. function ViewportWidget(vpNumber, vpWidget, documentInterface) {
  36. this.vpNumber = vpNumber;
  37. this.vpWidget = vpWidget;
  38. this.documentInterface = documentInterface;
  39. this.eventHandler = undefined;
  40. }
  41. /**
  42. * \return Array of ViewportWidget objects, one for each child of widget that
  43. * is called "ViewportXX".
  44. */
  45. ViewportWidget.getViewports = function(widget, documentInterface) {
  46. var vpWidget;
  47. var c = 0;
  48. var vps = [];
  49. do {
  50. var vpName = sprintf("Viewport%02d", c);
  51. vpWidget = widget.findChild(vpName);
  52. if (isNull(vpWidget)) {
  53. break;
  54. }
  55. var viewport = new ViewportWidget(c, vpWidget, documentInterface);
  56. vps.push(viewport);
  57. ++c;
  58. } while (!isNull(vpWidget));
  59. return vps;
  60. };
  61. ViewportWidget.initEventHandler = function(viewports) {
  62. for ( var i = 0; i < viewports.length; ++i) {
  63. viewports[i].initEventHandler();
  64. }
  65. };
  66. ViewportWidget.initializeViewports = function(viewports, uiFile, graphicsSceneClass) {
  67. for ( var i = 0; i < viewports.length; ++i) {
  68. var vp = viewports[i];
  69. vp.init(uiFile, graphicsSceneClass);
  70. }
  71. };
  72. ViewportWidget.updateViewports = function(viewports) {
  73. // TODO auto zoom for each graphics view works only for the first viewport
  74. for (var i = 0; i < viewports.length; ++i) {
  75. var vp = viewports[i];
  76. vp.getEventHandler().viewportChanged();
  77. var view = vp.getGraphicsView();
  78. if (RSettings.getAutoZoomOnLoad() || i>0) {
  79. view.autoZoom(-1, true);
  80. }
  81. else {
  82. // restore first viewport (zoom / pan):
  83. var di = vp.getDocumentInterface();
  84. var doc = di.getDocument();
  85. var c = doc.getVariable("ViewportCenter", undefined);
  86. var w = doc.getVariable("ViewportWidth", undefined);
  87. var h = doc.getVariable("ViewportHeight", undefined);
  88. if (!isNull(c) && !isNull(w) && !isNull(h)) {
  89. view.zoomTo(new RBox(c, w, h));
  90. }
  91. }
  92. }
  93. };
  94. ViewportWidget.initMdiChild = function(mdiChild, uiFileName) {
  95. var w = WidgetFactory.createWidget("", ViewportWidget.templateDir + QDir.separator + uiFileName, mdiChild);
  96. w.setWindowTitle("");
  97. mdiChild.setWidget(w);
  98. };
  99. ViewportWidget.prototype.initEventHandler = function() {
  100. var self = this;
  101. this.eventHandler = new EventHandler(this, this.documentInterface);
  102. if (isOfType(this.graphicsView, RGraphicsViewQt)) {
  103. this.graphicsView.drop.connect(function(e) { self.eventHandler.drop(e); });
  104. this.graphicsView.dragEnter.connect(function(e) { self.eventHandler.dragEnter(e); });
  105. this.graphicsView.viewportChanged.connect(function() { self.eventHandler.viewportChanged(); });
  106. this.graphicsView.updateSnapInfo.connect(function(painter, snap, restriction) { self.eventHandler.updateSnapInfo(painter, snap, restriction); });
  107. this.graphicsView.updateTextLabel.connect(function(painter, textLabel) { self.eventHandler.updateTextLabel(painter, textLabel); });
  108. }
  109. if (!isNull(this.hsb)) {
  110. this.hsb.valueChanged.connect(function(value) { self.eventHandler.horizontalScrolled(value); } );
  111. this.vsb.valueChanged.connect(function(value) { self.eventHandler.verticalScrolled(value); } );
  112. }
  113. };
  114. /**
  115. * Initializes this viewport widget.
  116. *
  117. * \param uiFile UI file to use for view port (defaults to ViewportWidgetQt.ui).
  118. * \param graphicsSceneClass Class to use for graphics scene (defaults to "RGraphicsSceneQt")
  119. */
  120. ViewportWidget.prototype.init = function(uiFile, graphicsSceneClass) {
  121. // delete placeholder children if there are any (clear out parent window):
  122. var chs = this.vpWidget.children();
  123. for (var i = 0; i < chs.length; ++i) {
  124. var ch = chs[i];
  125. if (isNull(ch)) {
  126. continue;
  127. }
  128. if (RSettings.getQtVersion()>=0x060000) {
  129. if (ch.isOfObjectType(RJSType.QLayout_Type) || ch.isOfObjectType(RJSType.QWidget_Type)) {
  130. destr(ch);
  131. }
  132. }
  133. else {
  134. destr(ch);
  135. }
  136. }
  137. if (isNull(uiFile)) {
  138. uiFile = "scripts/Widgets/ViewportWidget/ViewportWidgetQt.ui";
  139. }
  140. // use ViewportWidgetQt.ui or given UI file:
  141. var vpw = WidgetFactory.createWidget("", uiFile, this.vpWidget);
  142. var layout = new QVBoxLayout();
  143. if (RSettings.isQt(6)) {
  144. layout.addWidget(vpw);
  145. }
  146. else {
  147. layout.addWidget(vpw, 0, Qt.AlignTop | Qt.AlignLeft);
  148. }
  149. layout.setStretch(0, 1);
  150. layout.setContentsMargins(0,0,0,0);
  151. if (!isNull(this.vpWidget.layout())) {
  152. // destroy existing layout manager
  153. destr(this.vpWidget.layout());
  154. }
  155. this.vpWidget.setLayout(layout);
  156. // clear style sheet
  157. this.vpWidget.styleSheet = "";
  158. this.graphicsView = this.vpWidget.findChild("GraphicsView");
  159. if (isNull(this.graphicsView)) {
  160. qWarning("graphics view not found");
  161. return;
  162. }
  163. this.graphicsView.setViewportNumber(this.vpNumber);
  164. if (isFunction(this.graphicsView.setFocusFrameWidget)) {
  165. this.graphicsView.setFocusFrameWidget(this.vpWidget);
  166. }
  167. this.graphicsView.setAntialiasing(RSettings.getBoolValue("GraphicsView/Antialiasing", false));
  168. // enable multithreaded graphics view:
  169. //if (RSettings.getBoolValue("GraphicsView/Multithreading", true)) {
  170. var numThreads = RSettings.getIntValue("GraphicsView/Threads", Math.min(RS.getIdealThreadCount(), 6));
  171. if (numThreads!==1) {
  172. this.graphicsView.setNumThreads(numThreads);
  173. //EAction.handleUserMessage(qsTr("Threads:") + " " + numThreads);
  174. }
  175. //}
  176. // create custom graphics scene (e.g. OpenGL, ...):
  177. var scene = undefined;
  178. if (!isNull(graphicsSceneClass)) {
  179. if (!isNull(global[graphicsSceneClass])) {
  180. scene = new global[graphicsSceneClass](this.documentInterface);
  181. }
  182. }
  183. if (isNull(scene)) {
  184. scene = new RGraphicsSceneQt(this.documentInterface);
  185. }
  186. if (RSettings.getBoolValue("GraphicsView/AutoSwitchLinetypes", false)===true) {
  187. scene.setScreenBasedLinetypes(true);
  188. }
  189. this.graphicsView.setScene(scene);
  190. if (typeof(DefaultNavigation)!=="undefined") {
  191. var navigationAction = new DefaultNavigation(this.vpWidget);
  192. this.graphicsView.setNavigationAction(navigationAction);
  193. }
  194. var grid = new ROrthoGrid(getRGraphicsView(this.graphicsView));
  195. this.graphicsView.setGrid(grid);
  196. if (RSettings.isQt(6)) {
  197. this.graphicsView.setFocus(Qt.OtherFocusReason);
  198. }
  199. else {
  200. this.graphicsView.setFocus();
  201. }
  202. this.hsb = this.vpWidget.findChild("HorizontalScrollBar");
  203. if (!isNull(this.hsb)) {
  204. this.hsb.singleStep = 50;
  205. }
  206. this.vsb = this.vpWidget.findChild("VerticalScrollBar");
  207. if (!isNull(this.vsb)) {
  208. this.vsb.singleStep = 50;
  209. }
  210. if (RSettings.getBoolValue("GraphicsView/ShowScrollBars", true)===false) {
  211. var infoLabel = this.vpWidget.findChild("InfoLabel");
  212. infoLabel.hide();
  213. if (!isNull(this.hsb)) {
  214. this.hsb.hide();
  215. }
  216. if (!isNull(this.vsb)) {
  217. this.vsb.hide();
  218. }
  219. }
  220. var hruler = this.vpWidget.findChild("HorizontalRuler");
  221. var vruler = this.vpWidget.findChild("VerticalRuler");
  222. // moved to RRulerQt:
  223. //var appWin = RMainWindowQt.getMainWindow();
  224. //appWin.addPaletteListener(hruler);
  225. //appWin.addPaletteListener(vruler);
  226. if (RSettings.getBoolValue("GraphicsView/ShowRulers", true)) {
  227. this.hruler = hruler;
  228. if (!isNull(this.hruler)) {
  229. this.hruler.setGraphicsView(this.graphicsView);
  230. this.documentInterface.addCoordinateListener(this.hruler);
  231. }
  232. this.vruler = vruler;
  233. if (!isNull(this.vruler)) {
  234. this.vruler.setGraphicsView(this.graphicsView);
  235. this.documentInterface.addCoordinateListener(this.vruler);
  236. }
  237. } else {
  238. if (!isNull(hruler)) {
  239. hruler.hide();
  240. }
  241. if (!isNull(vruler)) {
  242. vruler.hide();
  243. }
  244. var cf = this.vpWidget.findChild("cornerFrame");
  245. if (!isNull(cf)) {
  246. cf.hide();
  247. }
  248. }
  249. };
  250. ViewportWidget.prototype.getVpWidget = function() {
  251. return this.vpWidget;
  252. };
  253. ViewportWidget.prototype.getGraphicsView = function() {
  254. return this.graphicsView;
  255. };
  256. ViewportWidget.prototype.getDocumentInterface = function() {
  257. return this.documentInterface;
  258. };
  259. ViewportWidget.prototype.getEventHandler = function() {
  260. return this.eventHandler;
  261. };
  262. /**
  263. * Event handler class. For each new document that is created or
  264. * opened, an event handler is created to handle various events
  265. * for the life time of the document.
  266. */
  267. function EventHandler(viewport, documentInterface) {
  268. REventHandler.call(this, viewport.getVpWidget(), documentInterface);
  269. }
  270. EventHandler.prototype = new REventHandler();
  271. /**
  272. * Handles drop into the drawing area
  273. * \param event QDropEvent
  274. */
  275. EventHandler.prototype.drop = function(event) {
  276. var mimeData = event.mimeData();
  277. var urls = getUrlsFromMimeData(mimeData);
  278. if (urls.length===0) {
  279. EAction.handleUserWarning(qsTr("Dropped data not supported"));
  280. event.acceptProposedAction();
  281. return;
  282. }
  283. var appWin = RMainWindowQt.getMainWindow();
  284. if (!isNull(appWin)) {
  285. appWin.activateWindow();
  286. appWin.raise();
  287. var view = EAction.getGraphicsView();
  288. if (!isNull(view)) {
  289. view.setFocus(Qt.OtherFocusReason);
  290. }
  291. else {
  292. appWin.setFocus(Qt.OtherFocusReason);
  293. }
  294. }
  295. var action;
  296. if (urls[0].isLocalFile()) {
  297. var filePath = urls[0].toLocalFile();
  298. var fi = new QFileInfo(filePath);
  299. if (fi.suffix().toLowerCase()==="cxf") {
  300. //openFiles(urls[0]);
  301. //event.acceptProposedAction();
  302. //event.ignore();
  303. EAction.handleUserWarning(qsTr("Cannot import file into existing drawing:") + " " + filePath);
  304. return;
  305. }
  306. EAction.handleUserMessage(qsTr("Importing file:") + " " + filePath);
  307. if (fi.isFile()) {
  308. include("scripts/Block/InsertScriptItem/InsertScriptItem.js");
  309. include("scripts/Draw/Image/Image.js");
  310. if (InsertScriptItem.isScriptFile(filePath)) {
  311. action = RGuiAction.getByScriptFile("scripts/Block/InsertScriptItem/InsertScriptItem.js");
  312. }
  313. else if (Image.isSupportedBitmapFile(filePath)) {
  314. action = RGuiAction.getByScriptFile("scripts/Draw/Image/Image.js");
  315. }
  316. else {
  317. action = RGuiAction.getByScriptFile("scripts/Block/InsertBlockItem/InsertBlockItem.js");
  318. }
  319. }
  320. }
  321. else {
  322. EAction.handleUserMessage(qsTr("Importing URL: ") + urls[0].toString());
  323. action = RGuiAction.getByScriptFile("scripts/Block/InsertBlockItem/InsertBlockItem.js");
  324. }
  325. if (isNull(action)) {
  326. event.acceptProposedAction();
  327. return;
  328. }
  329. action.setData(urls[0]);
  330. action.slotTrigger();
  331. event.acceptProposedAction();
  332. event.accept();
  333. };