| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646 |
- /**
- * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
- *
- * This file is part of the QCAD project.
- *
- * QCAD is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * QCAD is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with QCAD.
- */
- include("../AddOn.js");
- include("Edit.js");
- function AbstractPreferences(guiAction, appPreferences, initialClassName) {
- Edit.call(this, guiAction);
- if (isNull(appPreferences)) {
- appPreferences = true;
- }
- this.appPreferences = appPreferences;
- this.restartWarningShown = false;
- this.initialClassName = initialClassName;
- }
- AbstractPreferences.prototype = new Edit();
- AbstractPreferences.includeBasePath = includeBasePath;
- AbstractPreferences.prototype.beginEvent = function() {
- Edit.prototype.beginEvent.call(this);
-
- this.dialog = this.createWidget(AbstractPreferences.includeBasePath + "/AbstractPreferences.ui");
- // TODO: Qt 5: add this flag (?)
- //var flags = new Qt.WindowFlags(Qt.WindowTitleHint);
- //this.dialog.setWindowFlags(flags);
- this.treeWidget = this.dialog.findChild("twCategory");
- var title;
- if (this.appPreferences) {
- title = qsTr("Application Preferences");
- } else {
- title = qsTr("Drawing Preferences");
- }
- this.dialog.setWindowTitle(title);
- this.treeWidget.setHeaderLabel(title);
- this.pageWidget = this.dialog.findChild("stwPage");
- this.filterWidget = this.dialog.findChild("leFilter");
- this.titleWidget = this.dialog.findChild("lbTitle");
-
- var splitter = this.dialog.findChild("splitter");
- splitter.setStretchFactor(0, 1);
- splitter.setStretchFactor(1, 4);
-
- // connections:
- this.treeWidget.itemSelectionChanged.connect(this, this.showPage);
- this.filterWidget.textChanged.connect(this, this.filterTree);
- var btApply = this.dialog.findChild("buttonBox").button(QDialogButtonBox.Apply);
- btApply.clicked.connect(this, this.apply);
- this.addOns = AddOn.getAddOns();
- AbstractPreferences.fillTreeWidget(this.addOns, this.treeWidget, this.appPreferences);
- this.treeWidget.expandAll();
- if (!isNull(this.initialClassName)) {
- this.showPageFor(this.initialClassName);
- }
- if (this.dialog.exec() === QDialog.Accepted.valueOf()) {
- // apply calls save and apply:
- this.apply();
- }
- this.uninit();
- destr(this.dialog);
- EAction.activateMainWindow();
- this.terminate();
- };
- /**
- * Initializes the navigation tree based on available add-ons with preferences.
- */
- AbstractPreferences.fillTreeWidget = function(addOns, treeWidget, appPreferences) {
- for (var i = 0; i < addOns.length; ++i) {
- var addOn = addOns[i];
- var className = addOn.getClassName();
- var scriptFile = addOn.getFilePath();
- if (appPreferences===false) {
- if (!scriptFile.contains("DrawingPreferences")) {
- continue;
- }
- }
- try {
- // include normally not needed
- var doInclude = false;
- if (isNull(global[className])) {
- doInclude = true;
- }
- if(doInclude) {
- include(addOn.getFilePath());
- }
- } catch (e1) {
- qWarning("AppPreferences.js: Exception: ", e1);
- continue;
- }
- var cat;
- cat = undefined;
- try {
- if (!isNull(global[className]) && isFunction(global[className].getPreferencesCategory)) {
- cat = global[className].getPreferencesCategory(appPreferences);
- }
- if (isNull(cat)) {
- continue;
- }
- } catch (e2) {
- qWarning("AppPreferences.js: Add-on class not found: ", className, " exception: ", e2);
- continue;
- }
-
- if (!addOn.preferenceFileExists()) {
- continue;
- }
- // update tree
- var items = treeWidget.findItems(cat[0], Qt.MatchFixedString);
- var item;
- item = undefined;
- if (items.length === 0) {
- item = new QTreeWidgetItem(treeWidget, [ cat[0] ]);
- treeWidget.addTopLevelItem(item);
- if (cat.length === 1) {
- item.setData(0, Qt.UserRole, i);
- }
- } else {
- item = items[0];
- }
- var parent = item;
- for (var x = 1; x < cat.length; ++x) {
- var subitem;
- subitem = undefined;
- for (var c = 0; c < parent.childCount(); ++c) {
- var child = parent.child(c);
- if (child.text(0) === cat[x]) {
- subitem = child;
- break;
- }
- }
- if (isNull(subitem)) {
- subitem = new QTreeWidgetItem(parent, [ cat[x] ]);
- parent.addChild(subitem);
- if (x == cat.length - 1) {
- subitem.setData(0, Qt.UserRole, i);
- }
- }
- parent = subitem;
- }
- }
- treeWidget.sortItems(0, Qt.AscendingOrder);
- };
- /**
- * Applies the settings of all preference pages by calling
- * 'applyPreferences' for every add-on class.
- */
- AbstractPreferences.prototype.apply = function() {
- var mdiChild, document;
- // force all settings to be reloaded from RSettings when they are
- // used next time:
- RSettings.resetCache();
-
- this.save();
- for (var i=0; i<this.addOns.length; ++i) {
- var addOn = this.addOns[i];
- var className = addOn.getClassName();
-
- var widget = addOn.getPreferenceWidget();
- if (isNull(widget)) {
- continue;
- }
- var hasChanged = widget.property("hasChanged");
- if (hasChanged !== true) {
- continue;
- }
- try {
- // include normally not needed
- var doInclude = false;
- if (isNull(global[className])) {
- doInclude = true;
- }
- if (doInclude) {
- include(addOn.getFilePath());
- }
- // apply application settings globally:
- if (this.appPreferences) {
- if (!isNull(global[className]) && isFunction(global[className].applyPreferences)) {
- global[className].applyPreferences(undefined, undefined, widget);
- }
- var mdiArea = EAction.getMdiArea();
- var mdiChildren = mdiArea.subWindowList();
- for (var j = 0; j < mdiChildren.length; ++j) {
- mdiChild = mdiChildren[j];
- document = mdiChild.getDocument();
- if (!isNull(global[className]) && isFunction(global[className].applyPreferences)) {
- global[className].applyPreferences(document, mdiChild, widget);
- }
- }
- }
- // apply document specific settings to current document:
- else {
- mdiChild = EAction.getMdiChild();
- document = EAction.getDocument();
- if (!isNull(global[className]) && isFunction(global[className].applyPreferences)) {
- global[className].applyPreferences(document, mdiChild, widget);
- }
- }
- } catch (e) {
- qWarning("AbstractPreferences.js:",
- "apply(): Exception: %1; %2; %3"
- .arg(e.message).arg(e.fileName).arg(e.lineNumber));
- continue;
- }
- }
- var di = EAction.getDocumentInterface();
- if (!isNull(di)) {
- di.regenerateScenes();
- }
- var appWin = EAction.getMainWindow();
- if (this.appPreferences) {
- appWin.notifyPreferencesListeners(null);
- }
- else {
- appWin.notifyPreferencesListeners(di);
- }
- };
- /**
- * Cleans up settings of all preference pages by calling
- * 'uninitPreferences' for every add-on class.
- */
- AbstractPreferences.prototype.uninit = function() {
- var mdiChild, document;
- for (var i = 0; i < this.addOns.length; ++i) {
- var addOn = this.addOns[i];
- var className = addOn.getClassName();
- var widget = addOn.getPreferenceWidget();
- // break link from add on to preference widget (preference widget is deleted with dialog):
- addOn.setPreferenceWidget(undefined);
- if (isNull(widget)) {
- continue;
- }
- var hasChanged = widget.property("hasChanged");
- if (hasChanged !== true) {
- continue;
- }
- try {
- // include normally not needed
- var doInclude = false;
- if (isNull(global[className])) {
- doInclude = true;
- }
- if (doInclude) {
- include(addOn.getFilePath());
- }
- // uninit application settings globally:
- if (this.appPreferences) {
- if (!isNull(global[className]) && isFunction(global[className].uninitPreferences)) {
- global[className].uninitPreferences(undefined, undefined, widget);
- }
- }
- // uninit document specific settings to current document:
- else {
- mdiChild = EAction.getMdiChild();
- document = EAction.getDocument();
- if (!isNull(global[className]) && isFunction(global[className].uninitPreferences)) {
- global[className].uninitPreferences(document, mdiChild, widget);
- }
- }
- } catch (e) {
- qWarning("AbstractPreferences.js:",
- "uninit(): Exception: %1; %2; %3"
- .arg(e.message).arg(e.fileName).arg(e.lineNumber));
- continue;
- }
- }
- };
- /**
- * Loads the preference page of the given add-on.
- * Called by 'showPage'.
- */
- AbstractPreferences.prototype.load = function(addOn) {
- var widget = addOn.getPreferenceWidget();
- if (widget == undefined) {
- return;
- }
- // load preferences
- var className = addOn.getClassName();
- var document;
- document = undefined;
- if (!this.appPreferences) {
- document = EAction.getDocument();
- }
- if (!isNull(global[className]) && isFunction(global[className].initPreferences)) {
- global[className].initPreferences(widget, true, document, this);
- }
- // check if preferences apply to block:
- var store = document;
- if (!this.appPreferences) {
- var preferencesScope = "document";
- if (!isNull(global[className]) && isFunction(global[className].getPreferencesScope)) {
- if (document.getCurrentBlockId()!==document.getModelSpaceBlockId()) {
- preferencesScope = global[className].getPreferencesScope();
- }
- }
- if (!isNull(document) && preferencesScope==="block") {
- store = document.queryCurrentBlock();
- }
- }
- WidgetFactory.restoreState(widget, undefined, undefined, false, store);
- if (!isNull(global[className]) && isFunction(global[className].postInitPreferences)) {
- global[className].postInitPreferences(widget, true, document, this);
- }
- };
- /**
- * Saves all preferences to the current document (this.appPreferences==false)
- * or to a global settings file (this.appPreferences==true).
- */
- AbstractPreferences.prototype.save = function() {
- var document = undefined;
- var transaction = undefined;
- if (!this.appPreferences) {
- document = EAction.getDocument();
- transaction = new RTransaction(document.getStorage(), qsTr("Apply preferences"), true);
- }
- for (var i = 0; i < this.addOns.length; ++i) {
- var addOn = this.addOns[i];
- var widget = addOn.getPreferenceWidget();
- if (isNull(widget)) {
- continue;
- }
- var hasChanged = widget.property("hasChanged");
- if (hasChanged !== true) {
- continue;
- }
- var className = addOn.getClassName();
- if (!isNull(global[className]) && isFunction(global[className].savePreferences)) {
- global[className].savePreferences(widget, true, document, transaction);
- }
- // check if preferences apply to block:
- var store = document;
- var preferencesScope = "document";
- if (!this.appPreferences) {
- if (!isNull(global[className]) && isFunction(global[className].getPreferencesScope)) {
- if (document.getCurrentBlockId()!==document.getModelSpaceBlockId()) {
- preferencesScope = global[className].getPreferencesScope();
- }
- }
- if (!isNull(document) && preferencesScope==="block") {
- store = document.queryCurrentBlock();
- }
- }
- WidgetFactory.saveState(widget, undefined, store);
- if (!this.appPreferences) {
- if (preferencesScope==="block") {
- transaction.addObject(store);
- }
- }
- }
- if (!this.appPreferences) {
- transaction.end();
- }
- // check if preference changes require application restart and show
- // message if appropriate:
- if (WidgetFactory.requiresRestart===true && this.restartWarningShown === false) {
- var appWin = EAction.getMainWindow();
- QMessageBox.warning(appWin,
- qsTr("Restart required"),
- qsTr("Please restart QCAD for\nthe preference changes to take effect.")
- );
- this.restartWarningShown = true;
- }
- WidgetFactory.requiresRestart = false;
- };
- /**
- * Updates the navigation tree based on the given filter string.
- */
- AbstractPreferences.prototype.updateTreeWidget = function(filterText) {
- if (isNull(filterText)) {
- filterText = "";
- }
- var rexp;
- try{
- rexp = new RegExp(filterText, "i");
- } catch (e) {
- rexp = new RegExp(".*", "i");
- }
-
- for(var i=0; i<this.treeWidget.topLevelItemCount; ++i) {
- var item = this.treeWidget.topLevelItem(i);
- var match = item.text(0).match(rexp);
- var found = this.filterItems(item, rexp, match);
- if (found || match) {
- item.setHidden(false);
- item.setExpanded(true);
- } else if(!match) {
- item.setHidden(true);
- }
- }
- };
- /**
- * \internal
- */
- AbstractPreferences.prototype.filterItems = function(item, rexp, showAll) {
- var foundAny = false;
- for(var i=0; i<item.childCount(); ++i) {
- var subitem = item.child(i);
- var match = subitem.text(0).match(rexp);
- var found = this.filterItems(subitem, rexp, match);
- if (found || match) {
- subitem.setHidden(false);
- subitem.setExpanded(true);
- foundAny = true;
- } else if(!match) {
- if(!showAll) {
- subitem.setHidden(true);
- }
- }
- }
- return foundAny;
- };
- /**
- * Called when user enters a filter text for the navigation tree.
- */
- AbstractPreferences.prototype.filterTree = function(text) {
- this.updateTreeWidget(text);
- };
- /**
- * Loads and shows the appropriate preferences page for the
- * current selected item in the navigation tree. Called
- * when the user selects an item in the tree.
- */
- AbstractPreferences.prototype.showPage = function() {
- var items = this.treeWidget.selectedItems();
- if (items.length!==1) {
- return;
- }
- var item = items[0];
- if (isNull(item)) {
- return;
- }
- var parent = item.parent();
- var warningLabel = this.dialog.findChild("Warning");
- warningLabel.text = "";
- warningLabel.visible = false;
- if (!isNull(parent)) {
- if (parent.text(0).contains(qsTr("Defaults for"))) {
- var col = "red";
- if (RSettings.hasDarkGuiBackground()) {
- col = "#C00000";
- }
- warningLabel.text = "<font color='" + col + "'>" +
- qsTr("These are default preferences for new drawings.") + "<br/>" +
- qsTr("Changes will affect new drawings but NOT the current drawing.") + "<br/>" +
- qsTr("Preferences of the current drawing can be changed under<br/><i>Edit > Drawing Preferences</i>.") +
- "</font>";
- warningLabel.visible = true;
- }
- }
- var pText = "";
- while (!isNull(parent)) {
- pText += parent.text(0) + ": " + pText;
- parent = parent.parent();
- }
- if (pText == "") {
- this.titleWidget.text = item.text(0);
- } else {
- this.titleWidget.text = pText + item.text(0);
- }
- var i = item.data(0, Qt.UserRole);
- var widget;
- if (!isNull(i)) {
- var addOn = this.addOns[i];
- widget = addOn.getPreferenceWidget();
- if (isNull(widget)) {
- var prefFile = addOn.getPreferenceFile();
- widget = this.createWidget(prefFile);
- this.pageWidget.addWidget(widget);
- addOn.setPreferenceWidget(widget);
- // loads (initializes) the page:
- this.load(addOn);
- var treeWidget = this.treeWidget;
- widget.settingChangedEvent = function() {
- // mark changed category in bold:
- var font = treeWidget.currentItem().font(0);
- font.setBold(true);
- treeWidget.currentItem().setFont(0, font);
- };
- var btReset = this.dialog.findChild("ResetToDefaults");
- try {
- btReset.clicked.disconnect(this, this.reset);
- } catch (e) {
- // ignored: signal might not be connected
- }
- btReset.clicked.connect(this, this.reset);
- }
- } else {
- widget = this.pageWidget.findChild("empty");
- }
- this.pageWidget.setCurrentWidget(widget);
- this.treeWidget.setCurrentItem(item);
- };
- AbstractPreferences.prototype.showPageFor = function(className) {
- var flags = makeQtMatchFlags(Qt.MatchWildcard, Qt.MatchContains, Qt.MatchRecursive);
- var items = this.treeWidget.findItems("*", flags, 0);
- for (var i = 0; i < items.length; ++i) {
- var item = items[i];
- var ix = item.data(0, Qt.UserRole);
- if (!isNull(ix)) {
- var addOn = this.addOns[ix];
- if (addOn.getClassName()===className) {
- this.treeWidget.setCurrentItem(item);
- }
- }
- }
- };
- /**
- * Called when user clicks reset button on preferences page.
- */
- AbstractPreferences.prototype.reset = function() {
- var widget = this.pageWidget.currentWidget();
- //qDebug("AbstractPreferences.js:", "reset(): widget.objectName:", widget.objectName);
- WidgetFactory.resetState(widget);
- var treeWidget = this.treeWidget;
- var font = treeWidget.currentItem().font(0);
- font.setBold(true);
- treeWidget.currentItem().setFont(0, font);
- widget.setProperty("hasChanged", true);
- };
- /**
- * Called when the global or drawing unit changes. Notifies all loaded
- * add-on pages.
- */
- AbstractPreferences.prototype.unitUpdated = function(unit) {
- for (var i=0; i<this.addOns.length; ++i) {
- var addOn = this.addOns[i];
- var className = addOn.getClassName();
- // pref page of this add-on is not opened yet, skip:
- var widget = addOn.getPreferenceWidget();
- if (isNull(widget)) {
- continue;
- }
- if (!isNull(global[className]) && isFunction(global[className].updateUnit)) {
- global[className].updateUnit(unit);
- }
- }
- };
- /**
- * Called when the global or drawing paper unit changes. Notifies all loaded
- * add-on pages.
- */
- AbstractPreferences.prototype.paperUnitUpdated = function(unit) {
- for (var i=0; i<this.addOns.length; ++i) {
- var addOn = this.addOns[i];
- var className = addOn.getClassName();
- // pref page of this add-on is not opened yet, skip:
- var widget = addOn.getPreferenceWidget();
- if (isNull(widget)) {
- continue;
- }
- if (!isNull(global[className]) && isFunction(global[className].updatePaperUnit)) {
- global[className].updatePaperUnit(unit);
- }
- }
- };
- AbstractPreferences.prototype.linearFormatUpdated = function(linearFormat) {
- for (var i=0; i<this.addOns.length; ++i) {
- var addOn = this.addOns[i];
- var className = addOn.getClassName();
- // pref page of this add-on is not opened yet, skip:
- var widget = addOn.getPreferenceWidget();
- if (isNull(widget)) {
- continue;
- }
- if (!isNull(global[className]) && isFunction(global[className].updateLinearFormat)) {
- global[className].updateLinearFormat(linearFormat);
- }
- }
- };
|