diff --git a/octoprint_mrbeam/iobeam/lid_handler.py b/octoprint_mrbeam/iobeam/lid_handler.py index 7dc39369f..a0270b2f6 100644 --- a/octoprint_mrbeam/iobeam/lid_handler.py +++ b/octoprint_mrbeam/iobeam/lid_handler.py @@ -63,7 +63,8 @@ SIMILAR_PICS_BEFORE_REFRESH = 20 MAX_PIC_THREAD_RETRIES = 2 - +CAMERA_SETTINGS_LAST_SESSION_YAML = "/home/pi/.octoprint/cam/last_session.yaml" +CAMERA_SETTINGS_FALLBACK_JSON = "/home/pi/.octoprint/cam/last_markers.json" from octoprint_mrbeam.iobeam.iobeam_handler import IoBeamEvents from octoprint.events import Events as OctoPrintEvents @@ -1317,39 +1318,58 @@ def _createFolder_if_not_existing(self, filename): makedirs(folder) self._logger.debug("Created folder '%s' for camera images.", folder) - def load_camera_settings(self, path="/home/pi/.octoprint/cam/last_session.yaml"): + def load_camera_settings(self, path=CAMERA_SETTINGS_LAST_SESSION_YAML): """ - Loads the settings saved from the last session. - The file is located by default at .octoprint/cam/pic_settings.yaml + Loads and returns the camera settings. + + Args: + path (str): path to the camera settings Yaml to load from + + Returns: + (list): ["calibMarkers", "shutter_speed"] + """ - backup = "/home/pi/.octoprint/cam/last_markers.json" - if os.path.isfile(path): - _path = path - else: - self._logger.info( - "last_session.yaml does not exist, using legacy backup (last_markers.json)" + + # To Be used in case the default file not there or invalid + backup_path = CAMERA_SETTINGS_FALLBACK_JSON + camera_settings = [] + + # 1. Load from default + try: + with open(path) as f: + settings = yaml.safe_load(f) + for k in ["calibMarkers", "shutter_speed"]: + camera_settings.append(settings.get(k, None)) + self._logger.debug("lid_handler: Default camera settings loaded from file: {}".format(path)) + return camera_settings + except(IOError, OSError, yaml.YAMLError, yaml.reader.ReaderError, AttributeError) as e: + if os.path.isfile(path): + # An extra step to insure a smooth experience moving forward + os.remove(path) + self._logger.warn( + "lid_handler: File: {} does not exist or invalid, Will try to use legacy backup_path...: {}".format( + path, backup_path) ) - _path = backup + + # 2. Load from Backup try: - ret = [] - with open(_path) as f: - settings = yaml.load(f) or {} - if _path == backup: - # No shutter speed info - settings = {k: v[-1] for k, v in settings.items()} - ret = [settings, None] - else: - for k in ["calibMarkers", "shutter_speed"]: - ret.append(settings.get(k, None)) - return ret - except (IOError, OSError) as e: - self._logger.warning("New or Legacy marker memory not found.") - return [None] * 2 + with open(backup_path) as f: + settings = yaml.safe_load(f) + # No shutter speed info present in this file + settings = {k: v[-1] for k, v in settings.items()} + camera_settings = [settings, None] + self._logger.debug("lid_handler: Fallback camera settings loaded from file: {}".format(backup_path)) + return camera_settings + except(IOError, OSError, yaml.YAMLError, yaml.reader.ReaderError, AttributeError) as e: + self._logger.exception( + "lid_handler: File: {} does not exist or invalid, Camera Settings Load failed".format(backup_path) + ) + return [None, None] # @logme(True) def save_camera_settings( self, - path="/home/pi/.octoprint/cam/last_session.yaml", + path=CAMERA_SETTINGS_LAST_SESSION_YAML, markers=None, shutter_speed=None, ): @@ -1371,10 +1391,10 @@ def save_camera_settings( settings = {} try: with open(path) as f: - settings = yaml.load(f) - except (OSError, IOError) as e: + settings = yaml.safe_load(f) + except (OSError, IOError, yaml.YAMLError, yaml.reader.ReaderError, AttributeError) as e: self._logger.warning( - "file %s does not exist or could not be read. Overwriting..." % path + "lid_handler: file %s does not exist or could not be read. Overwriting..." % path ) settings = dict_merge( @@ -1389,7 +1409,7 @@ def save_camera_settings( try: with open(path, "w") as f: f.write(yaml.dump(settings)) - except (OSError, IOError) as e: + except (OSError, IOError, yaml.YAMLError) as e: self._logger.error(e) except TypeError as e: self._logger.warning( diff --git a/octoprint_mrbeam/static/js/render_fills.js b/octoprint_mrbeam/static/js/render_fills.js index 2fd2f944b..919a25d64 100644 --- a/octoprint_mrbeam/static/js/render_fills.js +++ b/octoprint_mrbeam/static/js/render_fills.js @@ -127,10 +127,12 @@ Snap.plugin(function (Snap, Element, Paper, global) { let rasterEl = marked[i]; let bbox; try { - bbox = rasterEl.get_total_bbox(); - } - catch(error) { - console.warn(`Getting bounding box for ${rasterEl} failed.`, error); + bbox = rasterEl.get_total_bbox(); + } catch (error) { + console.warn( + `Getting bounding box for ${rasterEl} failed.`, + error + ); continue; } // find overlaps @@ -172,13 +174,14 @@ Snap.plugin(function (Snap, Element, Paper, global) { rasterEl.addClass(`rasterCluster${c}`) ); let tmpSvg = svg.clone(); - tmpSvg.selectAll(`.toRaster:not(.rasterCluster${c})`).forEach((element) => { - let elementToBeRemoved = tmpSvg.select('#' + element.attr('id')); - let elementsToBeExcluded = ["text", "tspan"] - if (elementToBeRemoved && !elementsToBeExcluded.includes(elementToBeRemoved.type)) { - elementToBeRemoved.remove(); - } - }); + tmpSvg.selectAll(`.toRaster:not(.rasterCluster${c})`).remove(); + // tmpSvg.selectAll(`.toRaster:not(.rasterCluster${c})`).forEach((element) => { + // let elementToBeRemoved = tmpSvg.select('#' + element.attr('id')); + // let elementsToBeExcluded = ["text", "tspan"] + // if (elementToBeRemoved && !elementsToBeExcluded.includes(elementToBeRemoved.type)) { + // elementToBeRemoved.remove(); + // } + // }); // Fix IDs of filter references, those are not cloned correct (probably because reference is in style="..." definition) tmpSvg.fixIds("defs filter[mb\\:id]", "mb:id"); // namespace attribute selectors syntax: [ns\\:attrname] // DON'T fix IDs of textPath references, they're cloned correct. @@ -335,10 +338,17 @@ Snap.plugin(function (Snap, Element, Paper, global) { // ); } - // TODO only enlarge on images and fonts - // Quick fix: in some browsers the bbox is too tight, so we just add an extra 10% to all the sides, making the height and width 20% larger in total - const enlargement_x = 0.4; // percentage of the width added to each side - const enlargement_y = 0.4; // percentage of the height added to each side + // only enlarge on fonts, images not necessary. + const doEnlargeBBox = + elem.selectAll("text").filter((e) => { + const bb = e.getBBox(); + // this filter is required, as every quick text creates an empty text element (for switching between curved and straight text) + return bb.width > 0 && bb.height > 0; + }).length > 0; + + // Quick fix: in some browsers the bbox is too tight, so we just add an extra margin to all the sides, making the height and width larger in total + const enlargement_x = doEnlargeBBox ? 0.4 : 0; // percentage of the width added to each side + const enlargement_y = doEnlargeBBox ? 0.4 : 0; // percentage of the height added to each side const x1 = Math.max(0, bbox.x - bbox.width * enlargement_x); const x2 = Math.min(wMM, bbox.x2 + bbox.width * enlargement_x); const w = x2 - x1; diff --git a/octoprint_mrbeam/static/js/snap_helpers.js b/octoprint_mrbeam/static/js/snap_helpers.js index dea6f94b4..99aec5265 100644 --- a/octoprint_mrbeam/static/js/snap_helpers.js +++ b/octoprint_mrbeam/static/js/snap_helpers.js @@ -66,4 +66,19 @@ Snap.plugin(function (Snap, Element, Paper, global) { const bb = el.getBBox(); return Snap.path.getBBoxWithTransformation(bb, mat); }; + + /** + * filter method for Snap Set like we know it from Array + * @param f function which decides wether to keep or discard set elements + * @returns {Set} a new Snap set + */ + Snap.Set.prototype.filter = function (f) { + const s = new Snap.Set(); + this.forEach((e) => { + if (f(e)) { + s.push(e); + } + }); + return s; + }; }); diff --git a/octoprint_mrbeam/static/js/software_channel_selector.js b/octoprint_mrbeam/static/js/software_channel_selector.js index 327ff1713..166a07146 100644 --- a/octoprint_mrbeam/static/js/software_channel_selector.js +++ b/octoprint_mrbeam/static/js/software_channel_selector.js @@ -132,7 +132,7 @@ $(function () { self.softwareUpdate.checking(true); OctoPrint.postJson("plugin/mrbeam/info/update", {user:user_clicked}) .done(function (response) { - self.fromCheckResponse(response, ignoreSeen, showIfNothingNew); + self.softwareUpdate.fromCheckResponse(response, ignoreSeen, showIfNothingNew); }) .fail(function (error) { console.error("Unable to reload update info."); diff --git a/octoprint_mrbeam/static/js/working_area.js b/octoprint_mrbeam/static/js/working_area.js index 07b192375..5aab39df8 100644 --- a/octoprint_mrbeam/static/js/working_area.js +++ b/octoprint_mrbeam/static/js/working_area.js @@ -1201,16 +1201,23 @@ $(function () { if (generator.generator === "inkscape") { let isOldInkscapeVersion = NaN; try { - isOldInkscapeVersion= window.compareVersions( - // 1.1.2 (1:1.1+202202050950+0a00cf5339) -> 1.1 - generator.version.split('.').slice(0,2).join('.'), - "0.91" - ) <= 0; - } catch(e) { + isOldInkscapeVersion = + window.compareVersions( + // 1.1.2 (1:1.1+202202050950+0a00cf5339) -> 1.1 + generator.version + .split(".") + .slice(0, 2) + .join("."), + "0.91" + ) <= 0; + } catch (e) { let payload = { error: e.message, }; - self._sendAnalytics("inkscape_version_comparison_error", payload); + self._sendAnalytics( + "inkscape_version_comparison_error", + payload + ); console.log("inkscape_version_comparison_error: ", e); // In case the comparison fails, we assume the version to be above 0.91 // This assumption (the scaling) does not have a major impact as it has @@ -1715,7 +1722,7 @@ $(function () { } else if ( event.target.classList.contains("unit_percent") ) { - const newWidth = + let newWidth = ((currentWidth / Math.abs(currentSx)) * value) / 100.0; if (Math.abs(newWidth) < 0.1) @@ -1759,7 +1766,7 @@ $(function () { } else if ( event.target.classList.contains("unit_percent") ) { - const newHeight = + let newHeight = ((currentHeight / Math.abs(currentSy)) * value) / 100.0; if (Math.abs(newHeight) < 0.1)