WidgetFactory.js 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544
  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/map.js");
  21. function WidgetFactory() {
  22. }
  23. WidgetFactory.includeBasePath = includeBasePath;
  24. /**
  25. * Creates a dialog with the given \c parent, based on the UI file
  26. * named \c uiFile in \c basePath. The dialog has a header area in
  27. * which a title and (error-)messages can be display through the
  28. * functions \c setTitle(title) and \c setText(text, error).
  29. */
  30. WidgetFactory.createHeaderDialog = function(basePath, uiFile, parent) {
  31. var dlg = WidgetFactory.createDialog("scripts/Widgets", "Dialog.ui", parent);
  32. var header = dlg.findChild("header");
  33. dlg.textFormat = header.text;
  34. dlg.setTitle = function(title) {
  35. var header = dlg.findChild("header");
  36. header.text = dlg.textFormat.arg(title).arg(dlg.text);
  37. dlg.title = title;
  38. };
  39. dlg.setText = function(text, error) {
  40. if (isNull(error)) {
  41. error = false;
  42. }
  43. var header = dlg.findChild("header");
  44. var t = text;
  45. if (error) {
  46. t = "<font color='red'>%1</font>".arg(text);
  47. }
  48. header.text = dlg.textFormat.arg(dlg.title).arg(t);
  49. dlg.text = text;
  50. };
  51. var inner = WidgetFactory.createWidget(basePath, uiFile, dlg);
  52. var w = dlg.findChild("inner");
  53. var sizePolicy = w.sizePolicy;
  54. var layout = dlg.findChild("layout");
  55. var i = layout.indexOf(w);
  56. layout.removeWidget(w);
  57. layout.insertWidget(i, inner);
  58. inner.sizePolicy = sizePolicy;
  59. return dlg;
  60. };
  61. /**
  62. * Creates a widget with the given \c parent, based on the UI file
  63. * named \c uiFile in \c basePath.
  64. */
  65. WidgetFactory.createWidget = function(basePath, uiFile, parent) {
  66. if (isNull(parent)) {
  67. parent = RMainWindowQt.getMainWindow();
  68. }
  69. var candidates;
  70. if (!new QFileInfo(uiFile).isAbsolute()) {
  71. candidates = [
  72. uiFile,
  73. basePath + "/" + uiFile
  74. ];
  75. if (!uiFile.startsWith(":")) {
  76. candidates.push(":" + uiFile);
  77. }
  78. if (!basePath.startsWith(":")) {
  79. candidates.push(":" + basePath + "/" + uiFile);
  80. }
  81. }
  82. else {
  83. candidates = [
  84. uiFile
  85. ];
  86. }
  87. for (var i=0; i<candidates.length; i++) {
  88. var candidate = candidates[i];
  89. var fileInfo = new QFileInfo(candidate);
  90. if (fileInfo.exists()) {
  91. uiFile = candidate;
  92. }
  93. }
  94. var fileInfo = new QFileInfo(uiFile);
  95. if (!fileInfo.exists()) {
  96. qWarning("WidgetFactory: File %1 does not exist".arg(uiFile));
  97. return undefined;
  98. }
  99. var buf = RFileCache.getBuffer(uiFile);
  100. if (isNull(buf)) {
  101. return undefined;
  102. }
  103. //buf.open(new QIODevice.OpenMode(QIODevice.ReadOnly));
  104. var loader = new QUiLoader();
  105. loader.setWorkingDirectory(fileInfo.dir());
  106. var formWidget = loader.load(buf, parent);
  107. buf.close();
  108. destr(loader);
  109. if (isNull(formWidget)) {
  110. qDebug("WidgetFactory.createWidget: widget is NULL");
  111. }
  112. if (RS.getSystemId()==="osx") {
  113. WidgetFactory.installComboBoxEventFilter(formWidget);
  114. }
  115. WidgetFactory.adjustIcons(fileInfo.absolutePath(), formWidget);
  116. return formWidget;
  117. };
  118. /**
  119. * Creates a dialog from the given UI file.
  120. * Overrides exec for testing dashboard mode.
  121. */
  122. WidgetFactory.createDialog = function(basePath, uiFile, parent) {
  123. var dialog = WidgetFactory.createWidget(basePath, uiFile, parent);
  124. var flags = dialog.windowFlags();
  125. flags = makeQtWindowFlags(flags & ~(Qt.WindowContextHelpButtonHint));
  126. dialog.setWindowFlags(flags);
  127. // a global function might be defined to do additional
  128. // initialization for all dialogs (e.g. for testing purposes):
  129. if (typeof(initDialog)!=="undefined") {
  130. for (var i=0; i<initDialog.length; i++) {
  131. initDialog[i](dialog);
  132. }
  133. }
  134. return dialog;
  135. };
  136. /**
  137. * \return Settings key for the given group / object. Usually that is
  138. * [group, object name]. An array with two items is returned for group / name.
  139. */
  140. WidgetFactory.getKey = function(group, obj) {
  141. if (isDeleted(obj)) {
  142. return ["", ""];
  143. }
  144. var g = group;
  145. if (typeof(obj.property("SettingsGroup"))!="undefined") {
  146. g = obj.property("SettingsGroup");
  147. }
  148. var key = [g, obj.objectName];
  149. // correct key:
  150. if (isOfType(obj, QRadioButton) || isOfType(obj, QToolButton)) {
  151. // correct to button group name:
  152. if (isFunction(obj.group) && !isNull(obj.group())) {
  153. key = [g, obj.group().objectName];
  154. }
  155. else {
  156. var parent = obj.parent();
  157. // correct to group box (parent) name:
  158. if (parent && isOfType(parent, QGroupBox)) {
  159. key = [g, parent.objectName];
  160. }
  161. }
  162. }
  163. return key;
  164. };
  165. WidgetFactory.getKeyString = function(group, obj) {
  166. var keyTuple = WidgetFactory.getKey(group, obj);
  167. if (keyTuple[0].length===0) {
  168. return keyTuple[1];
  169. }
  170. else {
  171. return keyTuple[0] + "/" + keyTuple[1];
  172. }
  173. };
  174. WidgetFactory.saveSize = function(widget) {
  175. if (!widget) {
  176. return;
  177. }
  178. var name = widget.objectName;
  179. if (name.length===0) {
  180. return;
  181. }
  182. RSettings.setValue(name + "/Width", widget.width);
  183. RSettings.setValue(name + "/Height", widget.height);
  184. };
  185. WidgetFactory.restoreSize = function(widget) {
  186. if (!widget) {
  187. return;
  188. }
  189. var name = widget.objectName;
  190. if (name.length===0) {
  191. return;
  192. }
  193. var w = RSettings.getIntValue(name + "/Width", widget.width);
  194. var h = RSettings.getIntValue(name + "/Height", widget.height);
  195. widget.resize(w, h);
  196. };
  197. /**
  198. * Saves the current state of the given \c widget and all its child widgets.
  199. *
  200. * \param group Used internally for recursive calls.
  201. * \param document RDocument or RObject to store settings or \c undefined to store
  202. * settings in RSettings (user scope, config file).
  203. * \param map Array to use to store settings in. Used by the testing dashboard
  204. * recorder only.
  205. */
  206. WidgetFactory.saveState = function(widget, group, document, map) {
  207. if (!widget) {
  208. return;
  209. }
  210. if (typeof(WidgetFactory.requiresRestart) === "undefined") {
  211. WidgetFactory.requiresRestart = false;
  212. }
  213. group = (isNull(group) ? widget.objectName : group);
  214. // Qt5: QWebView has no scriptable children method:
  215. if (!isFunction(widget["children"])) {
  216. return;
  217. }
  218. var value;
  219. var data;
  220. var children = widget.children();
  221. for (var i = 0; i < children.length; ++i) {
  222. var c = children[i];
  223. if (!c || isDeleted(c) || c.toString().startsWith("QVariantAnimation") ||
  224. c.toString().startsWith("QWidgetAction") || c.objectName==="" ||
  225. c.objectName==="Icon" || c.objectName==="qt_toolbar_ext_button") {
  226. continue;
  227. }
  228. // ignore Qt internal widgets:
  229. if (typeof(c.objectName)!="undefined" &&
  230. c.objectName==="qt_toolbar_ext_button") {
  231. continue;
  232. }
  233. // ignore widgets that have been saved elsewhere (e.g. plugins might
  234. // save widgets contents by themselves in savePreferences):
  235. if (typeof(c.property("Saved")) != "undefined" && c.property("Saved")===true) {
  236. continue;
  237. }
  238. // skip children from other groups in this widget (for options toolbar):
  239. if (typeof(c.property("SettingsGroup")) != "undefined" && c.property("SettingsGroup") != group) {
  240. if (isNull(map)) {
  241. continue;
  242. }
  243. }
  244. var key = WidgetFactory.getKeyString(group, c);
  245. value = undefined;
  246. if (isOfType(c, QLineEdit)) {
  247. value = c.text;
  248. }
  249. else if (isOfType(c, QPlainTextEdit)) {
  250. value = c.toPlainText();
  251. }
  252. else if (isOfType(c, RMathLineEdit)) {
  253. //value = [c.text, c.getDefaultUnit()];
  254. value = c.text;
  255. }
  256. else if (isOfType(c, RMathComboBox)) {
  257. value = c.currentText;
  258. }
  259. else if (isOfType(c, QCheckBox)) {
  260. value = c.checked;
  261. }
  262. else if (isOfType(c, QRadioButton) ||
  263. isOfType(c, QToolButton) ||
  264. isOfType(c, QPushButton)) {
  265. if (!c.group() && !c.autoExclusive) {
  266. if (c.checkable) {
  267. value = c.checked;
  268. }
  269. }
  270. else {
  271. if (c.checked) {
  272. // if tool button or radio button is in a group,
  273. // the button group or group box handles the value:
  274. value = c.objectName;
  275. }
  276. }
  277. }
  278. else if (isOfType(c, QComboBox) || isOfType(c, QFontComboBox)) {
  279. var forceSaveText = false;
  280. var forceSaveIndex = false;
  281. if (typeof(c.property("ForceSaveText")) != "undefined"
  282. && c.property("ForceSaveText") === true) {
  283. forceSaveText = true;
  284. }
  285. if (typeof(c.property("ForceSaveIndex")) != "undefined"
  286. && c.property("ForceSaveIndex") === true) {
  287. forceSaveIndex = true;
  288. }
  289. if (forceSaveIndex == true) {
  290. value = c.currentIndex;
  291. }
  292. else if (forceSaveText === true || isNull(c.itemData(c.currentIndex))) {
  293. value = c.currentText;
  294. } else {
  295. value = c.itemData(c.currentIndex);
  296. }
  297. }
  298. else if (isOfType(c, RColorCombo)) {
  299. value = c.getColor();
  300. }
  301. else if (isOfType(c, RLineweightCombo)) {
  302. value = c.getLineweight();
  303. }
  304. else if (isOfType(c, RLinetypeCombo)) {
  305. value = c.getLinetypePattern();
  306. }
  307. else if (isOfType(c, QSpinBox) || isOfType(c, QDoubleSpinBox)) {
  308. value = c.value;
  309. }
  310. else if (isOfType(c, QSlider)) {
  311. value = c.value;
  312. }
  313. else if (isOfType(c, QListWidget)) {
  314. var items = [];
  315. if (c.count != 0) {
  316. for ( var j = 0; j < c.count; ++j) {
  317. items.push(c.item(j).text());
  318. }
  319. }
  320. value = items;
  321. // save user data of current item
  322. data = undefined;
  323. if (!isNull(c.currentItem())) {
  324. data = c.currentItem().data(Qt.UserRole);
  325. }
  326. if (!isNull(data)) {
  327. var dataKey = key + ".data";
  328. if (document) {
  329. if (isObject(document)) {
  330. document.setCustomProperty("QCAD", dataKey, data);
  331. }
  332. else {
  333. document.setVariable(dataKey, data);
  334. }
  335. } else {
  336. RSettings.setValue(dataKey, data);
  337. }
  338. }
  339. }
  340. else if (c.toString().startsWith("RFontChooserWidget")) {
  341. value = c.getChosenFont();
  342. }
  343. if (isNull(value)) {
  344. WidgetFactory.saveState(c, group, document, map);
  345. continue;
  346. }
  347. // save property
  348. if (typeof(c.property("SaveProperty")) != "undefined") {
  349. var prop = c.property("SaveProperty");
  350. RSettings.setValue(key + "." + prop, c[prop]);
  351. }
  352. // widgets with dynamic property "RequiresRestart" trigger a
  353. // restart application warning after changing preferences:
  354. if (typeof(c.property("RequiresRestart")) != "undefined"
  355. && c.property("RequiresRestart") === true) {
  356. WidgetFactory.requiresRestart = true;
  357. }
  358. // widgets can be ignored by setting the dynamic property
  359. // "SaveContents" = false
  360. var saveContents = true;
  361. if (typeof(c.property("SaveContents")) != "undefined"
  362. && c.property("SaveContents") === false) {
  363. saveContents = false;
  364. }
  365. if (saveContents) {
  366. if (document) {
  367. if (isObject(document)) {
  368. // save key / value pair to object:
  369. document.setCustomProperty("QCAD", key, value);
  370. }
  371. else {
  372. // save key / value pair to document:
  373. document.setVariable(key, value);
  374. }
  375. } else if (map) {
  376. // save key / value pair to map:
  377. map.put(key, value);
  378. } else {
  379. // save key / value pair to settings (e.g. ini file):
  380. RSettings.setValue(key, value);
  381. }
  382. }
  383. }
  384. };
  385. /**
  386. * Restores the state of the given \c widget to a previously saved state.
  387. *
  388. * \param group Used internally for recursive calls.
  389. * \param signalReceiver Object that receives signals whenever a child widget
  390. * changes its value.
  391. * \param reset True: Reset values to original values as defined in
  392. * designer (.ui file). \see resetState
  393. * \param document RDocument object or RObject to restore settings from or \c undefined
  394. * to restore settings from RSettings (user scope, config file).
  395. * \param map Map object to restore settings from.
  396. */
  397. WidgetFactory.restoreState = function(widget, group, signalReceiver, reset, document, map) {
  398. var f, index, j, hasData;
  399. var topLevelSet = false;
  400. if (isNull(WidgetFactory.topLevelWidget)) {
  401. widget.slotSettingChanged = function() {
  402. if (isFunction(this.settingChangedEvent)) {
  403. this.settingChangedEvent();
  404. }
  405. this.setProperty("hasChanged", true);
  406. };
  407. WidgetFactory.topLevelWidget = widget;
  408. topLevelSet = true;
  409. }
  410. group = (isNull(group) ? widget.objectName : group);
  411. reset = (isNull(reset) ? false : reset);
  412. if (isDeleted(widget)) {
  413. return;
  414. }
  415. // Qt5: QWebView has no scriptable children method:
  416. if (!isFunction(widget.children)) {
  417. return;
  418. }
  419. var children = widget.children();
  420. for ( var i = 0; i < children.length; ++i) {
  421. var c = children[i];
  422. if (!c || isDeleted(c)) {
  423. continue;
  424. }
  425. // ignore widgets without name:
  426. if (isNull(c.objectName) || c.objectName==="") {
  427. continue;
  428. }
  429. // ignore Qt internal widgets:
  430. if (c.objectName==="qt_toolbar_ext_button") {
  431. continue;
  432. }
  433. // ignore labels, widget actions:
  434. if (isOfType(c, QLabel) || isOfType(c, QWidgetAction)) {
  435. continue;
  436. }
  437. // skip children from other groups in this widget (for options toolbar):
  438. // but not if used from a test [map != undefined]
  439. if (isNull(map) && typeof (c.property("SettingsGroup")) != "undefined" && c.property("SettingsGroup") !== group) {
  440. continue;
  441. }
  442. // skip ignored children (future need?):
  443. //if (typeof(c["Ignore"])!="undefined" && c["Ignore"]==true) {
  444. // continue;
  445. //}
  446. // handle widgets which have their own reset method
  447. var hasOwnReset = false;
  448. if (typeof(c.property("hasOwnReset")) != "undefined" && c.property("hasOwnReset") == true) {
  449. hasOwnReset = true;
  450. }
  451. if (reset && hasOwnReset) {
  452. if (isFunction(c.resetState)) {
  453. c.resetState();
  454. }
  455. continue;
  456. }
  457. var key = WidgetFactory.getKeyString(group, c);
  458. var value = undefined;
  459. if (reset && !isNull(c.property("defaultValue")) && (typeof(c.property("SettingsGroup"))=="undefined" || c.property("SettingsGroup")===group)) {
  460. value = c.property("defaultValue");
  461. } else {
  462. if (!isNull(map)) {
  463. value = map.get(key);
  464. } else {
  465. if (!isNull(document)) {
  466. if (isObject(document)) {
  467. value = document.getCustomProperty("QCAD", key, undefined);
  468. }
  469. else {
  470. value = document.getVariable(key);
  471. }
  472. }
  473. // document / object has no value for key, try settings for default value:
  474. if (isNull(document) || isNull(value)) {
  475. value = RSettings.getValue(key);
  476. }
  477. }
  478. }
  479. // only process children if key delivered no value:
  480. if (isNull(value) || isOfType(c, QGroupBox)) {
  481. // never process internal children of these widgets:
  482. if (WidgetFactory.processChildren(c)) {
  483. WidgetFactory.restoreState(c, group, signalReceiver, reset, document, map);
  484. }
  485. }
  486. // don't restore widgets that have been restored elsewhere (e.g. script
  487. // add-ons might load widgets contents by themselves in initPreferences):
  488. // [but always restore widgets if used from a test (map != undefined)]
  489. if (isNull(map) && !reset && c.property("Loaded")===true) {
  490. value = undefined;
  491. }
  492. // restore property
  493. if (typeof(c.property("SaveProperty")) != "undefined") {
  494. var prop = c.property("SaveProperty");
  495. var val = RSettings.getValue(key + "." + prop);
  496. if (!isNull(val)) {
  497. c[prop] = val;
  498. }
  499. }
  500. if (isOfType(c, QLabel)) {
  501. continue;
  502. }
  503. // qDebug("restoring: ", c.objectName);
  504. // qDebug(" value: ", value);
  505. if (isOfType(c, QPlainTextEdit)) {
  506. if (!reset) {
  507. WidgetFactory.connect(c.textChanged, signalReceiver, c.objectName);
  508. WidgetFactory.connect(c.textChanged, WidgetFactory.topLevelWidget, "Setting");
  509. }
  510. if (isNull(c.property("defaultValue"))) {
  511. c.setProperty("defaultValue", c.toPlainText());
  512. }
  513. if (!isNull(value)) {
  514. c.setPlainText(value);
  515. }
  516. continue;
  517. }
  518. if (isOfType(c, RMathLineEdit)) {
  519. if (!reset) {
  520. WidgetFactory.connect(c.valueChanged, signalReceiver, c.objectName);
  521. WidgetFactory.connect(c.valueChanged, WidgetFactory.topLevelWidget, "Setting");
  522. }
  523. if (isNull(c.property("defaultValue"))) {
  524. //c.defaultValue = [c.text, c.getDefaultUnit()];
  525. c.setProperty("defaultValue", c.text);
  526. c.slotTextChanged(c.text);
  527. }
  528. if (!isNull(value)) {
  529. // deprecated: value and default unit:
  530. if (isArray(value) && value.length===2) {
  531. if (isNull(value[0])) {
  532. c.text = "";
  533. }
  534. else {
  535. c.text = value[0].toString();
  536. }
  537. }
  538. else {
  539. if (isString(value)) {
  540. c.text = value;
  541. }
  542. else {
  543. c.text = "%1".arg(value);
  544. }
  545. }
  546. }
  547. continue;
  548. }
  549. if (isOfType(c, RMathComboBox)) {
  550. if (!reset) {
  551. WidgetFactory.connect(c.valueChanged, signalReceiver, c.objectName);
  552. WidgetFactory.connect(c.valueChanged, WidgetFactory.topLevelWidget, "Setting");
  553. }
  554. if (isNull(c.property("defaultValue"))) {
  555. //c.defaultValue = [c.text, c.getDefaultUnit()];
  556. c.setProperty("defaultValue", c.currentText);
  557. c.slotTextChanged(c.currentText);
  558. }
  559. if (!isNull(value)) {
  560. if (isString(value)) {
  561. c.currentText = value;
  562. }
  563. else {
  564. c.currentText = "%1".arg(value);
  565. }
  566. }
  567. continue;
  568. }
  569. if (isOfType(c, QLineEdit)) {
  570. if (!reset) {
  571. WidgetFactory.connect(c.textChanged, signalReceiver, c.objectName);
  572. WidgetFactory.connect(c.textChanged, WidgetFactory.topLevelWidget, "Setting");
  573. }
  574. if (isNull(c.property("defaultValue"))) {
  575. c.setProperty("defaultValue", c.text);
  576. }
  577. if (!isNull(value)) {
  578. c.text = value.toString();
  579. }
  580. continue;
  581. }
  582. if (isOfType(c, QToolButton) || isOfType(c, QPushButton)) {
  583. if (isNull(c.group()) && !c.autoExclusive) {
  584. if (c.checkable) {
  585. if (!reset) {
  586. WidgetFactory.connect(c.toggled, signalReceiver, c.objectName);
  587. WidgetFactory.connect(c.toggled, WidgetFactory.topLevelWidget, "Setting");
  588. }
  589. if (isNull(c.property("defaultValue"))) {
  590. c.setProperty("defaultValue", c.checked);
  591. }
  592. if (!isNull(value)) {
  593. c.checked = (value === true || value === "true");
  594. }
  595. }
  596. else {
  597. if (!reset) {
  598. WidgetFactory.connect(c.clicked, signalReceiver, c.objectName, false);
  599. }
  600. }
  601. }
  602. else {
  603. if (!reset) {
  604. WidgetFactory.connect(c.toggled, signalReceiver, c.objectName);
  605. }
  606. }
  607. continue;
  608. }
  609. if (isOfType(c, QCheckBox)) {
  610. if (!reset) {
  611. WidgetFactory.connect(c.toggled, signalReceiver, c.objectName);
  612. WidgetFactory.connect(c.stateChanged, WidgetFactory.topLevelWidget, "Setting");
  613. }
  614. if (isNull(c.property("defaultValue"))) {
  615. c.setProperty("defaultValue", c.checked);
  616. if (!isNull(signalReceiver)) {
  617. f = signalReceiver["slot"+c.objectName+"Changed"];
  618. if (isFunction(f)) {
  619. f.call(signalReceiver, c.checked);
  620. }
  621. }
  622. }
  623. if (!isNull(value)) {
  624. c.checked = (value === true || value == "true");
  625. }
  626. continue;
  627. }
  628. if (isOfType(c, QRadioButton)) {
  629. if (!c.group() && !c.autoExclusive) {
  630. WidgetFactory.connect(c.toggled, signalReceiver, c.objectName);
  631. WidgetFactory.connect(c.toggled, WidgetFactory.topLevelWidget, "Setting");
  632. if (isNull(c.property("defaultValue"))) {
  633. c.setProperty("defaultValue", c.checked);
  634. }
  635. if (!isNull(value)) {
  636. c.checked = (value === true || value == "true");
  637. }
  638. }
  639. else {
  640. WidgetFactory.connect(c.toggled, signalReceiver, c.objectName);
  641. WidgetFactory.connect(c.toggled, WidgetFactory.topLevelWidget, "Setting");
  642. if (value==="true") {
  643. c.checked = true;
  644. }
  645. else {
  646. c.checked = (c.objectName == value);
  647. }
  648. }
  649. continue;
  650. }
  651. if (isOfType(c, QButtonGroup)) {
  652. if (!reset) {
  653. WidgetFactory.connect(c["buttonClicked(QAbstractButton*)"], signalReceiver, c.objectName);
  654. WidgetFactory.connect(c["buttonClicked(QAbstractButton*)"], WidgetFactory.topLevelWidget, "Setting");
  655. }
  656. if (isNull(c.property("defaultValue"))) {
  657. var button = c.checkedButton();
  658. if (!isNull(button) && !isNull(button.objectName)) {
  659. c.setProperty("defaultValue", button.objectName);
  660. if (!isNull(signalReceiver)) {
  661. f = signalReceiver["slot"+c.objectName+"Changed"];
  662. if (isFunction(f)) {
  663. f.call(signalReceiver, button);
  664. }
  665. }
  666. }
  667. }
  668. if (!isNull(value)) {
  669. var buttons = c.buttons();
  670. for (var k=0; k<buttons.length; k++) {
  671. if (buttons[k].objectName==value) {
  672. buttons[k].checked = true;
  673. if (!isNull(signalReceiver)) {
  674. f = signalReceiver["slot"+c.objectName+"Changed"];
  675. if (isFunction(f)) {
  676. f.call(signalReceiver, buttons[k]);
  677. }
  678. }
  679. break;
  680. }
  681. }
  682. }
  683. }
  684. if (isOfType(c, QComboBox) && c.editable) {
  685. if (!reset) {
  686. WidgetFactory.connect(c.editTextChanged, signalReceiver, c.objectName);
  687. WidgetFactory.connect(c.editTextChanged, WidgetFactory.topLevelWidget, "Setting");
  688. }
  689. if (isNull(c.property("defaultValue"))) {
  690. c.setProperty("defaultValue", c.currentText);
  691. if (!isNull(signalReceiver)) {
  692. f = signalReceiver["slot" + c.objectName + "Changed"];
  693. if (isFunction(f)) {
  694. f.call(signalReceiver, c.currentText);
  695. }
  696. }
  697. }
  698. if (!isNull(value)) {
  699. index = c.findText(value);
  700. if (index !== -1) {
  701. c.currentIndex = index;
  702. continue;
  703. }
  704. c.setEditText(value);
  705. }
  706. continue;
  707. }
  708. if ((isOfType(c, QComboBox) && !c.editable) || isOfType(c, QFontComboBox)) {
  709. if (!reset) {
  710. WidgetFactory.connect(c['currentIndexChanged(int)'], signalReceiver, c.objectName);
  711. WidgetFactory.connect(c['currentIndexChanged(int)'], WidgetFactory.topLevelWidget, "Setting");
  712. }
  713. hasData = false;
  714. if (c.itemData(c.currentIndex)!=undefined || (c.count>0 && c.itemData(0)!=undefined)) {
  715. hasData = true;
  716. }
  717. if (isNull(c.property("defaultValue"))) {
  718. if (hasData) {
  719. if (c.currentIndex>=0 && c.currentIndex<c.count) {
  720. c.setProperty("defaultValue", c.itemData(c.currentIndex));
  721. }
  722. } else {
  723. c.setProperty("defaultValue", c.currentText);
  724. }
  725. if (signalReceiver!=undefined) {
  726. f = signalReceiver["slot" + c.objectName + "Changed"];
  727. if (typeof(f)=="function") {
  728. f.call(signalReceiver, c.currentIndex);
  729. }
  730. }
  731. }
  732. var forceSaveText = false;
  733. var forceSaveIndex = false;
  734. if (typeof(c.property("ForceSaveText")) != "undefined"
  735. && c.property("ForceSaveText") == true) {
  736. forceSaveText = true;
  737. }
  738. if (typeof(c.property("ForceSaveIndex")) != "undefined"
  739. && c.property("ForceSaveIndex") == true) {
  740. forceSaveIndex = true;
  741. }
  742. if (!isNull(value)) {
  743. index = -1;
  744. if (forceSaveIndex == true) {
  745. index = parseInt(value);
  746. }
  747. else if (forceSaveText == false && hasData) {
  748. index = c.findData(value);
  749. } else {
  750. if (isString(value)) {
  751. index = c.findText(value);
  752. }
  753. }
  754. if (index !== -1) {
  755. c.currentIndex = index;
  756. continue;
  757. }
  758. }
  759. continue;
  760. }
  761. if (isOfType(c, RColorCombo)) {
  762. if (!reset) {
  763. WidgetFactory.connect(c.editTextChanged, signalReceiver, c.objectName);
  764. WidgetFactory.connect(c["currentIndexChanged(int)"], WidgetFactory.topLevelWidget, "Setting");
  765. }
  766. if (isNull(c.property("defaultValue"))) {
  767. c.setProperty("defaultValue", c.getColor());
  768. }
  769. if (!isNull(value)) {
  770. // color name given:
  771. if (isString(value)) {
  772. c.setColor(new RColor(value));
  773. }
  774. // color object given:
  775. else {
  776. if (isOfType(value, RColor)) {
  777. c.setColor(value);
  778. }
  779. else {
  780. qWarning("value is not of type RColor:", value);
  781. }
  782. }
  783. }
  784. continue;
  785. }
  786. if (isOfType(c, RLineweightCombo)) {
  787. if (!reset) {
  788. WidgetFactory.connect(c.editTextChanged, signalReceiver, c.objectName);
  789. WidgetFactory.connect(c["currentIndexChanged(int)"], WidgetFactory.topLevelWidget, "Setting");
  790. }
  791. if (isNull(c.property("defaultValue"))) {
  792. c.setProperty("defaultValue", c.getLineweight());
  793. }
  794. if (!isNull(value)) {
  795. if (isString(value)) {
  796. value = parseInt(value, 10);
  797. }
  798. c.setLineweight(value);
  799. }
  800. continue;
  801. }
  802. if (isOfType(c, RLinetypeCombo)) {
  803. if (!reset) {
  804. WidgetFactory.connect(c.editTextChanged, signalReceiver, c.objectName);
  805. WidgetFactory.connect(c["currentIndexChanged(int)"], WidgetFactory.topLevelWidget, "Setting");
  806. }
  807. if (isNull(c.property("defaultValue"))) {
  808. c.setProperty("defaultValue", c.getLinetypePattern());
  809. }
  810. if (!isNull(value)) {
  811. c.setLinetypePattern(value);
  812. }
  813. continue;
  814. }
  815. if (isOfType(c, QSpinBox) || isOfType(c, QDoubleSpinBox)) {
  816. if (!reset) {
  817. if (isOfType(c, QSpinBox)) {
  818. WidgetFactory.connect(c["valueChanged(int)"], signalReceiver, c.objectName);
  819. WidgetFactory.connect(c["valueChanged(int)"], WidgetFactory.topLevelWidget, "Setting");
  820. }
  821. else {
  822. WidgetFactory.connect(c["valueChanged(double)"], signalReceiver, c.objectName);
  823. WidgetFactory.connect(c["valueChanged(double)"], WidgetFactory.topLevelWidget, "Setting");
  824. }
  825. }
  826. if (isNull(c.property("defaultValue"))) {
  827. c.setProperty("defaultValue", c.value);
  828. if (signalReceiver!=undefined) {
  829. f = signalReceiver["slot" + c.objectName + "Changed"];
  830. if (isFunction(f)) {
  831. f.call(signalReceiver, c.value);
  832. }
  833. }
  834. }
  835. if (!isNull(value)) {
  836. if (isOfType(c, QSpinBox)) {
  837. c.value = parseInt(value);
  838. }
  839. else {
  840. c.value = parseFloat(value);
  841. }
  842. }
  843. continue;
  844. }
  845. if (isOfType(c, QSlider)) {
  846. if (!reset) {
  847. WidgetFactory.connect(c["valueChanged(int)"], signalReceiver, c.objectName);
  848. WidgetFactory.connect(c["valueChanged(int)"], WidgetFactory.topLevelWidget, "Setting");
  849. }
  850. if (isNull(c.property("defaultValue"))) {
  851. c.setProperty("defaultValue", c.value);
  852. if (signalReceiver!=undefined) {
  853. f = signalReceiver["slot" + c.objectName + "Changed"];
  854. if (isFunction(f)) {
  855. f.call(signalReceiver, c.value);
  856. }
  857. }
  858. }
  859. if (!isNull(value)) {
  860. c.value = value;
  861. }
  862. continue;
  863. }
  864. if (isOfType(c, QListWidget)) {
  865. // the SaveContents property is set to false
  866. // if the list contents should not be saved to
  867. // the configuration file or document:
  868. var saveContents = true;
  869. if (typeof(c.property("SaveContents")) != "undefined"
  870. && c.property("SaveContents") == false) {
  871. saveContents = false;
  872. }
  873. if (saveContents) {
  874. if (isNull(c.property("defaultValue"))) {
  875. var items = [];
  876. for (j = 0; j < c.count; ++j) {
  877. items.push(c.item(j).text());
  878. }
  879. c.setProperty("defaultValue", items);
  880. }
  881. if (!isNull(value)) {
  882. c.addItems(value);
  883. }
  884. } else {
  885. if (isNull(c.property("defaultValue")) && !isNull(c.currentItem())) {
  886. c.setProperty("defaultValue", c.currentItem().data(Qt.UserRole));
  887. }
  888. if (!isNull(value)) {
  889. for (j=0; j<c.count; ++j) {
  890. if (c.item(j).data(Qt.UserRole) == value) {
  891. c.currentRow = j;
  892. break;
  893. }
  894. }
  895. }
  896. }
  897. if (reset===false) {
  898. // restore user data of selected row
  899. hasData = false;
  900. if (!isNull(c.item(0)) && !isNull(c.item(0).data(Qt.UserRole))) {
  901. hasData = true;
  902. }
  903. if (hasData) {
  904. var data;
  905. var dataKey = key + ".data";
  906. if (!isNull(document)) {
  907. if (isObject(document)) {
  908. data = document.getCustomProperty("QCAD", key, undefined);
  909. }
  910. else {
  911. data = document.getVariable(dataKey);
  912. }
  913. }
  914. // document has no value for key,
  915. // try settings for default value
  916. if (isNull(document) || isNull(data)) {
  917. data = RSettings.getValue(dataKey);
  918. }
  919. if (!isNull(data)) {
  920. for (j = 0; j < c.count; ++j) {
  921. if (c.item(j).data(Qt.UserRole) == data.toString()) {
  922. c.currentRow = j;
  923. break;
  924. }
  925. }
  926. }
  927. }
  928. }
  929. if (!reset) {
  930. WidgetFactory.connect(c.itemChanged, signalReceiver, c.objectName);
  931. c.itemSelectionChanged.connect(WidgetFactory.topLevelWidget, WidgetFactory.topLevelWidget.slotSettingChanged);
  932. c.model().rowsInserted.connect(WidgetFactory.topLevelWidget, WidgetFactory.topLevelWidget.slotSettingChanged);
  933. }
  934. continue;
  935. }
  936. if (isOfType(c, RFontChooserWidget)) {
  937. if (!reset) {
  938. WidgetFactory.connect(c.valueChanged, signalReceiver, c.objectName);
  939. c.valueChanged.connect(WidgetFactory.topLevelWidget, WidgetFactory.topLevelWidget.slotSettingChanged);
  940. }
  941. if (isNull(c.property("defaultValue"))) {
  942. c.setProperty("defaultValue", c.getChosenFont());
  943. }
  944. if (!isNull(value)) {
  945. if (isString(value)) {
  946. var fnt = new QFont();
  947. fnt.fromString(value);
  948. value = fnt;
  949. }
  950. c.setChosenFont(value);
  951. }
  952. continue;
  953. }
  954. }
  955. if (topLevelSet) {
  956. WidgetFactory.topLevelWidget = undefined;
  957. }
  958. };
  959. /**
  960. * Resets values to original values as defined in designer (.ui file).
  961. */
  962. WidgetFactory.resetState = function(widget, group) {
  963. WidgetFactory.restoreState(widget, group, undefined, true);
  964. };
  965. WidgetFactory.processChildren = function(c) {
  966. if (isOfType(c, QSpinBox) ||
  967. isOfType(c, QDoubleSpinBox) ||
  968. isOfType(c, QComboBox) ||
  969. isOfType(c, QFontComboBox) ||
  970. isOfType(c, QPlainTextEdit) ||
  971. isOfType(c, RMathLineEdit) ||
  972. isOfType(c, RMathComboBox)) {
  973. return false;
  974. }
  975. return true;
  976. };
  977. /**
  978. * \internal
  979. */
  980. WidgetFactory.connect = function(sig, signalReceiver, objectName, isValue) {
  981. if (isNull(signalReceiver)) {
  982. return;
  983. }
  984. // connect signal to given function:
  985. // obsolete?
  986. if (isFunction(signalReceiver)) {
  987. sig.connect(signalReceiver);
  988. return;
  989. }
  990. // connect signal to automatically named slot of receiver object:
  991. var slot;
  992. if (isNull(isValue) || isValue===true) {
  993. slot = "slot" + objectName + "Changed";
  994. }
  995. else {
  996. slot = "slot" + objectName;
  997. }
  998. //if (eval("signalReceiver." + slot) != undefined) {
  999. if (!isNull(signalReceiver[slot])) {
  1000. if (RSettings.getQtVersion() >= 0x060000) {
  1001. sig.connect(signalReceiver, signalReceiver[slot]);
  1002. }
  1003. else {
  1004. sig.connect(signalReceiver, slot);
  1005. }
  1006. }
  1007. };
  1008. /**
  1009. * Moves all child objects from sourceWidget to targetWidget (usually a toolbar).
  1010. *
  1011. * \return Array of actions that were added to targetWidget.
  1012. */
  1013. WidgetFactory.moveChildren = function(sourceWidget, targetWidget, settingsGroup) {
  1014. var ret = [];
  1015. var a;
  1016. // move child widgets of UI file based widget directly to
  1017. // options toolbar. rendering of tool buttons greatly depends
  1018. // on this (especially on macOS):
  1019. var children = sourceWidget.children();
  1020. for(var i=0;i<children.length;++i) {
  1021. var w = children[i];
  1022. if (isNull(w)) {
  1023. continue;
  1024. }
  1025. w.setProperty("SettingsGroup", settingsGroup);
  1026. // add separator:
  1027. if (isSeparator(w)) {
  1028. a = targetWidget.addSeparator();
  1029. a.objectName = w.objectName + "Action";
  1030. ret.push(a);
  1031. }
  1032. // reparent required for non-widgets (e.g. QButtonGroup):
  1033. else if (!isFunction(w.show)) {
  1034. // these children would crash QCAD on exit if they are reparented:
  1035. if (!w.toString().startsWith("QBoxLayout") &&
  1036. !w.toString().startsWith("QFormInternal") &&
  1037. !w.toString().startsWith("QVariantAnimation")) {
  1038. w.setParent(targetWidget);
  1039. }
  1040. }
  1041. // add widgets:
  1042. else {
  1043. if (isOfType(w, QLabel) || isOfType(w, QCheckBox)) {
  1044. // prevent styles from overriding fixed size (e.g. for icon labels):
  1045. if (w.sizePolicy.horizontalPolicy()!==QSizePolicy.Fixed) {
  1046. w.styleSheet = "margin-left: 5px; margin-right: 5px;" + w.styleSheet;
  1047. }
  1048. }
  1049. // add line edit or math edit with maximum width:
  1050. if (isOfType(w, QLineEdit) || isOfType(w, RMathLineEdit) || isOfType(w, RMathComboBox)) {
  1051. if (w.maximumWidth>=1024) {
  1052. w.maximumWidth = 75;
  1053. }
  1054. }
  1055. if (isOfType(w, RMathLineEdit) || isOfType(w, RMathComboBox)) {
  1056. WidgetFactory.initLineEditInfoTools(w);
  1057. }
  1058. a = targetWidget.addWidget(w);
  1059. a.objectName = w.objectName + "Action";
  1060. ret.push(a);
  1061. }
  1062. // automatically set tool tip and icon for reset button:
  1063. if (w.objectName==="Reset") {
  1064. w.icon = new QIcon(WidgetFactory.includeBasePath + "/ResetToDefaults.svg");
  1065. w.toolTip = qsTr("Restore defaults");
  1066. }
  1067. }
  1068. return ret;
  1069. };
  1070. WidgetFactory.adjustIcons = function(includeBasePath, widget) {
  1071. if (isNull(widget) || !isFunction(widget.children)) {
  1072. return;
  1073. }
  1074. var children = widget.children();
  1075. for(var i=0;i<children.length;++i) {
  1076. var w=children[i];
  1077. // adjust icon for theme / dark mode:
  1078. if (isOfType(w, QToolButton)) {
  1079. var iconFile = autoIconPath(includeBasePath + "/" + w.objectName + ".svg");
  1080. if (!isNull(iconFile)) {
  1081. w.icon = new QIcon(iconFile);
  1082. }
  1083. }
  1084. else {
  1085. WidgetFactory.adjustIcons(includeBasePath, w);
  1086. }
  1087. }
  1088. };
  1089. WidgetFactory.initLineEditInfoTools = function(mathLineEdit) {
  1090. };
  1091. /**
  1092. * Adds an "insert symbol" menu entry to the context menu of the given
  1093. * line edit.
  1094. *
  1095. * \param lineEdit QLineEdit object
  1096. * \param dimension bool Add symbols that are only appropriate for
  1097. * dimension labels (<> for measured value).
  1098. */
  1099. WidgetFactory.initLineEdit = function(lineEdit, dimension) {
  1100. lineEdit.contextMenuPolicy = Qt.CustomContextMenu;
  1101. lineEdit.customContextMenuRequested.connect(function(pos) {
  1102. var menu = lineEdit.createStandardContextMenu();
  1103. var subMenu = new QMenu(qsTr("Insert Symbol"));
  1104. // TODO: split into submenus (math, greek, ...):
  1105. var symbols = [
  1106. [0x00B0, qsTr("Degrees")],
  1107. [0x00B1, qsTr("Plus/Minus")],
  1108. [0x00F8, qsTr("Diameter")],
  1109. [0x00F7, qsTr("Division")],
  1110. [0x2248, qsTr("Almost Equal")],
  1111. [0x2220, qsTr("Angle")],
  1112. [0x2312, qsTr("Arc")],
  1113. [0x2243, qsTr("Asymptotically Equal")],
  1114. //[0xE100, qsTr("Boundary Line")],
  1115. [0x2104, qsTr("Center Line")],
  1116. [0x0394, qsTr("Delta")],
  1117. [0x0278, qsTr("Electrical Phase")],
  1118. //[0xE101, qsTr("Flow Line")],
  1119. [0x2261, qsTr("Identity")],
  1120. //[0xE200, qsTr("Initial Length")],
  1121. //[0xE102, qsTr("Monument Line")],
  1122. [0x00D7, qsTr("Multiplication")],
  1123. [0x2260, qsTr("Not Equal")],
  1124. [0x2126, qsTr("Ohm")],
  1125. [0x03A9, qsTr("Omega")],
  1126. [0x03C9, qsTr("omega")],
  1127. [0x03A6, qsTr("Phi")],
  1128. [0x0278, qsTr("phi")],
  1129. [0x03C6, qsTr("Alt phi")],
  1130. [0x03C0, qsTr("Pi")],
  1131. [0x214A, qsTr("Property Line")],
  1132. [0x2082, qsTr("Subscript 2")],
  1133. [0x221A, qsTr("Square Root")],
  1134. [0x25FB, qsTr("Square")],
  1135. [0x00B2, qsTr("Squared")],
  1136. [0x00B3, qsTr("Cubed")],
  1137. ["\\SA^B;", qsTr("Stacked text"), "\\\\SA^B;"]
  1138. ];
  1139. if (dimension===true) {
  1140. symbols.unshift([]);
  1141. symbols.unshift(["<>", qsTr("Measured value")]);
  1142. }
  1143. for (var i=0; i<symbols.length; ++i) {
  1144. var symbol = symbols[i];
  1145. if (symbol.length===0) {
  1146. subMenu.addSeparator();
  1147. continue;
  1148. }
  1149. var symbolCode = symbol[0];
  1150. var symbolCodeStr;
  1151. var symbolSelf;
  1152. if (isNumber(symbolCode)) {
  1153. symbolCodeStr = symbolCode.toString(16);
  1154. while (symbolCodeStr.length<4) {
  1155. symbolCodeStr = "0" + symbolCodeStr;
  1156. }
  1157. symbolCodeStr = ", \\U+" + symbolCodeStr;
  1158. symbolSelf = String.fromCharCode(symbolCode);
  1159. }
  1160. else {
  1161. symbolCodeStr = "";
  1162. symbolSelf = symbolCode;
  1163. }
  1164. var symbolText = symbol[1];
  1165. var insertion = String.fromCharCode(symbol[0]);
  1166. if (symbol.length===3) {
  1167. insertion = symbol[2];
  1168. }
  1169. var action = subMenu.addAction(symbolSelf + "\t(" + symbolText + symbolCodeStr + ")");
  1170. eval("action.triggered.connect(function() { lineEdit.setFocus(Qt.OtherFocusReason); lineEdit.insert(\"" + insertion + "\"); });");
  1171. }
  1172. var actions = menu.actions();
  1173. menu.removeAction(actions[actions.length-1]);
  1174. menu.removeAction(actions[actions.length-2]);
  1175. var separatorAction = menu.insertSeparator(actions[0]);
  1176. menu.insertMenu(separatorAction, subMenu);
  1177. menu.exec(QCursor.pos());
  1178. if (!isDeleted(menu)) {
  1179. destr(menu);
  1180. }
  1181. });
  1182. };
  1183. WidgetFactory.initTextBrowser = function(textBrowser, slot) {
  1184. textBrowser.openLinks = false;
  1185. textBrowser.anchorClicked.connect(slot);
  1186. };
  1187. //WidgetFactory.initWebView = function(webView, linkHandler, slot) {
  1188. // var webPage = webView.page();
  1189. // webPage.linkDelegationPolicy = QWebPage.DelegateExternalLinks;
  1190. // webPage.linkClicked.connect(linkHandler, slot);
  1191. // var webSettings = webView.settings();
  1192. // webSettings.setFontFamily(QWebSettings.StandardFont, EAction.getMainWindow().font.family());
  1193. // if (RS.getSystemId()==="osx") {
  1194. // webSettings.setFontSize(QWebSettings.DefaultFontSize, EAction.getMainWindow().font.pointSize());
  1195. // }
  1196. // if (!RSettings.isQt(5)) {
  1197. // // make web view transparent:
  1198. // var palette = webView.palette;
  1199. // palette.setBrush(QPalette.Base, new QColor(0,0,0,0));
  1200. // webPage.palette = palette;
  1201. // webView.setAttribute(Qt.WA_OpaquePaintEvent, false);
  1202. // }
  1203. //};
  1204. WidgetFactory.initLayerCombo = function(comboBox, doc, clear) {
  1205. var i;
  1206. if (isNull(doc)) {
  1207. return;
  1208. }
  1209. if (isNull(clear)) {
  1210. clear = true;
  1211. }
  1212. var existingLayerNames = [];
  1213. if (clear) {
  1214. comboBox.clear();
  1215. }
  1216. else {
  1217. for (i=0; i<comboBox.count; i++) {
  1218. var t = comboBox.itemText(i);
  1219. existingLayerNames.push(t);
  1220. }
  1221. }
  1222. comboBox.iconSize = new QSize(16, 10);
  1223. var names = doc.getLayerNames();
  1224. //names = RS.sortAlphanumerical(names);
  1225. names.sort(Array.alphaNumericalSorter);
  1226. for (i=0; i<names.length; i++) {
  1227. var name = names[i];
  1228. var layer = doc.queryLayer(name);
  1229. if (existingLayerNames.containsIgnoreCase(layer.getName())) {
  1230. // don't overwrite existing layers:
  1231. continue;
  1232. }
  1233. var icon = RColor.getIcon(layer.getColor(), new QSize(comboBox.iconSize.width(),10));
  1234. comboBox.addItem(icon, layer.getName());
  1235. }
  1236. };
  1237. WidgetFactory.initBlockCombo = function(comboBox, doc, showSpaces) {
  1238. if (isNull(doc)) {
  1239. return;
  1240. }
  1241. if (isNull(showSpaces)) {
  1242. showSpaces = false;
  1243. }
  1244. comboBox.clear();
  1245. var names = doc.getBlockNames();
  1246. names.sort(Array.alphaNumericalSorter);
  1247. //names = RS.sortAlphanumerical(names);
  1248. for (var i=0; i<names.length; i++) {
  1249. var name = names[i];
  1250. if (showSpaces || !name.startsWith("*")) {
  1251. comboBox.addItem(name);
  1252. }
  1253. }
  1254. };
  1255. WidgetFactory.initList = function(list, groupName) {
  1256. if (isNull(list)) {
  1257. return;
  1258. }
  1259. if (RSettings.getBoolValue(groupName + "/EnableAlternatingRowColor", false)===true) {
  1260. list.alternatingRowColors = true;
  1261. var p = list.palette;
  1262. var col = RSettings.getColorValue(groupName + "/AlternatingRowColor", new RColor(230, 235, 250));
  1263. p.setColor(QPalette.AlternateBase, new QColor(col.red(), col.green(), col.blue(), col.alpha()));
  1264. list.palette = p;
  1265. }
  1266. else {
  1267. list.alternatingRowColors = false;
  1268. }
  1269. };
  1270. WidgetFactory.initHAlignCombo = function(comboBox) {
  1271. comboBox.clear();
  1272. comboBox.addItem(qsTr("Left"), RS.HAlignLeft);
  1273. comboBox.addItem(qsTr("Center"), RS.HAlignCenter);
  1274. comboBox.addItem(qsTr("Right"), RS.HAlignRight);
  1275. comboBox.addItem(qsTr("Aligned"), RS.HAlignAlign);
  1276. comboBox.addItem(qsTr("Middle"), RS.HAlignMid);
  1277. comboBox.addItem(qsTr("Fit"), RS.HAlignFit);
  1278. };
  1279. WidgetFactory.initVAlignCombo = function(comboBox) {
  1280. comboBox.clear();
  1281. comboBox.addItem(qsTr("Top"), RS.VAlignTop);
  1282. comboBox.addItem(qsTr("Middle"), RS.VAlignMiddle);
  1283. comboBox.addItem(qsTr("Base"), RS.VAlignBase);
  1284. comboBox.addItem(qsTr("Bottom"), RS.VAlignBottom);
  1285. };
  1286. WidgetFactory.initDimlunitCombo = function(comboBox) {
  1287. comboBox.clear();
  1288. comboBox.addItem(qsTr("Scientific"), RS.Scientific);
  1289. comboBox.addItem(qsTr("Decimal"), RS.Decimal);
  1290. comboBox.addItem(qsTr("Engineering"), RS.Engineering);
  1291. comboBox.addItem(qsTr("Architectural"), RS.ArchitecturalStacked);
  1292. comboBox.addItem(qsTr("Fractional"), RS.FractionalStacked);
  1293. };
  1294. WidgetFactory.initDimtadCombo = function(comboBox) {
  1295. comboBox.clear();
  1296. comboBox.addItem(qsTr("Centered"), 0);
  1297. comboBox.addItem(qsTr("Above"), 1);
  1298. };
  1299. WidgetFactory.initDimdsepCombo = function(comboBox) {
  1300. comboBox.clear();
  1301. comboBox.addItem(".", '.');
  1302. comboBox.addItem(",", ',');
  1303. };
  1304. WidgetFactory.initDimzinCombo = function(comboBox) {
  1305. comboBox.clear();
  1306. //comboBox.addItem(qsTr("Suppress 0'0\" (unsupported)"), 0);
  1307. comboBox.addItem(qsTr("Show trailing zeroes"), 0);
  1308. comboBox.addItem(qsTr("Include 0'0\"") + " " + qsTr("(unsupported)"), 1);
  1309. comboBox.addItem(qsTr("Include 0', suppress 0\"") + " " + qsTr("(unsupported)"), 2);
  1310. comboBox.addItem(qsTr("Include 0\", suppress 0'") + " " + qsTr("(unsupported)"), 3);
  1311. comboBox.addItem(qsTr("Suppress leading zeroes") + " " + qsTr("(unsupported)"), 4);
  1312. comboBox.addItem(qsTr("Suppress trailing zeroes"), 8);
  1313. comboBox.addItem(qsTr("Suppress leading / trailing zeroes") + " " + qsTr("(unsupported)"), 12);
  1314. // comboBox.addItem(qsTr("Suppress 0'0\""), 0);
  1315. // comboBox.addItem(qsTr("Include 0'0\""), 1);
  1316. // comboBox.addItem(qsTr("Include 0', suppress 0\""), 2);
  1317. // comboBox.addItem(qsTr("Include 0\", suppress 0'"), 3);
  1318. };
  1319. WidgetFactory.initDimdecCombo = function(comboBox) {
  1320. comboBox.clear();
  1321. comboBox.addItem("0", 0);
  1322. comboBox.addItem("1", 1);
  1323. comboBox.addItem("2", 2);
  1324. comboBox.addItem("3", 3);
  1325. comboBox.addItem("4", 4);
  1326. comboBox.addItem("5", 5);
  1327. comboBox.addItem("6", 6);
  1328. comboBox.addItem("7", 7);
  1329. comboBox.addItem("8", 8);
  1330. };
  1331. WidgetFactory.initDimaunitCombo = function(comboBox) {
  1332. comboBox.clear();
  1333. comboBox.addItem(qsTr("Decimal Degrees"), RS.DegreesDecimal);
  1334. comboBox.addItem(qsTr("Deg/min/sec"), RS.DegreesMinutesSeconds);
  1335. comboBox.addItem(qsTr("Gradians"), RS.Gradians);
  1336. comboBox.addItem(qsTr("Radians"), RS.Radians);
  1337. comboBox.addItem(qsTr("Surveyor's units"), RS.Surveyors);
  1338. };
  1339. WidgetFactory.initDimazinCombo = function(comboBox) {
  1340. comboBox.clear();
  1341. comboBox.addItem(qsTr("Show trailing zeroes"), 0);
  1342. comboBox.addItem(qsTr("Suppress leading zeroes") + " " + qsTr("(unsupported)"), 1);
  1343. comboBox.addItem(qsTr("Suppress trailing zeroes"), 2);
  1344. comboBox.addItem(qsTr("Suppress leading / trailing zeroes") + " " + qsTr("(unsupported)"), 3);
  1345. };
  1346. WidgetFactory.initDimadecCombo = function(comboBox) {
  1347. comboBox.clear();
  1348. comboBox.addItem("0", 0);
  1349. comboBox.addItem("1", 1);
  1350. comboBox.addItem("2", 2);
  1351. comboBox.addItem("3", 3);
  1352. comboBox.addItem("4", 4);
  1353. comboBox.addItem("5", 5);
  1354. comboBox.addItem("6", 6);
  1355. comboBox.addItem("7", 7);
  1356. comboBox.addItem("8", 8);
  1357. };
  1358. WidgetFactory.initOrientationCombo = function(comboBox) {
  1359. comboBox.clear();
  1360. if (RSettings.isQt(5)) {
  1361. comboBox.addItem("↻ " + qsTr("Clockwise"), RS.CW);
  1362. comboBox.addItem("↺ " + qsTr("Counterclockwise"), RS.CCW);
  1363. }
  1364. else {
  1365. comboBox.addItem(qsTr("Clockwise"), RS.CW);
  1366. comboBox.addItem(qsTr("Counterclockwise"), RS.CCW);
  1367. }
  1368. };
  1369. WidgetFactory.initArcSymbolTypeCombo = function(comboBox) {
  1370. comboBox.clear();
  1371. comboBox.addItem(qsTr("Preceding"), 0);
  1372. comboBox.addItem(qsTr("Above"), 1);
  1373. comboBox.addItem(qsTr("None"), 2);
  1374. };
  1375. WidgetFactory.installComboBoxEventFilter = function(widget) {
  1376. if (isNull(widget)) {
  1377. return;
  1378. }
  1379. if (!isQWidget(widget) || !isFunction(widget.children)) {
  1380. return;
  1381. }
  1382. var children = widget.children();
  1383. for ( var i = 0; i < children.length; ++i) {
  1384. var c = children[i];
  1385. if (!c || isDeleted(c)) {
  1386. break;
  1387. }
  1388. if (isOfType(c, QSpinBox) ||
  1389. isOfType(c, QComboBox) ||
  1390. isOfType(c, QFontComboBox) ||
  1391. isOfType(c, RColorCombo) ||
  1392. isOfType(c, RLineweightCombo) ||
  1393. isOfType(c, RLinetypeCombo)) {
  1394. if (isFunction(c.installEventFilter)) {
  1395. c.installEventFilter(new REventFilter(QEvent.Wheel.valueOf(), true));
  1396. }
  1397. c.focusPolicy = Qt.ClickFocus;
  1398. continue;
  1399. }
  1400. WidgetFactory.installComboBoxEventFilter(c);
  1401. }
  1402. };